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
Android——华为手机(G9)调用Camera需要手动申请权限
原文:http://www.cnblogs.com/ityizhainan/p/6283328.html