本文最后更新于 142 天前,其中的信息可能已经有所发展或是发生改变。
替换Instrumentation
public class GmInstrumentationHooker {
private static final String TAG = "Hooker";
public static void hookInstrumentation() {
Class<?> activityThread = null;
try {
activityThread = Class.forName("android.app.ActivityThread");
Method sCurrentActivityThread = activityThread.getDeclaredMethod("currentActivityThread");
sCurrentActivityThread.setAccessible(true);
Object activityThreadObject = sCurrentActivityThread.invoke(activityThread);
Field mInstrumentation = activityThread.getDeclaredField("mInstrumentation");
mInstrumentation.setAccessible(true);
mInstrumentation.set(activityThreadObject, GmInstrumentation.Companion.getInstance());
Log.d("dqs",">>>>>>>>>>>>>>>>>>>>>>>> hook instrumentation ");
} catch (Exception e) {
GmInstrumentation.Companion.setInitSuccess(false);
Log.d("dqs",">>>>>>>>>>>>>>>>>>>>>>>> " + e.getMessage());
}
}
}
通过反射设置Activity的onPause和onStop方法的mCalled字段实现拦截
open class GmInstrumentation : Instrumentation() {
var inPipActivity: String = ""
var onLifeCycleCall: (() -> Unit)? = null
// 是否已经进入小窗
var isEnterPip: Boolean = false
companion object {
var isInitSuccess = true
// 是否开启后台自动小窗
private var enableAutomaticPip: Boolean = false
val instance: GmInstrumentation by lazy {
GmInstrumentation()
}
fun enableAutomaticPip(enableAutomaticPip: Boolean) {
enableAutomaticPip(enableAutomaticPip, null)
}
fun enableAutomaticPip(
enableAutomaticPip: Boolean,
permissionResult: GmOnPermissionResult?
) {
this.enableAutomaticPip = enableAutomaticPip
if (permissionResult != null) {
val activity = GmLifecycleUtils.getTopActivity()
val rst = PermissionUtils.checkPermission(activity)
if (!rst) {
PermissionUtils.requestPermission(activity, permissionResult)
}
}
}
}
override fun callActivityOnPause(activity: Activity) {
var needReStart = activity.localClassName == inPipActivity
if (enableAutomaticPip && !isEnterPip && PermissionUtils.checkPermission(activity)) {
try {
val clazz = Class.forName("com.ssy185.app.sdk.GMTBOX")
val method = clazz.getMethod("enterGmPip", Activity::class.java)
method.invoke(null, activity)
needReStart = true
} catch (e: Exception) {
e.printStackTrace()
}
}
// Log.d(
// "iichen",
// ">>>>>>>>>>>>>>>>>callActivityOnPause needReStart:$needReStart enableAutomaticPip: $enableAutomaticPip isEnterPip: $isEnterPip localClassName:${activity.localClassName} inPipActivity:$inPipActivity instance: $instance"
// )
if (!needReStart) {
super.callActivityOnPause(activity)
} else {
try {
val mCalled = Activity::class.java.getDeclaredField("mCalled")
mCalled.isAccessible = true
mCalled[activity] = true
} catch (e: Exception) {
Log.d("iichen", ">>>>>>>>>>>>>>>> hook callActivityOnPause error ${e.message}")
}
}
}
override fun callActivityOnStop(activity: Activity) {
val needReStart = activity.localClassName == inPipActivity
// Log.d(
// "iichen",
// ">>>>>>>>>>>>>>>>>callActivityOnStop needReStart:$needReStart enableAutomaticPip: $enableAutomaticPip isEnterPip: $isEnterPip localClassName:${activity.localClassName} inPipActivity:$inPipActivity instance: $instance"
// )
if (!needReStart) {
super.callActivityOnStop(activity)
} else {
try {
val mCalled = Activity::class.java.getDeclaredField("mCalled")
mCalled.isAccessible = true
mCalled[activity] = true
if (inPipActivity.isNotEmpty()) {
onLifeCycleCall?.invoke()
}
isEnterPip = false
inPipActivity = ""
} catch (e: Exception) {
Log.d("iichen", ">>>>>>>>>>>>>>>> hook callActivityOnStop error ${e.message}")
}
}
}
}
评论