代码改变世界

Android——华为手机(G9)调用Camera需要手动申请权限

2017-01-13 16:44  It一zhai男  阅读(8093)  评论(0编辑  收藏  举报

1. 背景

Environment.getExternalStorageDirectory()是Android 2.x时代的产物,那时Android主流设备只有很小的内置存储器,然后都会外置一张sd卡,那时这个方法返回的就是外置sd卡的根路径。

但随着Android进入4.x时代,大部分Android设备都已经内置一个较大存储卡,甚至不提供外置存储卡插槽了,此时Environment.getExternalStorageDirectory()返回的路径其实是由内置存储卡虚拟出来的一个目录,用户在这一目录下有全部权限。

按理说Android应该继续提供其他的方法来返回其他的外置存储卡的路径,但这一次Android却没有,因为Android系统开发者们发现之前直接允许程序任意访问sd卡的做法导致sd卡上垃圾文件的不可管理性,尤其在程序被卸载后,由于不知道那些文件是由这一程序创建的,所以无法关联删除,因此Android 4.0并不给程序开发者提供外置存储卡的路径,而是提供了诸如getExternalFilesDirs()和getExternalCacheDirs()这样的方法,直接给开发者提供一个限制内的存储文件的空间,这个空间是与程序关联的,因此在卸载程序时这两个目录下的文件也会被关联删除。

 

2.问题一

在AndroidManifest里写入了相机权限,读写权限,但华为手机调用Camera失败,无法写入手机内存等。

原因:Android系统从6.0版本开始增加了一种运行时权限,Camera正好属于运行时权限,这种权限的授权不像6.0以前的Android系统可以安装APP的时候就一次性授权。所以需要在代码里手动申请权限。某些程序在华为G9上一测试就崩掉的原因:程序在运行中请求camera.open()时实际上程序并未获得操作Camera的权限,所以camera.open()会一直打开失败。对于运行时权限不清楚的可以百度搜索Android6.0运行时权限。

 

问题二

华为G9手机Environment.getExternalStorageDirectory()得到的是什么?

答:从手机上自带的文件管理器来看,上面有两个存储位置,一个是内部存储,是华为G9内置的SD卡;一个是SanDisk SD 卡,这个是自己买的然后安装上去的。那么,用Environment.getExternalStorageDirectory()得到的是哪个内存里的路径呢?该方法得到的是/storage/emulated/0是内部存储,也就是华为G9内置的SD卡,当然这是我经过测试后得到的,如下图所示。

 

问题三

使用ContextCompat和ActivityCompat报错

原因:因为这两个是sdk19以上版本v4包新加的,所以要导入V4包,最好是导入最新的版本,步骤file->project structure->dependencies->右边“+”号然后添加v4包即可。

 

 

代码部分就只写最主要的吧,最底下有源码地址

MainActivity.java

public class MainActivity extends Activity {
    public static final int TAKE_PHOTO = 1;
    public static final int CROP_PHOTO = 2;
    private static final String IMAGE_FILE_NAME = "head_image.jpg";// 头像文件
    private static final int CODE_CAMERA_REQUEST = 0xa1;//拍照请求码
    private static String[] PERMISSIONS_STORAGE = {
//            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,//写权限
            Manifest.permission.CAMERA//照相权限
    };
    private Button btn;
    private ImageView img;
    private Uri imageUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.take_photo);
        img = (ImageView) findViewById(R.id.picture);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //用intent调用相机
                Intent intentFromCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                //判断sd卡是否可用
                if (SDCardUtils.isSDCardEnable()){
                    //ContentValues与HashMap类似,但ContentValues只能保存数据类型,不能保存对象类型
                    ContentValues values = new ContentValues();
                    //key-value形式
                    values.put(MediaStore.Images.Media.TITLE,IMAGE_FILE_NAME);
                    //EXTRA_OUTPUT用于存储所请求的图像或视频的解析Uri
                    imageUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),IMAGE_FILE_NAME));
                    intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
                }
                //
                startActivityForResult(intentFromCapture,CODE_CAMERA_REQUEST);
            }
        });


        //用于判断SDK版本是否大于23
        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
            //检查权限
            int i = ContextCompat.checkSelfPermission(this,PERMISSIONS_STORAGE[0]);
            //如果权限申请失败,则重新申请权限
            if(i!= PackageManager.PERMISSION_GRANTED){
                //重新申请权限函数
                startRequestPermission();
                Log.e("这里","权限请求成功");
            }
        }
    }

    /**
     * 重新申请权限函数
     */
    private void startRequestPermission(){
        //321为请求码
        ActivityCompat.requestPermissions(this,PERMISSIONS_STORAGE,321);
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode==CODE_CAMERA_REQUEST&&resultCode==RESULT_OK){
            try {
                Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                img.setImageBitmap(bitmap);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

 源码地址:http://download.csdn.net/detail/u013293125/9737050