it-swarm.com.de

Android 6: Kann keine Dateien mehr teilen?

Ich teile ein Bild, und dieser Code funktioniert für Geräte vor Android 6 ordnungsgemäß:

Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri uri = Uri.fromFile(new File(mFilename));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle));

Ich bekomme jedoch den Toast-Fehler " kann keine leeren Dateien anhängen ", wenn ich versuche, mit Android 6 zu teilen.

Ich habe überprüft, dass die Datei vorhanden ist und nicht die Länge Null hat.

Hat jemand eine Lösung dafür?

29
Daniele B

Eine Einschränkung des Android 6.0-Laufzeitberechtigungssystems besteht darin, dass es Eckfälle geben wird, die Probleme verursachen. Sie haben Folgendes festgestellt: Versuchen Sie, eine Datei im externen Speicher für eine App freizugeben, für die keine Laufzeitberechtigungsprüfungen für diesen bestimmten UI-Pfad vorhanden sind.

Ich sage, dass dies ein "Eckfall" ist, da der Benutzer die App nicht zuvor verwendet und die erforderliche Berechtigung erteilt haben kann, damit dieser Fehler in der empfangenden App Auswirkungen auf den Benutzer hat. Entweder:

  • Der Benutzer hat diese App noch nie zuvor verwendet und versucht dennoch, Inhalte für ihn freizugeben, oder

  • Der Benutzer hat die Berechtigung über Einstellungen widerrufen, wusste jedoch nicht, dass diese Funktionalität beeinträchtigt würde

Beides sind Ereignisse mit niedriger Wahrscheinlichkeit.

Sie als Absender haben zwei Hauptoptionen:

  1. Wechseln Sie statt der Verwendung von file://Uri-Werten zugunsten einer dateibedienenden ContentProvider wie FileProvider, sodass die Berechtigung nicht mehr benötigt wird

  2. Nur mit dem Eckfall leben

22
CommonsWare

Ich habe es gelöst, indem ich eine FileProvider implementiert habe, wie von @CommonsWare vorgeschlagen

Sie müssen zuerst einen FileProvider konfigurieren:

  • fügen Sie zuerst den <provider> zu Ihrem Dateiformat XML hinzu

    <provider
        Android:name="Android.support.v4.content.FileProvider"
        Android:authorities="com.myfileprovider"
        Android:exported="false"
        Android:grantUriPermissions="true">
        <meta-data
            Android:name="Android.support.FILE_PROVIDER_PATHS"
            Android:resource="@xml/file_provider_paths" />
    </provider>
    
  • zweitens definieren Sie Ihre Dateipfade in einer separaten XML-Datei. Ich habe sie "file_provider_paths.xml" genannt.

    <paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
        <external-path name="share" path="/" />
    </paths>
    

die vollständige Erklärung finden Sie auf dieser Dokumentationsseite

nachdem Sie Ihren Datei-Provider in XML eingerichtet haben, ist dies der Code zum Freigeben der Bilddatei:

Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri fileUri = FileProvider.getUriForFile(mContext, "com.myfileprovider", new File(mFilename));
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle));
36
Daniele B

Alternativ benötigen Sie keinen ContentProvider/FileProvider. Sie können einfach das Flag hinzufügen, das die Leseberechtigung für den gemeinsam genutzten URI gewährt. Insbesondere sollte share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); den Trick tun. 

2
yrizk

Eine andere Möglichkeit, dieses Problem zu umgehen, bestand darin, URI mit MediaScannerConnection direkt nach dem Schreiben Ihrer Datei in das öffentliche Verzeichnis zu erstellen:

        MediaScannerConnection.scanFile(context, new String[] {imageFile.toString()}, yourMimeType, new OnScanCompletedListener() {
            @Override
            public void onScanCompleted(String path, Uri uri) {
                //uri = "content://" style URI that is safe to attach to share intent
            }
        });

Dies kann eine kürzere Lösung für Ihre Bedürfnisse sein.

0
AndroidEx