2015-11-11 22 views
36

Sto provando a far sì che Camera App memorizzi l'output nella memoria interna. Capisco anche che le app di terze parti non sono in grado di accedere alla memoria interna della mia applicazione MA, siamo in grado di farlo esponendo la directory interna tramite FileProvider. Ho seguito la guida qui:FileProvider che non funziona con la fotocamera

ho specificare il mio AndroidManifest.xml nel seguente modo:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.stackoverflow.test.camerawithfileprovider" > 

    <application> 
     <activity 
      ... 
     </activity> 

     <provider 
      android:name="android.support.v4.content.FileProvider" 
      android:authorities="com.stackoverflow.test.camerawithfileprovider.fileprovider" 
      android:exported="false" 
      android:grantUriPermissions="true" > 
      <meta-data 
       android:name="android.support.FILE_PROVIDER_PATHS" 
       android:resource="@xml/file_provider_path" /> 
     </provider> 
    </application> 

</manifest> 

ho creato un file XML denominato file_provider_path.xml in /res/xml/:

<?xml version="1.0" encoding="utf-8"?> 
<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <files-path name="image_capture" path="public/" /> 
</paths> 

Questo è quanto ho creare e chiamare l'intento di fotocamera:

private static final int CAMERA_REQUEST_CODE = 5000; 
private static final String CAMERA_FP_AUTHORITY = "com.stackoverflow.test.camerawithfileprovider.fileprovider"; 

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 

Context context = MainActivity.this; 
File imagePath = new File(context.getFilesDir(), "public"); 
if (!imagePath.exists()) imagePath.mkdirs(); 
File newFile = new File(imagePath, "tmp.jpg"); 

Uri imageUri = FileProvider.getUriForFile(context, CAMERA_FP_AUTHORITY, newFile); 
//context.grantUriPermission("com.google.android.GoogleCamera", imageUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); 
Log.d("YouQi", "Image URI Passing to Camera: " + imageUri.toString()); 

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); 
startActivityForResult(intent, CAMERA_REQUEST_CODE); 

Quando eseguo l'applicazione, posso ottenere il seguito risultato Logcat:

11-11 20:07:39.581 18303-18303/com.stackoverflow.test.camerawithfileprovider D/YouQi: Image URI Passing to Camera: content://com.stackoverflow.test.camerawithfileprovider.fileprovider/image_capture/tmp.jpg 

Proprio nel momento in cui il la fotocamera si chiude, premo il seguente Eccezione:

com.google.android.GoogleCamera E/AndroidRuntime: FATAL EXCEPTION: main 
com.google.android.GoogleCamera E/AndroidRuntime: Process: com.google.android.GoogleCamera, PID: 19420 
com.google.android.GoogleCamera E/AndroidRuntime: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{42e44f70 19420:com.google.android.GoogleCamera/u0a83} (pid=19420, uid=10083) that is not exported from uid 10312 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.os.Parcel.readException(Parcel.java:1465) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.os.Parcel.readException(Parcel.java:1419) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:2882) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.app.ActivityThread.acquireProvider(ActivityThread.java:4544) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2274) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1425) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:906) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.content.ContentResolver.openOutputStream(ContentResolver.java:669) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.content.ContentResolver.openOutputStream(ContentResolver.java:645) 
com.google.android.GoogleCamera E/AndroidRuntime:  at com.android.camera.PhotoModule.onCaptureDone(PhotoModule.java:1281) 
com.google.android.GoogleCamera E/AndroidRuntime:  at com.android.camera.PhotoModule$8.onClick(PhotoModule.java:593) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.view.View.performClick(View.java:4445) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.view.View$PerformClick.run(View.java:18446) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.os.Handler.handleCallback(Handler.java:733) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.os.Handler.dispatchMessage(Handler.java:95) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.os.Looper.loop(Looper.java:136) 
com.google.android.GoogleCamera E/AndroidRuntime:  at android.app.ActivityThread.main(ActivityThread.java:5146) 
com.google.android.GoogleCamera E/AndroidRuntime:  at java.lang.reflect.Method.invokeNative(Native Method) 
com.google.android.GoogleCamera E/AndroidRuntime:  at java.lang.reflect.Method.invoke(Method.java:515) 
com.google.android.GoogleCamera E/AndroidRuntime:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732) 
com.google.android.GoogleCamera E/AndroidRuntime:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566) 
com.google.android.GoogleCamera E/AndroidRuntime:  at dalvik.system.NativeStart.main(Native Method) 

Qualcuno può aiutare a spiegare perché il problema si verifica? Ho creato un progetto di esempio del mio problema: http://www.axzae.com/downloads/CameraWithFileProvider.zip

In ogni caso, l'applicazione funzionerà se esplicitamente specificare:

context.grantUriPermission(
    "com.google.android.GoogleCamera", 
    imageUri, 
    Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION 
); 

Ma questo funziona solo per i dispositivi Nexus/cianogeno. L'app per fotocamere Samsung potrebbe utilizzare un nome di pacchetto diverso.

risposta

91
  1. Si prega di non provare a mettere exported="true" come ha sottolineato pskink, la vostra applicazione si blocca nel momento in cui viene caricato. FileProvider non è pensato per funzionare in questo stato.

  2. Provato intent.addFlags soluzione da CommonsWare. Non funziona. probabilmente funzionerà solo con il tipo di intento ACTION_SEND.

  3. Ho trovato la risposta in this post. Apparentemente la strada della concessione manuale è l'unica soluzione. Ma possiamo sempre passare attraverso l'elenco dei pacchetti candidati e grantPermission a tutti loro.

    List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 
    for (ResolveInfo resolveInfo : resInfoList) { 
        String packageName = resolveInfo.activityInfo.packageName; 
        context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); 
    } 
    
+3

Hack molto soddisfacente :) –

+26

'addFlags()' funziona su Android 5.0+. Sui dispositivi più vecchi, è richiesto il tuo approccio. Vedi https://github.com/commonsguy/cw-omnibus/tree/master/Camera/FileProvider per un esempio. – CommonsWare

+2

Ho un dubbio qui. Mi dispiace per la mia conoscenza molto meno di Android, ma sono confuso. Prima di avviare la fotocamera, imposto la directory come "Environment.getExternalStoragePublicDirectory ( Environment.DIRECTORY_PICTURES"). Devo ancora usare FileProvider O è usato solo per le immagini memorizzate nell'area dell'app privata? – AndroidGuy

0

Ho avuto un problema simile, ma in seguito ho scoprire di avere un errore di battitura nel mio codice. L'errore di battitura era in AndroidManifest.xml, precisamente nel tag sulla riga "autorità".

Per me,

android:authorities="com.stackoverflow.test.camerawithfileprovider.fileprovider" 

non funziona (quando chiamo l'istanza della fotocamera, l'applicazione si blocca), ma se elimino "file" e sostituire la stringa come segue:

android:authorities="com.stackoverflow.test.camerawithfileprovider.provider" 

la mia app funziona senza problemi (l'app prende la foto, la memorizza e restituisce un'anteprima all'attività nell'app client).

La tua app ha anche lo stesso problema?

Problemi correlati