предотвращение сбоя при подключении SD-карты Android - PullRequest
4 голосов
/ 17 февраля 2011

У меня есть файл, открытый на SD-карте.Когда кто-то монтирует SD-карту, происходит сбой моего приложения.Я пытаюсь зарегистрироваться для трансляции события ACTION_MEDIA_EJECT, и я получаю это, но мне кажется, что я получаю это слишком поздно.К тому времени, когда я получаю это, это уже сломало мое приложение.Есть ли какой-нибудь способ получить уведомление до сбоя моего приложения?

Добавлен очень простой пример кода.Когда я это делаю, происходит сбой службы при включении USB (режим MSC).

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;
    }
}

Ответы [ 2 ]

7 голосов
/ 27 января 2012

Это убивает ваше приложение, потому что это задокументированное дизайнерское решение для Android, чтобы убить любой процесс, держащий открытый дескриптор на SD-карте, когда SD-карту необходимо отключить от устройства (например, подключить USB к подключенному ПК) ,

Файловая система, в которой все еще имеются открытые файловые дескрипторы, не может быть чисто размонтирована. На уровне операционной системы нет способа отозвать дескриптор файла, если не считать уничтожение процесса, которому он был предоставлен, и именно это в конечном итоге делает android.

2 голосов
/ 17 февраля 2011
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
    //access external file
}

Не зная больше о том, какие исключения выдают, это все, что я могу порекомендовать.

Также может помочь следующий код из документации класса Environment:

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);
}
...