diff --git a/replugin-host-gradle/build.gradle b/replugin-host-gradle/build.gradle index 9e2feb44..5653433c 100644 --- a/replugin-host-gradle/build.gradle +++ b/replugin-host-gradle/build.gradle @@ -22,13 +22,14 @@ apply plugin: 'maven-publish' repositories { jcenter() mavenCentral() - maven() { url 'https://maven.google.com' } + google() } buildscript { repositories { jcenter() mavenCentral() + google() } dependencies { @@ -38,10 +39,7 @@ buildscript { } dependencies { - compile 'com.android.tools.build:gradle:2.1.3' // >= 2.14.1 -// compile 'com.android.tools.build:gradle:2.3.3' // gradle 3.3 <= {} < gradle-4.10 -// compile 'com.android.tools.build:gradle:3.3.2' // >= gradle-4.10 -// compile 'com.android.tools.build:gradle:3.4.1' // >= gradle-5.1.1 + compile 'com.android.tools.build:gradle:3.5.4' compile 'org.json:json:20160212' compile 'org.codehaus.groovy:groovy:2.4.7' compile 'com.squareup:javapoet:1.5.1' diff --git a/replugin-host-gradle/gradle/wrapper/gradle-wrapper.properties b/replugin-host-gradle/gradle/wrapper/gradle-wrapper.properties index 681c63bc..73c7b5b3 100644 --- a/replugin-host-gradle/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-host-gradle/gradle/wrapper/gradle-wrapper.properties @@ -19,4 +19,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/RePlugin.groovy b/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/RePlugin.groovy index bac248b6..aeeacb2d 100644 --- a/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/RePlugin.groovy +++ b/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/RePlugin.groovy @@ -111,7 +111,7 @@ public class Replugin implements Plugin { /** * * @hyongbai - * + * * 在gradle plugin 3.0.0之前,file是文件,且文件名为AndroidManifest.xml * 在gradle plugin 3.0.0之后,file是目录,(特别是3.3.2)在这里改成递归的方式替换内部所有的 manifest 文件 * @@ -203,6 +203,8 @@ public class Replugin implements Plugin { println '--------------------------------------------------------------------------' // println "${TAG} appID=${appID}" println "${TAG} useAppCompat=${config.useAppCompat}" + + println "${TAG} useAndroidX=${config.useAndroidX}" // println "${TAG} persistentName=${config.persistentName}" println "${TAG} countProcess=${config.countProcess}" @@ -286,4 +288,7 @@ class RepluginConfig { /** 当发现插件目录下面有不合法的插件 jar (有可能是特殊定制 jar)时是否停止构建,默认是 true */ def enablePluginFileIllegalStopBuild = true + + /** 宿主是否支持了 Androidx 库 */ + def useAndroidX = false } diff --git a/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/creator/impl/java/RePluginHostConfigCreator.groovy b/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/creator/impl/java/RePluginHostConfigCreator.groovy index c2e70abb..827d72df 100644 --- a/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/creator/impl/java/RePluginHostConfigCreator.groovy +++ b/replugin-host-gradle/src/main/groovy/com/qihoo360/replugin/gradle/host/creator/impl/java/RePluginHostConfigCreator.groovy @@ -90,6 +90,9 @@ public class RePluginHostConfig { // 是否使用 AppCompat 库 public static boolean ACTIVITY_PIT_USE_APPCOMPAT = ${config.useAppCompat}; + // HOST 是否使用 androidx 库 + public static boolean HOST_USE_ANDROIDX = ${config.useAndroidX}; + //------------------------------------------------------------ // 主程序支持的插件版本范围 //------------------------------------------------------------ diff --git a/replugin-host-library/build.gradle b/replugin-host-library/build.gradle index 1777f2bc..4fbf8afc 100644 --- a/replugin-host-library/build.gradle +++ b/replugin-host-library/build.gradle @@ -20,9 +20,10 @@ buildscript { repositories { jcenter() mavenCentral() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:3.5.4' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' } @@ -32,6 +33,7 @@ allprojects { repositories { jcenter() mavenCentral() + google() } } diff --git a/replugin-host-library/gradle.properties b/replugin-host-library/gradle.properties index ac69367c..ec76eee8 100644 --- a/replugin-host-library/gradle.properties +++ b/replugin-host-library/gradle.properties @@ -25,7 +25,7 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m +org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit diff --git a/replugin-host-library/gradle/wrapper/gradle-wrapper.properties b/replugin-host-library/gradle/wrapper/gradle-wrapper.properties index ada24495..4845cddb 100644 --- a/replugin-host-library/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-host-library/gradle/wrapper/gradle-wrapper.properties @@ -19,4 +19,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-host-library/replugin-host-lib/build.gradle b/replugin-host-library/replugin-host-lib/build.gradle index 1280694a..0a73f9fd 100644 --- a/replugin-host-library/replugin-host-lib/build.gradle +++ b/replugin-host-library/replugin-host-lib/build.gradle @@ -20,8 +20,8 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 25 - buildToolsVersion '25.0.2' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 9 @@ -43,10 +43,6 @@ android { dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') - - // 以“占位符”(Provided)的方式来引用support-v4,不会编入AAR - // 但宿主需要支持Support-v4(至少应支持LocalBroadcastManager) - provided 'com.android.support:support-v4:25.2.0' } project.ext.RP_ARTIFACT_ID = 'replugin-host-lib' diff --git a/replugin-host-library/replugin-host-lib/src/main/aidl/com/qihoo360/replugin/packages/IPluginManagerServer.aidl b/replugin-host-library/replugin-host-lib/src/main/aidl/com/qihoo360/replugin/packages/IPluginManagerServer.aidl index d1538ff6..ec886878 100644 --- a/replugin-host-library/replugin-host-lib/src/main/aidl/com/qihoo360/replugin/packages/IPluginManagerServer.aidl +++ b/replugin-host-library/replugin-host-lib/src/main/aidl/com/qihoo360/replugin/packages/IPluginManagerServer.aidl @@ -93,4 +93,26 @@ interface IPluginManagerServer { * @return 正在运行此插件的进程名列表。一定不会为Null */ String[] getRunningProcessesByPlugin(String pluginName); + + /** + * 预安装内置插件到app_p_a目录,只做p.l文件的写入,真正的安装执行,在做插件Load的时候执行 + * + * @param 待安装的插件列表 + * @return 安装后的所有插件列表 + */ + List preInstallBuiltins(in List pluginInfos); + + void updateTP(String plugin,int type,String path); + + /** + * 设置isUsed状态,并通知所有进程更新 + * + * @param pluginName 插件名 + * @param path 是否已经使用 + * @param type 是否已经使用 + * @param used 是否已经使用 + */ + void updateUsedNew(String pluginName, String path, int type, boolean used); + + } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader/utils/LocalBroadcastManager.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader/utils/LocalBroadcastManager.java new file mode 100644 index 00000000..39325a36 --- /dev/null +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader/utils/LocalBroadcastManager.java @@ -0,0 +1,104 @@ +package com.qihoo360.loader.utils; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import com.qihoo360.replugin.utils.ReflectUtils; + +public class LocalBroadcastManager { + + private static String V4_MANAGER = "android.support.v4.content.LocalBroadcastManager"; + private static String ANDROIDX_MANAGER = "androidx.localbroadcastmanager.content.LocalBroadcastManager"; + private static LocalBroadcastManager instance; + + private Context context; + private boolean init; + private static Object managerObj; + + public static LocalBroadcastManager getInstance(Context context) { + if (instance == null) { + synchronized (LocalBroadcastManager.class) { + if (instance == null) { + instance = new LocalBroadcastManager(context); + } + } + } + return instance; + } + + private LocalBroadcastManager(Context context) { + this.context = context.getApplicationContext(); + loadClass(); + } + + private void loadClass() { + try { + Class cls = null; + try { + cls = ReflectUtils.getClass(ANDROIDX_MANAGER); + } catch (Exception e) { + cls = ReflectUtils.getClass(V4_MANAGER); + } + if (cls == null) { + return; + } + managerObj = ReflectUtils.getMethod(cls, "getInstance", new Class[]{Context.class}).invoke(null, context); + init = true; + } catch (Exception e) { + } + } + + public boolean registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + if (!init || managerObj == null) { + return false; + } + try { + ReflectUtils.getMethod(managerObj.getClass(), "registerReceiver", + BroadcastReceiver.class, IntentFilter.class).invoke(managerObj, receiver, filter); + return true; + } catch (Exception e) { + } + return false; + } + + public boolean unregisterReceiver(BroadcastReceiver receiver) { + if (!init || managerObj == null) { + return false; + } + try { + ReflectUtils.getMethod(managerObj.getClass(), "unregisterReceiver", + BroadcastReceiver.class).invoke(managerObj, receiver); + return true; + } catch (Exception e) { + } + return false; + } + + public boolean sendBroadcast(Intent intent) { + if (!init || managerObj == null) { + return false; + } + try { + ReflectUtils.getMethod(managerObj.getClass(), "sendBroadcast", + Intent.class).invoke(managerObj, intent); + return true; + } catch (Exception e) { + } + return false; + } + + public boolean sendBroadcastSync(Intent intent) { + if (!init || managerObj == null) { + return false; + } + try { + ReflectUtils.getMethod(managerObj.getClass(), "sendBroadcastSync", + Intent.class).invoke(managerObj, intent); + return true; + } catch (Exception e) { + } + return false; + } +} diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Builder.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Builder.java index cde356da..9d690709 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Builder.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Builder.java @@ -196,29 +196,6 @@ final void addNormal(PluginInfo info) { static final void builder(Context context, PxAll all) { // 搜索所有本地插件和V5插件 Finder.search(context, all); - - // 删除不适配的PLUGINs - for (PluginInfo p : all.getOthers()) { - // TODO 如果已存在built-in和V5则不删除 - if (LOG) { - LogDebug.d(PLUGIN_TAG, "delete obsolote plugin=" + p); - } - boolean rc = p.deleteObsolote(context); - if (!rc) { - if (LOG) { - LogDebug.d(PLUGIN_TAG, "can't delete obsolote plugin=" + p); - } - } - } - - // 删除所有和PLUGINs不一致的DEX文件 - deleteUnknownDexs(context, all); - - // 删除所有和PLUGINs不一致的SO库目录 - // Added by Jiongxuan Zhang - deleteUnknownLibs(context, all); - - // 构建数据 } private static File getDexDir(Context context) { @@ -286,7 +263,7 @@ private static void deleteUnknownDexs(Context context, PxAll all) { private static void deleteUnknownLibs(Context context, PxAll all) { HashSet names = new HashSet<>(); for (PluginInfo p : all.getPlugins()) { - names.add(p.getNativeLibsDir().getName()); + names.add(p.getOldNativeLibsDir().getName()); } File dir = context.getDir(Constant.LOCAL_PLUGIN_DATA_LIB_DIR, 0); diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Finder.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Finder.java index d13db494..408fc828 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Finder.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Finder.java @@ -37,35 +37,8 @@ public class Finder { * 扫描插件 */ static final void search(Context context, PxAll all) { - // 扫描内置插件 + // 扫描内置插件-builtin FinderBuiltin.loadPlugins(context, all); - - // 扫描V5插件 - File pluginDir = context.getDir(Constant.LOCAL_PLUGIN_SUB_DIR, 0); - V5Finder.search(context, pluginDir, all); - - // 扫描现有插件,包括刚才从V5插件文件更新过来的文件 - HashSet deleted = new HashSet(); - { - if (LOG) { - LogDebug.d(PLUGIN_TAG, "search plugins: dir=" + pluginDir.getAbsolutePath()); - } - searchLocalPlugins(pluginDir, all, deleted); - } - - // 删除非插件文件和坏的文件 - for (File f : deleted) { - if (LOG) { - LogDebug.d(PLUGIN_TAG, "search: delete plugin dir invalid file=" + f.getAbsolutePath()); - } - boolean rc = f.delete(); - if (!rc) { - if (LOG) { - LogDebug.d(PLUGIN_TAG, "search: can't delete plugin dir invalid file=" + f.getAbsolutePath()); - } - } - } - deleted.clear(); } private static final void searchLocalPlugins(File dir, PxAll all, HashSet others) { diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/FinderBuiltin.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/FinderBuiltin.java index 6937b369..69129dd2 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/FinderBuiltin.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/FinderBuiltin.java @@ -18,6 +18,7 @@ import android.content.Context; import android.text.TextUtils; +import android.util.Log; import com.qihoo360.replugin.utils.Charsets; import com.qihoo360.replugin.utils.CloseableUtils; @@ -37,6 +38,7 @@ import static com.qihoo360.replugin.helper.LogDebug.LOG; import static com.qihoo360.replugin.helper.LogDebug.PLUGIN_TAG; +import static com.qihoo360.replugin.helper.LogDebug.TAG_NO_PN; /** * @author RePlugin Team @@ -89,6 +91,9 @@ private static final void readConfig(InputStream in, PxAll all) throws IOExcepti if (LOG) { LogDebug.d(PLUGIN_TAG, "built-in plugins config: item: " + info); } + if (LOG) { + Log.d(TAG_NO_PN, "add builtin plugin=" + info); + } all.addBuiltin(info); } } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Loader.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Loader.java index aa054aa3..6ff0c9dc 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Loader.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Loader.java @@ -63,6 +63,7 @@ import static com.qihoo360.replugin.helper.LogDebug.LOADER_TAG; import static com.qihoo360.replugin.helper.LogDebug.LOG; import static com.qihoo360.replugin.helper.LogDebug.PLUGIN_TAG; +import static com.qihoo360.replugin.helper.LogDebug.TAG_NO_PN; import static com.qihoo360.replugin.helper.LogRelease.LOGR; /** @@ -452,6 +453,7 @@ final boolean invoke(PluginCommImpl manager) { } final boolean loadEntryMethod2() { + long start = System.currentTimeMillis(); // try { String className = Factory.PLUGIN_ENTRY_PACKAGE_PREFIX + "." + mPluginName + "." + Factory.PLUGIN_ENTRY_CLASS_NAME; @@ -466,6 +468,9 @@ final boolean loadEntryMethod2() { // LogRelease.e(PLUGIN_TAG, e.getMessage(), e); // } } + if (LOG) { + Log.d(TAG_NO_PN, "load loadEntryMethod2 for " + mPluginName + " time=" + (System.currentTimeMillis() - start)); + } return mCreateMethod2 != null; } @@ -488,6 +493,8 @@ final boolean loadEntryMethod3() { final boolean invoke2(PluginCommImpl x) { try { + + long start = System.currentTimeMillis(); IBinder manager = null; // TODO IBinder b = (IBinder) mCreateMethod2.invoke(null, mPkgContext, getClass().getClassLoader(), manager); if (b == null) { diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Plugin.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Plugin.java index 0e54ecf5..1575985b 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Plugin.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/Plugin.java @@ -20,11 +20,13 @@ import android.content.pm.PackageInfo; import android.content.res.Resources; import android.os.Build; +import android.os.ConditionVariable; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.text.TextUtils; +import android.util.Log; import com.qihoo360.i.IModule; import com.qihoo360.i.IPlugin; @@ -51,6 +53,7 @@ import static com.qihoo360.replugin.helper.LogDebug.LOG; import static com.qihoo360.replugin.helper.LogDebug.MAIN_TAG; import static com.qihoo360.replugin.helper.LogDebug.PLUGIN_TAG; +import static com.qihoo360.replugin.helper.LogDebug.TAG_NO_PN; import static com.qihoo360.replugin.helper.LogRelease.LOGR; /** @@ -116,6 +119,12 @@ class Plugin { * */ PluginInfo mInfo; + /** + * sync + */ + private final Object LOCK = new Object(); + + private final ConditionVariable APPLICATION_LOCK = new ConditionVariable(); /** * 没有IPlugin对象 @@ -140,7 +149,8 @@ class Plugin { /** * */ - boolean mInitialized; + volatile boolean mInitialized; + /** * @@ -155,7 +165,7 @@ class Plugin { /** * 用来控制插件里的Application对象 */ - PluginApplicationClient mApplicationClient; + volatile PluginApplicationClient mApplicationClient; private static class UpdateInfoTask implements Runnable { @@ -531,41 +541,43 @@ private boolean loadLocked(int load, boolean useCache) { } return false; } - if (mInitialized) { - if (mLoader == null) { - if (LOG) { - LogDebug.i(MAIN_TAG, "loadLocked(): Initialized but mLoader is Null"); + synchronized (LOCK) { + if (mInitialized) { + if (mLoader == null) { + if (LOG) { + LogDebug.i(MAIN_TAG, "loadLocked(): Initialized but mLoader is Null"); + } + return false; } - return false; - } - if (load == LOAD_INFO) { - boolean rl = mLoader.isPackageInfoLoaded(); - if (LOG) { - LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, pkginfo loaded = " + rl); + if (load == LOAD_INFO) { + boolean rl = mLoader.isPackageInfoLoaded(); + if (LOG) { + LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, pkginfo loaded = " + rl); + } + return rl; } - return rl; - } - if (load == LOAD_RESOURCES) { - boolean rl = mLoader.isResourcesLoaded(); - if (LOG) { - LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, resource loaded = " + rl); + if (load == LOAD_RESOURCES) { + boolean rl = mLoader.isResourcesLoaded(); + if (LOG) { + LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, resource loaded = " + rl); + } + return rl; } - return rl; - } - if (load == LOAD_DEX) { - boolean rl = mLoader.isDexLoaded(); + if (load == LOAD_DEX) { + boolean rl = mLoader.isDexLoaded(); + if (LOG) { + LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, dex loaded = " + rl); + } + return rl; + } + boolean il = mLoader.isAppLoaded(); if (LOG) { - LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, dex loaded = " + rl); + LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, is loaded = " + il); } - return rl; - } - boolean il = mLoader.isAppLoaded(); - if (LOG) { - LogDebug.i(MAIN_TAG, "loadLocked(): Initialized, is loaded = " + il); + return il; } - return il; + mInitialized = true; } - mInitialized = true; // 若开启了“打印详情”则打印调用栈,便于观察 if (RePlugin.getConfig().isPrintDetailLog()) { @@ -738,9 +750,9 @@ final IBinder query(String binder) { } /** - * 抽出方法,将mLoader设置为null与doload中mLoader的使用添加同步锁,解决在多线程下导致mLoader为空指针的问题。 + * 抽出方法 */ - private synchronized boolean tryLoadAgain(String tag, Context context, ClassLoader parent, PluginCommImpl manager, int load) { + private boolean tryLoadAgain(String tag, Context context, ClassLoader parent, PluginCommImpl manager, int load) { mLoader = null; return doLoad(tag, context, parent, manager, load); } @@ -750,8 +762,8 @@ private final boolean doLoad(String tag, Context context, ClassLoader parent, Pl // 试图释放文件 PluginInfo info = null; if (mInfo.getType() == PluginInfo.TYPE_BUILTIN) { - // - File dir = context.getDir(Constant.LOCAL_PLUGIN_SUB_DIR, 0); + //内置插件,首次加载的时候,把数据写到p.l中,然后把文件拷贝到对应目录 + File dir = new File(mInfo.getApkDir()); File dexdir = mInfo.getDexParentDir(); String dstName = mInfo.getApkFile().getName(); boolean rc = AssetsUtils.quickExtractTo(context, mInfo, dir.getAbsolutePath(), dstName, dexdir.getAbsolutePath()); @@ -765,57 +777,21 @@ private final boolean doLoad(String tag, Context context, ClassLoader parent, Pl File file = new File(dir, dstName); info = (PluginInfo) mInfo.clone(); info.setPath(file.getPath()); - - // FIXME 不应该是P-N,即便目录相同,未来会优化这里 - info.setType(PluginInfo.TYPE_PN_INSTALLED); - - } else if (mInfo.getType() == PluginInfo.TYPE_PN_JAR) { - // - V5FileInfo v5i = V5FileInfo.build(new File(mInfo.getPath()), mInfo.getV5Type()); - if (v5i == null) { - // build v5 plugin info failed: plugin= - if (LOGR) { - LogRelease.e(PLUGIN_TAG, "p e b v i f " + mInfo); - } - return false; - } - File dir = context.getDir(Constant.LOCAL_PLUGIN_SUB_DIR, 0); - info = v5i.updateV5FileTo(context, dir, true, true); - if (info == null) { - // update v5 file to failed: plugin= - if (LOGR) { - LogRelease.e(PLUGIN_TAG, "p u v f t f " + mInfo); + info.setType(PluginInfo.TYPE_EXTRACTED); + + } else if(mInfo.getType() == PluginInfo.TYPE_PN_INSTALLED || mInfo.getType() == PluginInfo.TYPE_EXTRACTED){ + try { + //针对升级上来的用户,重新释放已安装插件的so,更换路径 + File oldSoLibDir = mInfo.getOldNativeLibsDir(); + File soLibDir = mInfo.getNativeLibsDir(); + if (oldSoLibDir.exists() && oldSoLibDir.listFiles() != null && oldSoLibDir.listFiles().length > 0 + && (!soLibDir.exists() || soLibDir.listFiles() == null || soLibDir.listFiles().length == 0)){ + PluginNativeLibsHelper.install(mInfo.getPath(), soLibDir); } + }catch (Exception e){ return false; } - // 检查是否改变了? - if (info.getLowInterfaceApi() != mInfo.getLowInterfaceApi() || info.getHighInterfaceApi() != mInfo.getHighInterfaceApi()) { - if (LOG) { - LogDebug.d(PLUGIN_TAG, "v5 plugin has changed: plugin=" + info + ", original=" + mInfo); - } - // 看看目标文件是否存在 - String dstName = mInfo.getApkFile().getName(); - File file = new File(dir, dstName); - if (!file.exists()) { - if (LOGR) { - LogRelease.e(PLUGIN_TAG, "can't load: v5 plugin has changed to " - + info.getLowInterfaceApi() + "-" + info.getHighInterfaceApi() - + ", orig " + mInfo.getLowInterfaceApi() + "-" + mInfo.getHighInterfaceApi() - + " bare not exist"); - } - return false; - } - // 重新构造 - info = PluginInfo.build(file); - if (info == null) { - return false; - } - } - - } else { - // } - // if (info != null) { // 替换 @@ -825,13 +801,23 @@ private final boolean doLoad(String tag, Context context, ClassLoader parent, Pl // mLoader = new Loader(context, mInfo.getName(), mInfo.getPath(), this); if (!mLoader.loadDex(parent, load)) { + //内置插件加载失败后,需要把释放的文件路径和类型写入到p.l中去。 + try { + PluginManagerProxy.updateTP(mInfo.getName(), mInfo.getType(), mInfo.getPath()); + } catch (RemoteException e) { + } return false; } // 设置插件为“使用过的” // 注意,需要重新获取当前的PluginInfo对象,而非使用“可能是新插件”的mInfo try { - PluginManagerProxy.updateUsedIfNeeded(mInfo.getName(), true); + long start = System.currentTimeMillis(); + PluginManagerProxy.updateUsedIfNeeded(mInfo.getName(), mInfo.getPath(), mInfo.getType(), true); + mInfo.setIsUsed(true); + if (LOG) { + Log.d(TAG_NO_PN, "update " + mInfo.getName() + " time=" + (System.currentTimeMillis() - start)); + } } catch (RemoteException e) { // 同步出现问题,但仍继续进行 if (LOGR) { @@ -839,6 +825,7 @@ private final boolean doLoad(String tag, Context context, ClassLoader parent, Pl } } + long startApp = System.currentTimeMillis(); // 若需要加载Dex,则还同时需要初始化插件里的Entry对象 if (load == LOAD_APP) { // NOTE Entry对象是可以在任何线程中被调用到 @@ -849,6 +836,9 @@ private final boolean doLoad(String tag, Context context, ClassLoader parent, Pl // 会出现Activity.onCreate比Application更早的情况,故应放在load外面立即调用 // callApp(); } + if (LOG) { + Log.d(TAG_NO_PN, "load entry for " + mInfo.getName() + " time=" + (System.currentTimeMillis() - startApp)); + } } if (load == LOAD_INFO) { @@ -914,16 +904,22 @@ public void run() { callAppLocked(); } }); + if(!APPLICATION_LOCK.block(3 * 1000)){ + if (LOGR) { + LogRelease.e(PLUGIN_TAG, "p.cal timeout " + mInfo.getName()); + } + } } } - private void callAppLocked() { + private synchronized void callAppLocked() { // 获取并调用Application的几个核心方法 if (!mDummyPlugin) { // NOTE 不排除A的Application中调到了B,B又调回到A,或在同一插件内的onCreate开启Service/Activity,而内部逻辑又调用fetchContext并再次走到这里 // NOTE 因此需要对mApplicationClient做判断,确保永远只执行一次,无论是否成功 if (mApplicationClient != null) { // 已经初始化过,无需再次处理 + APPLICATION_LOCK.open(); return; } @@ -939,5 +935,6 @@ private void callAppLocked() { LogRelease.e(PLUGIN_TAG, "p.cal dm " + mInfo.getName()); } } + APPLICATION_LOCK.open(); } } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginDesc.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginDesc.java index 76bed95b..61956879 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginDesc.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginDesc.java @@ -20,10 +20,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.util.Log; +import com.qihoo360.loader.utils.LocalBroadcastManager; +import com.qihoo360.replugin.helper.HostConfigHelper; import com.qihoo360.replugin.utils.Charsets; import com.qihoo360.replugin.utils.CloseableUtils; import com.qihoo360.mobilesafe.core.BuildConfig; @@ -196,8 +197,7 @@ public void onReceive(Context context, Intent intent) { } }; IntentFilter filter = new IntentFilter(ACTION_UPDATE); - LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(PMF.getApplicationContext()); - lbm.registerReceiver(sUpdateReceiver, filter); + LocalBroadcastManager.getInstance(PMF.getApplicationContext()).registerReceiver(sUpdateReceiver,filter); } } } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginLibraryInternalProxy.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginLibraryInternalProxy.java index 98e6d1c8..2e0074bc 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginLibraryInternalProxy.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginLibraryInternalProxy.java @@ -779,8 +779,13 @@ private int getThemeId(Activity activity, Intent intent) { */ private static int getDefaultThemeId() { if (HostConfigHelper.ACTIVITY_PIT_USE_APPCOMPAT) { + Class clazz; try { - Class clazz = ReflectUtils.getClass("android.support.v7.appcompat.R$style"); + if (HostConfigHelper.HOST_USE_ANDROIDX){ + clazz = ReflectUtils.getClass("androidx.appcompat.R$style"); + } else { + clazz = ReflectUtils.getClass("android.support.v7.appcompat.R$style"); + } return (int) ReflectUtils.readStaticField(clazz, "Theme_AppCompat"); } catch (ClassNotFoundException e) { e.printStackTrace(); diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessMain.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessMain.java index c1ade55c..93b4c65d 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessMain.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessMain.java @@ -20,7 +20,6 @@ import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; -import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; @@ -226,10 +225,24 @@ static final void installHost(IPluginHost host) { } } + /** + * 连接常驻进程后的Action + */ + public interface DiedAction { + void onDied(); + } + /** * 非常驻进程调用,获取常驻进程的 IPluginHost */ static final void connectToHostSvc() { + connectToHostSvc(null); + } + + /** + * 非常驻进程调用,获取常驻进程的 IPluginHost + */ + static final void connectToHostSvc(final DiedAction diedAction) { Context context = PMF.getApplicationContext(); IBinder binder = PluginProviderStub.proxyFetchHostBinder(context); if (LOG) { @@ -261,6 +274,11 @@ public void binderDied() { // 断开和插件化管理器服务端的连接,因为已经失效 PluginManagerProxy.disconnect(); + + //断开连接后,需要尝试重新连接 + if (diedAction != null) { + diedAction.onDied(); + } } }, 0); } catch (RemoteException e) { @@ -756,7 +774,7 @@ public Void call() { /// - private static T writeProcessClientLock(@NonNull final Action action) { + private static T writeProcessClientLock( final Action action) { final long start = System.currentTimeMillis(); // final String stack = OptUtil.stack2Str(Thread.currentThread().getStackTrace()[3]); try { @@ -773,7 +791,7 @@ private static T writeProcessClientLock(@NonNull final Action action) { } } - private static T readProcessClientLock(@NonNull final Action action) { + private static T readProcessClientLock( final Action action) { final long start = System.currentTimeMillis(); // final String stack = OptUtil.stack2Str(Thread.currentThread().getStackTrace()[3]); try { diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessPer.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessPer.java index c77af54f..c90bc55a 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessPer.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PluginProcessPer.java @@ -22,9 +22,10 @@ import android.content.pm.ActivityInfo; import android.os.IBinder; import android.os.RemoteException; -import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; +import com.qihoo360.loader.utils.LocalBroadcastManager; + import com.qihoo360.i.IPluginManager; import com.qihoo360.loader2.alc.ActivityController; import com.qihoo360.replugin.RePlugin; diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmBase.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmBase.java index f67f5147..84eefe64 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmBase.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmBase.java @@ -27,8 +27,9 @@ import android.os.IBinder; import android.os.Parcelable; import android.os.RemoteException; -import android.support.v4.content.LocalBroadcastManager; +import com.qihoo360.loader.utils.LocalBroadcastManager; import android.text.TextUtils; +import android.util.Log; import com.qihoo360.i.Factory; import com.qihoo360.i.IModule; @@ -54,6 +55,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -62,6 +64,7 @@ import static com.qihoo360.replugin.helper.LogDebug.LOG; import static com.qihoo360.replugin.helper.LogDebug.PLUGIN_TAG; +import static com.qihoo360.replugin.helper.LogDebug.TAG_NO_PN; import static com.qihoo360.replugin.helper.LogRelease.LOGR; import static com.qihoo360.replugin.packages.PluginInfoUpdater.ACTION_UNINSTALL_PLUGIN; @@ -313,12 +316,26 @@ private final void initForServer() { // 兼容即将废弃的p-n方案 by Jiongxuan Zhang mAll = new Builder.PxAll(); Builder.builder(mContext, mAll); - refreshPluginMap(mAll.getPlugins()); // [Newest!] 使用全新的RePlugin APK方案 // Added by Jiongxuan Zhang try { List l = PluginManagerProxy.load(); + if (l == null || l.isEmpty()) { + //说明是第一次启动,内置信息还没有添加进去,需要添加内置信息,自己单纯的更新到p.l文件,没有执行文件的拷贝和安装,路径还是plugins/xxx.jar + //主要是为了让内置插件被Replugin认识,加载的时候,我们做真正的安装(拷贝文件到app_p_a) + l = PluginManagerProxy.preInstallBuiltins(mAll.getPlugins()); + if (LOG && l != null) { + Log.d(TAG_NO_PN, "installBuiltins, plugin size=" + l.size()); + } + } else { + //需要找到内置有更新的插件,然后重新写入p.l文件中 + List newestBuiltin = findNewestBuiltin(mAll.getPlugins(), l); + if (!newestBuiltin.isEmpty()) { + newestBuiltin = PluginManagerProxy.preInstallBuiltins(newestBuiltin); + refreshPluginMap(newestBuiltin); + } + } if (l != null) { // 将"纯APK"插件信息并入总的插件信息表中,方便查询 // 这里有可能会覆盖之前在p-n中加入的信息。本来我们就想这么干,以"纯APK"插件为准 @@ -331,6 +348,38 @@ private final void initForServer() { } } + /** + * 找到内置插件列表中,有更新的插件 + * @param builtin 内置插件列表 + * @param plList p.l插件列表 + */ + private List findNewestBuiltin(List builtin, List plList) { + List newest = new ArrayList<>(); + if (builtin != null) { + for (PluginInfo builtinItem : builtin) { + boolean found = false; + for (PluginInfo plItem : plList) { + if (TextUtils.equals(plItem.getName(), builtinItem.getName())) { + found = true; + if (builtinItem.getVersion() > plItem.getVersion()) { + //找到最新版 + if (LOGR) { + LogRelease.d(TAG_NO_PN, "发现新版内置插件:" + builtinItem); + } + newest.add(builtinItem); + break; + } + } + } + //新增的内置插件,也需要写入p.l + if (!found) { + newest.add(builtinItem); + } + } + } + return newest; + } + /** * Client(UI进程)的初始化 * @@ -340,8 +389,18 @@ private final void initForClient() { LogDebug.d(PLUGIN_TAG, "list plugins from persistent process"); } - // 1. 先尝试连接 - PluginProcessMain.connectToHostSvc(); + // 1. 先尝试连接,需要注册binder连接断开监听,以便于能重新建立连接 + PluginProcessMain.connectToHostSvc(new PluginProcessMain.DiedAction() { + @Override + public void onDied() { + //重新建立连接,然后刷新插件列表 + initForClient(); + // 最新快照 + PluginTable.initPlugins(mPlugins); + //重新加载后,需要为当前进程的所有Plugin对象attach上context等属性,避免出现后续插件加载失败 + callAttach(); + } + }); // 2. 然后从常驻进程获取插件列表 refreshPluginsFromHostSvc(); @@ -450,6 +509,9 @@ private void putPluginObject(PluginInfo info, Plugin plugin) { } } } else { + if (LOG) { + LogRelease.i(PLUGIN_TAG, "更新插件,plugin=" + info); + } // 同时加入PackageName和Alias(如有) mPlugins.put(info.getPackageName(), plugin); if (!TextUtils.isEmpty(info.getAlias())) { @@ -1163,6 +1225,9 @@ final void insertNewPlugin(PluginInfo info) { } final void newPluginFound(PluginInfo info, boolean persistNeedRestart) { + if (LOGR) { + LogRelease.i(PLUGIN_TAG, "newPluginFound=" + info + ",execute update plugintable"); + } // 更新最新插件表 PluginTable.updatePlugin(info); diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmHostSvc.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmHostSvc.java index f3fae174..43c4c238 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmHostSvc.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/loader2/PmHostSvc.java @@ -25,9 +25,10 @@ import android.os.IBinder; import android.os.Parcelable; import android.os.RemoteException; -import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; +import com.qihoo360.loader.utils.LocalBroadcastManager; + import com.qihoo360.mobilesafe.api.Tasks; import com.qihoo360.replugin.RePlugin; import com.qihoo360.replugin.RePluginConstants; @@ -335,6 +336,9 @@ public PluginInfo pluginDownloaded(String path) throws RemoteException { if (pi != null) { // 通常到这里,表示“安装已成功”,这时不管处于什么状态,都应该通知外界更新插件内存表 + if (LOG) { + LogDebug.d(PLUGIN_TAG, "plugin install success,pi=" + pi); + } syncInstalledPluginInfo2All(pi); } @@ -357,6 +361,9 @@ public boolean pluginUninstalled(PluginInfo info) throws RemoteException { } private void syncInstalledPluginInfo2All(PluginInfo pi) { + if (LOG) { + LogDebug.d(PLUGIN_TAG, "syncInstalledPluginInfo2All: pn=" + pi); + } // PS:若更新了“正在运行”的插件(属于“下次重启进程后更新”),则由于install返回的是“新的PluginInfo”,为防止出现“错误更新”,需要使用原来的 // // 举例,有一个正在运行的插件A(其Info为PluginInfoOld)升级到新版(其Info为PluginInfoNew),则: @@ -375,14 +382,19 @@ private void syncInstalledPluginInfo2All(PluginInfo pi) { } // 在常驻进程内更新插件内存表 + if (LOG) { + LogDebug.d(PLUGIN_TAG, "syncInstalledPluginInfo2All,newPluginFound=" + needToSyncPi); + } mPluginMgr.newPluginFound(needToSyncPi, false); // 通知其它进程去更新 Intent intent = new Intent(PmBase.ACTION_NEW_PLUGIN); intent.putExtra(RePluginConstants.KEY_PERSIST_NEED_RESTART, mNeedRestart); intent.putExtra("obj", (Parcelable) needToSyncPi); + if (LOG) { + LogDebug.d(PLUGIN_TAG, "ACTION_NEW_PLUGIN broadcast start"); + } IPC.sendLocalBroadcast2AllSync(mContext, intent); - if (LOG) { LogDebug.d(TAG, "syncInstalledPluginInfo2All: Sync complete! syncPi=" + needToSyncPi); } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/mobilesafe/loader/a/DummyActivity.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/mobilesafe/loader/a/DummyActivity.java index b19d2f1e..1a4d3b97 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/mobilesafe/loader/a/DummyActivity.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/mobilesafe/loader/a/DummyActivity.java @@ -17,6 +17,7 @@ package com.qihoo360.mobilesafe.loader.a; import android.app.Activity; +import android.content.Intent; import android.os.Bundle; import com.qihoo360.replugin.helper.LogRelease; @@ -40,7 +41,11 @@ protected void onCreate(Bundle savedInstanceState) { // 这时如果常驻进程已被杀,这时立即恢复后,由于插件还没有准备好,故会出现崩溃情况 // 详细见:Crash Hash = 5C863A3E0CACDAEA9DBD05B9A7D353FE super.onCreate(null); + setIntent(new Intent()); + try { + finish(); + } catch (Exception e) { - finish(); + } } } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/PluginDexClassLoader.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/PluginDexClassLoader.java index 9ae22c5a..48812e6c 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/PluginDexClassLoader.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/PluginDexClassLoader.java @@ -18,6 +18,7 @@ import android.os.Build; +import com.qihoo360.loader2.PluginManager; import com.qihoo360.replugin.helper.LogDebug; import com.qihoo360.replugin.model.PluginInfo; import com.qihoo360.replugin.utils.CloseableUtils; @@ -76,7 +77,13 @@ public PluginDexClassLoader(PluginInfo pi, String dexPath, String optimizedDirec installMultiDexesBeforeLollipop(pi, dexPath, parent); - mHostClassLoader = RePluginInternal.getAppClassLoader(); + ClassLoader host = RePluginInternal.getAppClassLoader(); + //防止再loader进程加载类出现死循环的问题 + if (PluginManager.isPluginProcess() && host instanceof RePluginClassLoader) { + mHostClassLoader = ((RePluginClassLoader) host).getOrig(); + } else { + mHostClassLoader = host; + } initMethods(mHostClassLoader); } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePlugin.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePlugin.java index 721449e7..1b39f8f5 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePlugin.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePlugin.java @@ -30,12 +30,13 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; -import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.qihoo360.loader.utils.LocalBroadcastManager; + import com.qihoo360.i.Factory; import com.qihoo360.i.Factory2; import com.qihoo360.i.IPluginManager; diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePluginClassLoader.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePluginClassLoader.java index 391258a5..9cc6e83c 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePluginClassLoader.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/RePluginClassLoader.java @@ -79,6 +79,10 @@ public RePluginClassLoader(ClassLoader parent, ClassLoader orig) { initMethods(orig); } + public ClassLoader getOrig(){ + return mOrig; + } + private void initMethods(ClassLoader cl) { Class c = cl.getClass(); findResourceMethod = ReflectUtils.getMethod(c, "findResource", String.class); diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/base/LocalBroadcastHelper.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/base/LocalBroadcastHelper.java index f1c4b721..422ae325 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/base/LocalBroadcastHelper.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/base/LocalBroadcastHelper.java @@ -18,7 +18,10 @@ import android.content.Context; import android.content.Intent; -import android.support.v4.content.LocalBroadcastManager; + +import com.qihoo360.replugin.helper.HostConfigHelper; + +import com.qihoo360.loader.utils.LocalBroadcastManager; import java.util.concurrent.Callable; @@ -26,7 +29,7 @@ * 和LocalBroadcastManager有关的帮助类 * * @author RePlugin Team - * @see android.support.v4.content.LocalBroadcastManager + * @see androidx.localbroadcastmanager.content.LocalBroadcastManager */ public class LocalBroadcastHelper { diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/activity/DynamicClassProxyActivity.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/activity/DynamicClassProxyActivity.java index dde864e2..faa6d19e 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/activity/DynamicClassProxyActivity.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/activity/DynamicClassProxyActivity.java @@ -20,7 +20,6 @@ import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; import android.text.TextUtils; import com.qihoo360.i.Factory2; @@ -37,7 +36,7 @@ public class DynamicClassProxyActivity extends Activity { @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ComponentName cn = getIntent().getComponent(); diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/dummy/DummyActivity.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/dummy/DummyActivity.java index b5da35c6..a7c6d143 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/dummy/DummyActivity.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/dummy/DummyActivity.java @@ -18,6 +18,7 @@ import android.app.Activity; import android.content.ComponentName; +import android.content.Intent; import android.os.Bundle; import com.qihoo360.replugin.helper.LogRelease; @@ -45,7 +46,12 @@ protected void onCreate(Bundle savedInstanceState) { // 这时如果常驻进程已被杀,这时立即恢复后,由于插件还没有准备好,故会出现崩溃情况 // 详细见:Crash Hash = 5C863A3E0CACDAEA9DBD05B9A7D353FE super.onCreate(null); + //设置空的intent,防止解包时反序列化失败 + setIntent(new Intent()); + try { + finish(); + } catch (Exception ignored) { - finish(); + } } } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/service/server/PluginPitService.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/service/server/PluginPitService.java index 1c7002c7..e8b8b55d 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/service/server/PluginPitService.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/component/service/server/PluginPitService.java @@ -21,7 +21,6 @@ import android.content.Context; import android.content.Intent; import android.os.IBinder; -import android.support.annotation.Nullable; import com.qihoo360.i.IPluginManager; @@ -44,7 +43,6 @@ public PluginPitService() { sService = new WeakReference<>(this); } - @Nullable @Override public IBinder onBind(Intent intent) { return null; diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/HostConfigHelper.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/HostConfigHelper.java index 54ba36ec..2b8ac5cb 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/HostConfigHelper.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/HostConfigHelper.java @@ -61,6 +61,9 @@ public class HostConfigHelper { // 是否使用 AppCompat 库 public static boolean ACTIVITY_PIT_USE_APPCOMPAT = false; + //host 是否支持了androidx库 + public static boolean HOST_USE_ANDROIDX = false; + //------------------------------------------------------------ // 主程序支持的插件版本范围 //------------------------------------------------------------ @@ -97,6 +100,12 @@ public class HostConfigHelper { // Ignore, Just use default value } + try { + HOST_USE_ANDROIDX = readField("HOST_USE_ANDROIDX"); + } catch (NoSuchFieldException e) { + // Ignore, Just use default value + } + try { ACTIVITY_PIT_COUNT_TS_STANDARD = readField("ACTIVITY_PIT_COUNT_TS_STANDARD"); } catch (NoSuchFieldException e) { diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/LogDebug.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/LogDebug.java index 78f73fe8..4960993f 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/LogDebug.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/helper/LogDebug.java @@ -266,4 +266,9 @@ public static int printPluginInfo(PluginInfo pi, int load) { public static final String MISC_TAG = "ws002"; public static final String LOADER_TAG = "createClassLoader"; + + /** + * 去掉pn逻辑的tag + */ + public static final String TAG_NO_PN = "nopn"; } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfo.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfo.java index 51cb7dd8..867e332b 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfo.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfo.java @@ -26,7 +26,6 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; import android.text.TextUtils; import com.qihoo360.loader2.Constant; @@ -329,10 +328,7 @@ public void setPath(String path) { */ public boolean isUsed() { // 注意:该方法不单纯获取JSON中的值,而是根据插件类型(p-n、纯APK)、所处环境(新插件、当前插件)而定 - if (isPnPlugin()) { - // 为兼容以前逻辑,p-n仍是判断dex是否存在 - return isDexExtracted(); - } else if (getParentInfo() != null) { + if (getParentInfo() != null) { // 若PluginInfo是其它PluginInfo中的PendingUpdate,则返回那个PluginInfo的Used即可 return getParentInfo().isUsed(); } else { @@ -389,9 +385,7 @@ public String getApkDir() { // 必须使用宿主的Context对象,防止出现“目录定位到插件内”的问题 Context context = RePluginInternal.getAppContext(); File dir; - if (isPnPlugin()) { - dir = context.getDir(Constant.LOCAL_PLUGIN_SUB_DIR, 0); - } else if (getIsPendingCover()) { + if (getIsPendingCover()) { dir = context.getDir(Constant.LOCAL_PLUGIN_APK_COVER_DIR, 0); } else { dir = context.getDir(Constant.LOCAL_PLUGIN_APK_SUB_DIR, 0); @@ -407,7 +401,6 @@ public String getApkDir() { * @param dirSuffix 目录后缀 * @return 插件的Dex所在目录的File对象 */ - @NonNull private File getDexDir(File dexDir, String dirSuffix) { File dir = new File(dexDir, makeInstalledFileName() + dirSuffix); @@ -463,9 +456,7 @@ public File getDexParentDir() { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { return new File(getApkDir() + File.separator + "oat" + File.separator + VMRuntimeCompat.getArtOatCpuType()); } else { - if (isPnPlugin()) { - return context.getDir(Constant.LOCAL_PLUGIN_ODEX_SUB_DIR, 0); - } else if (getIsPendingCover()) { + if (getIsPendingCover()) { return context.getDir(Constant.LOCAL_PLUGIN_APK_COVER_DIR, 0); } else { return context.getDir(Constant.LOCAL_PLUGIN_APK_ODEX_SUB_DIR, 0); @@ -506,12 +497,16 @@ public File getDexFile() { * @return SO释放路径所在的File对象 */ public File getNativeLibsDir() { + File oldDir = getOldNativeLibsDir(); + return new File(oldDir.getAbsolutePath(), VMRuntimeCompat.getArtOatCpuType()); + } + + @Deprecated + public File getOldNativeLibsDir(){ // 必须使用宿主的Context对象,防止出现“目录定位到插件内”的问题 Context context = RePluginInternal.getAppContext(); File dir; - if (isPnPlugin()) { - dir = context.getDir(Constant.LOCAL_PLUGIN_DATA_LIB_DIR, 0); - } else if (getIsPendingCover()) { + if (getIsPendingCover()) { dir = context.getDir(Constant.LOCAL_PLUGIN_APK_COVER_DIR, 0); } else { dir = context.getDir(Constant.LOCAL_PLUGIN_APK_LIB_DIR, 0); @@ -724,18 +719,14 @@ public JSONObject getJSON() { * @return 文件名(不含扩展名) */ public String makeInstalledFileName() { - if (isPnPlugin() || getType() == TYPE_BUILTIN) { - return formatName(); - } else { - // 混淆插件名字,做法: - // 1. 生成最初的名字:[插件包名(小写)][协议最低版本][协议最高版本][插件版本][ak] - // 必须用小写和数字、无特殊字符,否则hashCode后会有一定的重复率 - // 2. 将其生成出hashCode - // 3. 将整体数字 - 88 - String n = getPackageName().toLowerCase() + getLowInterfaceApi() + getHighInterfaceApi() + getVersion() + "ak"; - int h = n.hashCode() - 88; - return Integer.toString(h); - } + // 混淆插件名字,做法: + // 1. 生成最初的名字:[插件包名(小写)][协议最低版本][协议最高版本][插件版本][ak] + // 必须用小写和数字、无特殊字符,否则hashCode后会有一定的重复率 + // 2. 将其生成出hashCode + // 3. 将整体数字 - 88 + String n = getPackageName().toLowerCase() + getLowInterfaceApi() + getHighInterfaceApi() + getVersion() + "ak"; + int h = n.hashCode() - 88; + return Integer.toString(h); } /** @@ -753,6 +744,19 @@ public void update(PluginInfo info) { setAlias(info.getAlias()); } + /** + * 更新插件的所有信息 + * @param info + */ + public void updateAll(PluginInfo info) { + synchronized (mJson) { + mJson.clear(); + for (String key : info.mJson.keySet()) { + mJson.put(key, info.mJson.get(key)); + } + } + } + /** * 若此Info为“新PluginInfo”,则这里返回的是“其父Info”的内容。通常和PendingUpdate有关 * @@ -874,8 +878,6 @@ private void toContentString(StringBuilder b) { { if (getType() == TYPE_BUILTIN) { b.append("[BUILTIN] "); - } else if (isPnPlugin()) { - b.append("[P-N] "); } else { b.append("[APK] "); } @@ -1110,8 +1112,8 @@ public final boolean deleteObsolote(Context context) { * @deprecated 只用于旧的P-n插件,可能会废弃 */ public final boolean canReplaceForPn(PluginInfo info) { - if (getType() != TYPE_PN_INSTALLED - && info.getType() == TYPE_PN_INSTALLED + if (getType() != TYPE_EXTRACTED + && info.getType() == TYPE_EXTRACTED && getName().equals(info.getName()) && getLowInterfaceApi() == info.getLowInterfaceApi() && getHighInterfaceApi() == info.getHighInterfaceApi() @@ -1202,9 +1204,11 @@ public String getV5MD5() { //// - private T get(String name, @NonNull T def) { - final Object obj = mJson.get(name); - return (def.getClass().isInstance(obj)) ? (T) obj : def; + private T get(String name, T def) { + synchronized (mJson) { + final Object obj = mJson.get(name); + return (def.getClass().isInstance(obj)) ? (T) obj : def; + } } public void put(String key, T value) { diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfoList.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfoList.java index a42a1c89..38231676 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfoList.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/model/PluginInfoList.java @@ -17,10 +17,11 @@ package com.qihoo360.replugin.model; import android.content.Context; -import android.support.annotation.NonNull; import android.text.TextUtils; +import android.util.Log; import com.qihoo360.loader2.Constant; +import com.qihoo360.replugin.RePlugin; import com.qihoo360.replugin.helper.LogDebug; import com.qihoo360.replugin.utils.Charsets; import com.qihoo360.replugin.utils.FileUtils; @@ -52,6 +53,16 @@ public void add(PluginInfo pi) { addToMap(pi); } + /** + * 强制更新内存列表,比如安装后需要立即更新p.l的情况 + * @param pi + */ + public void addForce(PluginInfo pi) { + if (pi == null) return; + if (!TextUtils.isEmpty(pi.getName())) mMap.put(pi.getName(), pi); + if (!TextUtils.isEmpty(pi.getAlias())) mMap.put(pi.getAlias(), pi); + } + public void remove(String pn) { mMap.remove(pn); } @@ -87,6 +98,12 @@ public boolean load(Context context) { } continue; } + + //block状态的插件丢弃 + if (RePlugin.getConfig().getCallbacks().isPluginBlocked(pi)) { + continue; + } + addToMap(pi); } return true; @@ -107,6 +124,9 @@ public boolean save(Context context) { final File f = getFile(context); final JSONArray jsonArr = new JSONArray(); for (PluginInfo i : getCopyValues()) jsonArr.put(i.getJSON()); + if (LogDebug.LOG) { + Log.d(LogDebug.TAG_NO_PN, "save json into p.l=" + jsonArr.toString()); + } FileUtils.writeStringToFile(f, jsonArr.toString(), Charsets.UTF_8); return true; } catch (IOException e) { @@ -124,18 +144,37 @@ public Iterator iterator() { /// - @NonNull private Collection getCopyValues() { return new HashSet(mMap.values()); //是否有必要去重??? } private void addToMap(PluginInfo pi) { if (pi == null) return; - if (!TextUtils.isEmpty(pi.getName())) mMap.put(pi.getName(), pi); - if (!TextUtils.isEmpty(pi.getAlias())) mMap.put(pi.getAlias(), pi); + if (!TextUtils.isEmpty(pi.getName())) updateMap(pi.getName(), pi); + if (!TextUtils.isEmpty(pi.getAlias())) updateMap(pi.getAlias(), pi); + } + + private void updateMap(String name, PluginInfo info) { + if (mMap.contains(info)) { + return; + } + if (LogDebug.LOG) { + Log.d(TAG, "updateMap=" + info + ",address=" + System.identityHashCode(info)); + } + //解决其他进程重启后,重新加载,导致内存中的PluginInfo对象被替换的问题 + if (mMap.containsKey(name)) { + PluginInfo oriInfo = mMap.get(name); + if (oriInfo != null) { + oriInfo.updateAll(info); + mMap.put(name, oriInfo); + } else { + mMap.put(name, info); + } + } else { + mMap.put(name, info); + } } - @NonNull private File getFile(Context context) { final File d = context.getDir(Constant.LOCAL_PLUGIN_APK_SUB_DIR, 0); return new File(d, "p.l"); diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginFastInstallProvider.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginFastInstallProvider.java index 6788071f..9866b5a3 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginFastInstallProvider.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginFastInstallProvider.java @@ -20,10 +20,9 @@ import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.text.TextUtils; + import com.qihoo360.loader2.PMF; import com.qihoo360.replugin.base.IPC; import com.qihoo360.replugin.helper.LogDebug; @@ -64,7 +63,7 @@ public boolean onCreate() { } @Override - public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { if (LogDebug.LOG) { LogDebug.d(TAG, "update: cv=" + values); } @@ -100,29 +99,27 @@ private int install(ContentValues cv) { } } - @Nullable @Override - public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { + public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Nothing return null; } - @Nullable @Override - public String getType(@NonNull Uri uri) { + public String getType( Uri uri) { // Nothing return null; } - @Nullable + @Override - public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { + public Uri insert( Uri uri, ContentValues values) { // Nothing return null; } @Override - public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { + public int delete( Uri uri, String selection, String[] selectionArgs) { // Nothing return 0; } diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginInfoUpdater.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginInfoUpdater.java index f68fd182..8d768f25 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginInfoUpdater.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginInfoUpdater.java @@ -20,11 +20,13 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; +import com.qihoo360.loader.utils.LocalBroadcastManager; + import com.qihoo360.loader2.MP; import com.qihoo360.replugin.base.IPC; +import com.qihoo360.replugin.helper.HostConfigHelper; import com.qihoo360.replugin.helper.LogDebug; import com.qihoo360.replugin.model.PluginInfo; @@ -53,7 +55,7 @@ static void updateIsUsed(Context context, String pluginName, boolean used) { Intent intent = new Intent(ACTION_UPDATE_INFO); intent.putExtra("pn", pluginName); intent.putExtra("used", used); - IPC.sendLocalBroadcast2AllSync(context, intent); + IPC.sendLocalBroadcast2All(context, intent); } private static class UpdateReceiver extends BroadcastReceiver { diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerProxy.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerProxy.java index 501c2354..a48cd6bb 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerProxy.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerProxy.java @@ -91,6 +91,18 @@ public static List load() throws RemoteException { return sRemote.load(); } + /** + * 预安装内置插件到app_p_a目录。因为考虑到内置插件的特殊性和缓存中针对内置插件需要做一些处理,最开始我们需要认为内置插件就已经属于安装了,读取列表应该能读取到才行。 + * 所以需要把插件信息写入到p.l中,以便于后续的加载和更新都可以读到。 + * 注意:只会在首次启动应用的时候做这个事 + * @param builtins 内置插件列表 + * @return 安装完后的插件列表,理论上就是内置插件 + * @throws RemoteException + */ + public static List preInstallBuiltins(List builtins) throws RemoteException { + return sRemote.preInstallBuiltins(builtins); + } + /** * 调用常驻进程的Server端去更新插件列表 * @@ -105,11 +117,13 @@ public static List updateAllPlugins() throws RemoteException { /** * 去常驻进程更新isUsed状态,并发送到所有进程中更新 * - * @param pluginName + * @param name 插件名字 + * @param path 插件释放的路径 + * @param type 插件状态类型 * @param used 插件是否已被使用 */ - public static void updateUsedIfNeeded(String pluginName, boolean used) throws RemoteException { - PluginInfo pi = MP.getPlugin(pluginName, false); + public static void updateUsedIfNeeded(String name, String path, int type, boolean used) throws RemoteException { + PluginInfo pi = MP.getPlugin(name, false); if (pi == null) { // 不太可能到这里 return; @@ -117,14 +131,11 @@ public static void updateUsedIfNeeded(String pluginName, boolean used) throws Re if (pi.isUsed() == used) { // 已经改变了?那就不做处理 if (LOG) { - LogDebug.i(TAG, "updateUsedIfNeeded: pi.isUsed == used, ignore. used=" + used + "; pn=" + pluginName); + LogDebug.i(TAG, "updateUsedIfNeeded: pi.isUsed == used, ignore. used=" + used + "; pn=" + name); } return; } - if (pi.isPnPlugin()) { - // 是常驻进程?老逻辑直接走dex文件存在判断,也无需做处理 - return; - } + if (sRemote == null) { // 常驻已挂掉,可以认为无需处理 if (LogRelease.LOGR) { @@ -134,7 +145,20 @@ public static void updateUsedIfNeeded(String pluginName, boolean used) throws Re } // 去常驻进程更新状态 - sRemote.updateUsed(pi.getName(), used); + sRemote.updateUsedNew(name, path, type, used); + } + + + /** + * 更新插件信息到常驻进程和p.l文件,一般是首次内置插件加载完毕后,需要调用 + * + * @param plugin 插件名字 + * @param type 插件的类型 + * @param path 插件的路径 + * @throws RemoteException + */ + public static void updateTP(String plugin, int type, String path) throws RemoteException { + sRemote.updateTP(plugin, type, path); } /** diff --git a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerServer.java b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerServer.java index bef0da22..3b6034db 100644 --- a/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerServer.java +++ b/replugin-host-library/replugin-host-lib/src/main/java/com/qihoo360/replugin/packages/PluginManagerServer.java @@ -21,8 +21,8 @@ import android.content.pm.PackageManager; import android.os.Build; import android.os.RemoteException; -import android.support.annotation.NonNull; import android.text.TextUtils; +import android.util.Log; import com.qihoo360.loader2.CertUtils; import com.qihoo360.loader2.MP; @@ -45,6 +45,7 @@ import java.util.concurrent.ConcurrentHashMap; import static com.qihoo360.replugin.helper.LogDebug.LOG; +import static com.qihoo360.replugin.helper.LogDebug.TAG_NO_PN; /** * 插件管理器。用来控制插件的安装、卸载、获取等。运行在常驻进程中

@@ -105,6 +106,19 @@ private List loadLocked() { return updateAllLocked(); } + private List installBuiltins(List builtins) { + if (builtins != null) { + for (PluginInfo builtin : builtins) { + if (LogDebug.LOG) { + Log.d(LogDebug.TAG_NO_PN, "installBuiltins, plugin=" + builtin + ",address=" + System.identityHashCode(builtin)); + } + mList.add(builtin); + } + } + mList.save(mContext); + return mList.cloneList(); + } + private List updateAllLocked() { // 判断是否需要更新插件(只有未运行的才可以) updateAllIfNeeded(); @@ -175,8 +189,15 @@ private PluginInfo installLocked(String path) { // 6. 若已经安装旧版本插件,则尝试更新插件信息,否则直接加入到列表中 if (curPli != null) { + if (LogDebug.LOG) { + Log.d(TAG_NO_PN, "cur exist pinfo,curinfo=" + curPli + ",address=" + System.identityHashCode(curPli)); + } updateOrLater(curPli, instPli); + Log.d(TAG_NO_PN, "updateOrLater,mList.get=" + mList.get(curPli.getName()) + ",address=" + System.identityHashCode(mList.get(curPli.getName()))); } else { + if (LogDebug.LOG) { + Log.d(TAG_NO_PN, "new install,pinfo=" + instPli + ",address=" + System.identityHashCode(instPli)); + } mList.add(instPli); } @@ -268,11 +289,6 @@ private void updateOrLater(PluginInfo curPli, PluginInfo instPli) { LogDebug.d(TAG, "updateOrLater: Need update. pn=" + curPli.getName() + "; cur_ver=" + curPli.getVersion() + "; update_ver=" + instPli.getVersion()); } - // 既然要更新到新的"纯APK"方案,自然需要把旧p-n的信息迁移到新列表中 - // FIXME 看看有没有别的兼容问题,尤其是和两个List表之间的 - if (curPli.isPnPlugin()) { - mList.add(curPli); - } // 已有“待更新版本”? PluginInfo curUpdatePli = curPli.getPendingUpdate(); @@ -314,6 +330,7 @@ private void updateOrLater(PluginInfo curPli, PluginInfo instPli) { LogDebug.i(TAG, "updateOrLater: Not running. Update now! pn=" + curPli.getName()); } updateNow(curPli, instPli); + mList.addForce(instPli); } } @@ -424,7 +441,7 @@ private void updateNow(PluginInfo curInfo, PluginInfo newInfo) { } } - private void move(@NonNull PluginInfo curPi, @NonNull PluginInfo newPi) { + private void move(PluginInfo curPi, PluginInfo newPi) { if (LogDebug.LOG) { LogDebug.i(TAG, "move. curPi=" + curPi.getPath() + "; newPi=" + newPi.getPath()); } @@ -463,7 +480,7 @@ private void move(@NonNull PluginInfo curPi, @NonNull PluginInfo newPi) { } } - private void delete(@NonNull PluginInfo pi) { + private void delete(PluginInfo pi) { try { FileUtils.forceDelete(new File(pi.getPath())); FileUtils.forceDelete(pi.getDexFile()); @@ -482,18 +499,52 @@ private void delete(@NonNull PluginInfo pi) { } } - private void updateUsedLocked(String pluginName, boolean used) { - PluginInfo pi = MP.getPlugin(pluginName, false); + /** + * 去掉pn之后,此方法不再使用,应该及时更新p.l中的Path和type + * @deprecated + * + * @param name + * @param used + */ + private void updateUsedLocked(String name, boolean used) { + final PluginInfo pi = MP.getPlugin(name, false); + if (LogDebug.LOG) { + Log.d(LogDebug.TAG_NO_PN, "prepare to update used for :" + name + ",pi=" + pi); + } if (pi == null) { return; } // 1. 设置状态并保存 pi.setIsUsed(used); + mList.save(mContext); // 2. 给各进程发送广播,要求更新Used状态(同步) - PluginInfoUpdater.updateIsUsed(RePluginInternal.getAppContext(), pluginName, used); + PluginInfoUpdater.updateIsUsed(RePluginInternal.getAppContext(), name, used); + } + + private void updateUsedLocked(String name, String path, int type, boolean used) { + final PluginInfo pi = MP.getPlugin(name, false); + if (LogDebug.LOG) { + Log.d(LogDebug.TAG_NO_PN, "prepare to update used for :" + name + ",pi=" + pi + ",address=" + System.identityHashCode(pi)); + } + if (pi == null) { + return; + } + + // 1. 设置状态并保存 + pi.setIsUsed(used); + pi.setPath(path); + pi.setType(type); + + if (LogDebug.LOG) { + Log.d(LogDebug.TAG_NO_PN, "plugin in list ,pi=" + mList.get(name) + ",address=" + System.identityHashCode(mList.get(name))); + } + mList.save(mContext); + + // 2. 给各进程发送广播,要求更新Used状态(同步) + PluginInfoUpdater.updateIsUsed(RePluginInternal.getAppContext(), name, used); } private boolean uninstallLocked(PluginInfo pi) { @@ -608,6 +659,17 @@ private String[] getRunningProcessesByPluginLocked(String pluginName) { return l.toArray(new String[0]); } + private void updateTP(String name, int type, String path) { + PluginInfo pi = MP.getPlugin(name, false); + if (pi == null) { + return; + } + pi.setType(type); + pi.setPath(path); + mList.add(pi); + mList.save(mContext); + } + private class Stub extends IPluginManagerServer.Stub { @Override @@ -624,6 +686,13 @@ public List load() throws RemoteException { } } + @Override + public List preInstallBuiltins(List builtins) throws RemoteException { + synchronized (LOCKER) { + return PluginManagerServer.this.installBuiltins(builtins); + } + } + @Override public List updateAll() throws RemoteException { synchronized (LOCKER) { @@ -632,9 +701,16 @@ public List updateAll() throws RemoteException { } @Override - public void updateUsed(String pluginName, boolean used) throws RemoteException { + public void updateUsed(String name, boolean used) throws RemoteException { + synchronized (LOCKER) { + PluginManagerServer.this.updateUsedLocked(name, used); + } + } + + @Override + public void updateUsedNew(String name, String path, int type, boolean used) throws RemoteException { synchronized (LOCKER) { - PluginManagerServer.this.updateUsedLocked(pluginName, used); + PluginManagerServer.this.updateUsedLocked(name, path, type, used); } } @@ -679,5 +755,13 @@ public String[] getRunningProcessesByPlugin(String pluginName) throws RemoteExce return PluginManagerServer.this.getRunningProcessesByPluginLocked(pluginName); } } + + @Override + public void updateTP(String plugin, int type, String path) throws RemoteException { + synchronized (LOCKER) { + PluginManagerServer.this.updateTP(plugin, type, path); + } + } + } } diff --git a/replugin-plugin-gradle/build.gradle b/replugin-plugin-gradle/build.gradle index 2182cf68..6311ba51 100644 --- a/replugin-plugin-gradle/build.gradle +++ b/replugin-plugin-gradle/build.gradle @@ -19,17 +19,18 @@ apply plugin: 'java' apply plugin: 'groovy' apply plugin: 'maven' apply plugin: 'maven-publish' -//apply from: 'config.gradle' repositories { jcenter() mavenCentral() + google() } buildscript { repositories { jcenter() mavenCentral() + google() } dependencies { // classpath 'com.android.tools.build:gradle:2.1.0' @@ -57,7 +58,7 @@ sourceSets { } dependencies { - compile 'com.android.tools.build:gradle:2.1.3' + compile 'com.android.tools.build:gradle:3.5.4' compile 'org.json:json:20160212' compile 'org.codehaus.groovy:groovy:2.4.7' compile 'com.squareup:javapoet:1.5.1' diff --git a/replugin-plugin-gradle/gradle/wrapper/gradle-wrapper.properties b/replugin-plugin-gradle/gradle/wrapper/gradle-wrapper.properties index 24971512..8c4fedb6 100644 --- a/replugin-plugin-gradle/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-plugin-gradle/gradle/wrapper/gradle-wrapper.properties @@ -20,4 +20,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/loaderactivity/LoaderActivityInjector.groovy b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/loaderactivity/LoaderActivityInjector.groovy index 059fd158..73825d28 100644 --- a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/loaderactivity/LoaderActivityInjector.groovy +++ b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/loaderactivity/LoaderActivityInjector.groovy @@ -45,6 +45,8 @@ public class LoaderActivityInjector extends BaseInjector { 'android.app.ActivityGroup' : 'com.qihoo360.replugin.loader.a.PluginActivityGroup', 'android.support.v4.app.FragmentActivity' : 'com.qihoo360.replugin.loader.a.PluginFragmentActivity', 'android.support.v7.app.AppCompatActivity': 'com.qihoo360.replugin.loader.a.PluginAppCompatActivity', + 'androidx.fragment.app.FragmentActivity' : 'com.qihoo360.replugin.loader.a.PluginFragmentXActivity', + 'androidx.appcompat.app.AppCompatActivity': 'com.qihoo360.replugin.loader.a.PluginAppCompatXActivity', 'android.preference.PreferenceActivity' : 'com.qihoo360.replugin.loader.a.PluginPreferenceActivity', 'android.app.ExpandableListActivity' : 'com.qihoo360.replugin.loader.a.PluginExpandableListActivity' ] diff --git a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastExprEditor.groovy b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastExprEditor.groovy index 871b403b..e9603ff9 100644 --- a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastExprEditor.groovy +++ b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastExprEditor.groovy @@ -26,7 +26,10 @@ import javassist.expr.MethodCall */ public class LocalBroadcastExprEditor extends ExprEditor { - static def TARGET_CLASS = 'android.support.v4.content.LocalBroadcastManager' + static def TARGET_CLASS = "" + static def includeClass = ['android.support.v4.content.LocalBroadcastManager', + 'androidx.localbroadcastmanager.content.LocalBroadcastManager'] + static def PROXY_CLASS = 'com.qihoo360.replugin.loader.b.PluginLocalBroadcastManager' /** 处理以下方法 */ @@ -41,7 +44,8 @@ public class LocalBroadcastExprEditor extends ExprEditor { @Override void edit(MethodCall call) throws CannotCompileException { - if (call.getClassName().equalsIgnoreCase(TARGET_CLASS)) { + if (call.getClassName() in includeClass ) { + TARGET_CLASS = call.getClassName() if (!(call.getMethodName() in includeMethodCall)) { // println "Skip $methodName" return diff --git a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastInjector.groovy b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastInjector.groovy index fcf297cd..6543c7b8 100644 --- a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastInjector.groovy +++ b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/injector/localbroadcast/LocalBroadcastInjector.groovy @@ -64,7 +64,8 @@ public class LocalBroadcastInjector extends BaseInjector { def stream, ctCls try { // 不处理 LocalBroadcastManager.class - if (filePath.contains('android/support/v4/content/LocalBroadcastManager')) { + if (filePath.contains('android/support/v4/content/LocalBroadcastManager') || + filePath.contains('androidx/localbroadcastmanager/content/LocalBroadcastManager')) { println "Ignore ${filePath}" return super.visitFile(file, attrs) } diff --git a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/manifest/ManifestAPI.groovy b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/manifest/ManifestAPI.groovy index 9948d4e4..40afcb51 100644 --- a/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/manifest/ManifestAPI.groovy +++ b/replugin-plugin-gradle/src/main/groovy/com/qihoo360/replugin/gradle/plugin/manifest/ManifestAPI.groovy @@ -72,7 +72,11 @@ public class ManifestAPI { } else { manifestOutputFile = new File(dir.getAsFile().get(), "AndroidManifest.xml") } - dir = processManifestTask.getInstantRunManifestOutputDirectory() + try { + dir = processManifestTask.getInstantRunManifestOutputDirectory() + }catch(Exception e1){ + dir = processManifestTask.getInstantAppManifestOutputDirectory() + } if (dir instanceof File || dir instanceof String) { instantRunManifestOutputFile = new File(dir, "AndroidManifest.xml") } else { diff --git a/replugin-plugin-library/build.gradle b/replugin-plugin-library/build.gradle index 1777f2bc..5ac48f59 100644 --- a/replugin-plugin-library/build.gradle +++ b/replugin-plugin-library/build.gradle @@ -19,10 +19,11 @@ buildscript { repositories { jcenter() + google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:3.5.4' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' } @@ -31,6 +32,7 @@ buildscript { allprojects { repositories { jcenter() + google() mavenCentral() } } diff --git a/replugin-plugin-library/gradle.properties b/replugin-plugin-library/gradle.properties index b903f115..6ee4857b 100644 --- a/replugin-plugin-library/gradle.properties +++ b/replugin-plugin-library/gradle.properties @@ -31,4 +31,5 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 \ No newline at end of file diff --git a/replugin-plugin-library/gradle/wrapper/gradle-wrapper.properties b/replugin-plugin-library/gradle/wrapper/gradle-wrapper.properties index 5b88596a..435da867 100644 --- a/replugin-plugin-library/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-plugin-library/gradle/wrapper/gradle-wrapper.properties @@ -19,4 +19,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-plugin-library/replugin-plugin-lib/build.gradle b/replugin-plugin-library/replugin-plugin-lib/build.gradle index 8adbbf94..affff1a1 100644 --- a/replugin-plugin-library/replugin-plugin-lib/build.gradle +++ b/replugin-plugin-library/replugin-plugin-lib/build.gradle @@ -17,8 +17,8 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 25 - buildToolsVersion '25.0.2' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 1 @@ -41,7 +41,8 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - provided 'com.android.support:appcompat-v7:23.4.0' + compileOnly 'com.android.support:appcompat-v7:28.+' + compileOnly 'androidx.appcompat:appcompat:1.1.0' } project.ext.RP_ARTIFACT_ID = 'replugin-plugin-lib' diff --git a/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/RePluginFramework.java b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/RePluginFramework.java index 58b816d2..cc29dee7 100644 --- a/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/RePluginFramework.java +++ b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/RePluginFramework.java @@ -47,7 +47,7 @@ public class RePluginFramework { * @param cl * @return 返回true表示运行在HOST中,返回false表示运行的是独立APK */ - static boolean init(ClassLoader cl) { + public static boolean init(ClassLoader cl) { synchronized (LOCK) { return initLocked(cl); } diff --git a/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/a/PluginAppCompatXActivity.java b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/a/PluginAppCompatXActivity.java new file mode 100644 index 00000000..e86121c3 --- /dev/null +++ b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/a/PluginAppCompatXActivity.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2005-2017 Qihoo 360 Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed To in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.qihoo360.replugin.loader.a; + +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; + +import com.qihoo360.replugin.RePluginInternal; +import com.qihoo360.replugin.helper.LogRelease; + +import java.lang.reflect.Field; + +/** + * @author RePlugin Team + */ +public abstract class PluginAppCompatXActivity extends AppCompatActivity { + + @Override + protected void attachBaseContext(Context newBase) { + newBase = RePluginInternal.createActivityContext(this, newBase); + super.attachBaseContext(newBase); + } + + @Override + public Context getBaseContext() { + + return super.getBaseContext(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + // + RePluginInternal.handleActivityCreateBefore(this, savedInstanceState); + + super.onCreate(savedInstanceState); + + // + RePluginInternal.handleActivityCreate(this, savedInstanceState); + } + + @Override + protected void onDestroy() { + // + RePluginInternal.handleActivityDestroy(this); + + super.onDestroy(); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + // + RePluginInternal.handleRestoreInstanceState(this, savedInstanceState); + + try { + super.onRestoreInstanceState(savedInstanceState); + } catch (Throwable e) { + // Added by Jiongxuan Zhang + // Crash Hash: B1F67129BC6A67C882AF2BBE62202BF0 + // java.lang.IllegalArgumentException: Wrong state class异常 + // 原因:恢复现场时,Activity坑位找错了。通常是用于占坑的Activity的层级过深导致 + // 举例:假如我们只有一个坑位可用,A和B分别是清理和通讯录的两个Activity + // 如果进程重启,系统原本恢复B,却走到了A,从而出现此问题 + // 解决:将其Catch住,这样系统在找ViewState时不会出错。 + // 后遗症: + // 1、可能无法恢复系统级View的保存的状态; + // 2、如果自己代码处理不当,可能会出现异常。故自己代码一定要用SecExtraUtils来获取Bundle数据 + if (LogRelease.LOGR) { + LogRelease.e("PluginFragmentActivity", "o r i s: p=" + getPackageCodePath() + "; " + e.getMessage(), e); + } + } + } + + @Override + public void startActivity(Intent intent) { + // + if (RePluginInternal.startActivity(this, intent)) { + // 这个地方不需要回调startActivityAfter,因为RePluginInternal最终还是会回调回来,最终还是要走super.startActivity() + return; + } + + super.startActivity(intent); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode) { + startActivityForResult(intent, requestCode, null); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode, Bundle options) { + // + if (RePluginInternal.startActivityForResult(this, intent, requestCode, options)) { + return; + } + + if (Build.VERSION.SDK_INT >= 16) { + super.startActivityForResult(intent, requestCode, options); + } else { + super.startActivityForResult(intent, requestCode); + } + } + + /** + * 这里的做法是支持Fragment中调用startActivityForResult特性 + *

+ * 由于卫士的插件需要hook住XXX-Activity的startActivity和startActivityForResult接口 + * 但早期版本的support-v4在startActivityFromFragment中直接调用了super.startActivityForResult, 因此这里还需要hook住这个点 + * 但新版的support-v4中Fragment最终的调用链还是会走到本XXX-Activity的startActivityForResult接口,因此不需要适配startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options)接口 + * + * @param fragment + * @param intent + * @param requestCode + */ + @Override + public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { + if (requestCode == -1) { + startActivityForResult(intent, -1); + } else if ((requestCode & -65536) != 0) { + throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); + } else { + int newRequestCode = -1; + try { + Field f = Fragment.class.getDeclaredField("mIndex"); + boolean acc = f.isAccessible(); + if (!acc) { + f.setAccessible(true); + } + Object o = f.get(fragment); + if (!acc) { + f.setAccessible(acc); + } + int index = (Integer) o; + newRequestCode = ((index + 1) << 16) + (requestCode & '\uffff'); + } catch (Throwable e) { + // Do Noting + } + startActivityForResult(intent, newRequestCode); + } + } + + @Override + public String getPackageCodePath() { + return super.getPackageCodePath(); + } +} diff --git a/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/a/PluginFragmentXActivity.java b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/a/PluginFragmentXActivity.java new file mode 100644 index 00000000..95c86530 --- /dev/null +++ b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/a/PluginFragmentXActivity.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2005-2017 Qihoo 360 Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed To in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.qihoo360.replugin.loader.a; + +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; + +import com.qihoo360.replugin.RePluginInternal; +import com.qihoo360.replugin.helper.LogRelease; + +import java.lang.reflect.Field; + +/** + * @author RePlugin Team + */ +public abstract class PluginFragmentXActivity extends FragmentActivity { + + @Override + protected void attachBaseContext(Context newBase) { + newBase = RePluginInternal.createActivityContext(this, newBase); + super.attachBaseContext(newBase); + } + + @Override + public Context getBaseContext() { + + return super.getBaseContext(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + // + RePluginInternal.handleActivityCreateBefore(this, savedInstanceState); + + super.onCreate(savedInstanceState); + + // + RePluginInternal.handleActivityCreate(this, savedInstanceState); + } + + @Override + protected void onDestroy() { + // + RePluginInternal.handleActivityDestroy(this); + + super.onDestroy(); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + // + RePluginInternal.handleRestoreInstanceState(this, savedInstanceState); + + try { + super.onRestoreInstanceState(savedInstanceState); + } catch (Throwable e) { + // Added by Jiongxuan Zhang + // Crash Hash: B1F67129BC6A67C882AF2BBE62202BF0 + // java.lang.IllegalArgumentException: Wrong state class异常 + // 原因:恢复现场时,Activity坑位找错了。通常是用于占坑的Activity的层级过深导致 + // 举例:假如我们只有一个坑位可用,A和B分别是清理和通讯录的两个Activity + // 如果进程重启,系统原本恢复B,却走到了A,从而出现此问题 + // 解决:将其Catch住,这样系统在找ViewState时不会出错。 + // 后遗症: + // 1、可能无法恢复系统级View的保存的状态; + // 2、如果自己代码处理不当,可能会出现异常。故自己代码一定要用SecExtraUtils来获取Bundle数据 + if (LogRelease.LOGR) { + LogRelease.e("PluginFragmentActivity", "o r i s: p=" + getPackageCodePath() + "; " + e.getMessage(), e); + } + } + } + + @Override + public void startActivity(Intent intent) { + // + if (RePluginInternal.startActivity(this, intent)) { + // 这个地方不需要回调startActivityAfter,因为RePluginInternal最终还是会回调回来,最终还是要走super.startActivity() + return; + } + + super.startActivity(intent); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode) { + startActivityForResult(intent, requestCode, null); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode, Bundle options) { + // + if (RePluginInternal.startActivityForResult(this, intent, requestCode, options)) { + return; + } + + if (Build.VERSION.SDK_INT >= 16) { + super.startActivityForResult(intent, requestCode, options); + } else { + super.startActivityForResult(intent, requestCode); + } + } + + /** + * 这里的做法是支持Fragment中调用startActivityForResult特性 + *

+ * 由于卫士的插件需要hook住XXX-Activity的startActivity和startActivityForResult接口 + * 但早期版本的support-v4在startActivityFromFragment中直接调用了super.startActivityForResult, 因此这里还需要hook住这个点 + * 但新版的support-v4中Fragment最终的调用链还是会走到本XXX-Activity的startActivityForResult接口,因此不需要适配startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options)接口 + * + * @param fragment + * @param intent + * @param requestCode + */ + @Override + public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { + if (requestCode == -1) { + startActivityForResult(intent, -1); + } else if ((requestCode & -65536) != 0) { + throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); + } else { + int newRequestCode = -1; + try { + Field f = Fragment.class.getDeclaredField("mIndex"); + boolean acc = f.isAccessible(); + if (!acc) { + f.setAccessible(true); + } + Object o = f.get(fragment); + if (!acc) { + f.setAccessible(acc); + } + int index = (Integer) o; + newRequestCode = ((index + 1) << 16) + (requestCode & '\uffff'); + } catch (Throwable e) { + // Do Noting + } + startActivityForResult(intent, newRequestCode); + } + } + + @Override + public String getPackageCodePath() { + return super.getPackageCodePath(); + } +} diff --git a/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/b/PluginLocalBroadcastManager.java b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/b/PluginLocalBroadcastManager.java index daa3fd5a..93c28192 100644 --- a/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/b/PluginLocalBroadcastManager.java +++ b/replugin-plugin-library/replugin-plugin-lib/src/main/java/com/qihoo360/replugin/loader/b/PluginLocalBroadcastManager.java @@ -390,12 +390,34 @@ public static class ProxyLocalBroadcastManagerVar { public static void initLocked(final ClassLoader classLoader) { // 填充LocalBroadcastManager各方法 - final String localBroadcastManager = "android.support.v4.content.LocalBroadcastManager"; - getInstance = new MethodInvoker(classLoader, localBroadcastManager, "getInstance", new Class[]{Context.class}); - registerReceiver = new MethodInvoker(classLoader, localBroadcastManager, "registerReceiver", new Class[]{BroadcastReceiver.class, IntentFilter.class}); - unregisterReceiver = new MethodInvoker(classLoader, localBroadcastManager, "unregisterReceiver", new Class[]{BroadcastReceiver.class}); - sendBroadcast = new MethodInvoker(classLoader, localBroadcastManager, "sendBroadcast", new Class[]{Intent.class}); - sendBroadcastSync = new MethodInvoker(classLoader, localBroadcastManager, "sendBroadcastSync", new Class[]{Intent.class}); + final String localBroadcastManagerX = "androidx.localbroadcastmanager.content.LocalBroadcastManager"; + //在android x 编译环境下,如果开启了android.enableJetifier,编译时会把support 相关的常量字符串替换为android x的路径,所以这个地方用运行时赋值 + String localBroadcastManagerV4 = ""; + if (classLoader != null) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("android"); + stringBuilder.append("."); + stringBuilder.append("support"); + stringBuilder.append("."); + stringBuilder.append("v4"); + stringBuilder.append("."); + stringBuilder.append("content"); + stringBuilder.append("."); + stringBuilder.append("LocalBroadcastManager"); + localBroadcastManagerV4 = stringBuilder.toString(); + } + + String target = localBroadcastManagerX; + try { + classLoader.loadClass(target); + } catch (Exception e){ + target = localBroadcastManagerV4; + } + getInstance = new MethodInvoker(classLoader, target, "getInstance", new Class[]{Context.class}); + registerReceiver = new MethodInvoker(classLoader, target, "registerReceiver", new Class[]{BroadcastReceiver.class, IntentFilter.class}); + unregisterReceiver = new MethodInvoker(classLoader, target, "unregisterReceiver", new Class[]{BroadcastReceiver.class}); + sendBroadcast = new MethodInvoker(classLoader, target, "sendBroadcast", new Class[]{Intent.class}); + sendBroadcastSync = new MethodInvoker(classLoader, target, "sendBroadcastSync", new Class[]{Intent.class}); } } } diff --git a/replugin-sample/host/app/build.gradle b/replugin-sample/host/app/build.gradle index 6b97f1d8..b19bfdb6 100644 --- a/replugin-sample/host/app/build.gradle +++ b/replugin-sample/host/app/build.gradle @@ -17,12 +17,12 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { applicationId "com.qihoo360.replugin.sample.host" - minSdkVersion 9 - targetSdkVersion 22 + minSdkVersion 14 + targetSdkVersion 28 versionCode 1 versionName "1.0" } @@ -37,13 +37,14 @@ android { apply plugin: 'replugin-host-gradle' repluginHostConfig { useAppCompat = true - + useAndroidX = true // 可以在这里自定义常驻进程的名字 // persistentName = ":XXXXService" } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:25.3.1' - compile "com.qihoo360.replugin:replugin-host-lib:${RP_VERSION}" + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' + implementation "com.qihoo360.replugin:replugin-host-lib:${RP_VERSION}" } diff --git a/replugin-sample/host/app/libs/common-utils-lib-1.0.0.jar b/replugin-sample/host/app/libs/common-utils-lib-1.0.0.jar deleted file mode 100644 index 5aca528c..00000000 Binary files a/replugin-sample/host/app/libs/common-utils-lib-1.0.0.jar and /dev/null differ diff --git a/replugin-sample/host/app/src/main/assets/external/demo3.apk b/replugin-sample/host/app/src/main/assets/external/demo3.apk index f3ec344e..658d0207 100644 Binary files a/replugin-sample/host/app/src/main/assets/external/demo3.apk and b/replugin-sample/host/app/src/main/assets/external/demo3.apk differ diff --git a/replugin-sample/host/app/src/main/assets/plugins/demo1.jar b/replugin-sample/host/app/src/main/assets/plugins/demo1.jar index 6fa856b6..e3c74f1a 100644 Binary files a/replugin-sample/host/app/src/main/assets/plugins/demo1.jar and b/replugin-sample/host/app/src/main/assets/plugins/demo1.jar differ diff --git a/replugin-sample/host/app/src/main/assets/plugins/demo2.jar b/replugin-sample/host/app/src/main/assets/plugins/demo2.jar index f09beea7..a8fd7afb 100644 Binary files a/replugin-sample/host/app/src/main/assets/plugins/demo2.jar and b/replugin-sample/host/app/src/main/assets/plugins/demo2.jar differ diff --git a/replugin-sample/host/app/src/main/assets/plugins/webview.jar b/replugin-sample/host/app/src/main/assets/plugins/webview.jar index a3c973bc..c09aa456 100644 Binary files a/replugin-sample/host/app/src/main/assets/plugins/webview.jar and b/replugin-sample/host/app/src/main/assets/plugins/webview.jar differ diff --git a/replugin-sample/host/app/src/main/java/com/qihoo360/replugin/sample/host/PluginFragmentActivity.java b/replugin-sample/host/app/src/main/java/com/qihoo360/replugin/sample/host/PluginFragmentActivity.java index c398df9c..286442e7 100644 --- a/replugin-sample/host/app/src/main/java/com/qihoo360/replugin/sample/host/PluginFragmentActivity.java +++ b/replugin-sample/host/app/src/main/java/com/qihoo360/replugin/sample/host/PluginFragmentActivity.java @@ -1,9 +1,10 @@ package com.qihoo360.replugin.sample.host; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; import com.qihoo360.replugin.RePlugin; diff --git a/replugin-sample/host/utils/src/main/java/com/qihoo360/replugin/common/utils/TimeUtils.java b/replugin-sample/host/app/src/main/java/com/qihoo360/replugin/sample/host/TimeUtils.java similarity index 97% rename from replugin-sample/host/utils/src/main/java/com/qihoo360/replugin/common/utils/TimeUtils.java rename to replugin-sample/host/app/src/main/java/com/qihoo360/replugin/sample/host/TimeUtils.java index 8d0873c2..f0aabb1e 100644 --- a/replugin-sample/host/utils/src/main/java/com/qihoo360/replugin/common/utils/TimeUtils.java +++ b/replugin-sample/host/app/src/main/java/com/qihoo360/replugin/sample/host/TimeUtils.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.qihoo360.replugin.common.utils; +package com.qihoo360.replugin.sample.host; import java.text.DateFormat; import java.text.SimpleDateFormat; diff --git a/replugin-sample/host/build.gradle b/replugin-sample/host/build.gradle index b879ef4c..179536c6 100644 --- a/replugin-sample/host/build.gradle +++ b/replugin-sample/host/build.gradle @@ -18,9 +18,11 @@ buildscript { repositories { mavenLocal() jcenter() + mavenCentral() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.5.4' classpath "com.qihoo360.replugin:replugin-host-gradle:${RP_VERSION}" } } @@ -29,6 +31,8 @@ allprojects { repositories { mavenLocal() jcenter() + mavenCentral() + google() } } diff --git a/replugin-sample/host/gradle.properties b/replugin-sample/host/gradle.properties index ac69367c..9462b6b8 100644 --- a/replugin-sample/host/gradle.properties +++ b/replugin-sample/host/gradle.properties @@ -31,3 +31,6 @@ org.gradle.jvmargs=-Xmx1536m # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true +android.useAndroidX=true +android.enableJetifier=true +android.injected.testOnly=false \ No newline at end of file diff --git a/replugin-sample/host/gradle/wrapper/gradle-wrapper.properties b/replugin-sample/host/gradle/wrapper/gradle-wrapper.properties index 9fd928c2..a2b396ae 100644 --- a/replugin-sample/host/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-sample/host/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-sample/host/settings.gradle b/replugin-sample/host/settings.gradle index 42331fec..a1101692 100644 --- a/replugin-sample/host/settings.gradle +++ b/replugin-sample/host/settings.gradle @@ -14,4 +14,4 @@ * the License. */ -include ':app', ':utils' +include ':app' diff --git a/replugin-sample/host/utils/build.gradle b/replugin-sample/host/utils/build.gradle deleted file mode 100644 index 699742c9..00000000 --- a/replugin-sample/host/utils/build.gradle +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2017 Qihoo 360 Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed To in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -apply plugin: 'com.android.application' - -android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" - - defaultConfig { - applicationId "com.qihoo360.replugin.common.utils" - minSdkVersion 9 - targetSdkVersion 22 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:support-v4:25.3.1' -} - -task makeJar(type: Jar, dependsOn: ['build']) { - destinationDir = file('build/outputs/jar/') - baseName = "common-utils-lib" - version = "1.0.0" - from('build/intermediates/classes/debug') - exclude('**/BuildConfig.class') - exclude('**/BuildConfig\$*.class') - exclude('**/R.class') - exclude('**/R\$*.class') - include('**/*.class') -} \ No newline at end of file diff --git a/replugin-sample/host/utils/proguard-rules.pro b/replugin-sample/host/utils/proguard-rules.pro deleted file mode 100644 index 7221de19..00000000 --- a/replugin-sample/host/utils/proguard-rules.pro +++ /dev/null @@ -1,25 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in D:\Liuzhiwei-ms\Android\sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/replugin-sample/host/utils/src/main/AndroidManifest.xml b/replugin-sample/host/utils/src/main/AndroidManifest.xml deleted file mode 100644 index c4c3e4f7..00000000 --- a/replugin-sample/host/utils/src/main/AndroidManifest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/replugin-sample/plugin/plugin-demo1/app/build.gradle b/replugin-sample/plugin/plugin-demo1/app/build.gradle index 9b987064..8c51822c 100644 --- a/replugin-sample/plugin/plugin-demo1/app/build.gradle +++ b/replugin-sample/plugin/plugin-demo1/app/build.gradle @@ -22,13 +22,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion '25.0.0' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { versionName "1.1" versionCode 104 - targetSdkVersion 21 + targetSdkVersion 28 applicationId "com.qihoo360.replugin.sample.demo1" minSdkVersion 15 multiDexEnabled false @@ -66,11 +66,8 @@ repluginPluginConfig { } dependencies { - compile "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" - provided files('libs/fragment.jar')//这个jar就是从Support-fragment中提取出来的并非特制包目的是为了骗过编译期 - provided files('libs/common-utils-lib-1.0.0.jar')//这个jar就是从Host的utils中编译生成的,其目的是为了骗过编译期 - compile(name: 'plugin-library', ext: 'aar')//sample:compile aar - + implementation "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" + compileOnly 'androidx.appcompat:appcompat:1.3.1' } if (android.defaultConfig.multiDexEnabled) { diff --git a/replugin-sample/plugin/plugin-demo1/app/libs/common-utils-lib-1.0.0.jar b/replugin-sample/plugin/plugin-demo1/app/libs/common-utils-lib-1.0.0.jar deleted file mode 100644 index 5aca528c..00000000 Binary files a/replugin-sample/plugin/plugin-demo1/app/libs/common-utils-lib-1.0.0.jar and /dev/null differ diff --git a/replugin-sample/plugin/plugin-demo1/app/libs/fragment.jar b/replugin-sample/plugin/plugin-demo1/app/libs/fragment.jar deleted file mode 100644 index 04764507..00000000 Binary files a/replugin-sample/plugin/plugin-demo1/app/libs/fragment.jar and /dev/null differ diff --git a/replugin-sample/plugin/plugin-demo1/app/libs/plugin-library.aar b/replugin-sample/plugin/plugin-demo1/app/libs/plugin-library.aar deleted file mode 100644 index eaf2cfc4..00000000 Binary files a/replugin-sample/plugin/plugin-demo1/app/libs/plugin-library.aar and /dev/null differ diff --git a/replugin-sample/plugin/plugin-demo1/app/src/main/AndroidManifest.xml b/replugin-sample/plugin/plugin-demo1/app/src/main/AndroidManifest.xml index e9d309cf..0bcf2151 100644 --- a/replugin-sample/plugin/plugin-demo1/app/src/main/AndroidManifest.xml +++ b/replugin-sample/plugin/plugin-demo1/app/src/main/AndroidManifest.xml @@ -174,5 +174,10 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/fileprovider_path" /> + + + diff --git a/replugin-sample/plugin/plugin-demo1/library/src/main/java/com/qihoo360/replugin/sample/library/LibMainActivity.java b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/LibMainActivity.java similarity index 85% rename from replugin-sample/plugin/plugin-demo1/library/src/main/java/com/qihoo360/replugin/sample/library/LibMainActivity.java rename to replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/LibMainActivity.java index 666c4dfa..2ef4d054 100644 --- a/replugin-sample/plugin/plugin-demo1/library/src/main/java/com/qihoo360/replugin/sample/library/LibMainActivity.java +++ b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/LibMainActivity.java @@ -1,4 +1,4 @@ -package com.qihoo360.replugin.sample.library; +package com.qihoo360.replugin.sample.demo1; import android.app.Activity; import android.os.Bundle; diff --git a/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/MainActivity.java b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/MainActivity.java index a11b23c7..df2edf8a 100644 --- a/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/MainActivity.java +++ b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/MainActivity.java @@ -39,7 +39,6 @@ import android.widget.Toast; import com.qihoo360.replugin.RePlugin; -import com.qihoo360.replugin.common.utils.TimeUtils; import com.qihoo360.replugin.sample.demo1.activity.file_provider.FileProviderActivity; import com.qihoo360.replugin.sample.demo1.activity.notify_test.NotifyActivity; import com.qihoo360.replugin.sample.demo1.activity.preference.PrefActivity2; @@ -54,7 +53,6 @@ import com.qihoo360.replugin.sample.demo1.service.PluginDemoService1; import com.qihoo360.replugin.sample.demo1.support.NotifyUtils; import com.qihoo360.replugin.sample.demo2.IDemo2; -import com.qihoo360.replugin.sample.library.LibMainActivity; import java.lang.reflect.Method; import java.util.ArrayList; diff --git a/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/TimeUtils.java b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/TimeUtils.java new file mode 100644 index 00000000..efac8823 --- /dev/null +++ b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/TimeUtils.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2017 Qihoo 360 Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed To in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.qihoo360.replugin.sample.demo1; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * @author RePlugin Team + */ +public class TimeUtils { + + private static final DateFormat DEFAULT_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); + + /** + * 将时间戳转为时间字符串 + * 格式为yyyy-MM-dd HH:mm:ss

+ * + * @param millis 毫秒时间戳 + * @return 时间字符串 + */ + public static String millis2String(final long millis) { + return millis2String(millis, DEFAULT_FORMAT); + } + + /** + * 将时间戳转为时间字符串 + * 格式为format

+ * + * @param millis 毫秒时间戳 + * @param format 时间格式 + * @return 时间字符串 + */ + public static String millis2String(final long millis, final DateFormat format) { + return format.format(new Date(millis)); + } + + /** + * 获取当前时间字符串 + * 格式为yyyy-MM-dd HH:mm:ss

+ * + * @return 时间字符串 + */ + public static String getNowString() { + return millis2String(System.currentTimeMillis(), DEFAULT_FORMAT); + } + + /** + * 获取当前时间字符串 + * 格式为format

+ * + * @param format 时间格式 + * @return 时间字符串 + */ + public static String getNowString(final DateFormat format) { + return millis2String(System.currentTimeMillis(), format); + } +} diff --git a/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/fragment/DemoFragment.java b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/fragment/DemoFragment.java index 2d8259b2..b6b1758f 100644 --- a/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/fragment/DemoFragment.java +++ b/replugin-sample/plugin/plugin-demo1/app/src/main/java/com/qihoo360/replugin/sample/demo1/fragment/DemoFragment.java @@ -1,12 +1,13 @@ package com.qihoo360.replugin.sample.demo1.fragment; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.fragment.app.Fragment; + import com.qihoo360.replugin.RePlugin; import com.qihoo360.replugin.sample.demo1.R; diff --git a/replugin-sample/plugin/plugin-demo1/library/src/main/res/layout/content_lib_main.xml b/replugin-sample/plugin/plugin-demo1/app/src/main/res/layout/content_lib_main.xml similarity index 100% rename from replugin-sample/plugin/plugin-demo1/library/src/main/res/layout/content_lib_main.xml rename to replugin-sample/plugin/plugin-demo1/app/src/main/res/layout/content_lib_main.xml diff --git a/replugin-sample/plugin/plugin-demo1/library/src/main/res/layout/lib_activity_main.xml b/replugin-sample/plugin/plugin-demo1/app/src/main/res/layout/lib_activity_main.xml similarity index 100% rename from replugin-sample/plugin/plugin-demo1/library/src/main/res/layout/lib_activity_main.xml rename to replugin-sample/plugin/plugin-demo1/app/src/main/res/layout/lib_activity_main.xml diff --git a/replugin-sample/plugin/plugin-demo1/build.gradle b/replugin-sample/plugin/plugin-demo1/build.gradle index 8f2deea3..c1d8a4a2 100644 --- a/replugin-sample/plugin/plugin-demo1/build.gradle +++ b/replugin-sample/plugin/plugin-demo1/build.gradle @@ -18,9 +18,11 @@ buildscript { repositories { mavenLocal() jcenter() + mavenCentral() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.5.4' classpath "com.qihoo360.replugin:replugin-plugin-gradle:${RP_VERSION}" } } @@ -29,6 +31,8 @@ allprojects { repositories { mavenLocal() jcenter() + mavenCentral() + google() } } diff --git a/replugin-sample/plugin/plugin-demo1/gradle.properties b/replugin-sample/plugin/plugin-demo1/gradle.properties index ba072bc6..ce9e92f0 100644 --- a/replugin-sample/plugin/plugin-demo1/gradle.properties +++ b/replugin-sample/plugin/plugin-demo1/gradle.properties @@ -31,4 +31,7 @@ org.gradle.jvmargs=-Xmx1536M # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.useAndroidX=true +android.enableJetifier=true +android.injected.testOnly=false \ No newline at end of file diff --git a/replugin-sample/plugin/plugin-demo1/gradle/wrapper/gradle-wrapper.properties b/replugin-sample/plugin/plugin-demo1/gradle/wrapper/gradle-wrapper.properties index 2a2f4342..15955579 100644 --- a/replugin-sample/plugin/plugin-demo1/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-sample/plugin/plugin-demo1/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-sample/plugin/plugin-demo1/library/.gitignore b/replugin-sample/plugin/plugin-demo1/library/.gitignore deleted file mode 100644 index 796b96d1..00000000 --- a/replugin-sample/plugin/plugin-demo1/library/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/replugin-sample/plugin/plugin-demo1/library/build.gradle b/replugin-sample/plugin/plugin-demo1/library/build.gradle deleted file mode 100644 index 2bffc915..00000000 --- a/replugin-sample/plugin/plugin-demo1/library/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 25 - buildToolsVersion "25.0.0" - - defaultConfig { - minSdkVersion 15 - targetSdkVersion 25 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - lintOptions { - abortOnError false - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - compile 'com.android.support:appcompat-v7:25.3.1' - testCompile 'junit:junit:4.12' -} - - -//task to copy library to libs -task copyLibrary(type: Copy) { - - from('build/outputs/aar/library-debug.aar') - into('../app/libs') - ///Rename the aar - rename('library-debug.aar', 'plugin-library.aar') -} - -copyLibrary.dependsOn(build) diff --git a/replugin-sample/plugin/plugin-demo1/library/proguard-rules.pro b/replugin-sample/plugin/plugin-demo1/library/proguard-rules.pro deleted file mode 100644 index 9786e21b..00000000 --- a/replugin-sample/plugin/plugin-demo1/library/proguard-rules.pro +++ /dev/null @@ -1,25 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in D:\Android\sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/replugin-sample/plugin/plugin-demo1/library/src/androidTest/java/com/qihoo360/replugin/sample/library/ExampleInstrumentedTest.java b/replugin-sample/plugin/plugin-demo1/library/src/androidTest/java/com/qihoo360/replugin/sample/library/ExampleInstrumentedTest.java deleted file mode 100644 index f0b47140..00000000 --- a/replugin-sample/plugin/plugin-demo1/library/src/androidTest/java/com/qihoo360/replugin/sample/library/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.qihoo360.replugin.sample.library; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.qihoo360.replugin.sample.library.test", appContext.getPackageName()); - } -} diff --git a/replugin-sample/plugin/plugin-demo1/library/src/main/AndroidManifest.xml b/replugin-sample/plugin/plugin-demo1/library/src/main/AndroidManifest.xml deleted file mode 100644 index 24bfa003..00000000 --- a/replugin-sample/plugin/plugin-demo1/library/src/main/AndroidManifest.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/replugin-sample/plugin/plugin-demo1/library/src/main/res/values/strings.xml b/replugin-sample/plugin/plugin-demo1/library/src/main/res/values/strings.xml deleted file mode 100644 index 49fc91e1..00000000 --- a/replugin-sample/plugin/plugin-demo1/library/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - library - diff --git a/replugin-sample/plugin/plugin-demo1/library/src/test/java/com/qihoo360/replugin/sample/library/ExampleUnitTest.java b/replugin-sample/plugin/plugin-demo1/library/src/test/java/com/qihoo360/replugin/sample/library/ExampleUnitTest.java deleted file mode 100644 index 25b4b9dc..00000000 --- a/replugin-sample/plugin/plugin-demo1/library/src/test/java/com/qihoo360/replugin/sample/library/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.qihoo360.replugin.sample.library; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/replugin-sample/plugin/plugin-demo1/settings.gradle b/replugin-sample/plugin/plugin-demo1/settings.gradle index c3d5e10d..a1101692 100644 --- a/replugin-sample/plugin/plugin-demo1/settings.gradle +++ b/replugin-sample/plugin/plugin-demo1/settings.gradle @@ -14,4 +14,4 @@ * the License. */ -include ':app', ':library' +include ':app' diff --git a/replugin-sample/plugin/plugin-demo2/app/build.gradle b/replugin-sample/plugin/plugin-demo2/app/build.gradle index 00560a3d..544f3434 100644 --- a/replugin-sample/plugin/plugin-demo2/app/build.gradle +++ b/replugin-sample/plugin/plugin-demo2/app/build.gradle @@ -22,13 +22,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion '25.0.0' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { versionName "1.1" versionCode 104 - targetSdkVersion 21 + targetSdkVersion 28 applicationId "com.qihoo360.replugin.sample.demo2" minSdkVersion 15 multiDexEnabled false @@ -64,9 +64,9 @@ repluginPluginConfig { } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:25.3.1' - compile "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" } if (android.defaultConfig.multiDexEnabled) { diff --git a/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/activity/appcompat/AppCompatActivityDemo.java b/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/activity/appcompat/AppCompatActivityDemo.java index 1dd6de41..a108eefd 100644 --- a/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/activity/appcompat/AppCompatActivityDemo.java +++ b/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/activity/appcompat/AppCompatActivityDemo.java @@ -1,12 +1,13 @@ package com.qihoo360.replugin.sample.demo2.activity.appcompat; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v7.app.AppCompatActivity; import android.view.Gravity; import android.widget.FrameLayout; import android.widget.TextView; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; /** diff --git a/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/databinding/DataBindingActivity.java b/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/databinding/DataBindingActivity.java index 59e7d905..2d808afd 100644 --- a/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/databinding/DataBindingActivity.java +++ b/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/databinding/DataBindingActivity.java @@ -17,9 +17,10 @@ package com.qihoo360.replugin.sample.demo2.databinding; import android.app.Activity; -import android.databinding.DataBindingUtil; import android.os.Bundle; +import androidx.databinding.DataBindingUtil; + import com.qihoo360.replugin.sample.demo2.R; /** diff --git a/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/service/PluginDemo2Service.java b/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/service/PluginDemo2Service.java index 8d0f59ae..152f410d 100644 --- a/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/service/PluginDemo2Service.java +++ b/replugin-sample/plugin/plugin-demo2/app/src/main/java/com/qihoo360/replugin/sample/demo2/service/PluginDemo2Service.java @@ -19,9 +19,10 @@ import android.app.Service; import android.content.Intent; import android.os.IBinder; -import android.support.annotation.Nullable; import android.widget.Toast; +import androidx.annotation.Nullable; + /** * @author RePlugin Team */ diff --git a/replugin-sample/plugin/plugin-demo2/build.gradle b/replugin-sample/plugin/plugin-demo2/build.gradle index 8f2deea3..c1d8a4a2 100644 --- a/replugin-sample/plugin/plugin-demo2/build.gradle +++ b/replugin-sample/plugin/plugin-demo2/build.gradle @@ -18,9 +18,11 @@ buildscript { repositories { mavenLocal() jcenter() + mavenCentral() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.5.4' classpath "com.qihoo360.replugin:replugin-plugin-gradle:${RP_VERSION}" } } @@ -29,6 +31,8 @@ allprojects { repositories { mavenLocal() jcenter() + mavenCentral() + google() } } diff --git a/replugin-sample/plugin/plugin-demo2/gradle.properties b/replugin-sample/plugin/plugin-demo2/gradle.properties index ba072bc6..ce9e92f0 100644 --- a/replugin-sample/plugin/plugin-demo2/gradle.properties +++ b/replugin-sample/plugin/plugin-demo2/gradle.properties @@ -31,4 +31,7 @@ org.gradle.jvmargs=-Xmx1536M # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.useAndroidX=true +android.enableJetifier=true +android.injected.testOnly=false \ No newline at end of file diff --git a/replugin-sample/plugin/plugin-demo2/gradle/wrapper/gradle-wrapper.properties b/replugin-sample/plugin/plugin-demo2/gradle/wrapper/gradle-wrapper.properties index 99639ba7..89cfee56 100644 --- a/replugin-sample/plugin/plugin-demo2/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-sample/plugin/plugin-demo2/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-sample/plugin/plugin-demo3-kotlin/app/build.gradle b/replugin-sample/plugin/plugin-demo3-kotlin/app/build.gradle index 09562afe..bc36e7c2 100644 --- a/replugin-sample/plugin/plugin-demo3-kotlin/app/build.gradle +++ b/replugin-sample/plugin/plugin-demo3-kotlin/app/build.gradle @@ -24,13 +24,13 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 25 - buildToolsVersion '25.0.0' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { versionName "1.0" versionCode 100 - targetSdkVersion 21 + targetSdkVersion 28 applicationId "com.qihoo360.replugin.sample.demo3" minSdkVersion 15 } @@ -54,10 +54,9 @@ android { dependencies { - compile "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" - provided files('libs/fragment.jar') - compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" - //这个jar就是从Support-fragment中提取出来的并非特制包目的是为了骗过编译期 + implementation "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } // 这个plugin需要放在android配置之后,因为需要读取android中的配置项 diff --git a/replugin-sample/plugin/plugin-demo3-kotlin/app/libs/fragment.jar b/replugin-sample/plugin/plugin-demo3-kotlin/app/libs/fragment.jar deleted file mode 100644 index 04764507..00000000 Binary files a/replugin-sample/plugin/plugin-demo3-kotlin/app/libs/fragment.jar and /dev/null differ diff --git a/replugin-sample/plugin/plugin-demo3-kotlin/build.gradle b/replugin-sample/plugin/plugin-demo3-kotlin/build.gradle index 8538d4e4..80fb58c7 100644 --- a/replugin-sample/plugin/plugin-demo3-kotlin/build.gradle +++ b/replugin-sample/plugin/plugin-demo3-kotlin/build.gradle @@ -15,13 +15,15 @@ */ buildscript { { p, cfg = "rp-config.gradle" -> if (new File(p, cfg).exists()) apply from: "${p}/${cfg}" else if (p.exists()) call(p.parentFile) }(buildscript.sourceFile.parentFile) - ext.kotlin_version = '1.1.3' + ext.kotlin_version = '1.3.72' repositories { mavenLocal() jcenter() + mavenCentral() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.5.4' classpath "com.qihoo360.replugin:replugin-plugin-gradle:${RP_VERSION}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } @@ -31,6 +33,8 @@ allprojects { repositories { mavenLocal() jcenter() + mavenCentral() + google() } } diff --git a/replugin-sample/plugin/plugin-demo3-kotlin/gradle.properties b/replugin-sample/plugin/plugin-demo3-kotlin/gradle.properties index 4de4515c..a5122b10 100644 --- a/replugin-sample/plugin/plugin-demo3-kotlin/gradle.properties +++ b/replugin-sample/plugin/plugin-demo3-kotlin/gradle.properties @@ -13,3 +13,6 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Tue Jul 11 21:08:48 CST 2017 +android.useAndroidX=true +android.enableJetifier=true +android.injected.testOnly=false diff --git a/replugin-sample/plugin/plugin-demo3-kotlin/gradle/wrapper/gradle-wrapper.properties b/replugin-sample/plugin/plugin-demo3-kotlin/gradle/wrapper/gradle-wrapper.properties index 2a2f4342..15955579 100644 --- a/replugin-sample/plugin/plugin-demo3-kotlin/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-sample/plugin/plugin-demo3-kotlin/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/replugin-sample/plugin/plugin-webview/app/build.gradle b/replugin-sample/plugin/plugin-webview/app/build.gradle index 3528d971..d71b969f 100644 --- a/replugin-sample/plugin/plugin-webview/app/build.gradle +++ b/replugin-sample/plugin/plugin-webview/app/build.gradle @@ -22,13 +22,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion '25.0.0' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { versionName "1.1" versionCode 100 - targetSdkVersion 21 + targetSdkVersion 28 applicationId "com.qihoo360.replugin.sample.webview" minSdkVersion 15 multiDexEnabled false @@ -60,7 +60,7 @@ repluginPluginConfig { } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:25.3.1' - compile "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation "com.qihoo360.replugin:replugin-plugin-lib:${RP_VERSION}" } \ No newline at end of file diff --git a/replugin-sample/plugin/plugin-webview/build.gradle b/replugin-sample/plugin/plugin-webview/build.gradle index 8f2deea3..c1d8a4a2 100644 --- a/replugin-sample/plugin/plugin-webview/build.gradle +++ b/replugin-sample/plugin/plugin-webview/build.gradle @@ -18,9 +18,11 @@ buildscript { repositories { mavenLocal() jcenter() + mavenCentral() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.5.4' classpath "com.qihoo360.replugin:replugin-plugin-gradle:${RP_VERSION}" } } @@ -29,6 +31,8 @@ allprojects { repositories { mavenLocal() jcenter() + mavenCentral() + google() } } diff --git a/replugin-sample/plugin/plugin-webview/gradle.properties b/replugin-sample/plugin/plugin-webview/gradle.properties index ba072bc6..ce9e92f0 100644 --- a/replugin-sample/plugin/plugin-webview/gradle.properties +++ b/replugin-sample/plugin/plugin-webview/gradle.properties @@ -31,4 +31,7 @@ org.gradle.jvmargs=-Xmx1536M # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.useAndroidX=true +android.enableJetifier=true +android.injected.testOnly=false \ No newline at end of file diff --git a/replugin-sample/plugin/plugin-webview/gradle/wrapper/gradle-wrapper.properties b/replugin-sample/plugin/plugin-webview/gradle/wrapper/gradle-wrapper.properties index 99639ba7..89cfee56 100644 --- a/replugin-sample/plugin/plugin-webview/gradle/wrapper/gradle-wrapper.properties +++ b/replugin-sample/plugin/plugin-webview/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/rp-config.gradle b/rp-config.gradle index 8fbf949f..d7bff14b 100644 --- a/rp-config.gradle +++ b/rp-config.gradle @@ -11,5 +11,6 @@ project.ext{ RP_LICENSES_NAME = 'Apache-2.0' // RP_GROUP = 'com.qihoo360.replugin' - RP_VERSION = '2.3.4' + RP_VERSION = '3.0.0' + } \ No newline at end of file