Skip to content

Commit

Permalink
feat:支持androidx-v1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
guidongqi committed Nov 8, 2019
1 parent afac4a1 commit 563ec41
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 25 deletions.
5 changes: 3 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ buildscript {
jcenter()
mavenCentral()
maven {url 'https://dl.bintray.com/a10188755550/maven'}

}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath 'com.android.tools.build:gradle:3.5.2'
classpath 'com.novoda:bintray-release:0.9.1'
classpath 'com.github.jokar:multi-languages.plugin:0.0.5'
classpath "com.github.jokar:multi-languages.plugin:0.0.5"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
Expand Down
4 changes: 3 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,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.enableD8=true
android.enableD8=true

version=0.0.6
2 changes: 1 addition & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ publish {
userOrg = 'a10188755550'
groupId = 'com.github.jokar'
artifactId = 'multi-languages'
publishVersion = '0.0.5'
publishVersion = "$version"
desc = 'android multi language support (support android O+)'
website = 'https://github.com/MichaelJokAr/MultiLanguages'
}
4 changes: 2 additions & 2 deletions plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ publish {
userOrg = 'a10188755550'
groupId = 'com.github.jokar'
artifactId = 'multi-languages.plugin'
publishVersion = '0.0.5'
publishVersion = "$version"
desc = 'android multi language support (support android O+)'
website = 'https://github.com/MichaelJokAr/MultiLanguages'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,19 @@ class MultiLanguagesTransform extends Transform {
private static void addAttachMethod(ActivityServiceClassVisitor cv, name, ClassWriter classWriter) {
if (cv.needAddAttach()) {
println("add attach method to ${name}")
if(cv.activity) {
//添加attachBaseContext方法
if (cv.activity) {
MethodVisitorUtil.addActivityAttach(classWriter)
}else if(cv.service){
} else if (cv.service) {
MethodVisitorUtil.addServiceAttach(classWriter)
}else if(cv.intentService){
} else if (cv.intentService) {
MethodVisitorUtil.addIntentServiceAttach(classWriter)
}
//添加applyOverrideConfiguration方法
if (cv.needAddACMethod()) {
println("add applyOverrideConfiguration method to ${name}")
MethodVisitorUtil.addApplyOverrideConfiguration(classWriter, cv.className)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ class PluginExtension {
String toString() {
return "PluginExtension{" +
"enable=" + enable +
'}';
'}'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
*/
public class ActivityServiceClassVisitor extends ClassVisitor implements Opcodes {
private String superClassName;
private String className;
/**
* 是否有applyOverrideConfiguration方法
*/
private boolean hasACMethod;

public ActivityServiceClassVisitor(ClassWriter cv) {
super(Opcodes.ASM5, cv);
Expand All @@ -20,36 +25,99 @@ public void visit(int version, int access, String name, String signature, String
String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
superClassName = superName;
this.className = name;
}

@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
//删除原有 attachBaseContext 方法
if (needAddAttach() && name.equals("attachBaseContext")) {
return null;
if (needAddAttach()) {
hasACMethod = name.equals("applyOverrideConfiguration");
if (name.equals("attachBaseContext")) {
//删除原有 attachBaseContext 方法
return null;
} else if (isAndroidxActivity() && name.equals("applyOverrideConfiguration")) {
//是继承androidx.AppCompatActivity的activity,在 applyOverrideConfiguration
//添加 overrideConfiguration.setTo(this.getBaseContext().getResources().getConfiguration());
return new ApplyOverrideConfigurationMV(cv.visitMethod(access, name, descriptor,
signature, exceptions), this.className);
}
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}

/**
* 是否需要添加
*
* @return
*/
public boolean needAddAttach() {
return isActivity() || isService() || isIntentService();
}

/**
* 是否需要添加applyOverrideConfiguration方法
*
* @return
*/
public boolean needAddACMethod() {
return isAndroidxActivity() && !hasACMethod;
}

/**
* 是否是Activity类
*
* @return
*/
public boolean isActivity() {
return superClassName.equals("android/support/v4/app/FragmentActivity")
if (className == null || superClassName == null) {
return false;
}
return (superClassName.equals("android/support/v4/app/FragmentActivity")
|| superClassName.equals("android/support/v7/app/AppCompatActivity")
|| superClassName.equals("android/app/Activity");
|| superClassName.equals("android/app/Activity")
|| isAndroidxActivity())
&& !isAndroidxPackageName(); //排除androidx包里的
}

/**
* 是否是继承androidx.AppCompatActivity activity
*
* @return
*/
private boolean isAndroidxActivity() {
if (superClassName == null) {
return false;
}
return superClassName.equals("androidx/appcompat/app/AppCompatActivity");
}

/**
* 是否是androidx包名下类
*
* @return
*/
public boolean isAndroidxPackageName() {
return className.contains("androidx/core/app");
}

public boolean isService() {
return superClassName.equals("android/app/Service");
if (className == null || superClassName == null) {
return false;
}
return superClassName.equals("android/app/Service")
&& !isAndroidxPackageName(); //排除androidx包里的
}

public boolean isIntentService() {
if (className == null || superClassName == null) {
return false;
}
return superClassName.equals("android/app/IntentService")
&& !isAndroidxPackageName(); //排除androidx包里的
}

public boolean isIntentService(){
return superClassName.equals("android/app/IntentService");
public String getClassName() {
return className;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.github.jokar.multilanguages.plugin;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
* applyOverrideConfiguration方法
* Create by JokAr. on 2019-11-08.
*/
public class ApplyOverrideConfigurationMV extends MethodVisitor {
private MethodVisitor mv;
private String className;

public ApplyOverrideConfigurationMV(MethodVisitor mv, String className) {
super(Opcodes.ASM4, mv);
this.mv = mv;
this.className = className;
}

@Override
public void visitCode() {
MethodVisitorUtil.addSetTo(mv, className);
super.visitCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,30 @@
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.IFNULL;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.RETURN;

/**
* Create by JokAr. on 2019-07-09.
*/
public class MethodVisitorUtil {

/**
* 添加activity下的attachBaseContext
*
* @param cw
*/
public static void addActivityAttach(ClassWriter cw) {
MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "attachBaseContext", "(Landroid/content/Context;)V",
MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "attachBaseContext",
"(Landroid/content/Context;)V",
null, null);
mv.visitCode();
Label l0 = new Label();
Expand All @@ -39,7 +49,11 @@ public static void addActivityAttach(ClassWriter cw) {
mv.visitEnd();
}


/**
* 添加intentService类下的attachBaseContext
*
* @param cw
*/
public static void addIntentServiceAttach(ClassWriter cw) {
MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "attachBaseContext",
"(Landroid/content/Context;)V", null, null);
Expand All @@ -57,29 +71,107 @@ public static void addIntentServiceAttach(ClassWriter cw) {
mv.visitInsn(RETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLocalVariable("newBase", "Landroid/content/Context;", null, l0, l2, 1);
mv.visitLocalVariable("newBase", "Landroid/content/Context;",
null, l0, l2, 1);
mv.visitMaxs(2, 2);
mv.visitEnd();
}

public static void addServiceAttach(ClassWriter cw){
MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "attachBaseContext", "(Landroid/content/Context;)V", null, null);
/**
* 添加service下的attachBaseContext
*
* @param cw
*/
public static void addServiceAttach(ClassWriter cw) {
MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "attachBaseContext",
"(Landroid/content/Context;)V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKESTATIC, "com/github/jokar/multilanguages/library/MultiLanguage",
"setLocal", "(Landroid/content/Context;)Landroid/content/Context;", false);
"setLocal", "(Landroid/content/Context;)Landroid/content/Context;",
false);
mv.visitMethodInsn(INVOKESPECIAL, "android/app/Service", "attachBaseContext",
"(Landroid/content/Context;)V", false);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitInsn(RETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLocalVariable("base", "Landroid/content/Context;", null, l0, l2, 1);
mv.visitLocalVariable("base", "Landroid/content/Context;",
null, l0, l2, 1);
mv.visitMaxs(2, 2);
mv.visitEnd();
}

/**
* 添加applyOverrideConfiguration方法
*
* @param cw
* @param className
*/
public static void addApplyOverrideConfiguration(ClassWriter cw, String className) {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "applyOverrideConfiguration",
"(Landroid/content/res/Configuration;)V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 1);
Label l1 = new Label();
mv.visitJumpInsn(IFNULL, l1);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, className, "getBaseContext",
"()Landroid/content/Context;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "android/content/Context", "getResources",
"()Landroid/content/res/Resources;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "android/content/res/Resources", "getConfiguration",
"()Landroid/content/res/Configuration;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "android/content/res/Configuration", "setTo",
"(Landroid/content/res/Configuration;)V", false);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKESPECIAL, "androidx/appcompat/app/AppCompatActivity",
"applyOverrideConfiguration", "(Landroid/content/res/Configuration;)V", false);
Label l3 = new Label();
mv.visitLabel(l3);
mv.visitInsn(RETURN);
Label l4 = new Label();
mv.visitLabel(l4);
mv.visitLocalVariable("this", "L" + className + ";", null, l0, l4, 0);
mv.visitLocalVariable("overrideConfiguration", "Landroid/content/res/Configuration;",
null, l0, l4, 1);
mv.visitMaxs(2, 2);
mv.visitEnd();
}

/**
* 添加 overrideConfiguration.setTo(this.getBaseContext().getResources().getConfiguration());
*/
public static void addSetTo(MethodVisitor mv, String className) {
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 1);
Label l1 = new Label();
mv.visitJumpInsn(IFNULL, l1);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, className,
"getBaseContext", "()Landroid/content/Context;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "android/content/Context", "getResources",
"()Landroid/content/res/Resources;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "android/content/res/Resources",
"getConfiguration", "()Landroid/content/res/Configuration;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "android/content/res/Configuration",
"setTo", "(Landroid/content/res/Configuration;)V", false);
mv.visitLabel(l1);
}
}

0 comments on commit 563ec41

Please sign in to comment.