Skip to content

Commit

Permalink
使用稳定版,2017年6月28号及之后的资源方案改动不能很好的适配android 7.0的插件动态加载(实时加载一个只含有Fragment…
Browse files Browse the repository at this point in the history
…/View的插件),所以回退到稳定版本。
  • Loading branch information
jimor1234567 committed Aug 16, 2017
1 parent 281404c commit bddb798
Show file tree
Hide file tree
Showing 17 changed files with 234 additions and 63 deletions.
1 change: 1 addition & 0 deletions ZeusPlugin/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/build
.idea/
80 changes: 33 additions & 47 deletions ZeusPlugin/src/main/java/zeus/plugin/PluginManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ public static boolean loadPlugin(String pluginId, int version) {
}
clearViewConstructorCache();
if ((meta.getFlag() & PluginManifest.FLAG_WITHOUT_RESOURCES) != PluginManifest.FLAG_WITHOUT_RESOURCES) {
reloadInstalledPluginResources(false);
reloadInstalledPluginResources();
}
}
return true;
Expand Down Expand Up @@ -530,56 +530,42 @@ static private void clearResoucesDrawableCache(Object resouces) {
/**
* 加载所有已安装的插件的资源,并清除资源中的缓存
*/
private static void reloadInstalledPluginResources(boolean isCalledInInit) {
private static void reloadInstalledPluginResources() {
try {
AssetManager assetManager = mBaseContext.getResources().getAssets().getClass().newInstance();
Method addAssetPath = PluginUtil.getMethod(assetManager.getClass(), "addAssetPath", String.class);
for (String assetpath : mOrgAssetPaths) {
addAssetPath.invoke(assetManager, assetpath);
}
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, mBaseContext.getPackageResourcePath());
if (mLoadedPluginList != null && mLoadedPluginList.size() != 0) {
//每个插件的packageID都不能一样
for (String id : mLoadedPluginList.keySet()) {
String pluginResPath = PluginUtil.getAPKPath(id, mLoadedDiffPluginPathinfoList.get(id));
addAssetPath.invoke(assetManager, pluginResPath);
}
}
Method ensureStringBlocksMethod = PluginUtil.getMethod(assetManager.getClass(), "ensureStringBlocks");
ensureStringBlocksMethod.invoke(assetManager);
Map resouresMap;
Object mResourcesManager = PluginUtil.getField(mBaseContext, "mResourcesManager");
if (mResourcesManager != null) {
resouresMap = (Map) PluginUtil.getField(mResourcesManager, "mActiveResources");
if (resouresMap == null) {
resouresMap = (Map) PluginUtil.getField(mResourcesManager, "mResourceImpls");
}
} else {
Object mMainThread = PluginUtil.getField(mBaseContext, "mMainThread");
resouresMap = (Map) PluginUtil.getField(mMainThread, "mActiveResources");
}
if (resouresMap != null) {
for (Object resourceKey : resouresMap.keySet()) {
Object resourcesWeakReference = resouresMap.get(resourceKey);
if (resourcesWeakReference != null &&
((WeakReference) resourcesWeakReference).get() != null) {
Object resources = ((WeakReference) resourcesWeakReference).get();
PluginUtil.setField(resources, "mAssets", assetManager);
if (!isCalledInInit) {
clearResoucesDrawableCache(resources);
}
//只有带有资源的补丁才会执行添加到assetManager中
PluginManifest manifest = mLoadedPluginList.get(id);
if (manifest.hasResoures()) {
addAssetPath.invoke(assetManager, PluginUtil.getAPKPath(id, mLoadedDiffPluginPathinfoList.get(id)));
}
}
} else {
PluginUtil.setField(mBaseContext.getResources(), "mAssets", assetManager);
Object mResourcesImpl = PluginUtil.getField(mBaseContext.getResources(), "mResourcesImpl");
PluginUtil.setField(mResourcesImpl, "mAssets", assetManager);
if (!isCalledInInit) {
clearResoucesDrawableCache(mResourcesImpl);
}
}
if (!isCalledInInit) {
clearResoucesDrawableCache(mBaseContext.getResources());
}
mBaseContext.getResources().updateConfiguration(mBaseContext.getResources().getConfiguration(), mBaseContext.getResources().getDisplayMetrics());
//这里提前创建一个resource是因为Resources的构造函数会对AssetManager进行一些变量的初始化
//还不能创建系统的Resources类,否则中兴系统会出现崩溃问题
Resources newResources = new Resources(assetManager,
mBaseContext.getResources().getDisplayMetrics(),
mBaseContext.getResources().getConfiguration());

PluginUtil.setField(mBaseContext, "mResources", newResources);
PluginUtil.setField(mPackageInfo, "mResources", newResources);

//清除一下之前的resource的数据,释放一些内存
//因为这个resource有可能还被系统持有着,内存都没被释放
clearResoucesDrawableCache(mNowResources);

mNowResources = newResources;
//需要清理mtheme对象,否则通过inflate方式加载资源会报错
PluginUtil.setField(mBaseContext, "mTheme", null);
//如果是activity动态加载一个View插件,则需要把activity的mTheme对象也设置为null
//比如:
// PluginUtil.setField(getCurrActivity().getBaseContext(), "mResources", null);
// PluginUtil.setField(getCurrActivity(), "mTheme", null);
// PluginUtil.setField(getCurrActivity().getBaseContext(), "mTheme", null);
} catch (Throwable e) {
e.printStackTrace();
}
Expand Down Expand Up @@ -608,7 +594,7 @@ private static void removeLoadedPlugin(String pluginId) {
ZeusClassLoader classLoader = (ZeusClassLoader) cl;
classLoader.removePlugin(pluginId);
}
reloadInstalledPluginResources(false);
reloadInstalledPluginResources();
}
}

Expand Down Expand Up @@ -717,7 +703,7 @@ private static void loadInstalledPlugins() {
Thread.currentThread().setContextClassLoader(classLoader);
mNowClassLoader = classLoader;
}
reloadInstalledPluginResources(true);
reloadInstalledPluginResources();
isIniteInstallPlugins = true;
}
}
Expand Down
7 changes: 7 additions & 0 deletions ZeusPlugin/src/main/java/zeus/plugin/PluginManifest.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ public int getFlag() {
return TextUtils.isEmpty(flag) ? 0 : Integer.valueOf(flag);
}

