最近学习AndroidStudio,用到File类的listFiles方法,其返回值总是为null,费了很大力气才解决。因此需要总结一下。
访问文件代码:
private File mImgDir;
private final String mTestPath = "/pictest/pic/";//该目录在模拟器上实际存在,里面有几张测试图片。
ListgetFileNameList() { File sdCard = Environment.getExternalStorageDirectory();//获取的值为: /storage/emulated/0 String folder = sdCard.getAbsolutePath() + mTestPath; //folder值为:/storage/emulated/0/pictest/pic
mImgDir = new File(folder);//初始化File对象File [] files = mImgDir.listFiles();//噩梦在这一行开始!
if (files!= null) { Toast.makeText(getApplicationContext(),"有内容!",Toast.LENGTH_SHORT).show(); Log.d("哈哈哈","能访问!"); } else { Toast.makeText(getApplicationContext(),"null!",Toast.LENGTH_SHORT).show(); Log.d("哎呀","仍然搞不定!"); }
}
噩梦在“File[] files =mImgDir.listFiles()”这一行开始!files的值是null!下面是探索过程:
1.在AndroidMenifest.xml中增加permission:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE">uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">uses-permission再次运行代码,files的值仍然是null !
2.加入运行时检查
拜读了自仁兄nianhua120的大作:http://blog.csdn.net/nianhua120/article/details/51525949 感觉有所悟,copy了两个关键函数
getPermission函数和onRequestPermissionsResult函数。代码变为:
private File mImgDir;
private final String mTestPath = "/pictest/pic/";//该目录在模拟器上实际存在,里面有几张测试图片。
ListgetFileNameList() { File sdCard = Environment.getExternalStorageDirectory();//获取的值为: /storage/emulated/0 String folder = sdCard.getAbsolutePath() + mTestPath; //folder值为:/storage/emulated/0/pictest/pic
getPermission();//加入运行时检查}
void getPermission() { int permissionCheck1 = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE); int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permissionCheck1 != PackageManager.PERMISSION_GRANTED || permissionCheck2 != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 124); } }
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 124) { if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { Log.d("heihei","获取到权限了!");} else { Log.d("heihei","搞不定啊!"); } }}mImgDir = new File(folder);//初始化File对象File [] files = mImgDir.listFiles();//噩梦结束了吗?
经过调试发现,执行到onRequestPermissionsResult,grantResults的返回值是{-1,-1}!
查看PackageManager.java, 发现:
public static final int PERMISSION_GRANTED = 0;
public static final int PERMISSION_DENIED = -1;噩梦仍未结束!这下很崩溃啊!
3.看了大量权限相关的文章,仍然无果。最后找到一篇外国人的帖子:
http://stackoverflow.com/questions/37162223/permission-denial-android-permission-read-external-storage
里面有一句关键的话:As a temporary workaround, drop your targetSdkVersion below 23.
我照着这句话做了。打开build.gradle(Module:app)文件,修改 targetSdkVersion25为 targetSdkVersion22
private File mImgDir;
private final String mTestPath = "/pictest/pic/";//该目录在模拟器上实际存在,里面有几张测试图片。
List getFileNameList()
{
File sdCard = Environment.getExternalStorageDirectory();//获取的值为: /storage/emulated/0
String folder = sdCard.getAbsolutePath() + mTestPath; //folder值为:/storage/emulated/0/pictest/pic
//getPermission();//加入运行时检查
mImgDir = new File(folder);//初始化File对象
File [] files = mImgDir.listFiles();//噩梦在这一行开始!
if (files!= null)
{
Toast.makeText(getApplicationContext(),"有内容!",Toast.LENGTH_SHORT).show();
Log.d("哈哈哈","能访问!");
}
else
{
Toast.makeText(getApplicationContext(),"null!",Toast.LENGTH_SHORT).show();
Log.d("哎呀","仍然搞不定!");
}
}
再次运行代码,屏幕弹出"哈哈哈",噩梦终于结束!
4.神奇的后续
1)神奇的是,把getPermission()注释掉,仍然可以工作!
2)更神奇的是,打开build.gradle(Module:app)文件,修改 targetSdkVersion 22为 targetSdkVersion 25,即把这个改动回退,仍然可以工作!
也就是说,最终能工作的代码其实就是第一步加入permission后的。第三步相当于提供了一把钥匙,开了门后,就不需要钥匙了!
这其中的谜,有待未来探索。。。