当前位置:   article > 正文

Android动态部署六:如何从插件apk中启动BroadcastReceiver和ContentProvider_android 如何根据contentprovider和instrumentation实现自启动

android 如何根据contentprovider和instrumentation实现自启动

转载请注明出处:http://blog.csdn.net/ximsfei/article/details/51083464

github地址:https://github.com/ximsfei/DynamicDeploymentApk

实现Android动态部署的过程中最重要的是从插件apk中启动四大组件,经过前面几篇文章的分析,现在只剩下BroadcastReceiver和ContentProvider了,BroadcastReceiver是可以通过java代码动态注册的,可想而知,偷懒一点的办法就是在解析完AndroidManifest.xml文件后手动注册一下就好了,这篇文章中会详细分析一下ContentProvider的安装流程以及调用getContentResolver方法后的获取ContentProvider的流程。

动态注册BroadcastReceiver

在解析完AndroidManifest.xml之后可以调用如下代码动态注册:

private void registerStaticBroadcastReceiver(DynamicApkInfo info) {
    int N = info.receivers.size();
    for (int i = 0; i < N; i++) {
   
        int M = info.receivers.get(i).intents.size();
        for (int j = 0; j < M; j++) {
   
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(info.receivers.get(i).intents.get(j).getAction(0));
            try {
                mApplicationContext.registerReceiver((BroadcastReceiver) info.classLoader
                        .loadClass(info.receivers.get(i).info.name).newInstance(), intentFilter);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

注:在实际项目中应用的时候,要注意,在整个应用生命周期中,不要多次调用该方法。

ContentProvider使用

Uri uri = Uri.parse("content://dynamic/content/1");
getContentResolver().query(uri, null, null, null, null);
  • 1
  • 2
<provider
    android:name=".PluginContentProvider"
    android:authorities="dynamic"
    android:enabled="true"
    android:exported="true" >
</provider>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

相信大部分的读者都知道,在Android中通过上面简单的两行代码就可以调用注册在manifest文件中的PluginContentProvider的query方法,接下来我们先分析一下,调用getContentResolver().query()方法之后,源码的执行流程,下图就是调用该方法后的时序图:
这里写图片描述
首先会从ContextImpl中获取ContextImpl$ApplicationContentResolver对象, 该类继承自ContentResolver,并且在ContextImpl构造方法中创建:

private static final class ApplicationContentResolver extends ContentResolver {
   }

private ContextImpl(ContextImpl container, ActivityThread mainThread,
            LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
            Display display, Configuration overrideConfiguration, int createDisplayWithId) {
    ...
    mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在ContentResolver的query方法中会调用ContextImpl$ApplicationContentResolver类重写的acquireUnstableProvider方法,并且最终会调用ActivityThread中的acquireProvider方法:

@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
    return mMainThread.acquireProvider(c,
            ContentProvider.getAuthorityWithoutUserId(auth),
            resolveUserIdFromAuthority(auth), false);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

ActivityThread.java

public final IContentProvider acquireProvider(
        Context c, String auth, int userId, boolean stable) {
    final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);//如果在mProviderMap中存在,则返回
    if (provider != null) {
        return
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/874102
推荐阅读
相关标签
  

闽ICP备14008679号