public boolean hasResoures() {
return (getFlag() & FLAG_WITHOUT_RESOURCES) != FLAG_WITHOUT_RESOURCES;
}

public boolean hasSoLibrary(){
return (getFlag() & FLAG_WITHOUT_SO_FILE) != FLAG_WITHOUT_SO_FILE;
}
@Override
public String toString() {
JSONObject jsonObject = new JSONObject();
Expand Down
40 changes: 40 additions & 0 deletions ZeusPlugin/src/main/java/zeus/plugin/ZeusBaseActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package zeus.plugin;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;

/**
* 基础的activity
* Created by huangjian on 2016/6/21.
*/
public class ZeusBaseActivity extends Activity {

//---------------------插件相关的代码-----------------------start
ZeusHelper helper = new ZeusHelper();

@Override
public Object getSystemService(String name) {
return helper.getSystemService(this, super.getSystemService(name), name);
}

@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
helper.attachBaseContext(newBase,this);
}

@Override
public Resources getResources() {
return PluginManager.getResources();
}

/**
* 解决有时插件通过inflate找不到资源的问题
* @return Resources.Theme
*/
public Resources.Theme getTheme() {
return helper.getTheme(super.getTheme());
}
//---------------------------插件相关代码-------------------------end
}
43 changes: 43 additions & 0 deletions ZeusPlugin/src/main/java/zeus/plugin/ZeusBaseApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package zeus.plugin;

import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;

/**
* 基础的Application
* Created by huangjian on 2016/6/21.
*/
public class ZeusBaseApplication extends Application {

//---------------------插件相关的代码-----------------------start
public ZeusHelper helper = new ZeusHelper();

@Override
public Object getSystemService(String name) {
return helper.getSystemService(this, super.getSystemService(name), name);
}

@Override
public Resources getResources() {//这里需要返回插件框架的resources
return PluginManager.getResources();
}

/**
* 解决有时插件通过inflate找不到资源的问题
*
* @return Resources.Theme
*/
public Resources.Theme getTheme() {
return helper.getTheme(super.getTheme());
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//支持切换语言
ZeusHelper.onConfigurationChanged();
}
//---------------------插件相关的代码-----------------------end
}
90 changes: 90 additions & 0 deletions ZeusPlugin/src/main/java/zeus/plugin/ZeusHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package zeus.plugin;

import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;

/**
* 一些重复的方法放到这里。
* Created by huangjian on 2016/7/14.
*/
public class ZeusHelper {

//---------------------插件相关的代码-----------------------start
/**
* 一旦插件resources发生变化,这个resources就可以用来比较了
*/
public Resources mMyResources = null;
/**
* mMyTheme.getResources()必须为插件resources
*/
public Resources.Theme mMyTheme = null;

public Context mContext = null;
/**
* 配置LAYOUT_INFLATER_SERVICE时的一些参数
*
* @param context 调用着的context
* @param systemServcie systemServer对象
* @param name server的名字
* @return systemServer对象
*/
public Object getSystemService(Context context, Object systemServcie, String name) {
if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) {
LayoutInflater inflater = (LayoutInflater) systemServcie;
inflater.cloneInContext(context);
//使用某些加固之后该inflater里的mContext变量一直是系统的context,根本不是当前Context
//所以这里手动设置一次
PluginUtil.setField(inflater, "mContext", context);
return inflater;
}
return systemServcie;
}

