在某些行業,APP可能被禁止使用存儲權限,或公司在寫SDK功能,不方便獲取權限
所以需要有 無存儲權限拍照方案。這里兩種方案都列出里。
對于寫入權限,在高版本中,已經廢棄, 不可用文件寫入讀取權限,所以拍照功能也最好使用無權限方式(如果需要獲取相冊, 需要使用新的權限---媒體權限)
?
?
業務前提
-
判斷拍照權限
if(activity.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
//開始拍照流程
}else{
activity.requestPermissions(new String[]{Manifest.permission.CAMERA},1001);
}
存儲地址及Uri
一、無存儲權限
1)、創建存儲路徑
var filePath:String?=null;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {filePath = mActivity.filesDir!!.absolutePath + Environment.DIRECTORY_PICTURES + File.separator;} else {filePath = FileUtil.getCachePath() + Environment.DIRECTORY_PICTURES + File.separator;}
工具類 FileUtil.getCachePath
public static String getCachePath() {File externalCacheDir = context.getExternalCacheDir();if (null != externalCacheDir) {return externalCacheDir.getAbsolutePath();}if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {return Environment.getExternalStorageDirectory().getAbsolutePath();}return context.getCacheDir().getAbsolutePath();}
2)、path轉Uri
// 指定拍照存儲位置的方式調起相機var fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss",Calendar.getInstance(Locale.CHINA)) + ".jpg";val file = File(filePath + fileName);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {val contentValues = ContentValues()contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName)contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")imageUri = mActivity.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)} else {imageUri = Uri.fromFile(file)}
二、有存儲權限
1)配置provider(官方適配方案)
1、androidx.core.content.FileProvider 可以用v4包 也可用 Androidx,看自己項目用哪個庫
2、applicationId 是在build.gradle文件中定義的一個進程Id,也是應用唯一id
<providerandroid:name="androidx.core.content.FileProvider"android:authorities="${applicationId}.provider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/filepaths" /></provider>
3、在main/res/xml 路徑下創建文件 filepaths.xml
<paths>
<files-path name="name" path="path" />
//物理路徑相當于Context.getFilesDir() + /path/<cache-path name="name" path="path" />
//物理路徑相當于Context.getCacheDir() + /path/<external-path name="name" path="path" />
//物理路徑相當于Environment.getExternalStorageDirectory() + /path/<external-files-path name="name" path="path" />
//物理路徑相當于Context.getExternalFilesDir(String) + /path/<external-cache-path name="name" path="path" />
//物理路徑相當于Context.getExternalCacheDir() + /path/
</paths>
代碼中每一個path配置,都對應一個java api,例如
mActivity.getExternalFilesDir("MyFilePath")
? 對應external-files-path的地址:
/storage/emulated/0/Android/data/{applicationId}/files/MyFilePath
后面需要自己拼接"/path"
getExternalFilesDir 入參可為null
4、java代碼
//判斷三個權限 寫入寫出 拍照
//android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGEif (activity.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {String path = FileUtil.getCachePath() + File.separator + cameraPath + System.currentTimeMillis() + ".jpg";File file = new File(path);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {imageUri= FileProvider.getUriForFile(activity.getApplication(), activity.getPackageName() + ".provider", file);activity.grantUriPermission(activity.getPackageName(), outputFileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);} else {imageUri= Uri.fromFile(file);}Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);outputFile.add(file);activity.startActivityForResult(intent, 1011);}
調用拍照
var intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);mActivity.startActivityForResult(intent, 1011);
獲取結果
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {if (resultCode == RESULT_OK) {if(requestCode==1011){
//兩種方式獲取結果
//1 直接使用 拍照傳入的Uri 參數
//2 data.getData() 返回一個Uri}}
}