[关闭]
@natsumi 2017-01-13T02:36:52.000000Z 字数 2820 阅读 3369

Android M运行时权限【引出篇】

Android


关注到运行时权限这个问题是
《第一行代码》这本书中8.3.2节的示例程序在API23(Android 6.0)的模拟器上不能正常运行,MainActivity.java如下:

  1. package com.firstcode.choosepictest;
  2. import android.content.Intent;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.net.Uri;
  6. import android.os.Bundle;
  7. import android.os.Environment;
  8. import android.provider.MediaStore;
  9. import android.support.v7.app.AppCompatActivity;
  10. import android.view.View;
  11. import android.widget.Button;
  12. import android.widget.ImageView;
  13. import java.io.File;
  14. import java.io.FileNotFoundException;
  15. import java.io.IOException;
  16. public class MainActivity extends AppCompatActivity {
  17. public static final int TAKE_PHOTO = 1;
  18. public static final int CROP_PHOTO=2;
  19. private Button takePhoto;
  20. private ImageView picture;
  21. private Uri imageUri;
  22. @Override
  23. protected void onCreate(Bundle savedInstanceState) {
  24. super.onCreate(savedInstanceState);
  25. setContentView(R.layout.activity_main);
  26. takePhoto= (Button) findViewById(R.id.take_photo);
  27. picture= (ImageView) findViewById(R.id.picture);
  28. takePhoto.setOnClickListener(new View.OnClickListener() {
  29. @Override
  30. public void onClick(View v) {
  31. File outputImage=new File(Environment.getExternalStorageDirectory(),"tempImage.jpg");
  32. try{
  33. if(outputImage.exists()){
  34. outputImage.delete();
  35. }
  36. outputImage.createNewFile();
  37. }catch (IOException e){
  38. e.printStackTrace();
  39. }
  40. imageUri=Uri.fromFile(outputImage);
  41. Intent intent =new Intent("android.media.action.IMAGE_CAPTURE");
  42. intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
  43. startActivityForResult(intent,TAKE_PHOTO);
  44. }
  45. });
  46. }
  47. @Override
  48. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  49. super.onActivityResult(requestCode, resultCode, data);
  50. switch (requestCode){
  51. case TAKE_PHOTO:
  52. if (resultCode==RESULT_OK){
  53. Intent intent=new Intent("com.android.camera.action.CROP");
  54. intent.setDataAndType(imageUri,"image/*");//???
  55. intent.putExtra("scale", true);
  56. intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
  57. startActivityForResult(intent,CROP_PHOTO);
  58. }
  59. break;
  60. case CROP_PHOTO:
  61. if(resultCode==RESULT_OK){
  62. try{
  63. Bitmap bitmap= BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
  64. picture.setImageBitmap(bitmap);
  65. }catch (FileNotFoundException e){
  66. e.printStackTrace();
  67. }
  68. }
  69. break;
  70. default:
  71. break;
  72. }
  73. }
  74. }

运行时第71行出现错误

  1. W/System.err: java.io.FileNotFoundException: /storage/emulated/0/tempImage.jpg: open failed: EACCES (Permission denied)

也就是说拍完照片剪裁完之后,存储到了sd卡中,但是没有权限读取出来
在网上查了很多文章说是因为除了WRITE权限还要加另外两个权限
第1行:创建文件或者目录需要的权限
第2行:读取sd卡的权限
然而这并没有什么卵用= =

  1. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  2. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

还是把manifest中加的权限恢复到书中说的只有WRITE

真正的原因在这里,长按APP图标,拖到App info处,打开App info页面,其中的permission一栏是no permission granted
permission none
所以其实在Android M环境下我们在manifest中加了uses-permission也并没有真正让App拥有这个权限。

点击permission,并将里面的storage权限enable
此处输入图片的描述

返回后看到permission一栏有了Storage权限
此处输入图片的描述

此时再次运行App即可正常访问SD卡中的图片

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注