/**
* 当系统调用attachBaseContext时,进行一些参数的设置
*
* @param newBase base的context即ContextImpl
* @param context 调用者自己
*/
public void attachBaseContext(Context newBase, Context context) {
//某些手机中的是mOuterContext作为context来用
//这样写还可以防止某些手机的内存泄漏,有些手机会记录它启动当前界面的activity作为mOuterContext,
//而如果之前的activity被finish,那么它也不能被GC回收
PluginUtil.setField(newBase, "mOuterContext", context);
//中兴手机是个奇葩,不知道它怎么实现的又重新生成了一个resources,这里得再次替换
PluginUtil.setField(newBase, "mResources", PluginManager.mNowResources);
mContext = context;
}

/**
* 解决有时插件通过inflate找不到资源的问题
*
* @return Resources.Theme 调用者自己生成的theme
*/
public Resources.Theme getTheme(Resources.Theme theme) {
Resources localResources = PluginManager.mNowResources;
if ((localResources != null) && (mMyTheme == null || mMyResources != localResources)) {
mMyTheme = localResources.newTheme();
mMyResources = localResources;
}
if (mMyTheme != null) {
mMyTheme.setTo(theme);
return mMyTheme;
}

return theme;
}

/**
* 系统配置改变时的回调,是为了支持插件的语言、地区、字体、字号等的切换
*/
public static void onConfigurationChanged() {
if (PluginManager.mNowResources != null
&& PluginManager.mBaseResources != null
&& PluginManager.mNowResources != PluginManager.mBaseResources) {
PluginManager.mNowResources.updateConfiguration(PluginManager.mBaseResources.getConfiguration(),
PluginManager.mBaseResources.getDisplayMetrics());
}
}
}
Binary file modified app/src/main/assets/zeushotfix_test.apk
Binary file not shown.
Binary file modified app/src/main/assets/zeusplugin_test.apk
Binary file not shown.
Binary file modified app/src/main/assets/zeusplugin_test_version2.apk
Binary file not shown.
3 changes: 2 additions & 1 deletion app/src/main/java/zeus/test/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import zeus.plugin.PluginManager;
import zeus.plugin.PluginUtil;
import zeus.plugin.ZeusBaseActivity;
import zeus.plugin.ZeusPlugin;
import zeus.test.hotfix.TestHotfixActivity1;
import zeus.test.plugin.TestPluginActivity;
Expand All @@ -20,7 +21,7 @@
/**
* Created by huangjian on 2016/6/21.
*/
public class MainActivity extends Activity {
public class MainActivity extends ZeusBaseActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/zeus/test/MyApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
import java.util.HashMap;

import zeus.plugin.PluginManager;
import zeus.plugin.ZeusBaseApplication;

/**
* Created by huangjain on 2016/6/21.
*/
public class MyApplication extends Application {
public class MyApplication extends ZeusBaseApplication {
public static final String PLUGIN_TEST = "zeusplugin_test"; //插件测试demo
public static final String HOTFIX_TEST = "zeushotfix_test"; //热修复补丁测试demo
@Override
Expand All @@ -25,7 +26,6 @@ public void onCreate() {
//插件必须以PluginUtil.EXP_PLUG_PREFIX开头,否则不会识别为插件
defaultList.put(PLUGIN_TEST, 1);
PluginManager.init(this, defaultList);

}
}

3 changes: 2 additions & 1 deletion app/src/main/java/zeus/test/hotfix/TestHotFixActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.widget.TextView;
import android.widget.Toast;

import zeus.plugin.ZeusBaseActivity;
import zeus.test.MainActivity;
import zeus.test.R;
import zeus.test.hotfixTest.MyInterface;
Expand All @@ -17,7 +18,7 @@
* @date 16/8/21
* @time 上午2:04
*/
public class TestHotFixActivity extends Activity {
public class TestHotFixActivity extends ZeusBaseActivity {

private MyInterface test = new MyInterface() {
@Override
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/zeus/test/plugin/TestPluginActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import zeus.plugin.PluginManager;
import zeus.plugin.PluginUtil;
import zeus.plugin.ZeusBaseActivity;
import zeus.plugin.ZeusPlugin;
import zeus.test.MyApplication;
import zeus.test.R;
Expand All @@ -23,7 +24,7 @@
* @date 16/8/21
* @time 上午1:09
*/
public class TestPluginActivity extends Activity {
public class TestPluginActivity extends ZeusBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand Down
Binary file modified testhotfix/sdk-jars/hotfix_sdk.jar
Binary file not shown.
Loading

0 comments on commit bddb798

Please sign in to comment.