Android:权限申请、运行时权限、调用相册选择图片

危险权限申请流程

调用相册过程就涉及了对于危险权限读取存储的申请、隐式跳转到相册
一个极简的demo方便回顾这两个点:
github:https://github.com/Gong-Shijie/pickphotos.git

权限

由于Android对于应用需要的权限做了分类处理分为了危险权限和普通权限,对于普通权限的申请可以直接在AndroidManifest里面申请即可
但是对于一些涉及用户隐私和财产的权限被列为危险权限,如果需要使用这些危险权限,就必须在程序使用的时候进行授权,运行时权限申请。

危险权限
危险权限表

因此对于开发时候需要什么样的权限,如果是普通权限直接申请,如果是危险权限则走流程进行运行时权限。
判断是否授权和请求授权

//判断是否授权这里以一个权限为例
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//没有授权进行权限申请
      ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission. WRITE_EXTERNAL_STORAGE }, 1);      

用户授权结束活动后回调

 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openAlbum();
                } else {
                    Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }

隐式意图跳转

 private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, CHOOSE_PHOTO); // 打开相册
    }

活动结束后的回调得到图片的Uri

  @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode){
            case CHOOSE_PHOTO:
                if(resultCode == RESULT_OK){
                   //使用Glide来加载图片data.getData()得到图片的Uri
                    Glide.with(this).load(data.getData()).into(photo);
                }
        }
    }

隐式启动intent

隐式启动intent来跳转到相应的活动,根据action和category同时匹配要跳转的意图
这两个属性可以在AndroidManife.xml里面配置每个活动用来响应的action和category
一个Activity只有一个action但是可以有多个category
但是需要考虑intent并不智能比如启动相册:
需要采用隐式启动

Intent intent = new Intent("android.intent.action.GET_CONTENT");
       intent.setType("image/*");
       startActivityForResult(intent, CHOOSE_PHOTO); // 打开相册

意图指定action为获取相应的内容, 但是不知道要获取什么内容,只有通过setType指定为image这样这个意图才可以成功跳转到相册。
这里由于是采用了startActivityForResult函数启动意图,在跳转到相册执行了操作后,得到的数据就在onActivityResult里面处理返回的数据。


常见的action:

ACTION_MAIN 作为一个主要的进入口,而并不期望去接受数据
ACTION_VIEW 向用户去显示数据
ACTION_ATTACH_DATA 用于指定一些数据应该附属于一些其他的地方,例如,图片数据应该附属于联系人
ACTION_EDIT 访问已给的数据,提供明确的可编辑
ACTION_PICK 从数据中选择一个子项目,并返回你所选中的项目
ACTION_CHOOSER 显示一个activity选择器,允许用户在进程之前选择他们想要的
ACTION_GET_CONTENT 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音)
ACTION_DIAL 拨打一个指定的号码,显示一个带有号码的用户界面,允许用户去启动呼叫
ACTION_CALL 根据指定的数据执行一次呼叫
(ACTION_CALL在应用中启动一次呼叫有缺陷,多数应用ACTION_DIAL,ACTION_CALL不能用在紧急呼叫上,紧急呼叫可以用ACTION_DIAL来实现)
ACTION_SEND 传递数据,被传送的数据没有指定,接收的action请求用户发数据
ACTION_SENDTO 发送一跳信息到指定的某人
ACTION_ANSWER 处理一个打进电话呼叫
ACTION_INSERT 插入一条空项目到已给的容器
ACTION_DELETE 从容器中删除已给的数据
ACTION_RUN 运行数据,无论怎么
ACTION_SYNC 同步执行一个数据
ACTION_PICK_ACTIVITY 为已知的Intent选择一个Activity,返回别选中的类
ACTION_SEARCH 执行一次搜索
ACTION_WEB_SEARCH 执行一次web搜索


category:

CATEGORY_APP_BROWSER 和ACTION_MAIN一起使用,用来启动浏览器应用程序
CATEGORY_APP_CALCULATOR 和ACTION_MAIN一起使用,用来启动计算器应用程序
CATEGORY_APP_CALENDAR 和ACTION_MAIN一起使用,用来启动日历应用程序
CATEGORY_APP_CONTACTS 和ACTION_MAIN一起使用,用来启动联系人应用程序
CATEGORY_APP_EMAIL 和ACTION_MAIN一起使用,用来启动邮件应用程序
CATEGORY_APP_GALLERY 和ACTION_MAIN一起使用,用来启动图库应用程序
CATEGORY_APP_MAPS 和ACTION_MAIN一起使用,用来启动地图应用程序
CATEGORY_APP_MARKET 这个activity允许用户浏览和下载新的应用程序
CATEGORY_APP_MESSAGING ACTION_MAIN一起使用,用来启动短信应用程序
CATEGORY_APP_MUSIC 和ACTION_MAIN一起使用,用来启动音乐应用程序
CATEGORY_BROWSABLE 能够被浏览器安全调用的activity必须支持这个


主要代码以打开相册选择图片为例子:

权限组问题

虽然有权限组的存在但是申请一个组内的权限应该遵循将需要的权限都列出的习惯。

ActivityCompat.requestPermissions(MainActivity.this, new String[]
{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE},
 GET_STORAGE_PERMISSION);
}
通过返回的Uri显示图片

因为Android KitKat后对于Uri做了封装所以对于回调中的数据Uri的取出得到图片路径的逻辑有些复杂,我们不重复制造轮子取出图片的path用bitmap加载图片

使用Glide框架来加载图片
添加依赖

implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'

简单加载图片方法:

 //使用Glide来加载图片data.getData()得到图片的Uri
                    Glide.with(this).load(data.getData()).into(photo);             
MainActivity代码:
public class MainActivity extends AppCompatActivity {

    private static final int CHOOSE_PHOTO = 1;
    private static final int GET_STORAGE_PERMISSION = 2;
    private Button pick;
    private ImageView photo;
    private String imagepath = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        pick = findViewById(R.id.pick_btn);
        photo = findViewById(R.id.photo);


        pick.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    //没有授权进行权限申请
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, GET_STORAGE_PERMISSION);}
                else{
                    pickPhoto();
                }
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case GET_STORAGE_PERMISSION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    pickPhoto();
                } else {
                    Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode){
            case CHOOSE_PHOTO:
                if(resultCode == RESULT_OK){
                   //使用Glide来加载图片data.getData()得到图片的Uri
                    Glide.with(this).load(data.getData()).into(photo);
                }
        }
    }

    private void pickPhoto() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        startActivityForResult(intent, CHOOSE_PHOTO); // 打开相册
    }
}

总结:申请权限调用对应的应用核心流程在于对于几个回调函数的处理

参考:书籍:<<第一行代码>>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容