關於Android7.0調用系統相機拍照、訪問相冊的一些問題:
在Android6.0中Google提出了動態申請權限的Api,調用相機拍照,訪問SDcard等操作都需要先申請對應的權限如下:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />Google是反對放寬私有目錄的訪問權限的,所以收起對私有文件的訪問權限是Android將來發展的趨勢。
Android7.0中嘗試傳遞 file:// URI 會觸發 FileUriExposedException,因爲在Android7.0之後Google認爲直接使用本地的根目錄即file:// URI是不安全的操作,直接訪問會拋出FileUriExposedExCeption異常,這就意味着在Android7.0以前我們訪問相機拍照存儲時,如果使用URI的方式直接存儲剪裁圖片就會造成這個異常,那麼如何解決這個問題呢?(文章結尾會附上demo的連接)
Google爲我們提供了FileProvider類,進行一種特殊的內容提供,FileProvider時ContentProvide的子類,它使用了和內容提供器類似的機制來對數據進行保護,可以選擇性地將封裝過的Uri共享給外部,從而提高了應用的安全性。下面就讓我們看一下如何使用這個內容提供者進行數據訪問的:
使用FileProvider獲取Uri就會將以前的file:// URI準換成content:// URI,實現一種安全的應用間數據訪問,內容提供者作爲Android的四大組件之一,使用同樣需要在清單文件AndroidManifest.xml中進行註冊的,註冊方法如下:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.zz.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>provider標籤裏的 android:name的值是FileProvider的包名+類名爲固定值。android:authorities的值相當於一個標誌,當我們使用FileProvider的getUriForFile方法時的一個參數需和清單文件註冊時的保持一致,這裏我使用的是:com.zz.fileprovider可自行定義。exported:要求必須爲false,爲true則會報安全異常。grantUriPermissions:true,表示授予 URI 臨時訪問權限。<meta-data />標籤裏面是用來指定共享的路徑。 android:resource="@xml/file_paths"就是我們的共享路徑配置的xml文件。關於xml文件的配置如下:
在res目錄下創建xml文件夾,file_paths.xml文件內容如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <paths> <external-path name="camera_photos" path="" /> </paths> </resources>external-path標籤用來指定Uri共享的,name屬性的值可以自定義,path屬性的值表示共享的具體位置,設置爲空,就表示共享整個SD卡,也可指定對應的SDcard下的文件目錄,根據需求自行定義。接下來就是調用系統相機進行拍照了,代碼如下:
首先獲取相機和訪問SDcard權限:
/** * 自動獲取相機權限 */ private void autoObtainCameraPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { ToastUtils.showShort(this, "您已經拒絕過一次"); } ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE}, CAMERA_PERMISSIONS_REQUEST_CODE); } else {//有權限直接調用系統相機拍照 if (hasSdcard()) { imageUri = Uri.fromFile(fileUri); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) imageUri = FileProvider.getUriForFile(MainActivity.this, "com.zz.fileprovider", fileUri);//通過FileProvider創建一個content類型的Uri PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST); } else { ToastUtils.showShort(this, "設備沒有SD卡!"); } } }
動態申請權限的回調方法:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case CAMERA_PERMISSIONS_REQUEST_CODE: {//調用系統相機申請拍照權限回調 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (hasSdcard()) { imageUri = Uri.fromFile(fileUri); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) imageUri = FileProvider.getUriForFile(MainActivity.this, "com.zz.fileprovider", fileUri);//通過FileProvider創建一個content類型的Uri PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST); } else { ToastUtils.showShort(this, "設備沒有SD卡!"); } } else { ToastUtils.showShort(this, "請允許打開相機!!"); } break; } case STORAGE_PERMISSIONS_REQUEST_CODE://調用系統相冊申請Sdcard權限回調 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { PhotoUtils.openPic(this, CODE_GALLERY_REQUEST); } else { ToastUtils.showShort(this, "請允許打操作SDCard!!"); } break; } }*注:PhotoUtils是博主對拍照和相冊獲取照片的封裝下面會給出,PhotoUtils類和完整的MainActivity類
重點看一下imageUri的獲取,代碼中imageUri是用於存儲拍照後照片的Uri,調用相機拍照之前首先判斷一下系統版本,AndroidN也就是Android7.0以上的系統通過FileProvider獲取Uri方法的參數分別爲,上下文對象、清單文件配置的android:authorities和對應的拍照存儲的圖片。之後就是通過PhotoUtils調用系統相機進行拍照。
PhotoUtils相應代碼如下:
/** * @param activity 當前activity * @param imageUri 拍照後照片存儲路徑 * @param requestCode 調用系統相機請求碼 */ public static void takePicture(Activity activity, Uri imageUri, int requestCode) { //調用系統相機 Intent intentCamera = new Intent(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加這一句表示對目標應用臨時授權該Uri所代表的文件 } intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE); //將拍照結果保存至photo_file的Uri中,不保留在相冊中 intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); activity.startActivityForResult(intentCamera, requestCode); }方法說明:通過Intent調用系統相機拍照,如果本機版本大於等於anroid7.0需要臨時授權Uri的訪問權限如下:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
其他部分和以前正常調用系統相機一樣。 接下來就是對拍完的照片進行剪裁:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { case CODE_CAMERA_REQUEST://拍照完成回調 cropImageUri = Uri.fromFile(fileCropUri); PhotoUtils.cropImageUri(this, imageUri, cropImageUri, 1, 1, output_X, output_Y, CODE_RESULT_REQUEST); break; case CODE_GALLERY_REQUEST://訪問相冊完成回調 if (hasSdcard()) { cropImageUri = Uri.fromFile(fileCropUri); Uri newUri = Uri.parse(PhotoUtils.getPath(this, data.getData())); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) newUri = FileProvider.getUriForFile(this, "com.zz.fileprovider", new File(newUri.getPath())); PhotoUtils.cropImageUri(this, newUri, cropImageUri, 1, 1, output_X, output_Y, CODE_RESULT_REQUEST); } else { ToastUtils.showShort(this, "設備沒有SD卡!"); } break; case CODE_RESULT_REQUEST: Bitmap bitmap = PhotoUtils.getBitmapFromUri(cropImageUri, this); if (bitmap != null) { showImages(bitmap); } break; } } }剪裁代碼如下:/** * @param activity 當前activity * @param orgUri 剪裁原圖的Uri * @param desUri 剪裁後的圖片的Uri * @param aspectX X方向的比例 * @param aspectY Y方向的比例 * @param width 剪裁圖片的寬度 * @param height 剪裁圖片高度 * @param requestCode 剪裁圖片的請求碼 */ public static void cropImageUri(Activity activity, Uri orgUri, Uri desUri, int aspectX, int aspectY, int width, int height, int requestCode) { 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); } intent.setDataAndType(orgUri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", aspectX); intent.putExtra("aspectY", aspectY); intent.putExtra("outputX", width); intent.putExtra("outputY", height); intent.putExtra("scale", true); //將剪切的圖片保存到目標Uri中 intent.putExtra(MediaStore.EXTRA_OUTPUT, desUri); intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); activity.startActivityForResult(intent, requestCode); }和以前正常剪裁代碼基本相同,和上面意圖打開相機一樣,如果本機版本大於等於anroid7.0需要臨時授權Uri的訪問權限如下:intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
到此整體調用系統相機拍照、剪裁完成,剪裁後照片存儲到cropImageUri對應路徑。
訪問相冊代碼如下:
/** * @param activity 當前activity * @param requestCode 打開相冊的請求碼 */ public static void openPic(Activity activity, int requestCode) { Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT); photoPickerIntent.setType("image/*"); activity.startActivityForResult(photoPickerIntent, requestCode); }上文中已貼出訪問相冊後的onActivityResult的回調,主要也是一樣的操作解析Uri調用剪裁圖片:if (hasSdcard()) { cropImageUri = Uri.fromFile(fileCropUri); Uri newUri = Uri.parse(PhotoUtils.getPath(this, data.getData())); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) newUri = FileProvider.getUriForFile(this, "com.zz.fileprovider", new File(newUri.getPath())); PhotoUtils.cropImageUri(this, newUri, cropImageUri, 1, 1, output_X, output_Y, CODE_RESULT_REQUEST); } else { ToastUtils.showShort(this, "設備沒有SD卡!"); } break;*注:Android4.4之後選取中的圖片不再返回真實的Uri了,而是封裝過的Uri,所以在4.4以上,就要對這個Uri進行解析,即上面的PhotoUtils.getPath()方法,
具體Uri的解析見PhotoUtils類。android4.4以前直接data.getData就可以獲取到真是Uri不用解析。
解析獲取真實的Uri後,判斷系統版本開始通過FileProvider獲取新的Uri之後就可以同樣的圖片剪裁了。MainActivity代碼如下:
package choicemmed.com.android60permissionsdemo; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Matrix; import android.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v4.content.FileProvider; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import com.google.android.gms.common.api.GoogleApiClient; import com.lidroid.xutils.ViewUtils; import com.lidroid.xutils.view.annotation.ViewInject; import com.lidroid.xutils.view.annotation.event.OnClick; import java.io.File; import de.hdodenhof.circleimageview.CircleImageView; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final String TAG = "MainActivity"; @ViewInject(R.id.photo) private CircleImageView photo; @ViewInject(R.id.takePic) private Button takePic; @ViewInject(R.id.takeGallery) private Button takeGallery; @ViewInject(R.id.test) private Button test; private static final int CODE_GALLERY_REQUEST = 0xa0; private static final int CODE_CAMERA_REQUEST = 0xa1; private static final int CODE_RESULT_REQUEST = 0xa2; private static final int CAMERA_PERMISSIONS_REQUEST_CODE = 0x03; private static final int STORAGE_PERMISSIONS_REQUEST_CODE = 0x04; private File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/photo.jpg"); private File fileCropUri = new File(Environment.getExternalStorageDirectory().getPath() + "/crop_photo.jpg"); private Uri imageUri; private Uri cropImageUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewUtils.inject(this); } @OnClick({R.id.takePic, R.id.takeGallery}) @Override public void onClick(View v) { switch (v.getId()) { case R.id.takePic: autoObtainCameraPermission(); break; case R.id.takeGallery: autoObtainStoragePermission(); break; } } /** * 自動獲取相機權限 */ private void autoObtainCameraPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { ToastUtils.showShort(this, "您已經拒絕過一次"); } ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE}, CAMERA_PERMISSIONS_REQUEST_CODE); } else {//有權限直接調用系統相機拍照 if (hasSdcard()) { imageUri = Uri.fromFile(fileUri); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) imageUri = FileProvider.getUriForFile(MainActivity.this, "com.zz.fileprovider", fileUri);//通過FileProvider創建一個content類型的Uri PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST); } else { ToastUtils.showShort(this, "設備沒有SD卡!"); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case CAMERA_PERMISSIONS_REQUEST_CODE: {//調用系統相機申請拍照權限回調 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (hasSdcard()) { imageUri = Uri.fromFile(fileUri); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) imageUri = FileProvider.getUriForFile(MainActivity.this, "com.zz.fileprovider", fileUri);//通過FileProvider創建一個content類型的Uri PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST); } else { ToastUtils.showShort(this, "設備沒有SD卡!"); } } else { ToastUtils.showShort(this, "請允許打開相機!!"); } break; } case STORAGE_PERMISSIONS_REQUEST_CODE://調用系統相冊申請Sdcard權限回調 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { PhotoUtils.openPic(this, CODE_GALLERY_REQUEST); } else { ToastUtils.showShort(this, "請允許打操作SDCard!!"); } break; } } private int output_X = 480; private int output_Y = 480; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { case CODE_CAMERA_REQUEST://拍照完成回調 cropImageUri = Uri.fromFile(fileCropUri); PhotoUtils.cropImageUri(this, imageUri, cropImageUri, 1, 1, output_X, output_Y, CODE_RESULT_REQUEST); break; case CODE_GALLERY_REQUEST://訪問相冊完成回調 if (hasSdcard()) { cropImageUri = Uri.fromFile(fileCropUri); Uri newUri = Uri.parse(PhotoUtils.getPath(this, data.getData())); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) newUri = FileProvider.getUriForFile(this, "com.zz.fileprovider", new File(newUri.getPath())); PhotoUtils.cropImageUri(this, newUri, cropImageUri, 1, 1, output_X, output_Y, CODE_RESULT_REQUEST); } else { ToastUtils.showShort(this, "設備沒有SD卡!"); } break; case CODE_RESULT_REQUEST: Bitmap bitmap = PhotoUtils.getBitmapFromUri(cropImageUri, this); if (bitmap != null) { showImages(bitmap); } break; } } } /** * 自動獲取sdk權限 */ private void autoObtainStoragePermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSIONS_REQUEST_CODE); } else { PhotoUtils.openPic(this, CODE_GALLERY_REQUEST); } } private void showImages(Bitmap bitmap) { photo.setImageBitmap(bitmap); } /** * 檢查設備是否存在SDCard的工具方法 */ public static boolean hasSdcard() { String state = Environment.getExternalStorageState(); return state.equals(Environment.MEDIA_MOUNTED); } }PhotoUtils代碼如下:package choicemmed.com.android60permissionsdemo; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ContentUris; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.provider.DocumentsContract; import android.provider.MediaStore; /** * Created by:zheng zhong on 2016/8/6 16:16 * Email [email protected] */ public class PhotoUtils { private static final String TAG = "PhotoUtils"; /** * @param activity 當前activity * @param imageUri 拍照後照片存儲路徑 * @param requestCode 調用系統相機請求碼 */ public static void takePicture(Activity activity, Uri imageUri, int requestCode) { //調用系統相機 Intent intentCamera = new Intent(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加這一句表示對目標應用臨時授權該Uri所代表的文件 } intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE); //將拍照結果保存至photo_file的Uri中,不保留在相冊中 intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); activity.startActivityForResult(intentCamera, requestCode); } /** * @param activity 當前activity * @param requestCode 打開相冊的請求碼 */ public static void openPic(Activity activity, int requestCode) { Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT); photoPickerIntent.setType("image/*"); activity.startActivityForResult(photoPickerIntent, requestCode); } /** * @param activity 當前activity * @param orgUri 剪裁原圖的Uri * @param desUri 剪裁後的圖片的Uri * @param aspectX X方向的比例 * @param aspectY Y方向的比例 * @param width 剪裁圖片的寬度 * @param height 剪裁圖片高度 * @param requestCode 剪裁圖片的請求碼 */ public static void cropImageUri(Activity activity, Uri orgUri, Uri desUri, int aspectX, int aspectY, int width, int height, int requestCode) { 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); } intent.setDataAndType(orgUri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", aspectX); intent.putExtra("aspectY", aspectY); intent.putExtra("outputX", width); intent.putExtra("outputY", height); intent.putExtra("scale", true); //將剪切的圖片保存到目標Uri中 intent.putExtra(MediaStore.EXTRA_OUTPUT, desUri); intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); activity.startActivityForResult(intent, requestCode); } /** * 讀取uri所在的圖片 * * @param uri 圖片對應的Uri * @param mContext 上下文對象 * @return 獲取圖像的Bitmap */ public static Bitmap getBitmapFromUri(Uri uri, Context mContext) { try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), uri); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } /** * @param context 上下文對象 * @param uri 當前相冊照片的Uri * @return 解析後的Uri對應的String */ @SuppressLint("NewApi") public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; String pathHead = "file:///"; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return pathHead + Environment.getExternalStorageDirectory() + "/" + split[1]; } } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return pathHead + getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } final String selection = "_id=?"; final String[] selectionArgs = new String[]{split[1]}; return pathHead + getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { return pathHead + getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return pathHead + uri.getPath(); } return null; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = {column}; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ private static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ private static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ private static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } }
最後附上demo的GitHub地址:點擊打開鏈接
關於Android7.0調用系統相機拍照、訪問系統相冊的問題大概就是這樣、如有其它的問題歡迎大家留言、指正O(≧口≦)O