分享
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
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
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 if (isGooglePhotosUri(uri)) {
uri.lastPathSegment
} else getDataColumn(context, uri, null, null)
} else if ("file".equals(uri.scheme, ignoreCase = true)) {
return uri.path
}
return ""
}
@JvmStatic
fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri.authority
}
@JvmStatic
fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri.authority
}
@JvmStatic
fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri.authority
}
@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)));
多文件分享
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)));
图片裁剪
图片存储路径
fun getInnerSDCardPath(Context context): String {
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;
if (Build.VERSION.SDK_INT >= 30) {
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);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_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());
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));
options.setToolbarWidgetColor(ContextCompat.getColor(this, R.color.white));
options.setFreeStyleCropEnabled(true);
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.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());
intent.putExtra("return-data", false);
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);
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
'name' 随便取,自己定义路径,'.'代表根目录
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="xx_images" path="."/>
<external-path name="xx_videos" path="."/>
<external-path name="images" path="."/>
<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的踩坑之路。》
|