Android问题解决--“StorageManager.getVolumeList NullPointerException”空指针再现,getExternalDirs
問題:
在獲取外部存儲目錄時,在某些低版本Android手機上發生StorageManager.getVolumeList 空指針錯誤,具體如下:
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.os.storage.StorageVolume[] android.os.storage.IStorageManager.getVolumeList(int, java.lang.String, int)' on a null object referenceat android.os.storage.StorageManager.getVolumeList(StorageManager.java:1267)at android.os.Environment$UserEnvironment.getExternalDirs(Environment.java:109)at android.os.Environment.getExternalStorageState(Environment.java:1026)?
分析:
getExternalDirs作用是獲取sdcard的目錄,在Android低版本(4.4以前),sdcard目錄是指設備插入的真正的可插拔存儲卡的目錄;
在高版本(Android4.4以后),由于手機的存儲空器越來越大,即使沒有插入外部存儲卡,系統也會默認創建sdcard,如果有卡插入,getExternalDirs就會返回多個File數組。
所以,上面的問題,應該發生在比較舊的設備上。
getExternalDirs 和getExternalDirs源碼如下:
Environment.java:/*** Returns the current state of the primary shared/external storage media.** @see #getExternalStorageDirectory()* @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED},* {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING},* {@link #MEDIA_NOFS}, {@link #MEDIA_MOUNTED},* {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED},* {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.*/public static String getExternalStorageState() {final File externalDir = sCurrentUser.getExternalDirs()[0];return getExternalStorageState(externalDir);}/** {@hide} */public static class UserEnvironment {private final int mUserId;@UnsupportedAppUsagepublic UserEnvironment(int userId) {mUserId = userId;}@UnsupportedAppUsagepublic File[] getExternalDirs() {final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId,StorageManager.FLAG_FOR_WRITE);final File[] files = new File[volumes.length];for (int i = 0; i < volumes.length; i++) {files[i] = volumes[i].getPathFile();}return files;}@UnsupportedAppUsage@Deprecatedpublic File getExternalStorageDirectory() {return getExternalDirs()[0];}@UnsupportedAppUsage@Deprecatedpublic File getExternalStoragePublicDirectory(String type) {return buildExternalStoragePublicDirs(type)[0];}。。。}可見,getExternalDirs被注解為@UnsupportedAppUsage, 表示該api已經不被支持App使用了。
getExternalDirs調用了StorageManager.getVolumeList, 而正是在這里發生了NullPointerException。
StorageManager.getVolumeList代碼定義在StorageManager.java:
/** {@hide} */@UnsupportedAppUsagepublic static @NonNull StorageVolume[] getVolumeList(int userId, int flags) {final IStorageManager storageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));try {String packageName = ActivityThread.currentOpPackageName();if (packageName == null) {// Package name can be null if the activity thread is running but the app// hasn't bound yet. In this case we fall back to the first package in the// current UID. This works for runtime permissions as permission state is// per UID and permission realted app ops are updated for all UID packages.String[] packageNames = ActivityThread.getPackageManager().getPackagesForUid(android.os.Process.myUid());if (packageNames == null || packageNames.length <= 0) {return new StorageVolume[0];}packageName = packageNames[0];}final int uid = ActivityThread.getPackageManager().getPackageUid(packageName,PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);if (uid <= 0) {return new StorageVolume[0];}return storageManager.getVolumeList(uid, packageName, flags); //1267行} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}再對比錯誤信息和代碼行數:
錯誤信息:
“at android.os.storage.StorageManager.getVolumeList(StorageManager.java:1267)”
代碼行數截圖:
?
問題解決:
1. 在api調用的時候,進行try catch異常的捕獲,以及null的判空;
2. 進行sdk level的判斷,在低版本和高版本進行區別對待。
?
?
?
總結
以上是生活随笔為你收集整理的Android问题解决--“StorageManager.getVolumeList NullPointerException”空指针再现,getExternalDirs的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL memo优化_mysql m
- 下一篇: 一种基于主板BIOS的身份认证方案及实现