安卓7.0打开相机(权限与内容提供器)

本文在笔者工作半年并详细接触了安卓文件系统后进行了更改
本文大部分来自第二行代码,只是部分权限问题改动与说明

其中主要问题就是安卓6.0权限问题和7.0url问题
  1. 首先需要设置权限
    `
    ` 这是使用照相机和可以修改内存的权限 然后具体代码申请权限:
if((ContextCompat.checkSelfPermission(getActivity().getBaseContex(),Manifest.permission.CAMERA)!=PackageManager.PERMISSION_GRANTED)||ContextCompat.checkSelfPermission(getActivity().getBaseContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) !=PackageManager.PERMISSION_GRANTED)) {
  //String数组中为申请的权限,第一个是相机,第二个为修改内存,最后的参数即为申请授权的返回值,我设置的1311
  //如果没有授权,则请求授权
       ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1311);
 }else{
//进行你想要的操作,比如拍照
}
   
//处理权限获取情况
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {  
               case 1311:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                    zhaoxiang();
                } else {
                    Toast.makeText(getContext(),"没有权限打开相机",Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }`

由于本文主要是拍照的模板,对权限的处理不做继续分析,如果你重点不在这,可以直接打开app的权限设置页基于权限。

2.然后是关于file的uri
安卓7.0要求,禁止暴露file的uri,否则会报错FileUriExposeException错误,必须使用fileProvider把uri封装再传给外部。

tips:这里讲解一下原因,如果你直接分享文件路径出去,会导致其他app直接获取你的文件,然后可能会导致隐私泄露,那你可能会问,其他app直接遍历我的文件呢,这就是谷歌一步步布局了,他在安卓10设置应用的私有目录不可被其他app读取。

配置如下
① 设置在<manifest>里设置

<application
    ```你的其他代码
	<provider   
	 android:name="android.support.v4.content.FileProvider"  
	  android:authorities="com.example.mbmob.fileprovider"
	 <!--此处的authorities可以设置任意值,但是不同应用间必须不同,否则会因为数据库重复无法安装,设置成应用id+fileprovider
	最好 -->
	  android:exported="false"
	 <!--必须为false ,意思是不可被分享,这是fileprovide要求-->
	   android:grantUriPermissions="true">
	  <meta-data         
	      android:name="android.support.FILE_PROVIDER_PATHS"
	     android:resource="@xml/file_paths" />
	     <!--meta指定uri的共享路径,并且引用了一个叫@xml/file_paths资源-->
	</provider>
</application>  

②接下来在右击res,new————directory,创建xml目录,然后生成file_paths,内容复制如下

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path  name ="my_images"  path=""/>
    <!--name名字任意,paths为空说明整个sd卡可共享(可能红色报错,不用管)-->
</paths>

然后你可能问,保密在哪了呢?? 你不是说要不泄露路径给别人吗,这就行了? 其实按照目前的写法是的,这也是大多数博客的写法,但是其实门道就出在上面的file_paths.xml文件里。fileprovider是如何做到不泄露路径的呢,就是通过xml文件进行路径置换。
具体置换方式:
root-path 对应DEVICE_ROOT,也就是File DEVICE_ROOT = new File("/"),即根目录,一般不需要配置。
files-path对应 content.getFileDir() 获取到的目录。
cache-path对应 content.getCacheDir() 获取到的目录
external-path对应 Environment.getExternalStorageDirectory() 指向的目录。
external-files-path对应 ContextCompat.getExternalFilesDirs() 获取到的目录。
external-cache-path对应 ContextCompat.getExternalCacheDirs() 获取到的目录

什么意思呢,就是说我们上面xml举例是设置了一个
<external-path name ="my_images" path="" />
那么会怎么样呢,external-path代表外部内存根目录,name代表要替换成的目录,path代表他可以替换的路径
所以 name可以替换的路径是 外部内存根目录+ “”(本例中我们的path设置的是空)
加入要分享的路径是 外部路径/a/b.jpg 那么转换后就会变成content://你的proivder名/a/b.jpg
如果你设置的xml文件中设置的path是“/a/s"
那么要分享的路径是 外部路径/a/s/q.pdf ,那么分享出去就是content://你的proivder名/q.pdf
这样就让别人搞不定到底在哪个目录了

3拍照的相关代码

public void zhaoxiang() {
        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);   
        headImage = new File(Environment.getExternalStorageDirectory() + "/mbmob/", year + "-" + month + "-" + day + i.getName() + "head.jpg");

        //创建一个file,第一个指数路径,第二个为图片名字  其中,路径为sd卡中一个名为mbmob的文件下,headImage是我提前声明的一个空file
        //如果不加/mbob/这句,就是获得手机里一个专门放置应用缓存的地方  get那个方法就是获取这个位置
        try {
            if (headImage.exists()) {
                headImage.delete();
            }
            headImage.createNewFile();
            //如果原来就有这个文件  删除
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (Build.VERSION.SDK_INT >= 24) {
            //判断安卓版本 高于7.0
            imageUri = FileProvider.getUriForFile(getActivity(), "com.example.mbmob.fileprovider", headImage);
            // 第一个是content ,第二个即为在provider里是设置的author那个,第三个是File对象
        } else {
            //低于7.0
            imageUri = Uri.fromFile(headImage);
            //获取图片路径
        }

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        //指定图片的输出地址
        startActivityForResult(intent, TAKE_PHOTO);
    }
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  //这部分代码要和权限获取的合并
        switch (requestCode) {
            case TAKE_PHOTO:
                //照相结束后就会返回,此时调用这个
                if (resultCode == RESULT_OK) {
                   //此时获得的headimage就是保存了图片的,这里如何利用看你情况
                }
                break;
            default:
                break;
        }

    }

奥里给

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值