大家好,欢迎来到IT知识分享网。
问题:
在获取外部存储目录时,在某些低版本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 reference
at 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;
@UnsupportedAppUsage
public UserEnvironment(int userId) {
mUserId = userId;
}
@UnsupportedAppUsage
public 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
@Deprecated
public File getExternalStorageDirectory() {
return getExternalDirs()[0];
}
@UnsupportedAppUsage
@Deprecated
public File getExternalStoragePublicDirectory(String type) {
return buildExternalStoragePublicDirs(type)[0];
}
。。。
}
可见,getExternalDirs被注解为@UnsupportedAppUsage, 表示该api已经不被支持App使用了。
getExternalDirs调用了StorageManager.getVolumeList, 而正是在这里发生了NullPointerException。
StorageManager.getVolumeList代码定义在StorageManager.java:
/** {@hide} */
@UnsupportedAppUsage
public 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的判断,在低版本和高版本进行区别对待。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/24822.html