* This article has been published exclusively by guolin_blog, an official wechat account
- preface
- Scene reappearance
- Permissions4m profile
- Afterword.
- To apply for a job
preface
permissions4m
How to build an Android compile-time annotation framework
ActivityCompat.shouldShowRequestPermissionRationale(Activity, String)
no
permissions4m
Scene reappearance
Boss: “MMP, why doesn’t the display of contacts appear on xiaomi phones?” Boss, there is no problem with other phones. I applied for permission on this one, but Mi doesn’t pop up the permission application dialog box. Meanwhile, mi failed to authorize by default, so I can’t read the address book. Boss: “MMP, how about this one? Obviously said that the access to the calendar was successful, why still not read?” Boss, there is no problem with other phones. I applied for permission here, but Xiaomi doesn’t pop up the permission application dialog. At the same time, Xiaomi’s authorization succeeded by default, but actually it failed. Boss: “MMP, how about this one? Obviously I refused to grant permission, why did you prompt me to grant permission successfully?” Boss, all the other phones have no problem. For mine, I applied for permission. Xiaomi pops up the permission application dialog and you click “Reject” at the same time. Boss: “What are you doing? I bought you a test machine, but still so bad, pack up and fuck off.” Programmer: “F **k mi!”
Native Android request mode in Xiaomi and other domestic models on the adaptation of the situation, I believe that some readers have experienced, here will not do the native test, take out a more famous domestic permission application framework we have a look:
Xiaomi Application Location:
Xiaomi Application Contact:
Xiaomi Application status:
In fact, not only Xiaomi, other Chinese phones will have the same problem, I made a screenshot of oppo A57:
It can be seen that there is no popup window in the application process, and it indicates that the authorization is successful. In fact, when we go to the permission management interface, we can see that the permission is not obtained.
Here is the effect using Permissions4m:
Permissions4m Application location:
Permissions4m Application Contact:
Permissions4m Request phone status (Xiaomi) :
Permissions4m Applying for SMS and Calendar (OPPO A57)
We can see that the permission request dialog box pops up and that the permission was granted.
In our daily life, whether as developers or ordinary users, we should have come into contact with xiaomi/Meizu mobile phones 5.0+. Readers who have used these mobile phones should have some impression — some Chinese mobile phones had permission application before Android 6.0, that is, before Google launched dynamic permissions. Permissions4m 2.0.0 has solved this problem, which means that from version 2.0.0, Permissions4m now supports domestic mobile 5.0 permission applications.
Permissions4m profile
The introduction is only an excerpt of the content, for more details, please go to the project: github.com/jokermonn/p… .
Note: As of this blog post, the latest version of Permissions4m is 2.0.0
Introduction of depend on
Gradle rely on
Build. gradle in project:
buildscript { // ... } allProjects {repositories {// Please add the following line maven {url'https://jitpack.io'}}}Copy the code
Build. gradle in app:
dependencies {
compile 'com. Making. Jokermonn: permissions4m: 2.0.0 - lib'
annotationProcessor 'com. Making. Jokermonn: permissions4m: 2.0.0 - processor'
}Copy the code
Note the callback
Called where permission requests are required
Permissions4m.get (mainactivity. this) // Whether to force the pop-up permission application dialog boxtrue
.requestForce(true) / / permissions. RequestPermission (Manifest) permission) RECORD_AUDIO) / / access code. The requestCode (AUDIO_CODE) / / if you need to use @permissionNonrationale Comments, Suggest to add the following line / / return the intent is to jump to the system Settings page * * * * / /. RequestPageType (Permissions4M. PageType. MANAGER_PAGE) / / return intent Is to jump to the stewards mobile page * * * * / /. RequestPageType (Permissions4M. PageType. ANDROID_SETTING_PAGE). The request ();Copy the code
Such as:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Permissions4M.get(MainActivity.this)
.requestForce(true) .requestPageType(Permissions4M.PageType.MANAGER_PAGE) .requestPermission(Manifest.permission.RECORD_AUDIO) .requestCode(AUDIO_CODE) .request(); }});Copy the code
The corresponding callback will then be called @ PermissionsGranted, @ PermissionsDenied, @ PermissionsRationale/PermissionsCustomRationale, @ PermissionsNonRationale the modification method
@PermissionsGranted
Call back when authorization succeeds. Annotations need to be passed in parameters. There are two cases:
-
Single argument: @permissionsgranted (LOCATION_CODE). The modified function does not need to pass arguments, for example:
@PermissionsGranted(LOCATION_CODE) public void granted() { ToastUtil.show("Geo-location authorization successful"); }Copy the code
-
@permissionsgranted ({LOCATION_CODE, SENSORS_CODE, CALENDAR_CODE}), the modified function needs to pass in an int parameter, for example:
@PermissionsGranted({LOCATION_CODE, SENSORS_CODE, CALENDAR_CODE}) public void granted(int code) { switch (code) { case LOCATION_CODE: ToastUtil.show("Geo-location permission granted successfully"); break; case SENSORS_CODE: ToastUtil.show("Sensor permission authorized successfully."); break; case CALENDAR_CODE: ToastUtil.show("Read calendar permission authorized successfully"); break; default: break; }}Copy the code
@PermissionsDenied
Callback when authorization fails, annotations need to be passed in parameters, divided into two cases:
-
Single argument: @permissionsdenied (LOCATION_CODE). The modified function does not need to pass in arguments, for example:
@PermissionsDenied(LOCATION_CODE)
public void denied() {}Copy the code
-
@permissionsdenied ({LOCATION_CODE, SENSORS_CODE, CALENDAR_CODE});
@PermissionsDenied({LOCATION_CODE, SENSORS_CODE, CALENDAR_CODE}) public void denied(int code) { switch (code) { case LOCATION_CODE: ToastUtil.show("Geo-location permission authorization failed"); break; case SENSORS_CODE: ToastUtil.show("Sensor permission authorization failed"); break; case CALENDAR_CODE: ToastUtil.show("Read calendar permission authorization failed"); break; default: break; }}Copy the code
@PermissionsRationale
This is used to explain why this permission is needed. The annotations need to be passed in parameters. There are two cases:
-
Single argument: @permissionsrationale (LOCATION_CODE). The modified function does not need to pass in arguments, for example:
@PermissionsRationale(LOCATION_CODE) public void rationale() { ToastUtil.show("Please enable geolocation access."); }Copy the code
-
@permissionSrationale ({LOCATION_CODE, SENSORS_CODE, CALENDAR_CODE}), the modified function needs to pass in an int parameter, for example:
@PermissionsRationale({LOCATION_CODE, SENSORS_CODE, CALENDAR_CODE}) public void rationale(int code) { switch (code) { case LOCATION_CODE: ToastUtil.show("Please enable geolocation permissions."); break; case SENSORS_CODE: ToastUtil.show("Please enable sensor permissions."); break; case CALENDAR_CODE: ToastUtil.show("Please enable calendar reading permission authorization"); break; default: break; }Copy the code
Note: The system pop-up permission request dialog and toast prompt are asynchronous operations, so if you want to pop up a dialog by yourself (or other synchronization requirements) and then pop up the system dialog, please use@PermissionsCustomRationale
@PermissionsCustomRationale
This is used to explain why this permission is needed. The annotations need to be passed in parameters. There are two cases:
- Single parameter:
@PermissionsCustomRationale(LOCATION_CODE)
, the modified function does not need to pass in parameters, for example:
@PermissionsCustomRationale(LOCATION_CODE)
public void cusRationale() {
new AlertDialog.Builder(this)
.setMessage("Request for Geolocation permissions: \n We need you to enable in activity with annotation")
.setPositiveButton("Sure", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {permissions4m.get (mainactivity.this) // Note adding.requestonrationale ().requestonrationale () .requestPermission(Manifest.permission.READ_SMS) .requestCode(SMS_CODE) .request(); } }) .show(); }Copy the code
- Many parameters:
@PermissionsCustomRationale({LOCATION_CODE, SENSORS_CODE, CALENDAR_CODE})
, the modified function needs to pass in an int. For example:
@PermissionsCustomRationale({SMS_CODE, AUDIO_CODE})
public void cusRationale(int code) {
switch (code) {
case SMS_CODE:
new AlertDialog.Builder(this)
.setMessage("SMS Permission Application: \n We need you to enable SMS permission (in activity with annotation)")
.setPositiveButton("Sure", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {permissions4m.get (mainactivity.this) // Note adding.requestonrationale ().requestonrationale () .requestPermission(Manifest.permission.READ_SMS) .requestCode(SMS_CODE) .request(); } }) .show();break;
case AUDIO_CODE:
new AlertDialog.Builder(this)
.setMessage("Recording Permission Request: \n We need you to enable recording permissions (in activity with annotation)")
.setPositiveButton("Sure", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {permissions4m.get (mainactivity.this) // Note adding.requestonrationale ().requestonrationale () .requestPermission(Manifest.permission.RECORD_AUDIO) .requestCode(AUDIO_CODE) .request(); } }) .show();break;
default:
break;
}Copy the code
Note: Dialog developers can customize other presentation effects, please use them when calling the privilege request, otherwise you will fall into a loop with unlimited calls to the self-defined Rationale:
Permissions4m.get (mainactivity.this) // Be sure to add the following line. RequestOnRationale () .requestPermission(Manifest.permission.RECORD_AUDIO) .requestCode(AUDIO_CODE) .request();Copy the code
@PermissionsNonRationale
When users click on refused permission and no longer prompt (domestic deformity permissions adapter extension) is used, this means that either @ PermissionsCustomRationale or @ PermissionsRationale will not be invoked, unable to give the user, When the function modified by the annotation is called, the annotation needs to pass in parameters. There are two cases:
-
Single parameter: @permissionsnonrationale (LOCATION_CODE). The function to be modified only needs to pass in an Intent parameter.
@PermissionsNonRationale({LOCATION_CODE}) public void nonRationale(Intent intent) { startActivity(intent); }Copy the code
-
Multiple parameters: @permissionsnonrationale (AUDIO_CODE, CALL_LOG_CODE). The modified function requires an int parameter and an Intent parameter. For example:
@PermissionsNonRationale({AUDIO_CODE, CALL_LOG_CODE}) public void nonRationale(int code, final Intent intent) { switch (code) { case AUDIO_CODE: new AlertDialog.Builder(MainActivity.this) .setMessage("Recording access Request: \n We need you to enable recording access") .setPositiveButton("Sure", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startActivity(intent); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }) .show(); break; case CALL_LOG_CODE: new AlertDialog.Builder(MainActivity.this) .setMessage("Call Record Access Permission Application: \n We need you to enable call record access permission") .setPositiveButton("Sure", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startActivity(intent); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }) .show(); break; default: break; }}Copy the code
The Intent is of two types: one is to jump to the system setting page, and the other is to jump to the mobile phone manager page. For details about how to set the Intent, see.requestPageType(int) in the annotation callback.
The Listener callback
Ex. :
Permissions4m.get (mainactivity.this) // Whether to force the pop-up permission request dialog box. RequestForce (trueRequestPermission (manifest.permission.read_contacts) // Permission code.requestcode (READ_CONTACTS_CODE) // Permission request result .requestCallback(new Wrapper.PermissionRequestListener() {
@Override
public void permissionGranted() {
ToastUtil.show("Read address book permission successfully in activity with listener");
}
@Override
public void permissionDenied() {
ToastUtil.show("Failed to access address book in activity with listener");
}
@Override
public void permissionRationale() {
ToastUtil.show("Enable access to address book in activity with listener"); }}) / / authority completely banned in the callback function returns intent type (mobile housekeeper interface) requestPageType (Permissions4M. PageType. MANAGER_PAGE) / / permissions completely banned in the callback function returns the intent Type (system Settings interface) / /. RequestPageType (Permissions4M. PageType. ANDROID_SETTING_PAGE) / / authority completely banned callback, The Intent parameter in the interface function is determined by the previous line. RequestPage (new Wrapper).PermissionPageListener() {
@Override
public void pageIntent(final Intent intent) {
new AlertDialog.Builder(MainActivity.this)
.setMessage("Address book access permission request: \n We need you in activity with Listener")
.setPositiveButton("Sure", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(intent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
})
.show();
}
})
.request();Copy the code
Synchronous application
-
Decorate an Activity or Fragment with @permissionsrequestSync
-
Pass in two sets of parameters
- Value array: request code
- Permission array: Request permission
-
Using Permissions4M. Get (MainActivity. This). RequestSync (); Apply for the synchronization permission
Example: Refer to the Settings on MainActivity in Sample
@PermissionsRequestSync(
permission = {Manifest.permission.BODY_SENSORS,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_CALENDAR},
value = {SENSORS_CODE,
LOCATION_CODE,
CALENDAR_CODE})
public class MainActivity extends AppCompatActivityCopy the code
Afterword.
permissions4m