分享
URI转换工具
class ImageUtils {
companion object {
fun getImageContentUri(context: Context, imageFile: File): Uri? {
val filePath = imageFile.absolutePath
val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
arrayOf(MediaStore.Images.Media._ID), MediaStore.Images.Media.DATA + "=? ",
arrayOf(filePath), null)
if (cursor != null && cursor.moveToFirst()) {
val id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID))
val baseUri = Uri.parse("content://media/external/images/media")
return Uri.withAppendedPath(baseUri, "" + id)
} else {
if (imageFile.exists()) {
val values = ContentValues()
values.put(MediaStore.Images.Media.DATA, filePath)
return context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
} else {
return null
}
}
}
fun getUriForFile(context: Context, file: File): Uri {
if (context == null || file == null) {
throw NullPointerException();
}
var uri: Uri;
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(context.applicationContext,
BuildConfig.APPLICATION_ID + ".fileProvider", file);
} else {
uri = Uri.fromFile(file);
}
return uri;
}
@TargetApi(19)
@JvmStatic
fun getPathFromUri(context: Context, uri: Uri): String? {
val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":").toTypedArray()
val type = split[0]
if ("primary".equals(type, ignoreCase = true)) {
return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
}
} else if (isDownloadsDocument(uri)) {
val id = DocumentsContract.getDocumentId(uri)
val contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
return getDataColumn(context, contentUri, null, null)
} else if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":").toTypedArray()
val type = split[0]
var contentUri: Uri? = null
if ("image" == type) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
} else if ("video" == type) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
} else if ("audio" == type) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = "_id=?"
val selectionArgs = arrayOf(
split[1]
)
return getDataColumn(context, contentUri, selection, selectionArgs)
}
} else if ("content".equals(uri.scheme, ignoreCase = true)) {
// Return the remote address
return if (isGooglePhotosUri(uri)) {
uri.lastPathSegment
} else getDataColumn(context, uri, null, null)
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
return uri.path
}
return ""
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
@JvmStatic
fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri.authority
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
@JvmStatic
fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri.authority
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
@JvmStatic
fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri.authority
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
@JvmStatic
fun isGooglePhotosUri(uri: Uri): Boolean {
return "com.google.android.apps.photos.content" == uri.authority
}
@JvmStatic
fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
var cursor: Cursor? = null
val column = MediaStore.Images.Media.DATA
val projection = arrayOf(column)
try {
cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
if (cursor != null && cursor.moveToFirst()) {
val index = cursor.getColumnIndexOrThrow(column)
return cursor.getString(index)
}
} finally {
cursor?.close()
}
return null
}
}
}
单图分享
Uri uri = ImageUtils.Companion.getUriForFile(mContext, ifrFile);
Intent sharedIntent = new Intent();
sharedIntent.setAction(Intent.ACTION_SEND);
sharedIntent.putExtra(Intent.EXTRA_STREAM, uri);
sharedIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
sharedIntent.setType("image/*");
startActivity(Intent.createChooser(sharedIntent, mContext.getString(R.string.share_to)));
单视频分享
Uri uri = ImageUtils.Companion.getUriForFile(mContext, ifrFile);
Intent sharedIntent = new Intent();
sharedIntent.setAction(Intent.ACTION_SEND);
sharedIntent.putExtra(Intent.EXTRA_STREAM, uri);
sharedIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
sharedIntent.setType("video/*");
startActivity(Intent.createChooser(sharedIntent, mContext.getString(R.string.share_to)));
多文件分享
//fori···
Uri uri;
if (Build.VERSION.SDK_INT >= 30) {
uri = ImageUtils.Companion.getUriForFile(mContext, ifrFile);
} else {
uri = ImageUtils.Companion.getImageContentUri(mContext, ifrFile);
}
uriList.add(uri);
//分享
Intent sharedIntent = new Intent();
sharedIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
sharedIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
sharedIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList);
if (type == Constants.MEDIA_TYPE_IMAGE) {
sharedIntent.setType("image/*");
} else {
sharedIntent.setType("video/*");
}
startActivity(Intent.createChooser(sharedIntent, mContext.getString(R.string.share_to)));
图片裁剪
图片存储路径
/**
* 获取内置SD卡路径
*
* @return
*/
fun getInnerSDCardPath(Context context): String {
//target sdk 设置为30且 、Android11设备上运行
var path:String? = null
if(Build.VERSION.SDK_INT >= 29){
path = context.getExternalFilesDir(Environment.DIRECTORY_DCIM)!!.absolutePath
}else{
path = Environment.getExternalStorageDirectory().absolutePath
}
return path
}
图片选择
const val BASE = "XXXX"
const val IMAGE_TAKEPHOTE_PATH = "TakePhote"
const val IMAGE_TAKEPHOTECROP_PATH = "TakePhoteCROP"
//图库
private void openGallery() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/jpeg");
startActivityForResult(intent, SCAN_OPEN_PHONE);
}
// 拍照
private void takePhoto() {
// 要保存的文件名
String time = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA).format(new Date());
fileName = "photo_" + time;
// 创建一个文件夹
File mCutFile = new File(SDCardUtils.Companion.getInnerSDCardPath() + File.separator + Constants.BASE
+ File.separator + Constants.IMAGE_TAKEPHOTE_PATH, fileName + ".jpeg");
if (!mCutFile.getParentFile().exists()) {
mCutFile.getParentFile().mkdirs();
}
// 要保存的图片文件
imgFile = mCutFile;
// 将file转换成uri
if (Build.VERSION.SDK_INT >= 30) {
// 通过 MediaStore API 插入file 为了拿到系统裁剪要保存到的uri(因为App没有权限不能访问公共存储空间,需要通过 MediaStore API来操作)
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, imgFile.getAbsolutePath());
values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
imgUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Log.w(TAG, "photoUri:" + imgUri.getAuthority() + ",photoUri:" + imgUri.getPath());
} else {
imgUri = Uri.fromFile(imgFile);
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 添加Uri读取权限
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
// 或者
// grantUriPermission("com.rain.takephotodemo", imgUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
// 添加图片保存位置
intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
intent.putExtra("return-data", false);
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
}
ucrop裁剪
implementation 'com.github.yalantis:ucrop:2.2.3'
String time = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA).format(new Date());
// 指定裁剪完成以后的图片所保存的位置,pic info显示有延时
fileName = "photo_" + time;
File mCutFile = new File(SDCardUtils.Companion.getInnerSDCardPath() + File.separator + Constants.BASE
+ File.separator + Constants.IMAGE_TAKEPHOTECROP_PATH, fileName + ".jpeg");
if (!mCutFile.getParentFile().exists()) {
mCutFile.getParentFile().mkdirs();
}
uploadFile = mCutFile;
mCutUri = Uri.fromFile(mCutFile);
uploadName = fileName + ".jpeg";
UCrop.Options options = new UCrop.Options();
//设置位图最大大小
options.withMaxResultSize(200, 200);
//宽高比
options.withAspectRatio(1, 1);
options.setToolbarColor(ContextCompat.getColor(this, R.color.black));
options.setToolbarTitle(uploadName);
options.setStatusBarColor(ContextCompat.getColor(this, R.color.black));
//设置Toolbar控件颜色
options.setToolbarWidgetColor(ContextCompat.getColor(this, R.color.white));
//设置Toolbar返回按钮图片
// options.setToolbarCancelDrawable(R.drawable.);
//设置Toolbar确定按钮图片
// options.setToolbarCropDrawable(R.drawable.);
options.setFreeStyleCropEnabled(true);
//jpeg 模式
options.setCompressionFormat(Bitmap.CompressFormat.JPEG);
/*底部控制栏颜色*/
options.setRootViewBackgroundColor(ContextCompat.getColor(this, R.color.black));
UCrop.of(sourceUri, mCutUri).withOptions(options).start(this);
系统裁剪
String time = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA).format(new Date());
Intent intent = new Intent("com.android.camera.action.CROP"); //打开系统自带的裁剪图片的intent
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
// 注意一定要添加该项权限,否则会提示无法裁剪
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.putExtra("scale", true);
// 设置裁剪区域的宽高比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// 设置裁剪区域的宽度和高度
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
// 取消人脸识别
intent.putExtra("noFaceDetection", false);
// 图片输出格式
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 若为false则表示不返回数据
intent.putExtra("return-data", false);
// 指定裁剪完成以后的图片所保存的位置,pic info显示有延时
fileName = "photo_" + time;
File mCutFile = new File(SDCardUtils.Companion.getInnerSDCardPath() + File.separator + Constants.BASE
+ File.separator + Constants.IMAGE_TAKEPHOTECROP_PATH, fileName + ".jpeg");
if (!mCutFile.getParentFile().exists()) {
mCutFile.getParentFile().mkdirs();
}
uploadFile = mCutFile;
mCutUri = Uri.fromFile(mCutFile);
uploadName = fileName + ".jpeg";
intent.putExtra(MediaStore.EXTRA_OUTPUT, mCutUri);
Toast.makeText(this, R.string.corp_pic, Toast.LENGTH_SHORT).show();
// 以广播方式刷新系统相册,以便能够在相册中找到刚刚所拍摄和裁剪的照片
Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intentBc.setData(uri);
this.sendBroadcast(intentBc);
startActivityForResult(intent, REQUEST_CROP); //设置裁剪参数显示图片至ImageVie
Android 7
<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>
file_paths
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!--SD卡-->
<external-path name="xx_images" path="."/>
<external-path name="xx_videos" path="."/>
<external-path name="images" path="."/>
<!--Android 11 不支持 SD卡的任何读写 只能在Data/包名下读写 -->
<external-files-path name="n_xx_images" path="." />
<external-files-path name="n_xx_videos" path="." />
<external-files-path name="n_images" path="."/>
</paths>
说明
该配置也仅仅适合Android7,到了Android 11不适用
<files-path>:内部存储空间应用私有目录下的 files/ 目录,等同于 Context.getFilesDir() 所获取的目录路径;
<cache-path>:内部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getCacheDir() 所获取的目录路径;
<external-path>:外部存储空间根目录,等同于 Environment.getExternalStorageDirectory() 所获取的目录路径;
<external-files-path>:外部存储空间应用私有目录下的 files/ 目录,等同于 Context.getExternalFilesDir(null) 所获取的目录路径;
<external-cache-path>:外部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getExternalCacheDir();
Android 10
android:requestLegacyExternalStorage="true"
参考链接:
《Android CameraX适配Android11的踩坑之路。》1
原文地址:https://blog.csdn.net/qq_20330595/article/details/122983161
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_39428.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。