Android动态权限,EasyPermissions 介绍及使用

来源:互联网 发布:知乎评价奚梦瑶 编辑:程序博客网 时间:2024/06/05 00:39

转载请注明出处,谢谢:http://blog.csdn.net/harryweasley/article/details/72928860

Android M(6.0)以上是动态权限,google官方推出了一个开源项目EasyPermissions 来方便集成动态权限的功能。
本篇博客先翻译一下github的内容,然后给出一个例子,看看具体怎么使用EasyPermissions 。
EasyPermissions 的github地址是:https://github.com/googlesamples/easypermissions
附上DEMO源码下载地址:https://github.com/HarryWeasley/DynamicPermissionDemo

在Android M(6.0)或更高版本,EasyPermissions 是一个封装好的用来简化基本系统权限逻辑的库。

安装

EasyPermissions 通过在build.gradle写入下面的依赖,来进行安装。

dependencies {    compile 'pub.devrel:easypermissions:0.4.0'}

用法

基本用法

为了开始使用EasyPermissions,你需要在你的Activity (或者Fragment)中重写onRequestPermissionsResult 方法:

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    @Override    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        // Forward results to EasyPermissions        //将结果传入EasyPermissions中        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);    }}

请求权限

下面的例子展示了如何获取权限,通过一个方法获取CAMERA和ACCESS_FINE_LOCATION权限,有几个点需要注意:

  • 用EasyPermissions#hasPermissions(…)来检查是否这个应用已经获取到需要请求的权限,这个方法可以接收任意数量的权限作为它的最后一个参数。
  • 用EasyPermissions#requestPermissions来获取权限。该方法将会获取到系统权限,如果需要的话还可以展示提供的rationale字符串内容,requestCode应该是唯一的来标识请求权限,该方法如同hasPermissions,也可以接收任意数量的权限作为他的最后一个参数。
  • AfterPermissionGranted 注解的用处。它是可选的,是为了开发方便才提供的。如果所有的请求权限都已经被授权,任何一个通过正确的requestCode注解的方法都将执行。在所有权限都被授权后,通过注解描述的该方法,将会自动执行。当然,你也可以不用AfterPermissionGranted 注解,你可以将该方法放入onPermissionsGranted 这个回调方法里面来执行。
