第一步配置图片路径(路径初始化在applicaton中,后面直接通过类名获取):
public static String filePath;
filePath = AppUtils.createFile(context).getAbsolutePath()+ File.separator;
public class AppUtils {
public static File createFile(Context context){
File appCacheDir = null;
//判断sd卡正常挂载并且拥有权限的时候创建文件
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
appCacheDir = new File(Environment.getExternalStorageDirectory()+File.separator+"image");
}
if (appCacheDir == null || !appCacheDir.exists() && !appCacheDir.mkdirs()) {
appCacheDir = context.getCacheDir();
}
return appCacheDir ;
}
}
private static boolean hasExternalStoragePermission(Context context) {
int perm = context.checkCallingOrSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE");
return perm == 0;
}
第二步配置provider: file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--"."表示所有路径-->
<files-path path="." name="base_camera_photos" />
<cache-path name="base_image" path="." />
<external-path name="base_name" path="." />
<external-files-path name="base_image_name" path="." />
<external-cache-path name="base_camera_image" path="." />
</paths>
/storage/emulated/0/image/1585808445493.png
以下为多种各种xml文件和对应path类的关系 <files-path path="." name="camera_photos" />
该方式提供在应用的内部存储区的文件/子目录的文件。它对应Context.getFilesDir返回的路径:eg:"/data/data/com.jph.simple/files"。 <cache-path name="name" path="path" />
该方式提供在应用的内部存储区的缓存子目录的文件。它对应getCacheDir返回的路径:eg:“/data/data/com.jph.simple/cache”; <external-path name="name" path="path" />
该方式提供在外部存储区域根目录下的文件。它对应Environment.getExternalStorageDirectory返回的路径:eg:"/storage/emulated/0"; <external-files-path name="name" path="path" />
该方式提供在应用的外部存储区根目录的下的文件。它对应Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)返回的路径。eg:"/storage/emulated/0/Android/data/com.jph.simple/files"。 <external-cache-path name="name" path="path" />
该方式提供在应用的外部缓存区根目录的文件。它对应Context.getExternalCacheDir()返回的路径。eg:"/storage/emulated/0/Android/data/com.jph.simple/cache"
这些就是FileProvider提供的所有支持的path类型
public class ImageFileProvider extends FileProvider {
public static String getFileProviderName(Context context) {
return context.getPackageName() + ".provider";
}
}
<provider
android:name=".provider.ImageFileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
1.调用方法
public class SystemIntentUtils {
public static final int SystemRequestCodePhoto=0x1111;
public static final int SystemRequestCodeCamera=0x1112;
public static final int SystemRequestCodeCrop=0x1113;
/**
* 开启相册
*/
public static void openPhoto(@NonNull Activity context) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
context.startActivityForResult(intent,SystemRequestCodePhoto);
}
/**
* 开启相机
*/
public static Uri openCamera(@NonNull Activity context,File file) {
Uri uri = null;
try {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(
context,
ImageFileProvider.getFileProviderName(context),
file);
} else {
uri = Uri.fromFile(file);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
context.startActivityForResult(intent, SystemRequestCodeCamera);
} catch (Exception e) {
e.printStackTrace();
}
return uri;
}
/**
* 裁剪
*/
public static void startPhotoCrop(Uri imageUri, File outCrop, int width, int height, Activity context) {
Intent intent = new Intent("com.android.camera.action.CROP");
//设置源地址uri
intent.setDataAndType(imageUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
intent.putExtra("scale", true);
Uri uriCrop = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//系統>7.0开启临时权限
uriCrop= FileProvider.getUriForFile(context, ImageFileProvider.getFileProviderName(context), outCrop);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, uriCrop));
}else{
uriCrop= Uri.fromFile(outCrop);
}
intent.putExtra("scale", true);
//设置裁剪完保存的URI
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriCrop);
//设置图片格式
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("return-data", false);//data不需要返回,避免图片太大异常。小米的系统使用这个会使返回数据为null,所以设置为false用uri来获取数据
//头像识别 会启动系统的拍照时人脸识别
intent.putExtra("noFaceDetection", true);
context.startActivityForResult(intent, SystemRequestCodeCrop);
}
}
使用方法:
private String imagePath;
private File file;
private Uri imageUri;
"从相册获取"
SystemIntentUtils.openPhoto((Activity) mContext);
"拍照"
imagePath = BaseApplication.filePath + System.currentTimeMillis() + ".png";
file = new File(imagePath);
imageUri = SystemIntentUtils.openCamera((Activity) mContext, file);
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
return;
}
int screenWidth = androiodScreenProperty.getWidth();
switch (requestCode) {
case SystemIntentUtils.SystemRequestCodePhoto:
//相册
imageUri = data.getData();
imagePath = BaseApplication.filePath + System.currentTimeMillis() + ".png";
file = new File(imagePath);
SystemIntentUtils.startPhotoCrop(imageUri,file,screenWidth,screenWidth, (Activity) mContext);
break;
case SystemIntentUtils.SystemRequestCodeCamera:
//拍照
SystemIntentUtils.startPhotoCrop(imageUri,file,screenWidth,screenWidth, (Activity) mContext);
break;
case SystemIntentUtils.SystemRequestCodeCrop:
try {
Bitmap photo = BitmapFactory.decodeStream(new FileInputStream(imagePath));
ivHead.setImageBitmap(photo);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
break;
}
}