功能:讀取外置存儲的資訊。
現象:在反彈插拔TF卡之後,會彈出強制關閉
機率:反複插拔TF卡會出現,在一定時間内多次插拔,可以達到必現
Logcat:
E/AndroidRuntime( 2920): FATAL EXCEPTION: main
E/AndroidRuntime( 2920): Process: com.borqs.factorytest, PID: 2920
E/AndroidRuntime( 2920): java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.MEDIA_MOUNTED dat=file:///mnt/external_sd flg=0x4000010 (has extras) } in [email protected]
E/AndroidRuntime( 2920): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:876)
E/AndroidRuntime( 2920): at android.os.Handler.handleCallback(Handler.java:739)
E/AndroidRuntime( 2920): at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime( 2920): at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime( 2920): at android.app.ActivityThread.main(ActivityThread.java:5280)
E/AndroidRuntime( 2920): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 2920): at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime( 2920): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:963)
E/AndroidRuntime( 2920): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:758)
E/AndroidRuntime( 2920): Caused by: java.lang.IllegalArgumentException: Invalid path: /mnt/external_sd
E/AndroidRuntime( 2920): at android.os.StatFs.doStat(StatFs.java:46)
E/AndroidRuntime( 2920): at android.os.StatFs.<init>(StatFs.java:39)
E/AndroidRuntime( 2920): at com.borqs.factorytest.activity.ComprehensiveTest.measureApproximateStorage(ComprehensiveTest.java:1001)
E/AndroidRuntime( 2920): at com.borqs.factorytest.activity.ComprehensiveTest.measureApproximateStorageAndRamAndRomAndCPU(ComprehensiveTest.java:945)
E/AndroidRuntime( 2920): at com.borqs.factorytest.activity.ComprehensiveTest.access$700(ComprehensiveTest.java:54)
E/AndroidRuntime( 2920): at com.borqs.factorytest.activity.ComprehensiveTest$7.onReceive(ComprehensiveTest.java:771)
E/AndroidRuntime( 2920): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:866)
E/AndroidRuntime( 2920): ... 8 more
E/AndroidRuntime( 2920): Caused by: android.system.ErrnoException: statvfs failed: EIO (I/O error)
E/AndroidRuntime( 2920): at libcore.io.Posix.statvfs(Native Method)
E/AndroidRuntime( 2920): at libcore.io.BlockGuardOs.statvfs(BlockGuardOs.java:298)
E/AndroidRuntime( 2920): at android.system.Os.statvfs(Os.java:459)
E/AndroidRuntime( 2920): at android.os.StatFs.doStat(StatFs.java:44)
E/AndroidRuntime( 2920): ... 14 more
源碼:
// sd card ext
if(Environment.getExternalStorageDirectory().getPath().equals("/storage/emulated/0")) {
if((new File("/mnt/sdcard_ext")).exists()) {
stat = new StatFs("/mnt/sdcard_ext");
} else if(!mSdPath.equals("")) {
if((new File(mSdPath)).exists()) {
stat = new StatFs(mSdPath);//-------------出錯行
}
} else {
callShellCommand_Sdcard("mount");
mSdPath = "/storage/" + mSdPath.substring(mSdPath.lastIndexOf("/") + 1);
if((new File(mSdPath)).exists()) {
stat = new StatFs(mSdPath);
}
}
解決方案:
在AndroidManifest.xml添加permission
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
解決原理:
1. 看log
抛出了java.lang.IllegalArgumentException: Invalid path: /mnt/external_sd
傳入的參數不合法,具體是非法路徑。問題出在這個位址上.
E/AndroidRuntime( 2920): at android.os.StatFs.doStat(StatFs.java:46)
E/AndroidRuntime( 2920): at android.os.StatFs.<init>(StatFs.java:39)
執行初始化的的時候挂的
2.看源碼錯誤位置
new StatFs(mSdPath);
3.得出可能結論
或許是因為檔案讀寫出問題
4. 看docs
READ_EXTERNAL_STORAGE
added in API level 16
String READ_EXTERNAL_STORAGE
Allows an application to read from external storage.
Any app that declares the
WRITE_EXTERNAL_STORAGE
permission is implicitly granted this permission.
This permission is enforced starting in API level 19. Before API level 19, this permission is not enforced and all apps still have access to read from external storage. You can test your app with the permission enforced by enabling Protect USB storage under Developer options in the Settings app on a device running Android 4.1 or higher.
Also starting in API level 19, this permission is not required to read/write files in your application-specific directories returned by
getExternalFilesDir(String)
and
getExternalCacheDir()
.
Note: If both your
minSdkVersion
and
targetSdkVersion
values are set to 3 or lower, the system implicitly grants your app this permission. If you don't need this permission, be sure your
targetSdkVersion
is 4 or higher.
Protection level: dangerous
Constant Value: "android.permission.READ_EXTERNAL_STORAGE"
對檔案進行讀寫的話,都需要這個權限,那麼擷取這個資訊,說不定也需要這個權限。