package android.app; import android.app.Activity; import android.app.ActivityThread; import android.app.AlertDialog; import android.app.Application; import android.app.Instrumentation; import android.app.PluginBlankService.PluginServiceConnection; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; import android.content.Context; import android.content.ContextWrapper; import android.content.DialogInterface; import android.content.IContentProvider; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageParser.ActivityIntentInfo; import android.content.pm.PackageParser.Provider; import android.content.res.AssetManager; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Process; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import android.widget.Toast; import dalvik.system.DexClassLoader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; /** * 真正pluginmanager的实现 * * @author zhaoxuyang * */ class PluginManagerImpl { /** * DEBUG */ private static final String TAG = "PLUGIN_MANAGER"; private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); /** * 初始化主程序的context */ private Context mContext; /** * 单例 */ private static PluginManagerImpl mInstance; /** * 所有已安装插件的hashmap */ private HashMap<String, Plugin> mPlugins = new HashMap<String, Plugin>(); /** * 所有插件信息 */ private HashMap<String, PluginInfo> mPluginInfos = new HashMap<String, PluginInfo>(); /** * 主程序的ActivityThread */ public ActivityThread mActivityThread; /** * 创建Object的方法,将插件注册到ActivityThread中 */ public Method getPackageInfo; /** * 创建application的方法 */ public Method makeApplication; /** * 启动activity的方法 */ public Method startActivityNow; /** * 用于给Object设置classloader */ public Field mClassLoader; /** * ContextImpl类 */ public Class contextImpl; /** * ContextImpl的初始化方法 */ public Method init; /** * 4.4.3创建context的方法 */ public Method createAppContext; /** * ContextImpl的setOuterContext方法 */ public Method setOuterContext; /** * classloader 的dex输出目录 */ private String mDexoutputPath; /** * 主程序原始的classloader,作为插件classloader的parent */ private ClassLoader mOriginalClassLoader; /** * 用于和主线程通信 */ private Handler mHandler; /** * 代理broadcastreceiver */ private PluginBlankBroadcastReceiver mReceiver; /** * 是否注册了receiver */ private boolean mHasRegisterReceiver; /** * 启动activity的时候用它查找 */ private ActivityIntentResolver mActivitys = new ActivityIntentResolver(); /** * 启动service的时候用它查找 */ private ServiceIntentResolver mServices = new ServiceIntentResolver(); /** * provider的时候用它查找 */ private HashMap<String, PackageParser.Provider> mProviderInfoMap = new HashMap<String, PackageParser.Provider>(); /** * 插件存放的目录 */ private File mPluginRootDir; private static final String SEPARATOR = "@"; private static final int STATUS_NORMAL = 0; private static final int STATUS_COPY = 1; private static final int STATUS_SCAN = 2; private static final int STATUS_INSTALLING = 3; private int mStatus = STATUS_NORMAL; private HashMap<ServiceConnection, PluginServiceConnection> mConnectionMap = new HashMap<ServiceConnection, PluginServiceConnection>(); /** * 获取单例 * * @return 插件单例 */ static PluginManagerImpl getInstance() { if (mInstance == null) { mInstance = new PluginManagerImpl(); } return mInstance; } /** * 初始化 * * @param context * 上下文 * @param dop * 插件dex的存放目录 */ void init(ContextWrapper context, String dop, String pluginRootDir) { mContext = context.getBaseContext(); mDexoutputPath = dop; if (!TextUtils.isEmpty(pluginRootDir)) { mPluginRootDir = new File(pluginRootDir); if (!mPluginRootDir.exists()) { mPluginRootDir.mkdirs(); } } mHandler = new Handler(Looper.getMainLooper()); Log.d(TAG, "start init environment"); initEnvironment(); Log.d(TAG, "after init environment"); } private boolean checkExists(String[] names, ApkFile apk) { for (int j = 0; j < names.length; j++) { String name = names[j]; int index = name.indexOf(SEPARATOR); if (index <= 0) { return false; } float version = Float.parseFloat(name.substring(index + 1)); name = name.substring(0, index); if (name.equals(apk.name) && version == apk.version) { return true; } } return false; } void copyApksFromAsset(final ArrayList<ApkFile> apks, final AssetManager asset, final CopyPluginListener listener) { if (STATUS_COPY == mStatus) { return; } mStatus = STATUS_COPY; new AsyncTask<Void, Void, Integer>() { protected void onPreExecute() { if (listener != null) { listener.onCopyStart(); } }; @Override protected Integer doInBackground(Void... arg0) { String[] names = mPluginRootDir.list(); for (int i = 0; i < apks.size(); i++) { try { ApkFile apk = apks.get(i); if (checkExists(names, apk)) { continue; } String name = apk.apkName + SEPARATOR + apk.version; File demo = new File(mPluginRootDir, name); if (!demo.exists()) { demo.mkdirs(); } InputStream is = asset.open(apk.name + "/" + apk.apkName); File file = new File(demo, apk.apkName); OutputStream os = new FileOutputStream(file); copyFile(is, os); is.close(); os.close(); File libs = new File(demo, "libs"); if (!libs.exists()) { libs.mkdirs(); } String abi = Build.CPU_ABI; File temp = new File(libs, abi); if (!temp.exists()) { temp.mkdirs(); } for (int j = 0; j < apk.nativeLibs.size(); j++) { is = asset.open(apk.name + "/libs/" + abi + "/" + apk.nativeLibs.get(j)); file = new File(temp, apk.nativeLibs.get(j)); os = new FileOutputStream(file); copyFile(is, os); is.close(); os.close(); } } catch (IOException e) { e.printStackTrace(); } } return 0; } private void copyFile(InputStream src, OutputStream des) throws IOException { byte[] bytes = new byte[1024]; int len = 0; while ((len = src.read(bytes)) > 0) { des.write(bytes, 0, len); } des.flush(); } protected void onPostExecute(Integer result) { mStatus = STATUS_NORMAL; if (listener != null) { listener.onCopyEnd(); } }; }.execute(); } /** * 初始化环境,需要反射一些类,处理不同版本的差异等 * */ @SuppressWarnings({ "rawtypes", "unchecked" }) void initEnvironment() { // 得到主程序的Object Object packageInfo = null; Class packageClass = null; try { packageClass = Class.forName("android.app.LoadedApk"); } catch (ClassNotFoundException e3) { e3.printStackTrace(); } try { mClassLoader = packageClass.getDeclaredField("mClassLoader"); mClassLoader.setAccessible(true); } catch (NoSuchFieldException e3) { e3.printStackTrace(); } try { contextImpl = Class.forName("android.app.ContextImpl"); } catch (ClassNotFoundException e3) { e3.printStackTrace(); } try { init = contextImpl.getDeclaredMethod("init", packageClass, IBinder.class, ActivityThread.class); init.setAccessible(true); } catch (NoSuchMethodException e3) { try { createAppContext = contextImpl .getDeclaredMethod("createAppContext", ActivityThread.class, packageClass); createAppContext.setAccessible(true); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { setOuterContext = contextImpl.getDeclaredMethod("setOuterContext", Context.class); setOuterContext.setAccessible(true); } catch (NoSuchMethodException e3) { e3.printStackTrace(); } Field f = null; try { f = contextImpl.getDeclaredField("mPackageInfo"); f.setAccessible(true); } catch (NoSuchFieldException e3) { e3.printStackTrace(); } try { packageInfo = (Object) f.get(mContext); } catch (IllegalAccessException e3) { e3.printStackTrace(); } catch (IllegalArgumentException e3) { e3.printStackTrace(); } try { mOriginalClassLoader = (ClassLoader) mClassLoader.get(packageInfo); } catch (IllegalAccessException e3) { e3.printStackTrace(); } catch (IllegalArgumentException e3) { e3.printStackTrace(); } try { makeApplication = packageClass.getDeclaredMethod("makeApplication", boolean.class, Instrumentation.class); makeApplication.setAccessible(true); } catch (NoSuchMethodException e3) { e3.printStackTrace(); } // 获得主程序的activitythread对象,并反射出getPackageInfo和startActivityNow两个方法。 // getPackageInfo用于将插件加载到主程序的mPackages里面 // startActivityNow 参照activitygroup的方法,用于启动activity。 if (packageClass != null) { try { f = packageClass.getDeclaredField("mActivityThread"); f.setAccessible(true); mActivityThread = (ActivityThread) f.get(packageInfo); } catch (NoSuchFieldException e3) { e3.printStackTrace(); } catch (IllegalAccessException e3) { e3.printStackTrace(); } catch (IllegalArgumentException e3) { e3.printStackTrace(); } try { Class clazz = Class.forName("android.content.res.CompatibilityInfo"); getPackageInfo = mActivityThread.getClass().getDeclaredMethod("getPackageInfoNoCheck", new Class[] { ApplicationInfo.class, clazz }); getPackageInfo.setAccessible(true); Log.d(TAG, "find method getPackageInfoNoCheck and os is high version"); } catch (Exception e) { try { getPackageInfo = mActivityThread.getClass().getDeclaredMethod("getPackageInfoNoCheck", new Class[] { ApplicationInfo.class }); getPackageInfo.setAccessible(true); Log.d(TAG, "find method getPackageInfoNoCheck and os is low version"); } catch (NoSuchMethodException e1) { e1.printStackTrace(); } } try { startActivityNow = mActivityThread.getClass().getDeclaredMethod( "startActivityNow", new Class[] { Activity.class, String.class, Intent.class, ActivityInfo.class, IBinder.class, Bundle.class, Object.class }); } catch (NoSuchMethodException e1) { try { Class localClass = Class.forName("android.app.Activity$NonConfigurationInstances"); startActivityNow = mActivityThread.getClass().getDeclaredMethod( "startActivityNow", new Class[] { Activity.class, String.class, Intent.class, ActivityInfo.class, IBinder.class, Bundle.class, localClass }); } catch (NoSuchMethodException e2) { e2.printStackTrace(); } catch (ClassNotFoundException e2) { e2.printStackTrace(); } } mReceiver = new PluginBlankBroadcastReceiver(); } } /** * 安装插件并启动 * * @param info * 插件信息 * @param listener * 插件安装的回掉 */ void installPlugin(final PluginInfo info, final InstallPluginListener listener) { if (!mPlugins.containsKey(info.packageName)) { beginInstall(info, listener); realInstallPluin(info); afterInstall(info, listener); } } /** * 开始安装 * * @param info * 插件信息 * @param listener * 安装回掉 */ private void beginInstall(final PluginInfo info, final InstallPluginListener listener) { if (listener != null) { listener.onInstallStart(info); } } /** * 结束安装 * * @param info * 插件信息 * @param listener * 安装回掉 */ private void afterInstall(final PluginInfo info, final InstallPluginListener listener) { if (listener != null) { listener.onInstallEnd(info); } } /** * 启动插件 * * @param info * 插件信息 */ void startPlugin(PluginInfo info) { if (info == null) { return; } if (!mPlugins.containsKey(info.packageName)) { Log.e(TAG, "no plugin or not install"); return; } Intent intent = new Intent(Intent.ACTION_MAIN); List res = mActivitys.queryIntentForPackage(intent, null, 0, info.mPackageObj.activities); if (res != null && res.size() > 0) { PackageParser.Activity activity = (android.content.pm.PackageParser.Activity) res.get(0); String className = activity.className; Intent newIntent = new Intent(mContext, PluginBlankActivity.class); newIntent.putExtra(PluginBlankActivity.ACTIVITY_NAME, className); newIntent.putExtra(PluginBlankActivity.PLUGIN_NAME, info.packageName); newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(newIntent); } else { showToast(mContext, "this plugin no enter class", Toast.LENGTH_LONG); } } /** * 启动一个插件的内的activity * * @param intent * 请求信息 */ void startPluginActivity(Intent intent) { ComponentName cn = intent.getComponent(); String className = null; PluginInfo info = null; if (cn != null) { PackageParser.Activity activity = mActivitys.mActivities.get(cn); className = activity.className; info = mPluginInfos.get(activity.getComponentName().getPackageName()); } else { String packageName = intent.getPackage(); if (packageName != null) { PluginInfo temp = mPluginInfos.get(packageName); List<PackageParser.Activity> res = mActivitys.queryIntentForPackage(intent, null, 0, info.mPackageObj.activities); if (res != null && res.size() > 0) { info = temp; className = res.get(0).className; } } else { List<PackageParser.Activity> res = mActivitys.queryIntent(intent, null, 0); if (res != null && res.size() > 0) { packageName = res.get(0).getComponentName().getPackageName(); info = mPluginInfos.get(packageName); className = res.get(0).className; } } } if (info != null) { installPlugin(info, null); Intent newIntent = new Intent(mContext, PluginBlankActivity.class); newIntent.putExtras(intent); newIntent.putExtra(PluginBlankActivity.ACTIVITY_NAME, className); newIntent.putExtra(PluginBlankActivity.PLUGIN_NAME, info.packageName); newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(newIntent); } else { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); } } /** * 启动一个插件的内的service * * @param intent * 请求信息 * @return 启动service的ComponentName */ ComponentName startPluginService(Intent intent) { ComponentName cn = deliverPluginService(intent, PluginBlankService.START_TYPE, null); if (cn != null) { return cn; } return mContext.startService(intent); } /** * 关闭一个插件的内的service * * @param intent * 请求信息 * @return 是否成功 */ boolean stopPluginService(Intent intent) { ComponentName cn = deliverPluginService(intent, PluginBlankService.STOP_TYPE, null); if (cn != null) { return true; } return mContext.stopService(intent); } boolean bindPluginService(Intent intent, ServiceConnection con, int flags) { ComponentName cn = deliverPluginService(intent, PluginBlankService.BIND_TYPE, con); if (cn != null) { return true; } return mContext.bindService(intent, con, flags); } public void unbindPluginService(ServiceConnection conn) { ComponentName cn = deliverPluginService(new Intent(), PluginBlankService.BIND_TYPE, conn); if (cn != null) { return; } mContext.unbindService(conn); } /** * 将请求派发给代理service * * @param intent * 请求信息 * @param type * 请求类型 * @return ComponentName */ private ComponentName deliverPluginService(Intent intent, int type, ServiceConnection con) { ComponentName cn = intent.getComponent(); String className = null; PluginInfo info = null; ComponentName rescn = null; if (cn != null) { PackageParser.Service service = mServices.mServices.get(cn); className = service.className; rescn = service.getComponentName(); info = mPluginInfos.get(rescn.getPackageName()); } else { String packageName = intent.getPackage(); if (packageName != null) { PluginInfo temp = mPluginInfos.get(packageName); List<PackageParser.Service> res = mServices.queryIntentForPackage(intent, null, 0, info.mPackageObj.services); if (res != null && res.size() > 0) { info = temp; PackageParser.Service s = res.get(0); rescn = s.getComponentName(); className = s.className; } } else { List<PackageParser.Service> res = mServices.queryIntent(intent, null, 0); if (res != null && res.size() > 0) { rescn = res.get(0).getComponentName(); packageName = rescn.getPackageName(); info = mPluginInfos.get(packageName); className = res.get(0).className; } } } if (info != null) { installPlugin(info, null); Intent newIntent = new Intent(mContext, PluginBlankService.class); newIntent.putExtras(intent); newIntent.putExtra(PluginBlankService.SERVICE_NAME, className); newIntent.putExtra(PluginBlankService.PLUGIN_NAME, info.packageName); newIntent.putExtra(PluginBlankService.TYPE, type); if (con != null) { PluginServiceConnection pconn = mConnectionMap.get(con); if (type == PluginBlankService.BIND_TYPE) { if (pconn == null) { pconn = new PluginServiceConnection(); pconn.conn = con; mConnectionMap.put(con, pconn); } newIntent.putExtra(PluginBlankService.SERVICE_CONNECTION, pconn); } else if (type == PluginBlankService.UNBIND_TYPE) { if (pconn != null) { mConnectionMap.remove(con); newIntent.putExtra(PluginBlankService.SERVICE_CONNECTION, pconn); } else { return null; } } } else if (type == PluginBlankService.BIND_TYPE || type == PluginBlankService.UNBIND_TYPE) { return null; } mContext.startService(newIntent); return rescn; } return null; } /** * 派发广播到插件 * * @param intent * 收到的广播信息 */ void onPluginReceive(Intent intent) { Iterator<Plugin> iter = mPlugins.values().iterator(); while (iter.hasNext()) { Plugin plugin = iter.next(); Iterator<LocalBroadcastManager> iter1 = plugin.mLocalBroadCastManagers.values().iterator(); while (iter1.hasNext()) { LocalBroadcastManager manager = iter1.next(); manager.sendBroadcast(intent); } } } /** * 注册广播 * * @param context * 上下文 * @param pluginname * 插件名称 * @param receiver * receiver * @param filter * filter * @return Intent */ Intent registerReceiver(Context context, String pluginname, BroadcastReceiver receiver, IntentFilter filter) { Plugin plugin = getPlugin(pluginname); if (plugin != null) { LocalBroadcastManager manager = plugin.mLocalBroadCastManagers.get(context); if (manager == null) { manager = new LocalBroadcastManager(context); plugin.mLocalBroadCastManagers.put(context, manager); } manager.registerReceiver(receiver, filter); } mHasRegisterReceiver = true; return mContext.registerReceiver(mReceiver, filter); } /** * 同上 * * @param context * context * @param pluginname * pluginname * @param receiver * receiver * @param filter * filter * @param broadcastPermission * broadcastPermission * @param scheduler * scheduler * @return Intent */ Intent registerReceiver(Context context, String pluginname, BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiver(context, pluginname, receiver, filter); } /** * 解除注册 * * @param context * context * @param pluginname * pluginname * @param receiver * receiver */ void unregisterReceiver(Context context, String pluginname, BroadcastReceiver receiver) { Plugin plugin = getPlugin(pluginname); if (plugin != null) { LocalBroadcastManager manager = plugin.mLocalBroadCastManagers.get(context); if (manager != null) { manager.unregisterReceiver(receiver); if (manager.getSize() == 0) { plugin.mLocalBroadCastManagers.remove(context); } } } } /** * @param name * @return */ IContentProvider getContentProvider(String name) { IContentProvider ip = getExistContentProvider(name); if (ip != null) { return ip; } if (mProviderInfoMap.containsKey(name)) { PackageParser.Provider p = mProviderInfoMap.get(name); String packageName = p.info.applicationInfo.packageName; PluginInfo info = mPluginInfos.get(packageName); if (info != null) { installPlugin(info, null); Plugin plugin = mPlugins.get(info.packageName); return plugin.mProviderMap.get(name); } } return mContext.getContentResolver().acquireProvider(name); } IContentProvider getExistContentProvider(String name) { Iterator<Plugin> iter = mPlugins.values().iterator(); while (iter.hasNext()) { Plugin plugin = iter.next(); if (plugin.mProviderMap.containsKey(name)) { return plugin.mProviderMap.get(name); } } return null; } /** * 真正安装插件的代码,核心方法 * * @param info * 插件信息 */ private void realInstallPluin(PluginInfo info) { try { Plugin plugin = new Plugin(); plugin.mPluginInfo = info; PackageInfo packageInfo = info.mPackageInfo; packageInfo.applicationInfo.uid = Process.myUid(); packageInfo.applicationInfo.sourceDir = info.apkPath; packageInfo.applicationInfo.publicSourceDir = info.apkPath; packageInfo.applicationInfo.dataDir = mContext.getDir(info.packageName, 0).getAbsolutePath(); packageInfo.applicationInfo.flags &= ApplicationInfo.FLAG_HAS_CODE; Object realPackageInfo = null; try { realPackageInfo = (Object) getPackageInfo.invoke(mActivityThread, new Object[] { packageInfo.applicationInfo, null }); } catch (Exception e) { realPackageInfo = (Object) getPackageInfo.invoke(mActivityThread, new Object[] { packageInfo.applicationInfo }); } plugin.mRealPackageInfo = realPackageInfo; // 本地库的路径 StringBuilder sb = new StringBuilder(); int size = info.nativeLibraryPaths.size(); for (int j = 0; j < size; j++) { sb.append(info.nativeLibraryPaths.get(j)); if (j < size - 1) { sb.append(":"); } } // 实例化插件的classloader DexClassLoader classLoader = new DexClassLoader(info.apkPath, mDexoutputPath, sb.toString(), mOriginalClassLoader); mClassLoader.set(realPackageInfo, classLoader); plugin.mClassLoader = classLoader; // 调用Application plugin.mApplication = (Application) makeApplication.invoke(realPackageInfo, false, null); if (plugin.mApplication instanceof PluginApplication) { PluginApplication pa = (PluginApplication) plugin.mApplication; pa.setPluginName(plugin.mPluginInfo.packageName); } plugin.mApplication.onCreate(); Context context = plugin.mApplication.getApplicationContext(); LocalBroadcastManager lbm = new LocalBroadcastManager(context); plugin.mLocalBroadCastManagers.put(context, lbm); // 注册manifest里面的receiver ArrayList<PackageParser.Activity> receivers = info.mPackageObj.receivers; for (int i = 0; i < receivers.size(); i++) { android.content.pm.PackageParser.Activity receiver = receivers.get(i); String receiverName = receiver.className; BroadcastReceiver broadcastreceiver = (BroadcastReceiver) plugin.mClassLoader.loadClass(receiverName) .newInstance(); ArrayList<ActivityIntentInfo> intentinfos = receiver.intents; for (int j = 0; j < intentinfos.size(); j++) { IntentFilter filter = intentinfos.get(j); lbm.registerReceiver(broadcastreceiver, filter); mContext.registerReceiver(mReceiver, filter); mHasRegisterReceiver = true; } } // 注册contentprovider ArrayList<PackageParser.Provider> providers = info.mPackageObj.providers; for (int i = 0; i < providers.size(); i++) { android.content.pm.PackageParser.Provider provider = providers.get(i); String providerName = provider.className; ContentProvider localProvider = (ContentProvider) plugin.mClassLoader.loadClass(providerName) .newInstance(); localProvider.attachInfo(plugin.mApplication, provider.info); IContentProvider realProvier = localProvider.getIContentProvider(); String names[] = PATTERN_SEMICOLON.split(provider.info.authority); for (int j = 0; j < names.length; j++) { plugin.mProviderMap.put(names[i], realProvier); } } // 恭喜,插件安装了 plugin.mPluginInfo.isInstalled = true; mPlugins.put(info.packageName, plugin); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 遍历目录下的所有插件 * * @param dir * dir * @param listener * listener */ void scanApks(final ScanPluginListener listener) { if (mPluginRootDir == null) { return; } if (STATUS_SCAN == mStatus) { return; } mStatus = STATUS_SCAN; new AsyncTask<Void, Integer, Void>() { @Override protected void onPreExecute() { super.onPreExecute(); if (listener != null) { listener.onScanStart(); } } @Override protected Void doInBackground(Void... arg0) { // 先清掉 mPluginInfos.clear(); mPlugins.clear(); File[] files = mPluginRootDir.listFiles(); for (int i = 0; i < files.length; i++) { File file = files[i]; String str = file.getName(); PluginInfo pluginInfo = new PluginInfo(); pluginInfo.applicationName = str; File[] files2 = file.listFiles(); for (int j = 0; j < files2.length; j++) { File temp = files2[j]; str = temp.getName(); if (str.toLowerCase().endsWith(".apk")) { pluginInfo.apkName = str; pluginInfo.apkPath = temp.getAbsolutePath(); } else if (str.equals("libs")) { temp = new File(temp, Build.CPU_ABI); if (temp.exists()) { pluginInfo.nativeLibraryPaths.add(temp.getAbsolutePath()); } } } if (pluginInfo.checkApk()) { getPackageInfo(pluginInfo); mPluginInfos.put(pluginInfo.packageName, pluginInfo); } } return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); mStatus = STATUS_NORMAL; if (listener != null) { listener.onScanEnd(new ArrayList<PluginInfo>(mPluginInfos.values())); } } }.execute(); } /** * 通过名称得到plugin * * @param name * 插件名称 * @return 插件 */ Plugin getPlugin(String name) { return mPlugins.get(name); } /** * 解析APK的manifest * * @param info * 插件信息 */ private void getPackageInfo(PluginInfo info) { int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES | PackageManager.GET_SIGNATURES; // 需要获取Package对象,主要是处理隐式启动插件中的activity PackageParser parser = new PackageParser(info.apkPath); DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); File sourceFile = new File(info.apkPath); PackageParser.Package pack = parser.parsePackage(sourceFile, info.apkPath, metrics, 0); // 因为PackagePaser的generatePackageInfo方法不同版本参数相差太多,所以还是用packagemanager的api // 但这样导致APK被解析了两次,上面获取Package是一次 PackageInfo packageInfo = mContext.getPackageManager().getPackageArchiveInfo(info.apkPath, flags); info.packageName = packageInfo.packageName; info.mPackageObj = pack; info.mPackageInfo = packageInfo; ArrayList<PackageParser.Activity> activitys = pack.activities; int size = activitys.size(); for (int i = 0; i < size; i++) { mActivitys.addActivity(activitys.get(i)); } ArrayList<PackageParser.Service> services = pack.services; size = services.size(); for (int i = 0; i < size; i++) { mServices.addService(services.get(i)); } ArrayList<PackageParser.Provider> providers = pack.providers; size = providers.size(); for (int i = 0; i < size; i++) { Provider p = providers.get(i); String names[] = PATTERN_SEMICOLON.split(p.info.authority); for (int j = 0; j < names.length; j++) { mProviderInfoMap.put(names[i], p); } } } /** * 卸载插件 * * @param activity * 外部的activity * @param name * 插件名称 */ void uninstallPlugin(Activity activity, String name) { if (mPlugins.containsKey(name)) { Plugin plugin = (Plugin) mPlugins.get(name); if (plugin.mPluginInfo.nativeLibraryPaths.size() > 0) { AlertDialog.Builder builder = new AlertDialog.Builder(activity).setMessage("检测到该插件包含本地库,如卸载需要重启程序") .setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { Process.killProcess(Process.myPid()); } }); builder.show(); return; } mPlugins.remove(name); plugin.mRealPackageInfo = null; plugin.mPluginInfo.isInstalled = false; plugin.mLocalBroadCastManagers.clear(); plugin.mProviderMap.clear(); System.gc(); } } /** * @param context * @param text * @param duration */ void showToast(Context context, String text, int duration) { Toast.makeText(mContext, text, duration).show(); } /** * @param context * @param resid * @param duration */ void showToast(Context context, int resid, int duration) { String text = context.getResources().getString(resid); Toast.makeText(mContext, text, duration).show(); } /** * 销毁 */ void destory() { if (mHasRegisterReceiver) { mContext.unregisterReceiver(mReceiver); } mPlugins.clear(); mPluginInfos.clear(); Process.killProcess(Process.myPid()); } }