Android 適配7.0拍照、圖庫、裁剪

Android在7.0以后傳遞Uri直接和低版本一樣操作會報FileUriExposedException,涉及到了數據共享問題,具體實現:

首先在AndroidManifest中添加如下:

</application>
    ...
    <!--文件共享-->
    <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>
</application>

在屬性android:authorities中值填寫為包名+fileprovider,然后在meta-data中的resource中對應相關的xml文件,創(chuàng)建該文件并填寫內容:

<?xml version="1.0" encoding="utf-8"?>
<path>
    <external-path
        name="my_images"
        path=""/>
</path>

其中

  • <files-path/> //代表的根目錄: Context.getFilesDir()
  • <external-path/> //代表的根目錄: Environment.getExternalStorageDirectory()
  • <cache-path/> //代表的根目錄: getCacheDir()

name 可以隨便填寫,path為共享空間,不填為整個根目錄,進入代碼模塊:

定義常量:

private final int TAKE_PHOTO_CODE = 1000;// 拍照
private final int SELECT_PHOTO_CODE = 1001;// 圖庫
private final int CUT_PICTURE_CODE = 1002;// 裁剪

private File file;// 拍的照片
private String filePath = Constant.TAKE_PHOTO_PATH;// 拍照的原圖地址
private File cropFile;// 剪切后的圖片
private String cropPath = Constant.CUT_PHOTO_PATH;// 剪切的原圖地址

然后初始化文件,如果已經存在要刪除后在創(chuàng)建:

file = new File(filePath);
cropFile = new File(cropPath);

try {
    if (file.exists()) {
        file.delete();
    }
    file.createNewFile();

    if (cropFile.exists()) {
        cropFile.delete();
    }
    cropFile.createNewFile();
} catch (IOException e) {
    e.printStackTrace();
}

開始拍照,在拍照之前請檢查權限,確認擁有相機權限之后調用如下方法:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri temp;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    temp = FileProvider.getUriForFile(ContextHandler.currentActivity(), "包名.fileprovider", file);// 一定要對應AndroidMainfast中配置的值
} else {
    temp = Uri.fromFile(file);
}
// 啟動相機程序
intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
intent.putExtra(MediaStore.EXTRA_OUTPUT, temp);
startActivityForResult(intent, TAKE_PHOTO_CODE);

調用圖庫就簡單多了:

Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, SELECT_PHOTO_CODE);

然后是裁剪的方法:

public void startPhotoZoom(Uri uri) {// 這里的uri也要經過處理
    Intent intent = new Intent("com.android.camera.action.CROP");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加這一句表示對目標應用臨時授權該Uri所代表的文件
    }
    intent.setDataAndType(uri, "image/*");
    // 下面這個crop=true是設置在開啟的Intent中設置顯示的VIEW可裁剪
    intent.putExtra("crop", "true");
    intent.putExtra("scale", true);

    intent.putExtra("aspectX", 1);// 比例
    intent.putExtra("aspectY", 1);

    intent.putExtra("outputX", 300);// 輸出大小
    intent.putExtra("outputY", 300);

    intent.putExtra("return-data", false);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cropFile));
    intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    intent.putExtra("noFaceDetection", true); // no face detection
    startActivityForResult(intent, CUT_PICTURE_CODE);
}

拍照、選圖、裁圖返回來的處理:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK && requestCode == TAKE_PHOTO_CODE) {// 拍照返回
        Uri mUri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// 處理uri
            mUri = FileProvider.getUriForFile(this, "com.nuhtech.cmedicine.fileprovider", file);
        }else{
            mUri = Uri.fromFile(file);
        }
        startPhotoZoom(mUri); //進行裁剪
    } else if (resultCode == Activity.RESULT_OK && requestCode == SELECT_PHOTO_CODE) {// 選圖返回
        if (data != null) {
            startPhotoZoom(data.getData());//進行裁剪
        }
    } else if (resultCode == Activity.RESULT_OK && requestCode == CUT_PICTURE_CODE) {// 裁圖返回
        // 現在已經裁剪完畢,根據需求處理結果即可:
        // cropFile 剪切后的圖片
        // cropPath 剪切的原圖地址
        // 圖片上傳完成之后記得刪除文件
        file.delete();
        cropFile.delete();
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,039評論 25 709
  • Android7.0發(fā)布已經有一個多月了,Android7.0在給用戶帶來一些新的特性的同時,也給開發(fā)者帶來了新的...
    東經315度閱讀 1,422評論 0 14
  • 前言 在Android7.0系統(tǒng)上,android框架強制執(zhí)行了 StrictMode API 政策禁止向你的應用...
    Blizzard_liu閱讀 1,276評論 1 4
  • 黑空 凄月 窗前獨憶悲切 留下相思淚…
    河馬0閱讀 195評論 0 0
  • 1. “快快快起來, 別挨在這里站著,這是高空危險區(qū)域,” 安全員很認真負責的勸叫站在沒有調試好升降機的一個男人說...
    匆匆不離去閱讀 246評論 4 0

友情鏈接更多精彩內容