Skip to content

Commit 2649e86

Browse files
committed
add ToastCompat
1 parent d603c6e commit 2649e86

File tree

6 files changed

+139
-1
lines changed

6 files changed

+139
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.panda912.defensor.plugin.internal.interceptor
2+
3+
import com.panda912.defensor.plugin.internal.BytecodeInterceptor
4+
import com.panda912.defensor.plugin.internal.Output
5+
import com.panda912.defensor.plugin.internal.visitor.BaseClassReader
6+
import com.panda912.defensor.plugin.internal.visitor.BaseClassVisitor
7+
import com.panda912.defensor.plugin.internal.visitor.BaseMethodVisitor
8+
import com.panda912.defensor.plugin.utils.TOAST_COMPAT
9+
import com.panda912.defensor.plugin.utils.convertToStaticDescriptor
10+
import com.panda912.defensor.plugin.utils.toInternalName
11+
import org.objectweb.asm.ClassWriter
12+
import org.objectweb.asm.MethodVisitor
13+
import org.objectweb.asm.Opcodes
14+
15+
/**
16+
* Created by panda on 2022/5/24 19:00
17+
*/
18+
class ToastInterceptor : BytecodeInterceptor {
19+
20+
override fun intercept(chain: BytecodeInterceptor.Chain): Output {
21+
val input = chain.request()
22+
23+
val cr = BaseClassReader(input.bytes)
24+
val cw = ClassWriter(cr, ClassWriter.COMPUTE_MAXS)
25+
cr.accept(object : BaseClassVisitor(cw) {
26+
override fun visitMethod(
27+
access: Int,
28+
name: String?,
29+
descriptor: String?,
30+
signature: String?,
31+
exceptions: Array<out String>?
32+
): MethodVisitor {
33+
val mv = super.visitMethod(access, name, descriptor, signature, exceptions)
34+
return ToastMethodVisitor(mv)
35+
}
36+
})
37+
input.bytes = cw.toByteArray()
38+
return chain.proceed(input)
39+
}
40+
}
41+
42+
class ToastMethodVisitor(mv: MethodVisitor) : BaseMethodVisitor(mv) {
43+
44+
override fun visitMethodInsn(
45+
opcode: Int,
46+
owner: String,
47+
name: String,
48+
descriptor: String,
49+
isInterface: Boolean
50+
) {
51+
52+
if (owner == "android/widget/Toast" && name == "show" && opcode == Opcodes.INVOKEVIRTUAL && descriptor == "()V") {
53+
super.visitMethodInsn(
54+
Opcodes.INVOKESTATIC,
55+
TOAST_COMPAT.toInternalName(),
56+
name,
57+
descriptor.convertToStaticDescriptor("Landroid/widget/Toast;"),
58+
isInterface
59+
)
60+
return
61+
}
62+
63+
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
64+
}
65+
}

defensor-gradle-plugin/src/main/java/com/panda912/defensor/plugin/internal/processor/BytecodeInjectorImpl.kt

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class BytecodeInjectorImpl : BytecodeInjector {
3838
SafeDialogInterceptor(),
3939
StringInterceptor(),
4040
ThrowableInterceptor(),
41+
ToastInterceptor(),
4142
UnboxingInterceptor(),
4243
UriInterceptor(),
4344
ValueAnimatorInterceptor(),

defensor-gradle-plugin/src/main/java/com/panda912/defensor/plugin/utils/Const.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.panda912.defensor.plugin.utils
22

33
import org.objectweb.asm.Type
4-
import java.io.File
54

65
/**
76
* Created by panda on 2021/8/13 17:25
@@ -85,6 +84,7 @@ const val SPANNABLE_STRING_BUILDER_DEFENSOR = "com.panda912.defensor.internal.Sp
8584
const val STRING_DEFENSOR = "com.panda912.defensor.internal.StringDefensor"
8685
const val TEXTVIEW_DEFENSOR = "com.panda912.defensor.internal.TextViewDefensor"
8786
const val THROWABLE_DEFENSOR = "com.panda912.defensor.internal.ThrowableDefensor"
87+
const val TOAST_COMPAT = "com.panda912.defensor.internal.ToastCompat"
8888
const val UNBOXING_DEFENSOR = "com.panda912.defensor.internal.UnboxingDefensor"
8989
const val URI_DEFENSOR = "com.panda912.defensor.internal.UriDefensor"
9090
const val VALUE_ANIMATOR_DEFENSOR = "com.panda912.defensor.internal.ValueAnimatorDefensor"

defensor/src/main/java/com/panda912/defensor/ErrorCode.java

+1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ public interface ErrorCode {
2121
int DialogException = 114;
2222
int URLDecoderException = 115;
2323
int IllegalStateException = 116;
24+
int ToastException = 117;
2425
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.panda912.defensor.internal;
2+
3+
import android.os.Handler;
4+
import android.os.Message;
5+
import android.widget.Toast;
6+
7+
import androidx.annotation.NonNull;
8+
9+
import com.panda912.defensor.CrashDefensor;
10+
import com.panda912.defensor.ErrorCode;
11+
12+
import java.lang.reflect.Field;
13+
14+
/**
15+
* Created by panda on 2020/9/18 18:33
16+
*/
17+
public class ToastCompat {
18+
19+
private static Field mTNField;
20+
private static Field mHandlerField;
21+
22+
static {
23+
try {
24+
mTNField = Toast.class.getDeclaredField("mTN");
25+
mTNField.setAccessible(true);
26+
mHandlerField = mTNField.getType().getDeclaredField("mHandler");
27+
mHandlerField.setAccessible(true);
28+
} catch (Throwable e) {
29+
CrashDefensor.onCrash(ErrorCode.ToastException, "reflect get Toast mTN or mHandler failed", e);
30+
}
31+
}
32+
33+
private static void hook(Toast toast) {
34+
try {
35+
Object mTN = mTNField.get(toast);
36+
mHandlerField.set(mTN, new HandlerProxy((Handler) mHandlerField.get(mTN)));
37+
} catch (Throwable e) {
38+
CrashDefensor.onCrash(ErrorCode.ToastException, "hook Toast mHandler failed", e);
39+
}
40+
}
41+
42+
private static class HandlerProxy extends Handler {
43+
44+
private final Handler mHandler;
45+
46+
HandlerProxy(Handler handler) {
47+
mHandler = handler;
48+
}
49+
50+
@Override
51+
public void dispatchMessage(@NonNull Message msg) {
52+
try {
53+
super.dispatchMessage(msg);
54+
} catch (Exception e) {
55+
CrashDefensor.onCrash(ErrorCode.ToastException, "Android 7.1 BadTokenException OR other custom device has BadTokenException", e);
56+
}
57+
}
58+
59+
@Override
60+
public void handleMessage(@NonNull Message msg) {
61+
mHandler.handleMessage(msg);
62+
}
63+
}
64+
65+
public static void show(Toast toast) {
66+
hook(toast);
67+
toast.show();
68+
}
69+
}

sample/src/main/java/com/panda912/defensor/sample/MainActivity.kt

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class MainActivity : AppCompatActivity() {
4242
)
4343
)
4444

45+
Toast.makeText(this.applicationContext, "Hello defensor!", Toast.LENGTH_SHORT).show()
46+
4547
// val context: Context = this
4648
// context.bindService(Intent(), object : ServiceConnection {
4749
// override fun onServiceConnected(name: ComponentName?, service: IBinder?) {

0 commit comments

Comments
 (0)