分享

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 &amp;&amp; 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

'name' 随便取,自己定义路径,'.'代表根目录

<?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


  1. Android CameraX适配Android11的踩坑之路。 ↩︎

原文地址:https://blog.csdn.net/qq_20330595/article/details/122983161

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_39428.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注