Android 7.0使用相機拍照,出現FileUriExposedException異常
阿新 • • 發佈:2019-02-06
以前寫的相機模組功能,在7.0手機上遇到錯誤,記錄一下。
Android 7.0以下 呼叫方式
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/test/" + System.currentTimeMillis() + ".jpg"); file.getParentFile().mkdirs(); Uri uri = Uri.fromFile(file); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
7.0以後再使用上面的方式會出現FileUriExposedException異常錯誤。
Android 7.0以上呼叫方式
使用FileProvider來解決,FileProvider是ContentProvider的一個子類。
1.res目錄新建xml資料夾,並新建xml\file_paths.xml
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="image_file" path="Android/data/你的包名/files/Pictures"/> </paths>
- <files-path/>代表的根目錄: Context.getFilesDir()
- <external-path/>代表的根目錄: Environment.getExternalStorageDirectory()
- <cache-path/>代表的根目錄: getCacheDir()
2.註冊FileProvider
<!-- 自定義URI 需要 provider --> <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"> </meta-data> </provider>
3. 詳細程式碼
/** * 拍照獲取圖片 **/ public void take_photo() { //建立File物件,用於儲存拍照後的圖片 File outputImage = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //external-path == Environment.getExternalStorageDirectory() outputImage = new File(Environment.getExternalStorageDirectory(), "output_image.jpg"); try { if (outputImage.exists()) { outputImage.delete(); } outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } uri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", outputImage); } else { outputImage = new File(getExternalCacheDir(), "output_image.jpg"); try { if (outputImage.exists()) { outputImage.delete(); } outputImage.createNewFile(); } catch (IOException e) { e.printStackTrace(); } uri = Uri.fromFile(outputImage); } //啟動相機程式 Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, Constant.REQUEST_CODE_CAPTURE_CAMEIA); }@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == Constant.REQUEST_CODE_CAPTURE_CAMEIA && resultCode == RESULT_OK && uri != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //建立File物件,用於儲存拍照後的圖片 File outputImage = new File(Environment.getExternalStorageDirectory(), "output_image.jpg"); filePath = outputImage.getAbsolutePath(); }else{ filePath = FileUtils.getRealFilePath(this, uri); } ImageUtils.getInstance().uploadImageToQiniu(filePath,QINIU_TOKEN,this); } }
getRealFilePath的方法
public static String getRealFilePath(final Context context, final Uri uri) { if (null == uri) return null; final String scheme = uri.getScheme(); String data = null; if (scheme == null) data = uri.getPath(); else if (ContentResolver.SCHEME_FILE.equals(scheme)) { data = uri.getPath(); } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null); if (null != cursor) { if (cursor.moveToFirst()) { int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); if (index > -1) { data = cursor.getString(index); } } cursor.close(); } } return data; }