zoukankan      html  css  js  c++  java
  • 7.0 FileProvide适配

    7.0 Build.VERSION_CODES.N 24

    为什么要适配

    在7.0中 ,Uri.from(file),可能会触发FileUriExposedException
    和动态权限一样,如果target选择24以下是不需要适配的,但还是应该尽早适配

    解决办法:在24及以上,使用content:// 替代 file:// (Uri.from(file))

    适配步骤

    1.在res下,新建一个xml目录,在其中创建一个任意名字的xml文件,如file_provider_paths.xml

    <?xml version="1.0" encoding="utf-8"?>
      <paths>
      <external-path
        name="external"
        path="." />
    </paths>

    xml说明

    external-path  等同于    Environment.getExternalStorageDirectory()
    如果将path设置为path=“pic”,则共享的文件限制为/storage/emulated/0/pic/
    为空,则共享文件目录为storage/emulated/0/
    
    <root-path/> 代表设备的根目录new File("/");
    <files-path/> 代表context.getFilesDir()
    <cache-path/> 代表context.getCacheDir()
    <external-path/> 代表Environment.getExternalStorageDirectory()
    <external-files-path>代表context.getExternalFilesDirs()
    <external-cache-path>代表context.getExternalCacheDirs()

    2.在Manifest文件中注册FileProvider对象

    <provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_provider_paths"/>
    </provider>

    3.修改java代码,场景拍照,裁剪,安装apk

     fp=context.getPackageName()+".fileprovider";

    3.1 拍照

    imgPath = FileUtil.generateImgePath();
        File imgFile = new File(imgPath);  //设置拍照后的图片的保存位置
        Log.i("TAG", imgFile.getAbsolutePath());
        Uri imgUri = null;
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //通过FileProvider创建一个content类型的Uri
            imgUri = FileProvider.getUriForFile(activity, fp, imgFile);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            imgUri = Uri.fromFile(imgFile);
        }
    
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
    
        final Uri uri = imgUri;
        activity.startActivityForResult(intent, new CallBackIntent() {
            @Override
            public void onResult(Intent data) {
                if (data == null || data.getData() == null)
                    //  ToastUtils.startShort(activity, "拍照数据返回为空");
                    Log.i("TAG", "拍照数据返回为空");
    
                startPhotoZoom(uri, activity, new IntentCallBack() {
                    @Override
                    public void onIntent(Intent intent) {
                        callBack.onBitmap(getImageView(intent));
                    }
                });
            }
        });

    imgPath,就是拍照后图片保存的路径

    3.2 裁剪

    //适配7.0的uri,(文件uri转化为ContentUri)
    public  Uri getImageContentUri(Context context, File imageFile) {
        String filePath = imageFile.getAbsolutePath();
        Cursor cursor = context.getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[] { MediaStore.Images.Media._ID },
                MediaStore.Images.Media.DATA + "=? ",
                new String[] { filePath }, null);
    
        if (cursor != null && cursor.moveToFirst()) {
            int id = cursor.getInt(cursor
                    .getColumnIndex(MediaStore.MediaColumns._ID));
            Uri baseUri = Uri.parse("content://media/external/images/media");
            return Uri.withAppendedPath(baseUri, "" + id);
        } else {
            if (imageFile.exists()) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, filePath);
                return context.getContentResolver().insert(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            } else {
                return null;
            }
        }
    }

    如果是由相机或者相册之后调用裁减,无需转化uri
    如果是单独使用裁减功能,则需要利用上述方法进行转化

    private void cropPicture(Uri uri) {
        Intent innerIntent = new Intent("com.android.camera.action.CROP");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        innerIntent.setDataAndType(uri, "image/*");
        innerIntent.putExtra("crop", "true");
    
        //不是1比1 主要是为了适配华为手机一比一时,裁减是圆形的
        innerIntent.putExtra("aspectX", 9998);
        innerIntent.putExtra("aspectY", 9999);
    
        innerIntent.putExtra("outputX", 320);
        innerIntent.putExtra("outputY", 320);
        innerIntent.putExtra("return-data", true);
        innerIntent.putExtra("scale", true);
    
        activity.startActivityForResult(intent, new CallBackIntent() {
            @Override
            public void onResult(Intent data) {
                callBack.onIntent(data);
                 //裁减后的图片
                //Bitmap bitmap = data.getParcelableExtra("data");
            }
        });
        
    }

    3.3 安装apk

    private void installAPK(UpdateInfo updateInfo) {
        File apkfile = new File(mSavePath, updateInfo.getClientVersionName());
        if (!apkfile.exists()) {
            return;
        }
        String cmd = "chmod 777 " + apkfile.toString();
        try {
            Runtime.getRuntime().exec(cmd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 通过Intent安装APK文件
        Intent i = new Intent(Intent.ACTION_VIEW);
        if (Build.VERSION.SDK_INT >= 24) { //适配安卓7.0
            i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri apkFileUri = FileProvider.getUriForFile(context.getApplicationContext(), fp, apkfile);
            i.setDataAndType(apkFileUri, "application/vnd.android.package-archive");
        } else {
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            i.setDataAndType(Uri.parse("file://" + apkfile.toString()),"application/vnd.android.package-archive");
        }
        context.startActivity(i);
        //关闭当前程序
        int pid = android.os.Process.myPid();
        android.os.Process.killProcess(pid);
    }
  • 相关阅读:
    mySQL教程 第1章 数据库设计
    数学符号大全
    C# 正则表达式 判断各种字符串(如手机号)
    C# 面向对象编程
    博客园 网址
    优化正则表达式的诀窍
    hdu 1596 floyd
    poj3259,简单判断有无负环,spfa
    hdu 1496 hash
    hdu 1429 bfs+二进制状态压缩
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/8459987.html
Copyright © 2011-2022 走看看