5

I'm currently developing a live wallpaper that reads from external storage. When the device is booting up, I assume it's possible for the live wallpaper to be launched before the storage is ready. Especially if its doing the periodic error check. Others are reporting issues and I think this is the reason. I can't seem to test this, because the external storage seems to mount instantly on my device, and I'm not sure how to force it to do the error check. So my first question is, does the system actually way for the BOOT_COMPLETED intent before it launches the live wallpaper.

If not, what is the proper way to wait for the external storage to be ready. I'm thinking of calling something like this in the beginning of the app

public void waitForExternalStorage()
{
    while(Environment.getExternalStorageState().equals(Environment.MEDIA_CHECKING))
    {
        try { Thread.sleep(1000L); }
        catch(InterruptedException e) { e.printStackTrace(); }
    }
}

Do I have to check for other cases, in case it goes MEDIA_REMOVED -> MEDIA_UNMOUNTED -> MEDIA_CHECKING(optional) -> MEDIA_READY on boot?

terryhau
  • 539
  • 2
  • 7
  • 17

3 Answers3

8

You can register a BroadcastReceiver to listen to changes in the external storage state:

BroadcastReceiver externalStorageStateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        updateExternalStorageState();
    }
};

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
registerReceiver(mExternalStorageReceiver, filter);
updateExternalStorageState(); // You can initialize the state here, before any change happens

And in updateExternalStorageState() you can check the actual state after the change:

protected void updateExternalStorageState() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        // SD card is mounted and ready for use
    } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        // SD card is mounted, but it is read only
    } else {
        // SD card is unavailable
    }
}
Adam Monos
  • 4,247
  • 1
  • 20
  • 25
  • I'm not sure how to use this. The wallpaper needs to read the external storage when it loads. I can't wait for the intent to launch the wallpaper because the system launches it automatically. Do I have to pause wallpaper loading and wait for the intent to resume. And also if there is no external storage, then the intent won't trigger. Basically, the functionality i need is: if(noExternalStorage) continue loading, if(externalStorageNotReady) wait, if(externalStorageReady) continue loading. – terryhau Oct 05 '12 at 15:24
  • Just the info I need, thanks - but just FYI there's a slight typo in a couple of copies of the class name (should be `BroadcastReceiver` rather than `BroadcastReciever`). SO won't let me edit – just me Jan 06 '14 at 09:19
3

use broadcast receiver, listen for Intent.ACTION_MEDIA_MOUNTED : Broadcast Action: External media is present and mounted at its mount point.

Buda Gavril
  • 19,769
  • 35
  • 114
  • 174
1

I needed exactly that. I am reading a configuration file from the SD card and my on-boot running app simply cannot run without reading it. A simple solution is to wait a maximum of 15-30 seconds for the SD card to be automatically mounted by the Android OS. If not, throw an exception. Here's the code. Just increase the max count limit to increase the wait time. The ExternalStorageNotReadyException is a custom exception.

public void awaitExternalStorageInitialization()
        throws ExternalStorageNotReadyException {
    boolean mExternalStorageAvailable = false;
    boolean mExternalStorageWriteable = false;
    int count = 0;

    do {
        String state = Environment.getExternalStorageState();
        if(count > 0) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(Constants.LOG_TAG, e.getMessage(), e);
            }
        }
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // We can read and write the media
            mExternalStorageAvailable = mExternalStorageWriteable = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // We can only read the media
            mExternalStorageAvailable = true;
            mExternalStorageWriteable = false;
        } else {
            // Something else is wrong. It may be one of many other states,
            // but all we need
            // to know is we can neither read nor write
            mExternalStorageAvailable = mExternalStorageWriteable = false;
        }
        count++;
    } while ((!mExternalStorageAvailable) && (!mExternalStorageWriteable) && (count < 5));
    if(!mExternalStorageWriteable)
        throw new ExternalStorageNotReadyException("External storage device (SD Card) not yet ready");
}
Srikanth
  • 1,595
  • 14
  • 17