安卓开发中我们可以使用hook技术拦截系统的方法做自己想要的操作,大多是通过反射实现.
应用场景之一:在用户跳转到目标页面时,我们经常需要判断用户是否登录,如果已登录,正常跳转.否则先跳转到登录页面,登录之后再跳转到目标页面.
1,先写工具类的方法
我们目标是:替换ActivityThread中的H类中的callback
public void hookHandlerCallback(Context context) {
this.context = context;
try {
//通过反射获取到ActivityThread对象threadObj
Class<?> ActivityThreadClass = Class.forName("android.app.ActivityThread");
Field sCurrentActivityThread = ActivityThreadClass.getDeclaredField("sCurrentActivityThread");
sCurrentActivityThread.setAccessible(true);
Object threadObj = sCurrentActivityThread.get(null);
//通过ActivityThread对象threadObj把系统mCallback替换为自己的callback
Field handlerField = ActivityThreadClass.getDeclaredField("mH");
handlerField.setAccessible(true);
Handler mH = (Handler) handlerField.get(threadObj);
Field callbackField = Handler.class.getDeclaredField("mCallback");
callbackField.setAccessible(true);
HandlerCallBack handlerCallBack = new HandlerCallBack(mH);
callbackField.set(mH, handlerCallBack);
} catch (Exception e) {
e.printStackTrace();
}
其中HandlerCallBack类实现如下:
class HandlerCallBack implements Handler.Callback {
private Handler mH;
public HandlerCallBack(Handler mH) {
this.mH = mH;
}
@Override
public boolean handleMessage(Message msg) {
handleLaunchActivity(msg);
mH.handleMessage(msg);
return true;
}
private void handleLaunchActivity(Message msg) {
Object obj = msg.obj;
try {
if (Build.VERSION.SDK_INT >= 26) { //如果是8.0以上
if (msg.what == 159) {
Field mActivityCallbacksField = obj.getClass().getDeclaredField("mActivityCallbacks");
mActivityCallbacksField.setAccessible(true);
List mActivityCallbacks = (List) mActivityCallbacksField.get(msg.obj);
for (int i = 0; i < mActivityCallbacks.size(); i++) {
if (mActivityCallbacks.get(i).getClass().getName()
.equals("android.app.servertransaction.LaunchActivityItem")) {
Log.d(TAG, "捕捉到启动activity消息");
Object launchActivityItem = mActivityCallbacks.get(i);
Field mIntentField = launchActivityItem.getClass().getDeclaredField("mIntent");
mIntentField.setAccessible(true);
Intent realIntent = (Intent) mIntentField.get(launchActivityItem);
Intent oldIntent = realIntent.getParcelableExtra("oldIntent");
if (oldIntent != null) {
SharedPreferences sp = context.getSharedPreferences("lzy", Context.MODE_PRIVATE);
if (sp.getBoolean("login", false)) {
realIntent.setComponent(oldIntent.getComponent());
} else {
Log.d(TAG, "handleLaunchActivity: 跳转到登录页面");
ComponentName componentName = new ComponentName(context, LoginActivity.class);
realIntent.putExtra("extraIntent", oldIntent.getComponent().getClassName());
realIntent.setComponent(componentName);
}
}
}
}
}
} else {
if (msg.what == 100) {
Log.d(TAG, "捕捉到启动activity消息");
Field intentField = obj.getClass().getDeclaredField("intent");
intentField.setAccessible(true);
Intent realIntent = (Intent) intentField.get(obj);
Intent oldIntent = realIntent.getParcelableExtra("oldIntent");
if (oldIntent != null) {
SharedPreferences sp = context.getSharedPreferences("lzy", Context.MODE_PRIVATE);
if (sp.getBoolean("login", false)) {
realIntent.setComponent(oldIntent.getComponent());
} else {
Log.d(TAG, "handleLaunchActivity: 跳转到登录页面");
ComponentName componentName = new ComponentName(context, LoginActivity.class);
realIntent.putExtra("extraIntent", oldIntent.getComponent().getClassName());
realIntent.setComponent(componentName);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这样我们启动activity时,系统会调用我们的callback方法,我们在里边做一些判断或其他一些操作,来控制activity的跳转.
2,在application中调用
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HookUtil hookUtil = new HookUtil();
hookUtil.hookStartActivity(this);
hookUtil.hookHandlerCallback(this);
}
}
3,在MainActivity中写跳转方法
startActivity(new Intent(this,SecondActivity.class));
4,在LoginActivity中模拟登陆
public void login(View view) {
SharedPreferences sp = getSharedPreferences("lzy", Context.MODE_PRIVATE);
SharedPreferences.Editor edit = sp.edit();
edit.putBoolean("login",true);
edit.apply();
if (className != null){
ComponentName componentName = new ComponentName(this, className);
Intent intent = new Intent();
intent.setComponent(componentName);
startActivity(intent);
finish();
}
}
版权声明:本文为qq_36335563原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。