public static ImageUploaderInterface getInstance( final Application application, final String uploader_name) { if (uploader_name == null) return null; final Intent intent = new Intent(INTENT_ACTION_EXTENSION_UPLOAD_IMAGE); final ComponentName component = ComponentName.unflattenFromString(uploader_name); intent.setComponent(component); if (application.getPackageManager().queryIntentServices(intent, 0).size() != 1) return null; return new ImageUploaderInterface(application, uploader_name); }
@Override public String getFullVersionName() { try { final PackageInfo info = myApplication.getPackageManager().getPackageInfo(myApplication.getPackageName(), 0); return info.versionName + " (" + info.versionCode + ")"; } catch (Exception e) { return ""; } }
public static String getAppVersionName(Application application) { try { PackageManager pm = application.getPackageManager(); if (pm != null) { PackageInfo pi = pm.getPackageInfo(application.getPackageName(), 0); String versionName = pi.versionName; if (versionName != null && versionName.length() > 0) { return versionName; } } } catch (PackageManager.NameNotFoundException e) { } return ""; }
@Before public void setUp() throws PackageManager.NameNotFoundException { initMocks(this); mockStatic(MoEHelper.class); when(analytics.getApplication()).thenReturn(context); when(context.getPackageManager()).thenReturn(manager); when(activity.getPackageManager()).thenReturn(manager); when(manager.getApplicationInfo(context.getPackageName(), 0)).thenReturn(applicationInfo); when(context.getApplicationContext()).thenReturn(RuntimeEnvironment.application); integration = new MoEngageIntegration( analytics, new ValueMap().putValue("pushSenderId", "12324441").putValue("apiKey", "ASJKSLJAL")); integration.helper = moeHelper; }
@Inject public BaseConfig(Application context) { try { packageName = context.getPackageName(); final int flags = context.getPackageManager().getApplicationInfo(packageName, 0).flags; minimumLogLevel = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 ? Log.VERBOSE : Log.INFO; scope = packageName.toUpperCase(); Ln.d("Configuring Logging, minimum log level is %s", logLevelToString(minimumLogLevel)); } catch (Exception e) { try { Log.e(packageName, "Error configuring logger", e); } catch (RuntimeException f) { // HACK ignore Stub! errors in mock objects during testing } } }
public static void init(Application app) { application = new WeakReference<Application>(app); TelephonyManager tm = (TelephonyManager) app.getSystemService(Context.TELEPHONY_SERVICE); // 获取本机ID deviceId = tm.getDeviceId(); // 初始化Volley的请求队列. requestQueue = Volley.newRequestQueue(app); // 是否有相机 hasCamera = app.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA); APP_BASE_EXTERNAL_STORAGE_PATH = EXTERNAL_STORAGE_PATH + File.separator + application.get().getPackageName() + File.separator; File base = new File(APP_BASE_EXTERNAL_STORAGE_PATH); if (base.exists() && !base.isDirectory()) { base.delete(); } if (!base.exists()) { base.mkdir(); } }
/** * 初始化loader, 只可调用一次 * * @param app */ public static synchronized void initLoader(Application app, PluginManager manager) { if (!isLoaderInited) { LogUtil.d("插件框架初始化中..."); isLoaderInited = true; sApplication = app; pluginManager = manager; changeListener = new PluginCallbackImpl(); AndroidAppIActivityManager.installProxy(); AndroidAppINotificationManager.installProxy(); AndroidAppIPackageManager.installProxy(sApplication.getPackageManager()); AndroidWidgetToast.installProxy(); // 不可在主进程中同步安装,因为此时ActivityThread还没有准备好, 会导致空指针。 new Handler() .postDelayed( new Runnable() { @Override public void run() { AndroidWebkitWebViewFactoryProvider.installProxy(); } }, 50); PluginInjector.injectInstrumentation(); PluginInjector.injectHandlerCallback(); PluginInjector.injectBaseContext(sApplication); pluginManager.loadInstalledPlugins(); Iterator<PluginDescriptor> itr = getPlugins().iterator(); while (itr.hasNext()) { PluginDescriptor plugin = itr.next(); LocalServiceManager.registerService(plugin); } changeListener.onPluginLoaderInited(); if (Build.VERSION.SDK_INT >= 14) { sApplication.registerActivityLifecycleCallbacks( new Application.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {} @Override public void onActivityStarted(Activity activity) {} @Override public void onActivityResumed(Activity activity) {} @Override public void onActivityPaused(Activity activity) {} @Override public void onActivityStopped(Activity activity) {} @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} @Override public void onActivityDestroyed(Activity activity) { PluginStubBinding.unBindLaunchModeStubActivity( activity.getClass().getName(), activity.getIntent()); } }); } LogUtil.d("插件框架初始化完成"); } }
/** * 安装一个插件 * * @param srcPluginFile * @return */ public static synchronized int installPlugin(String srcPluginFile) { LogUtil.e("开始安装插件", srcPluginFile); if (TextUtils.isEmpty(srcPluginFile) || !new File(srcPluginFile).exists()) { return SRC_FILE_NOT_FOUND; } // 第0步,先将apk复制到宿主程序私有目录,防止在安装过程中文件被篡改 if (!srcPluginFile.startsWith(sApplication.getCacheDir().getAbsolutePath())) { String tempFilePath = sApplication.getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".apk"; if (FileUtil.copyFile(srcPluginFile, tempFilePath)) { srcPluginFile = tempFilePath; } else { LogUtil.e("复制插件文件失败", srcPluginFile, tempFilePath); return COPY_FILE_FAIL; } } // 第1步,验证插件APK签名,如果被篡改过,将获取不到证书 // sApplication.getPackageManager().getPackageArchiveInfo(srcPluginFile, // PackageManager.GET_SIGNATURES); Signature[] pluginSignatures = PackageVerifyer.collectCertificates(srcPluginFile, false); boolean isDebugable = (0 != (sApplication.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)); if (pluginSignatures == null) { LogUtil.e("插件签名验证失败", srcPluginFile); new File(srcPluginFile).delete(); return SIGNATURES_INVALIDATE; } else if (NEED_VERIFY_CERT && !isDebugable) { // 可选步骤,验证插件APK证书是否和宿主程序证书相同。 // 证书中存放的是公钥和算法信息,而公钥和私钥是1对1的 // 公钥相同意味着是同一个作者发布的程序 Signature[] mainSignatures = null; try { PackageInfo pkgInfo = sApplication .getPackageManager() .getPackageInfo(sApplication.getPackageName(), PackageManager.GET_SIGNATURES); mainSignatures = pkgInfo.signatures; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } if (!PackageVerifyer.isSignaturesSame(mainSignatures, pluginSignatures)) { LogUtil.e("插件证书和宿主证书不一致", srcPluginFile); new File(srcPluginFile).delete(); return VERIFY_SIGNATURES_FAIL; } } // 第2步,解析Manifest,获得插件详情 PluginDescriptor pluginDescriptor = PluginManifestParser.parseManifest(srcPluginFile); if (pluginDescriptor == null || TextUtils.isEmpty(pluginDescriptor.getPackageName())) { LogUtil.e("解析插件Manifest文件失败", srcPluginFile); new File(srcPluginFile).delete(); return PARSE_MANIFEST_FAIL; } PackageInfo packageInfo = sApplication .getPackageManager() .getPackageArchiveInfo(srcPluginFile, PackageManager.GET_GIDS); if (packageInfo != null) { pluginDescriptor.setApplicationTheme(packageInfo.applicationInfo.theme); pluginDescriptor.setApplicationIcon(packageInfo.applicationInfo.icon); pluginDescriptor.setApplicationLogo(packageInfo.applicationInfo.logo); } boolean isNeedPending = false; // 第3步,检查插件是否已经存在,若存在删除旧的 PluginDescriptor oldPluginDescriptor = getPluginDescriptorByPluginId(pluginDescriptor.getPackageName()); if (oldPluginDescriptor != null) { LogUtil.e( "已安装过,安装路径为", oldPluginDescriptor.getInstalledPath(), oldPluginDescriptor.getVersion(), pluginDescriptor.getVersion()); // 检查插件是否已经加载 if (oldPluginDescriptor.getPluginContext() != null) { if (!oldPluginDescriptor.getVersion().equals(pluginDescriptor.getVersion())) { LogUtil.e("旧版插件已经加载, 且新版插件和旧版插件版本不同,进入pending状态,新版插件将在安装后进程重启再生效"); isNeedPending = true; } else { LogUtil.e("旧版插件已经加载, 且新版插件和旧版插件版本相同,拒绝安装"); new File(srcPluginFile).delete(); return FAIL_BECAUSE_HAS_LOADED; } } else { LogUtil.e("旧版插件还未加载,忽略版本,直接删除旧版,尝试安装新版"); remove(oldPluginDescriptor.getPackageName()); } } // 第4步骤,复制插件到插件目录 String destApkPath = pluginManager.genInstallPath( pluginDescriptor.getPackageName(), pluginDescriptor.getVersion()); boolean isCopySuccess = FileUtil.copyFile(srcPluginFile, destApkPath); if (!isCopySuccess) { LogUtil.e("复制插件到安装目录失败", srcPluginFile); // 删掉临时文件 new File(srcPluginFile).delete(); return COPY_FILE_FAIL; } else { // 第5步,先解压so到临时目录,再从临时目录复制到插件so目录。 在构造插件Dexclassloader的时候,会使用这个so目录作为参数 File apkParent = new File(destApkPath).getParentFile(); File tempSoDir = new File(apkParent, "temp"); Set<String> soList = FileUtil.unZipSo(srcPluginFile, tempSoDir); if (soList != null) { for (String soName : soList) { FileUtil.copySo(tempSoDir, soName, apkParent.getAbsolutePath()); } // 删掉临时文件 FileUtil.deleteAll(tempSoDir); } // 第6步 添加到已安装插件列表 pluginDescriptor.setInstalledPath(destApkPath); boolean isInstallSuccess = false; if (!isNeedPending) { isInstallSuccess = pluginManager.addOrReplace(pluginDescriptor); } else { isInstallSuccess = pluginManager.pending(pluginDescriptor); } // 删掉临时文件 new File(srcPluginFile).delete(); if (!isInstallSuccess) { LogUtil.e("安装插件失败", srcPluginFile); new File(destApkPath).delete(); return INSTALL_FAIL; } else { // 通过创建classloader来触发dexopt,但不加载 LogUtil.d("正在进行DEXOPT...", pluginDescriptor.getInstalledPath()); FileUtil.deleteAll(new File(apkParent, "dalvik-cache")); PluginCreator.createPluginClassLoader( pluginDescriptor.getInstalledPath(), pluginDescriptor.isStandalone(), null); LogUtil.d("DEXOPT完毕"); if (!isNeedPending) { LocalServiceManager.registerService(pluginDescriptor); } changeListener.onPluginInstalled( pluginDescriptor.getPackageName(), pluginDescriptor.getVersion()); LogUtil.e("安装插件成功," + (isNeedPending ? " 重启进程生效" : " 立即生效"), destApkPath); return SUCCESS; } } }
/** * 安装一个插件 * * @param srcPluginFile * @return */ public static synchronized int installPlugin(String srcPluginFile) { LogUtil.d("开始安装插件", srcPluginFile); if (TextUtils.isEmpty(srcPluginFile) || !new File(srcPluginFile).exists()) { return SRC_FILE_NOT_FOUND; } // 第0步,先将apk复制到宿主程序私有目录,防止在安装过程中文件被篡改 if (!srcPluginFile.startsWith(sApplication.getCacheDir().getAbsolutePath())) { String tempFilePath = sApplication.getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".apk"; if (FileUtil.copyFile(srcPluginFile, tempFilePath)) { srcPluginFile = tempFilePath; } else { LogUtil.e("复制插件文件失败失败", srcPluginFile, tempFilePath); return COPY_FILE_FAIL; } } // 第1步,验证插件APK签名,如果被篡改过,将获取不到证书 // sApplication.getPackageManager().getPackageArchiveInfo(srcPluginFile, // PackageManager.GET_SIGNATURES); Signature[] pluginSignatures = PackageVerifyer.collectCertificates(srcPluginFile, false); boolean isDebugable = (0 != (sApplication.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)); if (pluginSignatures == null) { LogUtil.e("插件签名验证失败", srcPluginFile); new File(srcPluginFile).delete(); return SIGNATURES_INVALIDATE; } else if (NEED_VERIFY_CERT && !isDebugable) { // 可选步骤,验证插件APK证书是否和宿主程序证书相同。 // 证书中存放的是公钥和算法信息,而公钥和私钥是1对1的 // 公钥相同意味着是同一个作者发布的程序 Signature[] mainSignatures = null; try { PackageInfo pkgInfo = sApplication .getPackageManager() .getPackageInfo(sApplication.getPackageName(), PackageManager.GET_SIGNATURES); mainSignatures = pkgInfo.signatures; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } if (!PackageVerifyer.isSignaturesSame(mainSignatures, pluginSignatures)) { LogUtil.e("插件证书和宿主证书不一致", srcPluginFile); new File(srcPluginFile).delete(); return VERIFY_SIGNATURES_FAIL; } } // 第2步,解析Manifest,获得插件详情 PluginDescriptor pluginDescriptor = ManifestParser.parseManifest(srcPluginFile); if (pluginDescriptor == null || TextUtils.isEmpty(pluginDescriptor.getPackageName())) { LogUtil.e("解析插件Manifest文件失败", srcPluginFile); new File(srcPluginFile).delete(); return PARSE_MANIFEST_FAIL; } PackageInfo packageInfo = sApplication .getPackageManager() .getPackageArchiveInfo(srcPluginFile, PackageManager.GET_GIDS); pluginDescriptor.setApplicationTheme(packageInfo.applicationInfo.theme); pluginDescriptor.setApplicationIcon(packageInfo.applicationInfo.icon); pluginDescriptor.setApplicationLogo(packageInfo.applicationInfo.logo); // 第3步,检查插件是否已经存在,若存在删除旧的 PluginDescriptor oldPluginDescriptor = getPluginDescriptorByPluginId(pluginDescriptor.getPackageName()); if (oldPluginDescriptor != null) { LogUtil.e("已安装过,先删除旧版本", pluginDescriptor.getInstalledPath()); remove(pluginDescriptor.getPackageName()); } // 第4步骤,复制插件到插件目录 String destPluginFile = pluginManager.genInstallPath( pluginDescriptor.getPackageName(), pluginDescriptor.getVersion()); boolean isCopySuccess = FileUtil.copyFile(srcPluginFile, destPluginFile); if (!isCopySuccess) { LogUtil.d("复制插件到安装目录失败", srcPluginFile); new File(srcPluginFile).delete(); return COPY_FILE_FAIL; } else { // 第5步,复制插件so到插件so目录, 在构造插件Dexclassloader的时候,会使用这个so目录作为参数 File tempDir = new File(new File(destPluginFile).getParentFile(), "temp"); Set<String> soList = FileUtil.unZipSo(srcPluginFile, tempDir); if (soList != null) { for (String soName : soList) { FileUtil.copySo( tempDir, soName, new File(destPluginFile).getParent() + File.separator + "lib"); } FileUtil.deleteAll(tempDir); } // 第6步 添加到已安装插件列表 pluginDescriptor.setInstalledPath(destPluginFile); boolean isInstallSuccess = pluginManager.addOrReplace(pluginDescriptor); new File(srcPluginFile).delete(); if (!isInstallSuccess) { LogUtil.d("安装插件失败", srcPluginFile); return INSTALL_FAIL; } else { changeListener.onPluginInstalled( pluginDescriptor.getPackageName(), pluginDescriptor.getVersion()); LogUtil.d("安装插件成功", destPluginFile); return SUCCESS; } } }