2016-08-03 18 views
1

Ich versuche, ein Bild im Verzeichnis res/raw meiner App zusammen mit einem Share Intent übergeben.Freigeben einer Datei im Raw-Ordner mit einem FileProvider

Ich folgte dem Prozess in der FileProvider docs beschrieben, und hier ist mein Code:

AndroidManifest.xml

<application ...> 
    <provider 
     android:name="android.support.v4.content.FileProvider" 
     android:authorities="com.myapp.fileprovider" 
     android:exported="false" 
     android:grantUriPermissions="true"> 

     <meta-data 
      android:name="android.support.FILE_PROVIDER_PATHS" 
      android:resource="@xml/paths" /> 
    </provider> 
</application> 

res/xml/paths.xml

<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <files-path name="shared" path="./"/> 
</paths> 

Der Code in meiner Tätigkeit:

String shareToPackage = ... 

File imageFile = new File(context.getFilesDir().getPath() + "/image"); 
if (!imageFile.exists()) { // image isn't in the files dir, copy from the res/raw 
    final InputStream inputStream = context.getResources().openRawResource(R.raw.my_image); 
    final FileOutputStream outputStream = context.openFileOutput("image", Context.MODE_PRIVATE); 

    byte buf[] = new byte[1024]; 
    int len; 
    while ((len = inputStream.read(buf)) > 0) { 
     outputStream.write(buf, 0, len); 
    } 

    outputStream.close(); 
    inputStream.close(); 

    imageFile = new File(context.getFilesDir().getPath() + "/image"); 
} 

if (!imageFile.exists()) { 
    throw new IOException("couldn't find file"); 
} 

final Uri uri = Uri.fromFile(imageFile); 
context.grantUriPermission(shareToPackage, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 

final Intent intent = new Intent(Intent.ACTION_SEND); 
intent.setType("image/png"); 
intent.putExtra(Intent.EXTRA_TEXT, "here's the image"); 
intent.putExtra(Intent.EXTRA_STREAM, uri); 
intent.setPackage(shareToPackage); 
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
context.startActivity(intent); 

Die oben nicht als Datei, die ich in der anderen App bekommen funktioniert nicht zugänglich ist:

java.io.FileNotFoundException: FILE_PATH: öffnen, ist fehlgeschlagen: EACCES (Permission denied)

Irgendeine Idee, was ich hier falsch mache?
Danke.

+0

Haben Sie dieses Problem jemals gelöst - vor der genau gleichen ... – brandall

+1

@brandall Nein. Ich habe es aufgegeben, weil zu viel Zeit dafür verschwendet wurde. Wenn Sie eine Lösung finden, beantworten Sie diese bitte hier, damit andere in Zukunft auch nicht viel Zeit verschwenden müssen. VIEL GLÜCK! –

+1

Unglaublich ... 6 Stunden auf der Toilette schon drauf, für etwas das so einfach sein sollte.Wenn ich es löse, werde ich zurück posten ..... – brandall

Antwort

2

Entfernen Sie das path Attribut in <files-path>, da es hier nicht benötigt wird, da Sie alles aus getFilesDir() bedienen.

Verwenden Sie keine Stringverkettung beim Erstellen von File Objekten. Ersetzen:

new File(context.getFilesDir().getPath() + "/image.png"); 

mit:

new File(context.getFilesDir().getPath(), "image.png"); 

Am wichtigsten ist, nicht Uri.fromFile() verwenden. Use FileProvider.getUriForFile(). Wie es aussieht, gehen Sie durch diese ganze Arbeit, um FileProvider einzurichten, dann verwenden Sie nicht die FileProvider, um den Inhalt für die andere App verfügbar zu machen.

Oder, loswerden von allem, und use my StreamProvider, die eine rohe Ressource direkt dienen kann.

Oder schreiben Sie Ihre eigene ContentProvider, die die Rohressource direkt dient.

+0

Danke. Ich habe alles geändert, was Sie vorgeschlagen haben, und die App, die die Absicht erhält, hat immer noch keinen Zugriff auf die Datei, aber jetzt heißt es, dass die Datei nicht existiert, anstatt zu sagen, dass die Berechtigung verweigert wurde. Die Datei ist da sicher, als ich nachschaue, bevor ich die Absicht sende, also was ist hier los? Dein 'StreamProvider' klingt interessant, aber ich möchte zuerst diese aktuelle Version reparieren und dann werde ich es versuchen. –

+0

@NitzanTomer: Fügen Sie vor 'outputStream.close();' 'outputStream.flush();' und 'outputStream.getFD(). Sync();' hinzu, um sicherzustellen, dass alle Bytes auf den Datenträger geschrieben werden. Kommentar "EXTRA_TEXT", da "ACTION_SEND" entweder 'EXTRA_TEXT' oder' EXTRA_STREAM' unterstützt, nicht unbedingt beides. Sie können auch die 'Uri' protokollieren, die Sie von' FileProvider' erhalten, um zu sehen, ob es sinnvoll ist. – CommonsWare

+0

Die 'flush' und' sync' wurden hinzugefügt, der 'EXTRA_TEXT' entfernt, aber die Datei existiert nicht. Die URL scheint mir ok zu sein: 'content: // com.myapp.fileprovider/shared/image', aber ich bin kein Experte, also könnte ich mich irren. –

0

@ nitzan-Tomer finden https://stackoverflow.com/a/33031091/966789

Was Runtime Berechtigungen sind?

Mit Android 6.0 Marshmallow hat Google ein neues Berechtigungsmodell eingeführt, mit dem Benutzer besser verstehen können, warum eine Anwendung bestimmte Berechtigungen anfordert. Anstatt dass der Benutzer während der Installation blind alle Berechtigungen akzeptiert, wird der Benutzer nun aufgefordert, Berechtigungen zu akzeptieren, wenn sie während der Anwendungsnutzung erforderlich werden.