Synchronize updates to permission series
There are more permissions library from shallow to deep first look at the simple appetizer
1, PermissionGen
PermissionGen
The library was committed 3 years ago. You can see how the library is used by looking at the readme of the library, which is easy to configure through chained calls
The core class diagram is as follows:
Encapsulate permissions related to core APIS in the framework, eliminate redundant functions, and users only care about functional functions.
One of the core points involved is the ability to call back directly to functions with permissions that failed or succeeded via annotations
When it succeeded in obtaining permission
@PermissionSuccess(requestCode = 100)
public void doSomething(){
Toast.makeText(this, "Contact permission is granted", Toast.LENGTH_SHORT).show();
}
Copy the code
When it failed in obtaining permission
@PermissionFail(requestCode = 100)
public void doFailSomething(){
Toast.makeText(this, "Contact permission is not granted", t.LENGTH_SHORT).show();
}
Copy the code
PermissionGen#requestPermissions(Object Object, int requestCode, String[] permissions) The function that finally calls the PermissionFail and PermissionSucess annotations through reflection
This eliminates redundant code and allows users to focus on business development
private static void requestPermissions(Object object, int requestCode, String[] permissions){ if(! Utils.isOverMarshmallow()) { doExecuteSuccess(object, requestCode); return; } List<String> deniedPermissions = Utils.findDeniedPermissions(getActivity(object), permissions); if(deniedPermissions.size() > 0){ if(object instanceof Activity){ ((Activity)object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode); } else if(object instanceof Fragment){ ((Fragment)object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode); } else { throw new IllegalArgumentException(object.getClass().getName() + " is not supported"); } } else { doExecuteSuccess(object, requestCode); } } private static void executeMethod(Object activity, Method executeMethod) { if(executeMethod ! = null){ try { if(! executeMethod.isAccessible()) executeMethod.setAccessible(true); executeMethod.invoke(activity, null); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }}}Copy the code
In the Utils method, you can learn how to use reflection, such as finding the corresponding annotation method
public static <A extends Annotation> Method findMethodWithRequestCode(Class clazz,
Class<A> annotation, int requestCode) {
for(Method method : clazz.getDeclaredMethods()){
if(method.isAnnotationPresent(annotation)){
if(isEqualRequestCodeFromAnntation(method, annotation, requestCode)){
return method;
}
}
}
return null;
}
Copy the code
Summary:
This library is relatively simple and has some advantages and disadvantages:
Advantages: preliminary encapsulation of the authority of the core function, eliminating redundant code; You can learn some uses of reflection
Disadvantages:
(1) Extensive use of reflection (apt can be used),
(2) THE API design is not very reasonable
Chain calls are usually horizontal calls to methods, but this one is obviously sequential and easy to write wrong
2, MPermissions
MPermissions
This is some optimization made by Hongyang on the basis of PermissionGen. According to the author, APT has solved the problem of runtime reflection and optimized the API provided to the outside world. Because application only needs three parameters, it has abandoned the singleton method of the original class library and directly has several static methods, which is simple, clean and violent.
I have a look at the code, mainly the core class MPermissions operates the interface, and indirectly operates the APT generation class that implements the interface (dependent flip, interface oriented programming).
Some things to learn:
2.1 APT failed to find classes before compiling
Interface oriented programming, APT code generation code implementation of this interface can be,
The core capabilities of a permission class are provided through an interface
public interface PermissionProxy<T> {
void grant(T source, int requestCode);
void denied(T source, int requestCode);
void rationale(T source, int requestCode);
boolean needShowRationale(int requestCode);
}
Copy the code
Function classes interact with the interface layer
2.2 APT technology
It is very useful to generate some duplicate template code with APT, which has been covered in previous blogs.
However, APT also has its disadvantages. The working principle of APT is to generate source code through Annotation when compiling class. However, in the process of Android construction, integration methods like Didi Chuxing Passenger terminal are integrated and constructed by AAR. There is no chance to compile all classes at the same time, so new methods of generating code are needed, such as building Gradle tasks that scan globally and generate javapoet code before compiling
In this library you can learn apt Processor exception handling to help us locate code
private void error(Element element, String message, Object... args) {
if (args.length > 0) {
message = String.format(message, args);
}
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message, element);
}
Copy the code
summary
The author only generates the template code through APT, but still uses reflection to generate the implementation class that implements the proxy interface
private static PermissionProxy findPermissionProxy(Object activity) {
try {
Class clazz = activity.getClass();
Class injectorClazz = Class.forName(clazz.getName() + SUFFIX);
return (PermissionProxy) injectorClazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
throw new RuntimeException(String.format("can not find %s , something when compiler.", activity.getClass().getSimpleName() + SUFFIX));
}
Copy the code
The idea of APT agent is worth learning from
3, PermissionsDispatcher
This library has 7726 starts, and has its own website instructions. It is like the first brother of the three libraries of dynamic permissions, so it needs to be analyzed
From the official use of this library is also very simple, a careful look at the code found similar to the previous two libraries use the way, through annotations to mark the permission application success, permission things failed, permission popup description and other function calls, the only more is:
Activity or Fragment(we support both) to handle Permissions
This library puts all the logical processing in the permission generation class xxxPermissionDispatcher (the generated code does a lot of the logical processing), rather than the MPermission library just putting the user-used function code, such as permission success and failure functions, into the generated class. The core logic is handled by the developer’s own code, which makes it easier to write the library and easier for users to read the code
Personally, I prefer MPermission