private void listAll() {
    ViewGroup root = mList;
    root.removeAllViews();

    // 列出所有已经安装的插件
    Collection<PluginDescriptor> plugins = PluginLoader.getPlugins();
    Iterator<PluginDescriptor> itr = plugins.iterator();
    while (itr.hasNext()) {
      final PluginDescriptor pluginDescriptor = itr.next();
      Button button = new Button(this);
      button.setPadding(10, 10, 10, 10);
      button.setText("插件id:" + pluginDescriptor.getPackageName() + ",点击查看");
      button.setOnClickListener(
          new View.OnClickListener() {

            @Override
            public void onClick(View v) {
              Intent intent = new Intent(PluginListActivity.this, PluginDetailActivity.class);
              intent.putExtra("plugin_id", pluginDescriptor.getPackageName());
              startActivity(intent);
            }
          });

      LayoutParams layoutParam =
          new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
      layoutParam.topMargin = 10;
      layoutParam.bottomMargin = 10;
      layoutParam.gravity = Gravity.LEFT;
      root.addView(button, layoutParam);
    }
  }
 public static String getLabel(PluginDescriptor pd) {
   PackageManager pm = PluginLoader.getApplication().getPackageManager();
   PackageInfo info =
       pm.getPackageArchiveInfo(pd.getInstalledPath(), PackageManager.GET_ACTIVITIES);
   if (info != null) {
     ApplicationInfo appInfo = info.applicationInfo;
     appInfo.sourceDir = pd.getInstalledPath();
     appInfo.publicSourceDir = pd.getInstalledPath();
     String label = null;
     try {
       if (!isMainResId(appInfo.labelRes)) {
         label = pm.getApplicationLabel(appInfo).toString();
       }
     } catch (Resources.NotFoundException e) {
     }
     if (label == null || label.equals(pd.getPackageName())) {
       // 可能设置的lable是来自宿主的资源
       if (pd.getDescription() != null) {
         int id = ResourceUtil.getResourceId(pd.getDescription());
         if (id != 0) {
           // 再宿主中查一次
           try {
             label = PluginLoader.getApplication().getResources().getString(id);
           } catch (Resources.NotFoundException e) {
           }
         }
       }
     }
     if (label != null) {
       return label;
     }
   }
   return pd.getDescription();
 }
 private Context findPluginContext() {
   String classId = getIntent().getStringExtra(PluginDispatcher.ACTIVITY_ID_IN_PLUGIN);
   LogUtil.d("findPluginContext ", classId);
   @SuppressWarnings("rawtypes")
   Class clazz = PluginLoader.loadPluginClassById(classId);
   if (clazz != null) {
     return PluginLoader.getDefaultPluginContext(clazz);
   }
   return null;
 }
 @Override
 public void onPluginStarted(String packageName) {
   Intent intent = new Intent(ACTION_PLUGIN_CHANGED);
   intent.putExtra(EXTRA_TYPE, "init");
   intent.putExtra(EXTRA_ID, packageName);
   PluginLoader.getApplicatoin().sendBroadcast(intent);
 }
  public static boolean copySo(File sourceDir, String so, String dest) {

    try {

      boolean isSuccess = false;

      if (Build.VERSION.SDK_INT >= 21) {
        String[] abis = Build.SUPPORTED_ABIS;
        if (abis != null) {
          for (String abi : abis) {
            LogUtil.d("try supported abi:", abi);
            String name = "lib" + File.separator + abi + File.separator + so;
            File sourceFile = new File(sourceDir, name);
            if (sourceFile.exists()) {
              isSuccess =
                  copyFile(
                      sourceFile.getAbsolutePath(),
                      dest + File.separator + "lib" + File.separator + so);
              // api21 64位系统的目录可能有些不同
              // copyFile(sourceFile.getAbsolutePath(), dest + File.separator +  name);
              break;
            }
          }
        }
      } else {
        LogUtil.d("supported api:", Build.CPU_ABI, Build.CPU_ABI2);

        String name = "lib" + File.separator + Build.CPU_ABI + File.separator + so;
        File sourceFile = new File(sourceDir, name);

        if (!sourceFile.exists() && Build.CPU_ABI2 != null) {
          name = "lib" + File.separator + Build.CPU_ABI2 + File.separator + so;
          sourceFile = new File(sourceDir, name);

          if (!sourceFile.exists()) {
            name = "lib" + File.separator + "armeabi" + File.separator + so;
            sourceFile = new File(sourceDir, name);
          }
        }
        if (sourceFile.exists()) {
          isSuccess =
              copyFile(
                  sourceFile.getAbsolutePath(),
                  dest + File.separator + "lib" + File.separator + so);
        }
      }

      if (!isSuccess) {
        Toast.makeText(
                PluginLoader.getApplicatoin(),
                "安装 " + so + " 失败: NO_MATCHING_ABIS",
                Toast.LENGTH_LONG)
            .show();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    return true;
  }
 @Override
 public void onPluginInstalled(String packageName, String version) {
   Intent intent = new Intent(ACTION_PLUGIN_CHANGED);
   intent.putExtra(EXTRA_TYPE, "install");
   intent.putExtra(EXTRA_ID, packageName);
   intent.putExtra(EXTRA_VERSION, version);
   PluginLoader.getApplicatoin().sendBroadcast(intent);
 }
 private void copyAndInstall(String name) {
   try {
     InputStream assestInput = getAssets().open(name);
     String dest = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + name;
     if (FileUtil.copyFile(assestInput, dest)) {
       PluginLoader.installPlugin(dest);
     } else {
       assestInput = getAssets().open(name);
       dest = getCacheDir().getAbsolutePath() + "/" + name;
       if (FileUtil.copyFile(assestInput, dest)) {
         PluginLoader.installPlugin(dest);
       } else {
         Toast.makeText(PluginListActivity.this, "解压Apk失败" + dest, Toast.LENGTH_LONG).show();
       }
     }
   } catch (IOException e) {
     e.printStackTrace();
     Toast.makeText(PluginListActivity.this, "安装失败", Toast.LENGTH_LONG).show();
   }
 }
 public static Bundle getApplicationMetaData(String apkPath) {
   // 暂时只查询Applicatoin节点下的meta信息,其他组件节点下的meta先不管
   PackageInfo info =
       PluginLoader.getApplication()
           .getPackageManager()
           .getPackageArchiveInfo(apkPath, PackageManager.GET_META_DATA);
   if (info.applicationInfo != null) {
     return info.applicationInfo.metaData;
   }
   return null;
 }
 @TargetApi(Build.VERSION_CODES.GINGERBREAD)
 public static Drawable getLogo(PluginDescriptor pd) {
   PackageManager pm = PluginLoader.getApplication().getPackageManager();
   PackageInfo info =
       pm.getPackageArchiveInfo(pd.getInstalledPath(), PackageManager.GET_ACTIVITIES);
   if (info != null) {
     ApplicationInfo appInfo = info.applicationInfo;
     appInfo.sourceDir = pd.getInstalledPath();
     appInfo.publicSourceDir = pd.getInstalledPath();
     Drawable logo = pm.getApplicationLogo(appInfo);
     return logo;
   }
   return null;
 }
 private void loadPluginActivity() {
   try {
     String classId = getIntent().getStringExtra(PluginDispatcher.ACTIVITY_ID_IN_PLUGIN);
     LogUtil.d("classId ", classId);
     @SuppressWarnings("rawtypes")
     Class clazz = PluginLoader.loadPluginClassById(classId);
     activity = (Activity) clazz.newInstance();
   } catch (InstantiationException e) {
     e.printStackTrace();
   } catch (IllegalAccessException e) {
     e.printStackTrace();
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
  public static ArrayList<String> matchPlugin(Intent intent, int type) {
    ArrayList<String> result = null;

    String packageName = intent.getPackage();
    if (packageName == null && intent.getComponent() != null) {
      packageName = intent.getComponent().getPackageName();
    }
    if (packageName != null
        && !packageName.equals(PluginLoader.getApplicatoin().getPackageName())) {
      PluginDescriptor dp = getPluginDescriptorByPluginId(packageName);
      if (dp != null) {
        List<String> list = dp.matchPlugin(intent, type);
        if (list != null && list.size() > 0) {
          if (result == null) {
            result = new ArrayList<>();
          }
          result.addAll(list);
        }
      }
    } else {
      Iterator<PluginDescriptor> itr = getPlugins().iterator();
      while (itr.hasNext()) {
        List<String> list = itr.next().matchPlugin(intent, type);
        if (list != null && list.size() > 0) {
          if (result == null) {
            result = new ArrayList<>();
          }
          result.addAll(list);
        }
        if (result != null && type != PluginDescriptor.BROADCAST) {
          break;
        }
      }
    }
    return result;
  }
 @Override
 public void onPluginRemoveAll() {
   Intent intent = new Intent(ACTION_PLUGIN_CHANGED);
   intent.putExtra("type", "remove_all");
   PluginLoader.getApplicatoin().sendBroadcast(intent);
 }