Skip to content

Commit 6d2b3fd

Browse files
committed
now code be more robust, support activitySelector
1 parent e8dea94 commit 6d2b3fd

10 files changed

Lines changed: 257 additions & 53 deletions

File tree

android-pluginmgr/src/main/java/androidx/pluginmgr/Globals.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package androidx.pluginmgr;
22

3-
import android.content.pm.ActivityInfo;
4-
53
/**
64
* 全局声明类
75
*
@@ -26,14 +24,5 @@ public class Globals {
2624
public static final String FLAG_ACTIVITY_FROM_PLUGIN = "flag_act_fp";
2725

2826

29-
/**
30-
* TODO:根据插件特征选择Activity
31-
*
32-
* @param activityInfo 插件ActivityInfo信息
33-
* @return 选择的Activity
34-
*/
35-
public static Class<?> selectDynamicActivity(ActivityInfo activityInfo) {
36-
return DynamicActivity.class;
37-
}
3827

3928
}

android-pluginmgr/src/main/java/androidx/pluginmgr/PluginManager.java

Lines changed: 122 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@
2525
import android.content.pm.ApplicationInfo;
2626
import android.content.res.AssetManager;
2727
import android.content.res.Resources;
28-
import android.os.Handler;
2928
import android.os.Looper;
30-
import android.util.Log;
3129

