java - FileUriExposedException in Android




android-intent directory (2)

Devo aprire la cartella nella memoria interna che contiene immagini.

Uso il seguente codice.

Giava

 File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),  "MyPhotos");
Intent intent = new Intent(Intent.ACTION_VIEW);
String path =folder.getPath();
Uri myImagesdir = Uri.parse("file://" + path );
intent.setDataAndType(myImagesdir,"*/*");   
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

PERCORSI

 <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <external-path name="images" path="Pictures" />
     <external-path name="external_files" path="."/>
     <external-path name="files_root" path="Android/data/${applicationId}"/> </paths>

Manifesto

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

xml / file_paths

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="images" path="Pictures" />
    <external-path name="external_files" path="."/>
    <external-path name="files_root" path="Android/data/${applicationId}"/>
</paths>

ERRORE

ECCEZIONE FATALE: processo principale: android.apps.bnb.company.myphotos, PID: 22482 android.os.FileUriExposedException: file: /// storage / emulato / 0 / Pictures / MyPhotos esposti oltre l'app tramite Intent.getData ()

C'è un altro modo per aprire la cartella nella memoria interna? Grazie!

AGGIORNAMENTO N. 1

Usando questo articolo https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en ho sostituito

Uri myImagesdir = Uri.parse("file://" + path );

con

 Uri myImagesdir = Uri.parse("content://" + path );

E l'errore è andato.

Comunque devo scegliere sempre l'app per aprire questa cartella.

È possibile utilizzare l'app My Files per impostazione predefinita per aprire determinate cartelle?


È possibile utilizzare l'app My Files per impostazione predefinita per aprire determinate cartelle?

Sì e No. Non è garantito al 100% che funzioni su tutti i dispositivi.

Modifica 1:

Di seguito è uno dei modi con cui può essere fatto. Ho testato su alcuni emulatori (con Android N e Android O) e carica il file explorer predefinito:

MainActivity.java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri dirUri = FileProvider.getUriForFile(this,getApplicationContext().getPackageName() + ".com.example.myapplication",Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        //intent.setDataAndtType(); I will change this value in the alternatives below
    }

AndroidManifest.xml

<provider
        android:name=".GenericFileProvider"
        android:authorities="${applicationId}.com.example.myapplication"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
</provider>

GenericFileProvider.java

public class GenericFileProvider extends FileProvider {
}

file_paths.xml

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

L'approccio di cui sopra non funziona su grandi giocatori come Samsung

alternative

1. Utilizzando il tipo DocumentsContract.Document.MIME_TYPE_DIR

intent.setDataAndType(dirUri,DocumentsContract.Document.MIME_TYPE_DIR);

Questo approccio funziona su diversi emulatori e un numero limitato di dispositivi. Non funziona con grandi giocatori come Samsung o Huawei.

2. Utilizzo di tipo resource/folder

intent.setDataAndType(dirUri,"resource/folder");

Questo approccio funziona solo se l'utente ha installato l'app di esplorazione file ES.

Se si sceglie di utilizzare, è necessario verificare se sono disponibili intenti per gestirlo utilizzando:

PackageManager packageManager = getActivity (). GetPackageManager ();

if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
   // either display error or take necessary action
}

3. Utilizzando il tipo */*

intent.setDataAndType(dirUri,"*/*");

Questo approccio funziona se l'utente sceglie l'app File Manager da Intent Chooser e la contrassegna come app predefinita per gestire */* . Tuttavia ha alcuni inconvenienti (grazie a @CommonsWare per averne fatto emergere alcuni):

  • Questo tipo caricherà tutte le app sul dispositivo e consentirà all'utente di sceglierne una per completare l'azione.
  • Se non c'è esploratore di file e l'utente sceglie altre app per caricare le tue intenzioni, l'altra app andrà in crash o mostrerà semplicemente una schermata nera. Ad esempio, usi Galleria o qualche altra app per avviarla invece di Esplora file, quindi l'app Galleria si bloccherà o mostrerà una schermata nera.
  • Anche se esiste Esplora file ma l'utente decide di utilizzare altre app, le altre app potrebbero bloccarsi

4. Usando digitare text/csv

intent.setDataAndType(uri, "text/csv")

Ciò limiterà il numero di app che verranno visualizzate all'utente ma le stesse limitazioni quando viene applicato */* . Verranno visualizzate le app in grado di gestire csv e se l'utente lo sceglie, le app andrebbero in crash.

Ci sono alcune implementazioni specifiche del dispositivo disponibili here come menzionato da @Academy of Programmer che richiede di identificare l'intento del gestore file predefinito e le necessità extra da esso.

Conclusione:

Non esiste un tipo standard disponibile per ottenerlo poiché al momento non esiste uno standard seguito dai File Manager per supportare il tipo specifico. In futuro Google potrebbe trovare un approccio. La migliore alternativa sarebbe quella di implementare il tuo file manager proprio come Dropbox o Google Drive. Sono disponibili diverse librerie che forniscono questa funzione.


Ho trovato la soluzione qui, here here

Questo codice funziona perfettamente nel mio Samsung J7 per aprire la cartella Immagini (e altre) dalla memoria interna utilizzando l'applicazione predefinita Samsung I miei file .

File path = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES);
Uri uri = Uri.fromFile(path);
Intent intent = getPackageManager().getLaunchIntentForPackage("com.sec.android.app.myfiles");
intent.setAction("samsung.myfiles.intent.action.LAUNCH_MY_FILES");
                    intent.putExtra("samsung.myfiles.intent.extra.START_PATH", path.getAbsolutePath());
startActivity(intent);

Sembra che dobbiamo decompilare File Manager di ciascun produttore per vedere come chiamarlo correttamente. :( Ed è troppo lavoro. Beh ... ho pensato che ci fosse una soluzione generica per farlo.





directory