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

转载请注明出处,谢谢: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,指导用户去系统设置界面,为你的应用开启权限。

@Override
public 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();
    }
}

@Override
public 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

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值