强制拔SDCard,App为啥会概率性crash?

异常状态:

录video时强制拔出SDCard,video出现两种状态:1.Force Close  2.未保存返回到Preview界面

===Force close===
10-16 15:32:32.794 I/CAM_VideoModule(22145): MMMstopabove
10-16 15:32:33.482 V/CAM_VideoModule(22145): stopVideoRecording: Setting current video filename: /storage/sdcard1/DCIM/Camera/VID_20151016_153226.mp4.tmp
10-16 15:32:33.482 I/CAM_VideoModule(22145): SavingThread finally
10-16 15:32:33.482 I/CAM_VideoModule(22145): lina mVideoFileDescriptor == null

===Return to Preview===
10-16 15:29:49.304 I/CAM_VideoModule(21338): MMMstopabove
10-16 15:29:49.906 V/CAM_VideoModule(21338): stopVideoRecording: Setting current video filename: /storage/sdcard1/DCIM/Camera/VID_20151016_152934.mp4.tmp
10-16 15:29:49.906 I/CAM_VideoModule(21338): SavingThread finally
10-16 15:29:49.907 I/CAM_VideoModule(21338): lina mVideoFileDescriptor == null
10-16 15:29:50.145 D/CAM_VideoModule(21338): saveVideo duration :14869
10-16 15:29:50.146 V/CAM_VideoModule(21338): Releasing media recorder.
10-16 15:29:50.173 W/CAM_VideoModule(21338): onPauseBeforeSuper
10-16 15:29:50.173 W/CAM_VideoModule(21338): closeCamera
10-16 15:29:50.238 W/CAM_VideoModule(21338): closeCamera() normal video,should change to photo!
10-16 15:29:50.238 V/CAM_VideoModule(21338): Releasing media recorder.


对照Log查看VideoModule.java代码,发现如下调用顺序
stopVideoRecording()->saveOnStopVideoRecording()->videoHasStoped(fail)->saveVideo()

FC就发生在saveVideo()函数中。

于是查看saveVideo()

private void saveVideo() {
        if (mVideoFileDescriptor == null) {
            long duration = SystemClock.uptimeMillis() - mRecordingStartTime;

            // [BUGFIX]-Add by TCTNB,haibo.chen, 2014-10-24,PR812550 Begin
            // Duration will be obtained first from decoder information to
            // avoid any errors about calculation.
            MediaPlayer mediaPlayer = new MediaPlayer();
            try {
                mediaPlayer.setDataSource(mCurrentVideoFilename);
                mediaPlayer.prepare();
                duration = mediaPlayer.getDuration();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                mediaPlayer.release();
                mediaPlayer = null;
            }
            Log.d(TAG, "saveVideo duration :" + duration);
            // [BUGFIX]-Add by TCTNB,haibo.chen, 2014-10-24,PR812550 End
            ……
}

发生FC的情况就没有走到红色Log处。就Crash退出啦。
10-16 16:45:12.862 W/ActivityManager(  834): Killing processes unmount media at adjustment 0
10-16 16:45:12.862 I/ActivityManager(  834): Killing 29369:android.process.media/u0a8 (adj 0): unmount media
10-16 16:45:12.899 W/ActivityManager(  834): Scheduling restart of crashed service com.android.providers.media/.MediaScannerService in 24702ms
10-16 16:45:12.899 I/ActivityManager(  834): Killing 29749:com.tct.camera/u0a154 (adj 0): depends on provider com.android.providers.media/.MediaProvider in dying proc android.process.media

MediaScannerService:  安卓系统会在后台扫描内存和外存设备,将多媒体数据更新到数据库中。同时也会扫描文件的信息。
MediaProvider: 在项目中你就可以通过ContentProvider查询数据库,获取存取卡里的多媒体信息。

每次开机的时候系统会先扫描sdcard,sdcard重新插拔(挂载)也会扫描一次sdcard。为什么要扫描sdcard,其实是为了给系统的其他应用提供便利,比如,Gallary、Music、VideoPlayer等应用,进入Gallary后会显示sdcard中的所有图片,如果进入Gallary后再去扫描,可想而知,你会厌恶这个应用,因为我们会觉得它反应太慢了。还有Music你看到播放列表的时候实际能看到这首歌曲的时长、演唱者、专辑等信息,这个也不是你进入应用后一下子可以读出来的。所以Android使用sdcard挂载后扫描的机制,先将这些媒体相关的信息扫描出来保存在数据库中,当打开应用的时候直接去数据库读取(或者所通过MediaProvider去从数据库读取)并show给用户,这样用户体验会好很多。

为什么有时候会crash,有时候不会呢?

刚刚插入SDCard的几秒钟内,系统还在扫描sdcard呢!你突然拔出,后面调用MediaProvider时,自然会crash啊。
人家食物都没有准备好,你就要吃啦。没食物可吃,所以就死啦。
据此分析,如果延迟几秒钟拔出SDCard,待扫描完成,再强制拔出,则Camera不会crash。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章