2011-01-20 9 views
11

La mia app consente a un utente di salvare un'immagine sulla propria scheda SD. Ma non sono sicuro di come farlo apparire nella galleria finché non smonti e rimonta la scheda SD. Ho cercato su Google un paio di giorni con questo problema, ma non sono sicuro di come farlo apparire automaticamente. Ho trovato il collegamento this ma non sono sicuro di come utilizzare la classe. Questo è quello che uso per salvare il file. Nella parte inferiore del blocco catch try è dove voglio scansionare la scheda SD per i nuovi media.Scansione scheda SD Android per nuovi file

FileOutputStream outStream = null; 
    File file = new File(dirPath, fileName); 
    try { 
     outStream = new FileOutputStream(file); 
     bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream); 
     outStream.flush(); 
     outStream.close(); 
    } catch { 
     ... 
    } 

Se qualcuno potesse indicarmi la giusta direzione, apprezzerei.

+0

L'app "sdrescan" fa quello che vuoi. È gratis; forse potresti chiedere all'autore un frammento di codice. O semplicemente lanciarlo dalla tua app. –

+0

Esiste un modo per eseguire nuovamente la scansione senza interrompere il lettore musicale? Dice Spiacente, il lettore multimediale non supporta questo file, fino a quando non premo una traccia, inoltro una traccia, quindi riproduce nuovamente. – NoBugs

risposta

5

Dall'ultima risposta che ho inviato a quanto pare non era un metodo appropriato, Ho trovato un altro metodo here. Fondamentalmente si crea una classe wrapper, la si inizializza e quindi si chiama il metodo scan(). Post molto utile Fammi sapere se anche questo non è appropriato.

+0

Nota: utilizza lo scanfile() che è disponibile dall'inizio API Level 1. Non il più recente scanFile() reso disponibile dopo l'API Livello 8. – Brian

0

È possibile utilizzare MediaStore.Images.Media.insertImage per inserire un elemento nella galleria.

+0

Grazie per l'aiuto. Ma non riuscivo a far funzionare "insertImage". Ho trovato la risposta su un altro forum però. – Brian

4

Uso MediaScannerConnection:

http://developer.android.com/reference/android/media/MediaScannerConnection.html

può essere un po 'di un dolore a causa dei molteplici livelli di chiamate asincrone, così come di API 8 (Froyo) è una funzione di supporto:

http://developer.android.com/reference/android/media/MediaScannerConnection.html#scanFile(android.content.Context, java.lang.String [], java.lang.String [], android.media.MediaScannerConnection.OnScanCompletedListener)

+0

Ho letto più volte il riferimento e non riesco a capire come far funzionare mediaScannerConnection. Per quanto riguarda la funzione di supporto, non penso che sarebbe ancora l'approccio migliore. L'API 8 non è molto vecchia e non sarebbe supportata su molti dispositivi (incluso il mio telefono di prova). Ho giocato per un paio di giorni con il link nel mio post iniziale e non ho potuto ottenere quell'esempio per funzionare. Se potessi pubblicare alcuni frammenti o indicarmi un altro esempio, lo apprezzerei. Fino ad allora dovrò lasciare il metodo "sendBroadcast" poiché è l'unico modo in cui funziona ora. – Brian

+0

C'è una demo API per la nuova funzione qui: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.html Puoi trovare l'implementazione del codice che funzione da modellare per la tua implementazione qui: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=media/java/android/media/MediaScannerConnection.java – hackbod

+1

Per ripetere: NON INVIARE ACTION_MEDIA_MOUNTED. Questo farà TUTTI i TIPI di cose, inclusa una scansione completa della scheda SD. In effetti, ho bisogno di assicurarmi che nelle future versioni della piattaforma le app non possano inviarlo, perché è probabile che causino un comportamento anomalo di parti della piattaforma se vengono rilevate nel momento sbagliato. Quindi aspettati in futuro se stai facendo questo per la tua app per rompere. – hackbod

2

È anche possibile chiamare in modo esplicito lo scanner del supporto inviando una trasmissione.

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri 
        .parse("file://" 
          + Environment.getExternalStorageDirectory()))); 
0

