Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

preventing a crash when someone mounts an Android SD card

I have a file open on the SD card. When someone mounts the SD card, it winds up crashing my application. I am trying to register for the ACTION_MEDIA_EJECT broadcast event, and i receive that, but it seems like i'm getting that too late. By the time I get that, it's already crashed my application. Is there any way to get notified before crashing my application?

Added some very simple sample code. When I do this, it winds up crashing the service when I turn on USB (MSC mode).

Test.java

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    try {
        startService(new Intent(this, TestService.class));
        bindService(new Intent(this, TestService.class), serviceConnection, Context.BIND_AUTO_CREATE);
    } catch (Exception e) {

    }
}

protected TestService testService;
private ServiceConnection serviceConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        TestService.LocalBinder binder = (TestService.LocalBinder) service;
        testService = binder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        testService = null;
    }

};

TestService.java

@Override
public void onCreate() {
    super.onCreate();
    try {
        mFileOutputStream = new FileOutputStream("/sdcard/test2", true);
    } catch (Exception e) {
    }
}

@Override
public IBinder onBind(Intent intent) { return binder; }

public static class LocalBinder extends Binder {
    public static TestService getService() {
        return _this;
    }
}
like image 912
user306517 Avatar asked Jan 20 '23 11:01

user306517


2 Answers

It is killing your application because it is a documented design decision in android to kill any process holding an open handle to the sdcard when the sdcard needs to be unmounted from the device (for example to be USB mounted to a connected PC).

A file system which still has open file handles cannot be cleanly unmounted. At the operating system level, there's no way to revoke a file handle, short of killing the process to which it was granted, so that is what android ultimately does.

like image 147
Chris Stratton Avatar answered Feb 07 '23 15:02

Chris Stratton


if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
    //access external file
}

Without knowing more about what exceptions are being thrown, this is about all I can recommend.

Also, the following code from the Environment class documentation may help:

BroadcastReceiver mExternalStorageReceiver;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;

void updateExternalStorageState() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        mExternalStorageAvailable = mExternalStorageWriteable = true;
    } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        mExternalStorageAvailable = true;
        mExternalStorageWriteable = false;
    } else {
        mExternalStorageAvailable = mExternalStorageWriteable = false;
    }
    handleExternalStorageState(mExternalStorageAvailable,
            mExternalStorageWriteable);
}

void startWatchingExternalStorage() {
    mExternalStorageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("test", "Storage: " + intent.getData());
            updateExternalStorageState();
        }
    };
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
    filter.addAction(Intent.ACTION_MEDIA_REMOVED);
    registerReceiver(mExternalStorageReceiver, filter);
    updateExternalStorageState();
}

void stopWatchingExternalStorage() {
    unregisterReceiver(mExternalStorageReceiver);
}
like image 24
Jon Willis Avatar answered Feb 07 '23 13:02

Jon Willis