3230
import java.io.File;
3331
import java.io.FileFilter;
@@ -45,8 +43,11 @@
4543
import androidx.pluginmgr.environment.PluginClassLoader;
4644
import androidx.pluginmgr.environment.PluginContext;
4745
import androidx.pluginmgr.environment.PluginInstrumentation;
46+
import androidx.pluginmgr.selector.DefaultActivitySelector;
47+
import androidx.pluginmgr.selector.DynamicActivitySelector;
4848
import androidx.pluginmgr.utils.FileUtil;
4949
import androidx.pluginmgr.utils.PluginManifestUtil;
50+
import androidx.pluginmgr.utils.Trace;
5051
import androidx.pluginmgr.verify.PluginNotFoundException;
5152
import androidx.pluginmgr.verify.PluginOverdueVerifier;
5253
import androidx.pluginmgr.verify.SimpleLengthVerifier;
@@ -59,8 +60,6 @@
5960
*/
6061
public class PluginManager implements FileFilter {
6162

62-
private static final String TAG = PluginManager.class.getSimpleName();
63-
6463
/**
6564
* 插件管理器单例
6665
*/
@@ -94,9 +93,7 @@ public class PluginManager implements FileFilter {
9493
*/
9594
private PluginOverdueVerifier pluginOverdueVerifier = new SimpleLengthVerifier();
9695

97-
private PluginInstrumentation pluginInstrumentation;
98-
99-
private Handler uiHandler;
96+
private DynamicActivitySelector activitySelector = DefaultActivitySelector.getDefault();
10097

10198

10299
/**
@@ -113,13 +110,10 @@ private PluginManager(Context context) {
113110
dexOutputPath = optimizedDexPath.getAbsolutePath();
114111
dexInternalStoragePath = context
115112
.getDir(Globals.PRIVATE_PLUGIN_ODEX_OUTPUT_DIR_NAME, Context.MODE_PRIVATE);
116-
uiHandler = new Handler(Looper.getMainLooper());
117113
DelegateActivityThread delegateActivityThread = DelegateActivityThread.getSingleton();
118114
Instrumentation originInstrumentation = delegateActivityThread.getInstrumentation();
119-
if (originInstrumentation instanceof PluginInstrumentation) {
120-
pluginInstrumentation = (PluginInstrumentation) originInstrumentation;
121-
} else {
122-
pluginInstrumentation = new PluginInstrumentation(originInstrumentation);
115+
if (!(originInstrumentation instanceof PluginInstrumentation)) {
116+
PluginInstrumentation pluginInstrumentation = new PluginInstrumentation(originInstrumentation);
123117
delegateActivityThread.setInstrumentation(pluginInstrumentation);
124118
}
125119
}
@@ -150,10 +144,10 @@ private static void checkInit() {
150144
*/
151145
public static void init(Context context) {
152146
if (SINGLETON != null) {
153-
Log.w(TAG, "PluginManager have been initialized, YOU needn't initialize it again!");
147+
Trace.store("PluginManager have been initialized, YOU needn't initialize it again!");
154148
return;
155149
}
156-
Log.i(TAG, "init PluginManager...");
150+
Trace.store("init PluginManager...");
157151
SINGLETON = new PluginManager(context);
158152
}
159153

@@ -233,7 +227,7 @@ private PlugInfo removePlugByPkg(String pkg) {
233227
public Collection<PlugInfo> loadPlugin(final File pluginSrcDirFile)
234228
throws Exception {
235229
if (pluginSrcDirFile == null || !pluginSrcDirFile.exists()) {
236-
Log.e(TAG, "invalidate plugin file or Directory :"
230+
Trace.store("invalidate plugin file or Directory :"
237231
+ pluginSrcDirFile);
238232
return null;
239233
}
@@ -311,7 +305,7 @@ private PlugInfo buildPlugInfo(File pluginApk, String pluginId,
311305
Application app = makeApplication(pluginClassLoader, appClassName);
312306
attachBaseContext(info, app);
313307
info.setApplication(app);
314-
Log.i(TAG, "buildPlugInfo: " + info);
308+
Trace.store("Build pluginInfo => " + info);
315309
return info;
316310
}
317311

@@ -331,7 +325,7 @@ private void attachBaseContext(PlugInfo info, Application app) {
331325
*
332326
* @param pluginClassLoader 类加载器
333327
* @param appClassName 类名
334-
* @return
328+
* @return 插件App
335329
*/
336330
private Application makeApplication(PluginClassLoader pluginClassLoader, String appClassName) {
337331
if (appClassName != null) {
@@ -340,20 +334,25 @@ private Application makeApplication(PluginClassLoader pluginClassLoader, String
340334
} catch (Throwable ignored) {
341335
}
342336
}
343-
337+
//default application
344338
return new Application();
345339
}
346340

347341

348342
/**
349343
* 将Apk复制到私有目录
344+
* @see PluginOverdueVerifier
345+
* 可设置插件覆盖校检器来验证插件是否需要覆盖
350346
*
351347
* @param pluginApk 插件apk原始路径
352348
* @param targetPutApk 要拷贝到的目标位置
353349
*/
354350
private void copyApkToPrivatePath(File pluginApk, File targetPutApk) {
355-
if (targetPutApk.exists() && pluginOverdueVerifier != null && pluginOverdueVerifier.isOverdue(pluginApk, targetPutApk)) {
356-
return;
351+
if (pluginOverdueVerifier != null) {
352+
//仅当私有目录中插件已存在时需要检验
353+
if (targetPutApk.exists() && pluginOverdueVerifier.isOverdue(pluginApk, targetPutApk)) {
354+
return;
355+
}
357356
}
358357
FileUtil.copyFile(pluginApk, targetPutApk);
359358
}
@@ -412,44 +411,134 @@ public boolean accept(File pathname) {
412411
//=================启动插件相关方法=======================
413412
//======================================================
414413

415-
public void startMainActivity(Context from, PlugInfo plugInfo) {
414+
415+
/**
416+
* 启动插件的主Activity
417+
*
418+
* @param from fromContext
419+
* @param plugInfo 插件Info
420+
* @param intent 通过此Intent可以向插件传参, 可以为null
421+
*/
422+
public void startMainActivity(Context from, PlugInfo plugInfo, Intent intent) {
416423
if (!pluginPkgToInfoMap.containsKey(plugInfo.getPackageName())) {
417424
return;
418425
}
419426
ActivityInfo activityInfo = plugInfo.getMainActivity().activityInfo;
420427
if (activityInfo == null) {
421428
throw new ActivityNotFoundException("Cannot find Main Activity from plugin.");
422429
}
423-
String mainActivityName = plugInfo.getMainActivity().activityInfo.name;
424-
CreateActivityData createActivityData = new CreateActivityData(mainActivityName, plugInfo.getPackageName());
425-
Intent intent = new Intent(from, Globals.selectDynamicActivity(activityInfo));
426-
intent.putExtra(Globals.FLAG_ACTIVITY_FROM_PLUGIN, createActivityData);
427-
from.startActivity(intent);
430+
startActivity(from, plugInfo, activityInfo, intent);
431+
432+
}
433+
434+
/**
435+
* 启动插件的主Activity
436+
*
437+
* @param from fromContext
438+
* @param plugInfo 插件Info
439+
*/
440+
public void startMainActivity(Context from, PlugInfo plugInfo) {
441+
startMainActivity(from, plugInfo, null);
428442
}
429443

444+
/**
445+
* 启动插件的主Activity
446+
* @param from fromContext
447+
* @param pluginPkgName 插件包名
448+
* @throws PluginNotFoundException 该插件未加载时抛出
449+
* @throws ActivityNotFoundException 插件Activity信息找不到时抛出
450+
*/
430451
public void startMainActivity(Context from, String pluginPkgName) throws PluginNotFoundException, ActivityNotFoundException {
431452
PlugInfo plugInfo = tryGetPluginInfo(pluginPkgName);
432453
startMainActivity(from, plugInfo);
433454
}
434455

435-
public void startActivity(Context from, PlugInfo plugInfo, String targetActivity) {
436-
ActivityInfo activityInfo = plugInfo.findActivityByClassName(targetActivity);
456+
457+
/**
458+
* 启动插件的指定Activity
459+
*
460+
* @param from fromContext
461+
* @param plugInfo 插件信息
462+
* @param activityInfo 要启动的插件activity信息
463+
* @param intent 通过此Intent可以向插件传参, 可以为null
464+
*/
465+
public void startActivity(Context from, PlugInfo plugInfo, ActivityInfo activityInfo, Intent intent) {
437466
if (activityInfo == null) {
438-
throw new ActivityNotFoundException("Cannot find " + targetActivity + " from plugin, could you declare this Activity in plugin?");
467+
throw new ActivityNotFoundException("Cannot find ActivityInfo from plugin, could you declare this Activity in plugin?");
468+
}
469+
if (intent == null) {
470+
intent = new Intent();
439471
}
440-
CreateActivityData createActivityData = new CreateActivityData(targetActivity, plugInfo.getPackageName());
441-
Intent intent = new Intent(from, Globals.selectDynamicActivity(activityInfo));
472+
CreateActivityData createActivityData = new CreateActivityData(activityInfo.name, plugInfo.getPackageName());
473+
intent.setClass(from, activitySelector.selectDynamicActivity(activityInfo));
442474
intent.putExtra(Globals.FLAG_ACTIVITY_FROM_PLUGIN, createActivityData);
443475
from.startActivity(intent);
444476
}
445477

478+
479+
public DynamicActivitySelector getActivitySelector() {
480+
return activitySelector;
481+
}
482+
483+
public void setActivitySelector(DynamicActivitySelector activitySelector) {
484+
if (activitySelector == null) {
485+
activitySelector = DefaultActivitySelector.getDefault();
486+
}
487+
this.activitySelector = activitySelector;
488+
}
489+
490+
/**
491+
* 启动插件的指定Activity
492+
*
493+
* @param from fromContext
494+
* @param plugInfo 插件信息
495+
* @param targetActivity 要启动的插件activity类名
496+
* @param intent 通过此Intent可以向插件传参, 可以为null
497+
*/
498+
public void startActivity(Context from, PlugInfo plugInfo, String targetActivity, Intent intent) {
499+
ActivityInfo activityInfo = plugInfo.findActivityByClassName(targetActivity);
500+
startActivity(from, plugInfo, activityInfo, intent);
501+
}
502+
503+
/**
504+
* 启动插件的指定Activity
505+
*
506+
* @param from fromContext
507+
* @param plugInfo 插件信息
508+
* @param targetActivity 要启动的插件activity类名
509+
*/
510+
public void startActivity(Context from, PlugInfo plugInfo, String targetActivity) {
511+
startActivity(from, plugInfo, targetActivity, null);
512+
}
513+
514+
515+
/**
516+
* 启动插件的指定Activity
517+
*
518+
* @param from fromContext
519+
* @param pluginPkgName 插件包名
520+
* @param targetActivity 要启动的插件activity类名
521+
*/
446522
public void startActivity(Context from, String pluginPkgName, String targetActivity) throws PluginNotFoundException, ActivityNotFoundException {
523+
startActivity(from, pluginPkgName, targetActivity, null);
524+
}
525+
526+
/**
527+
* 启动插件的指定Activity
528+
*
529+
* @param from fromContext
530+
* @param pluginPkgName 插件包名
531+
* @param targetActivity 要启动的插件activity类名
532+
* @param intent 通过此Intent可以向插件传参, 可以为null
533+
*/
534+
public void startActivity(Context from, String pluginPkgName, String targetActivity, Intent intent) throws PluginNotFoundException, ActivityNotFoundException {
447535
PlugInfo plugInfo = tryGetPluginInfo(pluginPkgName);
448-
startActivity(from, plugInfo, targetActivity);
536+
startActivity(from, plugInfo, targetActivity, intent);
449537
}
450538

539+
451540
public void dump() {
452-
Log.d(TAG, pluginPkgToInfoMap.size() + " Plugins is loaded, " + Arrays.toString(pluginPkgToInfoMap.values().toArray()));
541+
Trace.store(pluginPkgToInfoMap.size() + " Plugins is loaded, " + Arrays.toString(pluginPkgToInfoMap.values().toArray()));
453542
}
454543

455544
/**

android-pluginmgr/src/main/java/androidx/pluginmgr/environment/PlugInfo.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package androidx.pluginmgr.environment;
1717

1818
import android.app.Application;
19+
import android.content.BroadcastReceiver;
1920
import android.content.pm.ActivityInfo;
2021
import android.content.pm.PackageInfo;
2122
import android.content.pm.ResolveInfo;
@@ -53,6 +54,7 @@ public class PlugInfo implements Serializable {
5354
private transient Application application;
5455
private transient AssetManager assetManager;
5556
private transient Resources resources;
57+
private transient boolean isApplicationOnCreated;
5658

5759
public String getPackageName() {
5860
return packageInfo.packageName;
@@ -286,6 +288,34 @@ public boolean equals(Object obj) {
286288
return true;
287289
}
288290

291+
public boolean isApplicationCreated() {
292+
return application != null && isApplicationOnCreated;
293+
}
294+
295+
public void ensureApplicationCreated() {
296+
if (application != null && !isApplicationOnCreated) {
297+
synchronized (this) {
298+
try {
299+
application.onCreate();
300+
if (receivers != null && receivers.size() > 0) {
301+
for (ResolveInfo resolveInfo : receivers) {
302+
if (resolveInfo.activityInfo != null) {
303+
try {
304+
BroadcastReceiver broadcastReceiver = (BroadcastReceiver) classLoader.loadClass(resolveInfo.activityInfo.name).newInstance();
305+
application.registerReceiver(broadcastReceiver, resolveInfo.filter);
306+
} catch (Throwable e) {
307+
e.printStackTrace();
308+
}
309+
}
310+
}
311+
}
312+
} catch (Throwable ignored) {
313+
}
314+
isApplicationOnCreated = true;
315+
}
316+
}
317+
}
318+
289319
@Override
290320
public String toString() {
291321
return super.toString() + "[ id=" + id + ", pkg=" + getPackageName()

android-pluginmgr/src/main/java/androidx/pluginmgr/environment/PluginContext.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ public Context getBaseContext() {
4646
}
4747

4848
private Context getBaseContextInner(Context baseContext) {
49-
if (baseContext instanceof ContextWrapper) {
50-
return getBaseContextInner(((ContextWrapper) baseContext).getBaseContext());
49+
Context realBaseContext = baseContext;
50+
while (realBaseContext instanceof ContextWrapper) {
51+
realBaseContext = ((ContextWrapper) realBaseContext).getBaseContext();
5152
}
52-
return baseContext;
53+
return realBaseContext;
5354
}
5455

5556

0 commit comments

Comments
 (0)