解決 Android 7.x 報(bào)錯(cuò) Android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
過去在Android 7.x之前的手機(jī)調(diào)用拍照直接簡單的喚起系統(tǒng)相機(jī)
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.fromFile(sdcardTempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
但是Android N 文件系統(tǒng)權(quán)限的變化(Android N == Android 7.x)赶熟;
為了提高私有文件的安全性奴烙,在targetSdk版本為N或者以后版本的app中,其私有目錄將會(huì)限制訪問乏苦。這可以防止私有文件元數(shù)據(jù)的泄露畅形,比如文件大小或者是文件是否存在养距。但這給開發(fā)者帶來了很多不利的影響;
如果你的targetSdk版本為N日熬,恭喜你
解決方案:
--- 使用FileProvider 能完美解決 ---
1棍厌、在res資源目錄下新建一個(gè)xml文件夾
2、在xml目錄下新建一 file_paths.xml,然后打開xml文件添加如下代碼
<?xml version="1.0"encoding="utf-8"?>
<paths>?
? ? <external-path name="files_root" ?path="Android/data/${你的包名}/"/>
? ? <external-path name="external_storage_root" ?path="."/>
</paths>
3、在AndroidManifest.xml中添加如下代碼
<provider
? ? ? android:name="android.support.v4.content.FileProvider"
? ? ? android:authorities="${ 你的包名 }.fileProvider"
? ? ?android:exported="false"
? ? ?android:grantUriPermissions="true">
? ? ?<meta-data
? ? ? ? ? ?android:name="android.support.FILE_PROVIDER_PATHS"
? ? ? ? ? android:resource="@xml/file_paths"/>
</provider>
4耘纱、修改代碼適配Android N敬肚,由于Android N對(duì)權(quán)限管理嚴(yán)格,所以呢要做權(quán)限處理
如下代碼內(nèi)容 == 如上圖顯示:(由于沒有格式化功能束析,所以可以直接復(fù)制進(jìn)IDE 進(jìn)行格式化跳整)
public voidselectPicFromCamera() {
? ? ?if(!EaseCommonUtils.isExitsSdcard()) {
? ? ? ? ? ? showToast("SD卡不存在艳馒,不能拍照");
? ? ? ? ? ?return;
? ? ? }
? ? ?if(Build.VERSION.SDK_INT>=23) {
? ? ? ? ?int checkPermission = ContextCompat.checkSelfPermission(this, ? ? Manifest.permission.CAMERA); ?
? ? ? ? ?if(checkPermission != PackageManager.PERMISSION_GRANTED) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},222);
return;
?}else{ openCamera(); } }else{ openCamera(); } }
@Override
public voidonRequestPermissionsResult(intrequestCode, String[] permissions,int[] grantResults) {
? ?switch(requestCode) {
? ? ?//就像onActivityResult一樣這個(gè)地方就是判斷你是從哪來的。
? ? ?case 222:
? ? ? ? ? ? if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ? ? ? openCamera(); }else{ ?Toast.makeText(this,"很遺憾你把相機(jī)權(quán)限禁用了员寇。請(qǐng)務(wù)必開啟相機(jī)權(quán)限享受我們提供的服務(wù)吧弄慰。", Toast.LENGTH_SHORT).show(); }
? ? ? ?break;
? ? ? ?default:
? ? ? ?super.onRequestPermissionsResult(requestCode, permissions, grantResults);
? ? } }
//拍照
private voidopenCamera() {
? ?cameraFile=newFile(PathUtil.getInstance().getImagePath(), ? ? ? ? EMClient.getInstance().getCurrentUser() + System.currentTimeMillis() +".jpg");
? ?cameraFile.getParentFile().mkdirs();
? ?Intent intent =newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
? ?//判斷是否是AndroidN以及更高的版本
? if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {
? ? ? Uri contentUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID+".fileProvider",cameraFile); ? ? ?intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
}else{ ?intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile)); } ?startActivityForResult(intent, Constants.REQUEST_CODE.IMAGE_CAPTURE); }
private void showToast(String c){ Toast.makeText(this,c,Toast.LENGTH_SHORT).show(); ?}
親測(cè)試完美解決
方法二:使用ContentProvider方式傳遞uri,