Android使用RxPermissions动态申请权限

Android使用RxPermissions动态申请权限

一、目标

动态申请运行时权限。

1. 效果图

  • 左侧,告知用户权限的用途
  • 右侧,引导用户手动设置权限

2. 下载地址

神马笔记最新版本:【神马笔记 版本1.2.0.apk

二、功能设计

从Android 6.0(API 23)开始后,部分权限除了需要在AndroidManifest.xml中声明外,还必须在运行时动态申请,比如WRITE_EXTERNAL_STORAGE

因此,涉及到运行时权限相关API时,首先要确保用户授予了应用相应的权限,才能继续执行之后的操作。

三、准备工作

时间紧,任务重。

直接使用第三方开源库来解决这个问题。我们将使用RxPermissions来实现这个功能。

GitHub项目地址:https://github.com/tbruyelle/RxPermissions

四、组合起来

1. PermissionHelper

对RxPermissions做了简单封装,对应三种情况分别做了处理。

  • 已经授予权限,通过回调继续之后操作
  • 需要显示申请,弹出对话框告知用户,并再次请求权限
  • 用户拒绝授权,弹出对话框告知用户,并跳转到应用设置手动开启权限

目前仅支持一种权限,多权限申请可以在这基础上进行扩展。

并且整理了一些国内手机厂商如小米、魅族、华为直接进入权限设置的方式。

(小米测试可用,魅族、华为未进行测试。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
public class PermissionHelper {

String mPermission;

CharSequence mRequestMsg;
CharSequence mDeniedMsg;

FragmentActivity mContext;

OnPermissionListener mOnPermissionListener;

public PermissionHelper(FragmentActivity context) {
this.mContext = context;

this.mPermission = Manifest.permission.WRITE_EXTERNAL_STORAGE;

this.mRequestMsg = "";
this.mDeniedMsg = "";
}

public PermissionHelper setPermission(String permission) {
this.mPermission = permission;

return this;
}

public PermissionHelper setRequestMessage(CharSequence text) {
this.mRequestMsg = text;

return this;
}

public PermissionHelper setDeniedMessage(CharSequence text) {
this.mDeniedMsg = text;

return this;
}

public PermissionHelper setOnPermissionListener(OnPermissionListener listener) {
this.mOnPermissionListener = listener;

return this;
}

public void request() {
RxPermissions rxPermission = new RxPermissions(mContext);

rxPermission.requestEach(mPermission).subscribe(this::accept);
}

void accept(Permission permission) {

if (permission.granted) {

// 用户已经同意该权限
if (mOnPermissionListener != null) {
mOnPermissionListener.onPermissionGranted(this);
}

} else if (permission.shouldShowRequestPermissionRationale) {

// 用户拒绝了该权限,没有选中『不再询问』(Never ask again),那么下次再次启动时,还会提示请求权限的对话框

DialogInterface.OnClickListener listener = (dialog, which) -> {

if (which == DialogInterface.BUTTON_POSITIVE) {
request();
} else if (which == DialogInterface.BUTTON_NEGATIVE) {

}

};

AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage(mRequestMsg);
builder.setPositiveButton(android.R.string.yes, listener);
builder.setNegativeButton(android.R.string.cancel, listener);

AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();

} else { // 用户拒绝了该权限,并且选中『不再询问』

DialogInterface.OnClickListener listener = (dialog, which) -> {

if (which == DialogInterface.BUTTON_POSITIVE) {
showSetting(mContext);
} else if (which == DialogInterface.BUTTON_NEGATIVE) {

}

};

AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage(mDeniedMsg);
builder.setPositiveButton(android.R.string.yes, listener);
builder.setNegativeButton(android.R.string.cancel, listener);
AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
}

static void showSetting(Context context) {

if (gotoMiuiPermission(context)) {
return;
}

if (gotoMeizuPermission(context)) {
return;
}

if (gotoHuaweiPermission(context)) {
return;
}

if (gotoAppDetailSetting(context)) {
return;
}
}

static boolean gotoMiuiPermission(Context context) {

// MIUI 8

try {

Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", context.getPackageName());
context.startActivity(localIntent);

return true;

} catch (Exception e) {


}

// MIUI 5/6/7

try {

Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", context.getPackageName());
context.startActivity(localIntent);

return true;

} catch (Exception e1) {

}

return false;
}

static boolean gotoMeizuPermission(Context context) {

try {

Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
context.startActivity(intent);

return true;

} catch (Exception e) {
e.printStackTrace();
}

return false;
}

static boolean gotoHuaweiPermission(Context context) {

try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");//华为权限管理
intent.setComponent(comp);
context.startActivity(intent);

return true;

} catch (Exception e) {
e.printStackTrace();

}

return false;
}

static boolean gotoAppDetailSetting(Context context) {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", context.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
}

try {
context.startActivity(localIntent);
return true;
} catch (Exception e) {
e.printStackTrace();
}

return false;
}

/**
*
*/
public interface OnPermissionListener {

void onPermissionGranted(PermissionHelper helper);
}
}

五、Final

RxPermissions工作良好,没有机会探究Android运行时权限的相关代码。

~幸甚至哉~幸甚至哉~