1. 程式人生 > >android7.0呼叫相機拍照的問題解決方案

android7.0呼叫相機拍照的問題解決方案

最近在應用中開發呼叫系統相機拍照的時候,遇到一個問題,就是在安卓7.0及以上機型使用,按照往常寫法Uri.fromFile(imgFile)回丟擲異常FileUriExposedException導致程式崩潰。通過上網檢視知道了安卓7.0及以上的特殊問題。因此整理了其他的人的處理方法,我也根據自身的專案需要進行了整改,特此奉上,供學習交流!

1.在清單檔案裡新增provider如下:

<application
    ...>
       <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="包名.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>
</application>

2.在res目錄下新建xml資料夾,並新建一個file_paths.xml檔案,內容如下

<?xml version="1.0" encoding="utf-8"?>

<paths>
                 
    <external-path
        name="external_storage_root"
        path="." />

</paths>

3.判斷許可權:

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
                            if (ContextCompat.checkSelfPermission(SetUserHeadActivity.this,
                                    android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                                //先判斷有沒有許可權 ,沒有就在這裡進行許可權的申請
                                ActivityCompat.requestPermissions(SetUserHeadActivity.this,
                                        new String[]{android.Manifest.permission.CAMERA}, CAMERA_OK);

                            } else {
                                //說明已經獲取到攝像頭許可權了 想幹嘛幹嘛
                                takePhoto();
                            }
                        } else {
                            //這個說明系統版本在6.0之下,不需要動態獲取許可權。

                        }

4.呼叫相機:

//拍照的程式碼
    private void takePhoto() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            //建立一個File
            File outputImage = new File(Environment.getExternalStorageDirectory(), "out_image.jpg");
            try {
                if (outputImage.exists()) {
                    outputImage.delete();
                }
                outputImage.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (outputImage != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    //如果是7.0及以上的系統使用FileProvider的方式建立一個Uri
                    Log.e(TAG, "Build.VERSION.SDK_INT >= Build.VERSION_CODES.N");
                    imageUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", outputImage);
                    takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    takePictureIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                } else {
                    //7.0以下使用這種方式建立一個Uri
                    imageUri = Uri.fromFile(outputImage);
                }
                //將Uri傳遞給系統相機
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(takePictureIntent, TAKE_PHOTO);
            }
        }
    }

5.獲取返回值:

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case CAMERA_OK:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //這裡已經獲取到了攝像頭的許可權,想幹嘛幹嘛了可以
                    takePhoto();

                } else {
                    //這裡是拒絕給APP攝像頭許可權,給個提示什麼的說明一下都可以。
                    Toast.makeText(SetUserHeadActivity.this, "請手動開啟相機許可權", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }

    }

參考網址: