美文网首页
适配Android7.0 文件共享FileProvider-拍照

适配Android7.0 文件共享FileProvider-拍照

作者: 伊泽瑞额 | 来源:发表于2019-06-03 15:19 被阅读0次
    1.首先在项目res目录下新建xml目录,并新建file_paths.xml,这个文件主要用来配置应用共享文件的路径
    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <root-path
            name="root"
            path="" />
    
        <!--理路径相当于Context.getFilesDir() + /path/。-->
        <files-path
            name="files"
            path="path" />
    
        <!--物理路径相当于Context.getCacheDir() + /path/-->
        <cache-path
            name="cache"
            path="path" />
    
    
        <!--物理路径相当于Context.getExternalFilesDir(String) + /path/-->
        <external-files-path
            name="external_file_path"
            path="path" />
    
        <!--物理路径相当于Context.getExternalCacheDir() + /path/-->
        <external-cache-path
            name="external_cache_path"
            path="path" />
    
    
        <!--物理路径相当于Environment.getExternalStorageDirectory() + /path/-->
        <external-path
            name="external"
            path="path" />
    
    
    </paths>
    
    
    2. 在AndroidManifest.xml的application节点下增加FileProvider的声明
    <application>
            ...
            ...
    
              <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.example.amn.doprint.fileprovider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths" />
            </provider>    </application>
    
    

    ####### FileProvider工具类,参考自鸿洋大神博客

    package com.example.amn.doprint.utils;
    
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.content.pm.ResolveInfo;
    import android.net.Uri;
    import android.os.Build;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    
    public class FileProviderUtil {
    
        public static Uri getUriForFile(Context context, File file) {
            Uri fileUri = null;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                fileUri = getUriForFile24(context, file);
            } else {
                fileUri = Uri.fromFile(file);
            }
            return fileUri;
        }
    
    
    
        private static Uri getUriForFile24(Context context, File file) {
            Uri fileUri = android.support.v4.content.FileProvider.getUriForFile(context,
                    context.getPackageName() + ".fileprovider",
                    file);
            return fileUri;
        }
    
    
        public static void setIntentDataAndType(Context context,
                                                Intent intent,
                                                String type,
                                                File file,
                                                boolean writeAble) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setDataAndType(getUriForFile(context, file), type);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                if (writeAble) {
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
            } else {
                intent.setDataAndType(Uri.fromFile(file), type);
                chmod("777", file.getAbsolutePath());//apk放在cache文件中,需要获取读写权限
            }
        }
    
        public static   void chmod(String permission, String path) {
            try {
                String command = "chmod " + permission + " " + path;
                Runtime runtime = Runtime.getRuntime();
                runtime.exec(command);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        public static void setIntentData(Context context,
                                         Intent intent,
                                         File file,
                                         boolean writeAble) {
            if (Build.VERSION.SDK_INT >= 24) {
                intent.setData(getUriForFile(context, file));
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                if (writeAble) {
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
            } else {
                intent.setData(Uri.fromFile(file));
            }
        }
    
    
        public static void grantPermissions(Context context, Intent intent, Uri uri, boolean writeAble) {
    
            int flag = Intent.FLAG_GRANT_READ_URI_PERMISSION;
            if (writeAble) {
                flag |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
            }
            intent.addFlags(flag);
            List<ResolveInfo> resInfoList = context.getPackageManager()
                    .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
            for (ResolveInfo resolveInfo : resInfoList) {
                String packageName = resolveInfo.activityInfo.packageName;
                context.grantUriPermission(packageName, uri, flag);
            }
        }
    
    }
    
    package com.example.amn.doprint.utils;
    
    import android.annotation.SuppressLint;
    import android.content.ContentUris;
    import android.content.Context;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    import android.provider.DocumentsContract;
    import android.provider.MediaStore;
    
    public class FileUtil {
    
        /**
         * 根据URI获取文件真实路径(兼容多张机型)
         * @param context
         * @param uri
         * @return
         */
        public static String getFilePathByUri(Context context, Uri uri) {
            if ("content".equalsIgnoreCase(uri.getScheme())) {
    
                int sdkVersion = Build.VERSION.SDK_INT;
                if (sdkVersion >= 19) { // api >= 19
                    return getRealPathFromUriAboveApi19(context, uri);
                } else { // api < 19
                    return getRealPathFromUriBelowAPI19(context, uri);
                }
            } else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
            return null;
        }
    
        /**
         * 适配api19及以上,根据uri获取图片的绝对路径
         *
         * @param context 上下文对象
         * @param uri     图片的Uri
         * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
         */
        @SuppressLint("NewApi")
        private static String getRealPathFromUriAboveApi19(Context context, Uri uri) {
            String filePath = null;
            if (DocumentsContract.isDocumentUri(context, uri)) {
                // 如果是document类型的 uri, 则通过document id来进行处理
                String documentId = DocumentsContract.getDocumentId(uri);
                if (isMediaDocument(uri)) { // MediaProvider
                    // 使用':'分割
                    String type = documentId.split(":")[0];
                    String id = documentId.split(":")[1];
    
                    String selection = MediaStore.Images.Media._ID + "=?";
                    String[] selectionArgs = {id};
    
                    //
                    Uri contentUri = null;
                    if ("image".equals(type)) {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(type)) {
                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(type)) {
                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }
    
                    filePath = getDataColumn(context, contentUri, selection, selectionArgs);
                } else if (isDownloadsDocument(uri)) { // DownloadsProvider
                    Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));
                    filePath = getDataColumn(context, contentUri, null, null);
                }else if (isExternalStorageDocument(uri)) {
                    // ExternalStorageProvider
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
                    if ("primary".equalsIgnoreCase(type)) {
                        filePath = Environment.getExternalStorageDirectory() + "/" + split[1];
                    }
                }else {
                    //Log.e("路径错误");
                }
            } else if ("content".equalsIgnoreCase(uri.getScheme())) {
                // 如果是 content 类型的 Uri
                filePath = getDataColumn(context, uri, null, null);
            } else if ("file".equals(uri.getScheme())) {
                // 如果是 file 类型的 Uri,直接获取图片对应的路径
                filePath = uri.getPath();
            }
            return filePath;
        }
    
        /**
         * 适配api19以下(不包括api19),根据uri获取图片的绝对路径
         * @param context 上下文对象
         * @param uri     图片的Uri
         * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
         */
        private static String getRealPathFromUriBelowAPI19(Context context, Uri uri) {
            return getDataColumn(context, uri, null, null);
        }
    
        /**
         * 获取数据库表中的 _data 列,即返回Uri对应的文件路径
         *
         * @return
         */
        private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
            String path = null;
    
            String[] projection = new String[]{MediaStore.Images.Media.DATA};
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
                if (cursor != null && cursor.moveToFirst()) {
                    int columnIndex = cursor.getColumnIndexOrThrow(projection[0]);
                    path = cursor.getString(columnIndex);
                }
            } catch (Exception e) {
                if (cursor != null) {
                    cursor.close();
                }
            }
            return path;
        }
    
        /**
         * @param uri the Uri to check
         * @return Whether the Uri authority is MediaProvider
         */
        private static boolean isMediaDocument(Uri uri) {
            return "com.android.providers.media.documents".equals(uri.getAuthority());
        }
    
        private static boolean isExternalStorageDocument(Uri uri) {
            return "com.android.externalstorage.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri the Uri to check
         * @return Whether the Uri authority is DownloadsProvider
         */
        private static boolean isDownloadsDocument(Uri uri) {
            return "com.android.providers.downloads.documents".equals(uri.getAuthority());
        }
    }
    
    
    4.最后在传递URI的时候调用相应的方法获取URI即可,例如下面代码是调用摄像头拍照:

    1.拍照权限申请

      if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                //未授权,申请授权()
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, RC_TAKE_PHOTO);
            } else {
                //已授权,
    
                Intent intentToTakePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File fileDir = new File(Environment.getExternalStorageDirectory() + File.separator + "photoTest" + File.separator);
                if (!fileDir.exists()) {
                    fileDir.mkdirs();
                }
    
                File photoFile = new File(fileDir, "imge.jpeg");
                mTakePhotoPath= photoFile.getAbsolutePath();
                imageUri = FileProviderUtil.getUriForFile(this, photoFile);
                intentToTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(intentToTakePhoto, RC_TAKE_PHOTO);
            }
    
    1. 从相册获取照片权限
       private void printImge() {
    
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                //未授权,申请授权(从相册选择图片需要读取存储卡的权限)
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, RC_CHOOSE_PHOTO);
            } else {
                //已授权,获取照片
                Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
                intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                startActivityForResult(intentToPickPic, RC_CHOOSE_PHOTO);
            }
        }
    

    3.权限申请结果回调

    
     /**
         * 权限申请结果回调
         */
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            switch (requestCode) {
                case RC_CHOOSE_PHOTO:   //相册选择照片权限申请返回
                    Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
                    intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                    startActivityForResult(intentToPickPic, RC_CHOOSE_PHOTO);
                    break;
                case RC_TAKE_PHOTO://拍照权限申请返回
    
                    Intent intentToTakePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    File fileDir = new File(Environment.getExternalStorageDirectory() + File.separator + "path" + File.separator);
                    if (!fileDir.exists()) {
                        fileDir.mkdirs();
                    }
    
                    File photoFile = new File(fileDir, "imge.jpeg");
                    mTakePhotoPath= photoFile.getAbsolutePath();
                    imageUri = FileProviderUtil.getUriForFile(this, photoFile);
                    intentToTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                    startActivityForResult(intentToTakePhoto, RC_TAKE_PHOTO);
                    break;
    
            }
        }
    

    4.onActivityResult 拍照和从相册选择照片结果回调

    
      @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    
            if (requestCode == RC_CHOOSE_PHOTO) {
                //从相册选择
                if (data != null) {
                    //获取图片路径
                    Uri uri = data.getData();
                    String filePath = FileUtil.getFilePathByUri(this, uri);
                    if (!TextUtils.isEmpty(filePath)) {
    //                    Log.i("aaa",anImage.toString());
                        PrintManager.setPrint(new PrintImage(this, filePath));
                        PrintManager.getInstance().print(mConnectMac);
                    }
    
                }
            }else if(requestCode == RC_TAKE_PHOTO){
                Log.i("aaa","mTakePhotoPath>>>>>"+mTakePhotoPath);
            }
            super.onActivityResult(requestCode, resultCode, data);
        }
    

    相关文章

      网友评论

          本文标题:适配Android7.0 文件共享FileProvider-拍照

          本文链接:https://www.haomeiwen.com/subject/ssscxctx.html