8

Sto scrivendo un'app per Android che memorizza molti file multimediali. Non sono il tipo (e sono troppi) per ingombrare la notifica degli utenti o altre directory multimediali, ma devono anche essere aggiornabili dall'utente, quindi non posso metterli nelle risorse. Posso usare getExternalFilesDir per ottenere un percorso sulla sdcard, ma voglio farlo solo se l'app stessa è installata sulla sdcard. Se l'app è installata internamente, voglio mettere il media nella memoria interna.Android 2.2 - Come posso rilevare se sono installato su SDCard o no?

Quindi, come posso determinare se la mia app è in esecuzione nella memoria interna o esterna?

risposta

9

È possibile utilizzare PackageManager per ottenere ApplicationInfo e da lì controllare "flags" per FLAG_EXTERNAL_STORAGE.

Ecco un rapido esempio che ho fatto per dimostrare:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    PackageManager pm = getPackageManager(); 
    try { 
     PackageInfo pi = pm.getPackageInfo("com.totsp.helloworld", 0); 
     ApplicationInfo ai = pi.applicationInfo; 
     // this only works on API level 8 and higher (check that first) 
     Toast 
       .makeText(
         this, 
         "Value of FLAG_EXTERNAL_STORAGE:" 
            + ((ai.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == ApplicationInfo.FLAG_EXTERNAL_STORAGE), 
         Toast.LENGTH_LONG).show(); 
    } catch (NameNotFoundException e) { 
     // do something 
    } 
} 

Eppure, a seconda della situazione (anche se non si dispone di tutti i "media" in anticipo, o l'utente ottiene/crea come usano l'app), si consiglia di metterlo nella memoria esterna indipendentemente. Un'applicazione interna di grandi dimensioni è disapprovata da molti utenti (e molti media interni probabilmente lo renderebbero enorme).

3

Ecco il mio codice per verificare se l'applicazione è installata su scheda SD:

/** 
    * Checks if the application is installed on the SD card. 
    * 
    * @return <code>true</code> if the application is installed on the sd card 
    */ 
    public static boolean isInstalledOnSdCard() { 

    Context context = MbridgeApp.getContext(); 
    // check for API level 8 and higher 
    if (VERSION.SDK_INT > android.os.Build.VERSION_CODES.ECLAIR_MR1) { 
     PackageManager pm = context.getPackageManager(); 
     try { 
     PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0); 
     ApplicationInfo ai = pi.applicationInfo; 
     return (ai.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == ApplicationInfo.FLAG_EXTERNAL_STORAGE; 
     } catch (NameNotFoundException e) { 
     // ignore 
     } 
    } 

    // check for API level 7 - check files dir 
    try { 
     String filesDir = context.getFilesDir().getAbsolutePath(); 
     if (filesDir.startsWith("/data/")) { 
     return false; 
     } else if (filesDir.contains("/mnt/") || filesDir.contains("/sdcard/")) { 
     return true; 
     } 
    } catch (Throwable e) { 
     // ignore 
    } 

    return false; 
    } 
+0

1. Controllo '/mnt' e '/ sdcard' sembrano hacky - perché non usi le directory dalla classe' Environment'? 2. Non l'ho ancora provato, la directory dei file non si trova sempre nella memoria interna? Qual è il punto del secondo controllo? Pre-Froyo non può comunque installare su scheda SD. O l'hai aggiunto per gestire il caso di ROM come CyanogenMod che avevano la loro implementazione app2sd? – EboMike

+0

1. Hai ragione, usare Environment.EXTERNAL_STORAGE_DIRECTORY è meglio. 2. Penso di no se l'app è installata su SD. E sì, il secondo controllo riguarda le ROM modificate. – peceps

0

Per controllare applicazione è installata nella scheda SD o no, basta fare questo:

ApplicationInfo io = context.getApplicationInfo(); 

if(io.sourceDir.startsWith("/data/")) { 

//application is installed in internal memory 

} else if(io.sourceDir.startsWith("/mnt/") || io.sourceDir.startsWith("/sdcard/")) { 

//application is installed in sdcard(external memory) 

} 
+0

Può essere installato come app di sistema. È necessario controllare '.startsWith ("/system/")' in questo caso. – Enyby