AppOps虽然涵盖了App的权限管理,但是Google原生的设计并不仅仅是对“权限”的管理,而是对App的“动作”的管理。我们平时讲的权限管理多是针对具体的权限(App开发者在Manifest里申请的权限),而AppOps所管理的是所有可能涉及用户隐私和安全的操作,包括access notification, keep weak lock, activate , display toast等等,有些操作是不需要Manifest里申请权限的。
使用Application中的ActivityLifecycleCallbacks,使用它的 registerActivityLifecycleCallbacks,感知Activity声明周期变化,获取到当前应用栈顶的Activity,这样我们就不需要自己手动传入了。
public class PermissionActivityLifecycle implements Application.ActivityLifecycleCallbacks {
WeakReference topActWeakReference;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
//原则上只需要onResume,兼容如果在onCreate的时候做权限申请保证此时有Activity对象
topActWeakReference = new WeakReference<>(activity);
}
//.....
@Override
public void onActivityResumed(Activity activity) {
topActWeakReference = new WeakReference<>(activity);
}
//.....
}
复制代码
注册它仅仅需要一个Application:
/**
* @param context Application
*/
private void registerLifecycle(Application context) {
if (null != lifecycle) {
context.unregisterActivityLifecycleCallbacks(lifecycle);
}
lifecycle = new PermissionActivityLifecycle();
context.registerActivityLifecycleCallbacks(lifecycle);
}
复制代码
这样一来,只要调用了初始化方法registerLifecycle,我们就能提供提供栈顶Activity了
/**
* 获取栈顶Activity
*
* @return 当前应用栈顶Activity
* @throws InitException 初始化失败
* @throws ContainerStatusException Activity状态异常
*/
private Activity getContainer() {
// may auto init failed
if (null == lifecycle || null == lifecycle.topActWeakReference) {
throw new InitException();
}
// activity status error
if (null == lifecycle.topActWeakReference.get() || lifecycle.topActWeakReference.get().isFinishing()) {
throw new ContainerStatusException();
}
return lifecycle.topActWeakReference.get();
}
复制代码
脱离Activity和Fragment,也无需重写onPermissionResult了,只需要一个ApplicationContext初始化即可。
参考Lifecycle组件的初始化:
//lifeCycle定义的初始化Provider
public class LifecycleRuntimeTrojanProvider extends ContentProvider {
@Override
public boolean onCreate() {
LifecycleDispatcher.init(getContext());
ProcessLifecycleOwner.init(getContext());
return true;
}
}
复制代码
和它的Manifest文件:
复制代码
参照它的实现给我们提供了一个很好的思路,我们可以自定义Provider去初始化一些库或者其他的内容,现在我们写一个自己的initContentProvider:
public class InitProvider extends ContentProvider {
@Override
public boolean onCreate() {
//初始化我们的库
SoulPermission.getInstance().autoInit((Application) getContext());
return true;
}
//......
}
复制代码
在库的AndroidManifest文件中声明:
复制代码
至于为什么这个Context就是Application,我们可以参考ActivityThread中的对ContentProvider的初始化:
public void handleInstallProvider(ProviderInfo info) {
//即我们的应用的Application
installContentProviders(mInitialApplication, Arrays.asList(info));
}
复制代码
至此,我们权限申请流程就跟Activity、Fragment、乃至Context都没有关系了
https://github.com/soulqw/SoulPermission