2015-10-06 21 views
29

sto condividendo un'immagine, e questo codice funziona correttamente per i dispositivi Android prima di 6:Android 6: non è più possibile condividere file?

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)); 

Tuttavia ottengo l'errore brindisi "non può allegare file vuoti" quando provo a condividere con Android 6

Ho verificato che il file esiste e non è a lunghezza zero.

Chiunque ha una soluzione per questo?

+0

Stai ottenendo questo 'Toast' prima o dopo la scelta? Se dopo, quale app hai scelto? Inoltre, dov'è 'mFilename' che punta, esattamente? – CommonsWare

+0

Dopo il selezionatore, succede con ogni app che ho provato. Almeno con Gmail e Hangout. –

+0

mFilename è all'interno di 'getExternalCacheDir()', a partire da '/ storage/emulated/0/Android/data /' –

risposta

22

Una limitazione del sistema di autorizzazione runtime di Android 6.0 è che ci saranno casi d'angolo che causano problemi. Quello che hai incontrato è uno: provare a condividere un file su una memoria esterna con un'app che non ha i permessi di autorizzazione in fase di esecuzione per quel particolare percorso dell'interfaccia utente.

Dico che si tratta di un "caso angolo" perché, poiché questo bug nell'app di ricezione influisce sull'utente, l'utente non può aver precedentemente utilizzato quell'app e ottenuto i permessi necessari. O:

  • L'utente non ha mai utilizzato tale applicazione prima, eppure ancora cercando di condividere i contenuti ad esso, o

  • L'utente revocato il permesso tramite Impostazioni, ma non rendersi conto che si spezzerebbe questo bit di funzionalità

Entrambi sono eventi a bassa probabilità.

È, come mittente, hanno due opzioni principali: lontano da utilizzando file://Uri valori

  1. interruttore, a favore di un file-serving ContentProvider come FileProvider, in modo che il consenso non è più necessario, o

  2. Basta vivere con il caso angolo

+1

Ok, ho implementato FileProvider e funziona perfettamente! –

+8

@DanieleB: FWIW, ho scritto [un post sul blog] (https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html) su questo. – CommonsWare

33

ho risolto da impl ementing un FileProvider, come suggerito da @CommonsWare

Innanzitutto è necessario configurare un FileProvider:

  • prima, aggiungere il <provider> al file XML manifest

    <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> 
    
  • secondo, definire il percorsi di file in un file XML separato, l'ho chiamato "file_provider_paths.xml "

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

trovi la spiegazione completa in questo documentation page

dopo aver impostato il vostro provider di file in formato XML, questo è il codice di condividere il file di immagine:

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)); 
+0

buona soluzione. –

+0

funziona perfettamente su Android 6.0 – Soham

+0

perfetto grazie ... –

0

Un altro modo per risolvere questo problema era ottenere l'URI di stile del provider di contenuti utilizzando MediaScannerConnection subito dopo aver scritto il file nella directory pubblica :

 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 
      } 
     }); 

Questa potrebbe essere una soluzione più breve per le vostre esigenze.

2

In alternativa, non è necessario disporre di ContentProvider/FileProvider. Puoi semplicemente aggiungere la flag che concede l'autorizzazione di lettura sull'uri che è condivisa. In particolare, share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); dovrebbe fare il trucco.

+0

presumendo che l'app sia già stata aperta, ovvero. – yrizk