@AfterPermissionGranted(RC_CAMERA_AND_LOCATION)private void methodRequiresTwoPermission() {    String[] perms = {Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION};    if (EasyPermissions.hasPermissions(this, perms)) {        // Already have permission, do the thing        //如果已经获取权限,在这里做一些事情        // ...    } else {        // Do not have permissions, request them now        //如果没有获取到权限,在这里获取权限,其中RC_CAMERA_AND_LOCATION是自己定义的一个唯一标识int值        EasyPermissions.requestPermissions(this, getString(R.string.camera_and_location_rationale),                RC_CAMERA_AND_LOCATION, perms);    }}

当然,为了一个更好的控制,可以让Activity / Fragment实现PermissionCallbacks 接口,如下所示:

public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    @Override    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        // Forward results to EasyPermissions        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);    }    @Override    public void onPermissionsGranted(int requestCode, List<String> list) {        // Some permissions have been granted        // 请求权限已经被授权        // ...    }    @Override    public void onPermissionsDenied(int requestCode, List<String> list) {        // Some permissions have been denied        // 请求权限被拒绝        // ...    }}

必需权限

有一些案例,如果你的应用没有这些权限,有些功能将不能正常使用。如果用户点击了“不再询问”框,并且拒绝授权权限,你的应用将不能从用户那里获取到权限,除非用户去应用设置里更改状态。在这种情况下,你可以用EasyPermissions.somePermissionPermanentlyDenied(…)这个方法来判断,最终展示一个Dialog,指导用户去系统设置界面,为你的应用开启权限。

@Overridepublic void onPermissionsDenied(int requestCode, List<String> perms) {    Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());    // (Optional) Check whether the user denied any permissions and checked "NEVER ASK AGAIN."    // This will display a dialog directing them to enable the permission in app settings.    //(可选的)检查用户是否拒绝授权权限,并且点击了“不再询问”    //下面的语句,展示一个对话框指导用户在应用设置里授权权限    if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {        new AppSettingsDialog.Builder(this).build().show();    }}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) {        // Do something after user returned from app settings screen, like showing a Toast.        // 当用户从应用设置界面返回的时候,可以做一些事情,比如弹出一个土司。        Toast.makeText(this, R.string.returned_from_app_settings_to_activity, Toast.LENGTH_SHORT)                .show();    }}

普通实例

下面是EasyPermissions的通用动态获取权限的实现方法,文末有源码下载地址:

package demo.lgx.com.dynamicpermissiondemo;import android.Manifest;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.Toast;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.List;import pub.devrel.easypermissions.AfterPermissionGranted;import pub.devrel.easypermissions.AppSettingsDialog;import pub.devrel.easypermissions.EasyPermissions;/** * Created by Harry on 2017/6/8. */public class DynamicActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks{    ImageView imageView;    /**     * 随便赋值的一个唯一标识码     */    public static final int WRITE_EXTERNAL_STORAGE=100;    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if (msg.what == 1) {                Toast.makeText(DynamicActivity.this, "保存成功", Toast.LENGTH_LONG).show();            }        }    };    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_dynamit);        Button save = (Button) findViewById(R.id.save);        imageView = (ImageView) findViewById(R.id.image);        save.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                checkPerm();            }        });    }    /**     * 检查权限     */    @AfterPermissionGranted(WRITE_EXTERNAL_STORAGE)    private void checkPerm() {        String[] params={Manifest.permission.WRITE_EXTERNAL_STORAGE};        if(EasyPermissions.hasPermissions(this,params)){            saveImage();        }else{            EasyPermissions.requestPermissions(this,"需要读写本地权限",WRITE_EXTERNAL_STORAGE,params);        }    }    private void saveImage() {        //请忽略我这个子线程的优化问题,这里主要是为了实现动态权限的功能,哈哈!        new Thread(new Runnable() {            @Override            public void run() {                //获取到bitmap                BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();                Bitmap bitmap = drawable.getBitmap();                //创建文件夹保存图片                File file = DynamicActivity.this.getExternalFilesDir(null).getAbsoluteFile();                String imageName = "test.jpg";                File imageFile = new File(file, imageName);                FileOutputStream fos = null;                try {                    fos = new FileOutputStream(imageFile);                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);                    fos.flush();                } catch (FileNotFoundException e) {                    e.printStackTrace();                } catch (IOException e) {                    e.printStackTrace();                } finally {                    if (fos != null) {                        try {                            fos.close();                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                }                //保存成功后发送message                handler.sendEmptyMessage(1);            }        }).start();    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        EasyPermissions.onRequestPermissionsResult(requestCode,permissions,grantResults,this);    }    @Override    public void onPermissionsGranted(int requestCode, List<String> perms) {        //如果checkPerm方法,没有注解AfterPermissionGranted,也可以在这里调用该方法。    }    @Override    public void onPermissionsDenied(int requestCode, List<String> perms) {        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {           //这里需要重新设置Rationale和title,否则默认是英文格式            new AppSettingsDialog.Builder(this)                    .setRationale("没有该权限,此应用程序可能无法正常工作。打开应用设置屏幕以修改应用权限")                    .setTitle("必需权限")                    .build()                    .show();        }    }}

复杂实例

之前看过一些app的功能,如果用户拒绝该权限,那么该app将不允许用户使用,直接退出,下面这个例子来实现这样的一个功能。
如果用户拒绝权限授权,则app退出该页面,如下图所示:
这里写图片描述

package demo.lgx.com.dynamicpermissiondemo;import android.Manifest;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.Toast;import java.util.List;import pub.devrel.easypermissions.AfterPermissionGranted;import pub.devrel.easypermissions.AppSettingsDialog;import pub.devrel.easypermissions.EasyPermissions;/** * Created by Harry on 2017/6/8. */public class MustPermissionActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {    ImageView imageView;    /**     * 随便赋值的一个唯一标识码     */    public static final int WRITE_EXTERNAL_STORAGE = 100;    private boolean isFirst = false;    //权限参数    String[] params = {Manifest.permission.WRITE_EXTERNAL_STORAGE};    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if (msg.what == 1) {                Toast.makeText(MustPermissionActivity.this, "保存成功", Toast.LENGTH_LONG).show();            }        }    };    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.i("MustPermissionActivity", "onCreate执行");        setContentView(R.layout.activity_dynamit);        isFirst = true;        Button save = (Button) findViewById(R.id.save);        imageView = (ImageView) findViewById(R.id.image);        save.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                checkPerm();            }        });    }    @Override    protected void onResume() {        super.onResume();        if (isFirst) {            //因为要通过一个Fragment来弹出弹出框,所以activity这里的onResume执行了两次,这里进行判断            isFirst = false;            if (!EasyPermissions.hasPermissions(this, params)) {                EasyPermissions.requestPermissions(this, "需要读写本地权限", WRITE_EXTERNAL_STORAGE, params);            }        }    }    /**     * 检查权限     */    @AfterPermissionGranted(WRITE_EXTERNAL_STORAGE)    private void checkPerm() {        if (EasyPermissions.hasPermissions(this, params)) {            //已经获取到权限            Toast.makeText(MustPermissionActivity.this, "获取到权限,正常进入", Toast.LENGTH_LONG).show();        } else {            EasyPermissions.requestPermissions(this, "需要读写本地权限", WRITE_EXTERNAL_STORAGE, params);        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);    }    @Override    public void onPermissionsGranted(int requestCode, List<String> perms) {    }    @Override    public void onPermissionsDenied(int requestCode, List<String> perms) {        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {            //这个方法有个前提是,用户点击了“不再询问”后,才判断权限没有被获取到            new AppSettingsDialog.Builder(this)                    .setRationale("没有该权限,此应用程序可能无法正常工作。打开应用设置界面以修改应用权限")                    .setTitle("必需权限")                    .build()                    .show();        } else if (!EasyPermissions.hasPermissions(this, params)) {            //这里响应的是除了AppSettingsDialog这个弹出框,剩下的两个弹出框被拒绝或者取消的效果            finish();        }    }    @Override    public void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) {            if (!EasyPermissions.hasPermissions(this, params)) {                //这里响应的是AppSettingsDialog点击取消按钮的效果                finish();            }        }    }}

两点说明

1.一定要记得要先在AndroidManifest.xml声明权限。
2.例子中的Context.getExternalFilesDir()的绝对路径是SDCard/Android/data/应用包名/files/,在api<19的时候,需要写入权限,但是在api>=19后,就不需要写入权限,也可以写入数据了。本篇文章例子,是为了写easyPermissions的功能,所以不要在意Context.getExternalFilesDir()该路径。关于该权限官网链接是https://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String)

附上源码下载地址:https://github.com/HarryWeasley/DynamicPermissionDemo

阅读全文
0 0
原创粉丝点击