package com.tws.plugin.core; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import tws.component.log.TwsLog; import android.app.Application; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.os.Environment; import android.text.TextUtils; import com.tws.plugin.content.DisplayConfig; import com.tws.plugin.content.PluginDescriptor; import com.tws.plugin.core.localservice.LocalServiceManager; import com.tws.plugin.manager.PluginManagerHelper; import com.tws.plugin.util.ProcessUtil; public class PluginApplication extends Application { private static final String TAG = "rick_Print:PluginApplication"; private static PluginApplication instance; private ArrayList<String> mEliminatePlugins = new ArrayList<String>(); public static String EXCLUDE_PLUGIN_FILE = "/plugins/exclude_plugin.ini"; public static String PLUGIN_BLACKLIST_FILE = "/plugins/plugin_blacklist.ini"; private Configuration mSaveConfiguration = null; public static PluginApplication getInstance() { return instance; } public ArrayList<String> getEliminatePlugins() { return mEliminatePlugins; } @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); instance = this; // 这个地方之所以这样写,是因为如果是插件进程,initPluginFramework必须在applicaiotn启动时执行 // 而如果是宿主进程,initPluginFramework可以在这里执行,也可以在需要时再在宿主的其他组件中执行, // 例如点击宿主的某个Activity中的button后再执行这个方法来启动插件框架。 // 总体原则有3点: // 1、插件进程和宿主进程都必须有机会执行initPluginFramework // 2、在插件进程和宿主进程的initPluginFramework方法都执行完毕之前,不可和插件交互 // 3、在插件进程和宿主进程的initPluginFramework方法都执行完毕之前启动的组件,即使在initPluginFramework都执行完毕之后,也不可和插件交互 // 如果initPluginFramework都在进程启动时就执行,自然很轻松满足上述条件。 if (ProcessUtil.isPluginProcess(this)) { TwsLog.d(TAG, "插件进程 PluginLoader.initPluginFramework"); // 插件进程,必须在这里执行initPluginFramework PluginLoader.initPluginFramework(this); // init ServiceManager LocalServiceManager.init(); } else if (ProcessUtil.isHostProcess(this)) { // 宿主进程,可以在这里执行,也可以选择在宿主的其他地方在需要时再启动插件框架 TwsLog.d(TAG, "宿主进程 PluginLoader.initPluginFramework"); PluginLoader.initPluginFramework(this); // init ServiceManager LocalServiceManager.init(); } } /** * 重写这个方法是为了支持Receiver,否则会出现ClassCast错误 */ @Override public Context getBaseContext() { return PluginLoader.fixBaseContextForReceiver(super.getBaseContext()); } @Override public void onCreate() { super.onCreate(); // 注册日志广播 全局生命周期 高优先级 需要放在application中 if (mSaveConfiguration == null) { mSaveConfiguration = new Configuration(getResources().getConfiguration()); } TwsLog.registerLogReceiver(this); initEliminatePlugins(); if (ProcessUtil.isPluginProcess(this)) { PluginLoader.loadPlugins(this); } } protected void startNeedPowerbootPlugin() { new Thread(new Runnable() { @Override public void run() { Collection<PluginDescriptor> plugins = PluginManagerHelper.getPlugins(); Iterator<PluginDescriptor> itr = plugins.iterator(); while (itr.hasNext()) { final PluginDescriptor pluginDescriptor = itr.next(); if (TextUtils.isEmpty(pluginDescriptor.getPackageName())) { TwsLog.e(TAG, "My god !!! how can have such a situatio~!"); continue; } if (mEliminatePlugins.contains(pluginDescriptor.getPackageName())) { TwsLog.w(TAG, "当前插件" + pluginDescriptor.getPackageName() + "已经被列入黑名单了"); continue; } final ArrayList<DisplayConfig> dcs = pluginDescriptor.getDisplayConfigs(); if (dcs != null) { for (DisplayConfig dc : dcs) { if (dc.pos == DisplayConfig.DISPLAY_AT_OTHER_POS) { switch (dc.contentType) { case DisplayConfig.TYPE_SERVICE: Intent intent = new Intent(); intent.setClassName(getApplicationContext(), dc.content); startService(intent); break; case DisplayConfig.TYPE_PACKAGENAEM: if (null == PluginLauncher.instance().startPlugin(dc.content)) { TwsLog.e(TAG, "startPlugin:" + dc.content + "失败!!!"); } break; default: break; } } } } } } }).start(); } private void initEliminatePlugins() { String configFile = Environment.getExternalStorageDirectory().getPath() + EXCLUDE_PLUGIN_FILE; try { File file = new File(configFile); if (!file.exists()) { return; } BufferedReader br = new BufferedReader(new FileReader(file)); String line = ""; while ((line = br.readLine()) != null) { line = line.trim(); if (TextUtils.isEmpty(line) || line.startsWith("#")) continue; if (mEliminatePlugins == null) { mEliminatePlugins = new ArrayList<String>(); } mEliminatePlugins.add(line); } br.close(); } catch (Exception e) { e.printStackTrace(); } if (mEliminatePlugins != null) { TwsLog.w(TAG + "getExceList()", "U config Eliminate the following plug-ins:"); for (String pStr : mEliminatePlugins) { TwsLog.d(TAG, " " + pStr); } } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (mSaveConfiguration.diff(newConfig) != 0 && ProcessUtil.isPluginProcess(this)) { mSaveConfiguration.updateFrom(newConfig); TwsLog.d(TAG, "更新所有插件的Config配置"); PluginLauncher.instance().onConfigurationChanged(newConfig); } } }