Here è un altro modo per forzare la scansione:

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,"uri to file")); 

E allora il sistema si attiva trasmissione ACTION_MEDIA_SCANNER_FINISHED in modo da poter reagire su di esso con BroadcastReceiver

Al fine di essere in grado di ricevere trasmissioni ACTION_MEDIA_SCANNER_FINISHED , il filtro intent dovrebbe contenere schema dati:

IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_FINISHED); 
intentFilter.addDataScheme("file"); 
context.registerReceiver(mMediaScannerFinishReceiver, intentFilter); 

dal doc:

pubblico static final String ACTION_MEDIA_SCANNER_SCAN_FILE

Aggiunto a livello di API 1 Azione Broadcast: Richiedere lo scanner media per la scansione di un file e inserirlo nel database multimediale. Il percorso del file è contenuto nel campo Intent.mData.

e

pubblico static final String ACTION_MEDIA_SCANNER_FINISHED

Aggiunto a livello di API 1 Azione Broadcast: Lo scanner dei media ha terminato la scansione di una directory. Il percorso della directory scansionata è contenuto nel campo Intent.mData.

9

Ho provato molti metodi diversi per attivare MediaScanner e questi sono i miei risultati.

SendBroadcast

La soluzione più semplice e ingenuo. Consiste nell'eseguire le seguenti istruzioni dal codice:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
       Uri.parse("file://"+ Environment.getExternalStorageDirectory()))); 

Tuttavia, questo non funziona più in dispositivi KitKat, a causa della mancanza di autorizzazioni necessarie.


MediaScannerWrapper

Come postato here (per @ risposta di Brian), consiste nello spostamento di un'istanza MediaScannerConnection al fine di innescare il metodo scan() su una directory specifica. Questo metodo ha dimostrato di funzionare correttamente per 4.3 e sotto, ma ancora senza fortuna con KitKat (4.4+).


Filewalker

Una delle molte applicazioni Play Store che cerca di superare la mancanza di impegno del MediaStore di aggiornare il suo database è ReScan SD. Si invia un sacco di diverse trasmissioni:

sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 
    sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable"))); 
    sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable/SD"))); 
    sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable/MicroSD"))); 
    sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///mnt/Removable/MicroSD"))); 
    sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///mnt"))); 
    sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///storage"))); 
    sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable"))); 

e cerca di sostenere KitKat innescando manualmente il metodo scan() su ogni file della directory di base. Sfortunatamente, è molto dispendioso in termini di CPU e richiede molto tempo, quindi non è molto raccomandato.


"Il modo in guscio"

L'unica cosa che sembra funzionare con KitKat in alcuni casi sta inviando la trasmissione via adb shell. Quindi, questo frammento di codice consente di fare proprio questo a livello di codice:

Runtime.getRuntime().exec("am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://" + Environment.getExternalStorageDirectory()); 

È più di un modo hack-ish di farlo, ma al momento è il meglio che ho potuto trovare.


Linea di fondo

Ognuna delle soluzioni di cui sopra in realtà lavora per tutto ciò che non è KitKat. Questo perché, grazie a Justin, un bug è stato trovato ed è stato rilasciato allo official Tracker. Questo significa che, fino a quando il bug non sarà risolto, non ci sarà alcun vero supporto per KitKat.

Quale usare? Tra questi, vorrei utilizzare la soluzione MediaScannerWrapper, insieme all'approccio shell-ish (l'ultimo).

+0

Il metodo shell su KITKAT che hai menzionato funziona in alcuni casi. Sono ansioso di sapere con quale caso questo metodo fallisce? o sotto il quale funziona? – Ahmed

+0

Non sono riuscito a trovare alcun caso d'uso fisso. L'unica cosa che sembra funzionare è l'aggiornamento del MediaScanner dopo che un file è stato aggiunto. D'altra parte, non funziona quando un file viene rimosso. – Sebastiano

+2

Ha funzionato quando ho inviato broadcast dalla riga di comando utilizzando la shell adb per i nuovi file e quelli cancellati. Ma non funziona in modo programmatico su KitKat né per i nuovi file né per quello rimosso. Stavo testando con file di musica audio e usando l'emulatore API 19. – Ahmed