Android插件化之startActivity hook实现登录拦截

Android 26及以上:startActivity -> startActivityForResult -> mInstrumentation.execStartActivity -> ActivityManagerNative.getDefault().startActivity
Android 26以下:startActivity -> startActivityForResult -> mInstrumentation.execStartActivity -> ActivityManager.getService().startActivity

startActivity hook

public class AuthHookHelper {
    private static AuthHookHelper mAuthHookHelper;
    private Context context;

    private AuthHookHelper(Context context) {
        this.context = context;
    }

    public static AuthHookHelper getInstance(Context context) {
        if (mAuthHookHelper == null) {
            synchronized (AuthHookHelper.class) {
                if (mAuthHookHelper == null) {
                    mAuthHookHelper = new AuthHookHelper(context.getApplicationContext());
                }
            }
        }
        return mAuthHookHelper;
    }

    public void hookAms() {
        try {
            Class<?> activityManagerClass;
            Field iActivityManagerSingleton;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                activityManagerClass = Class.forName("android.app.ActivityManager");
                iActivityManagerSingleton = activityManagerClass.getDeclaredField("IActivityManagerSingleton");
            } else {
                activityManagerClass = Class.forName("android.app.ActivityManagerNative");
                iActivityManagerSingleton = activityManagerClass.getDeclaredField("gDefault");
            }
            iActivityManagerSingleton.setAccessible(true);
            Object defaultValue = iActivityManagerSingleton.get(null);

            Class<?> singletonClass = Class.forName("android.util.Singleton");
            Field mInstance = singletonClass.getDeclaredField("mInstance");
            mInstance.setAccessible(true);
            Object iActivityManagerObject = mInstance.get(defaultValue);

            Class<?> IActivityManager = Class.forName("android.app.IActivityManager");
            Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                    new Class[] {IActivityManager},
                    new AmsInvocationHandler(iActivityManagerObject));
            mInstance.set(defaultValue, proxy);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    class AmsInvocationHandler implements InvocationHandler {
        private Object iActivityManagerObject;

        public AmsInvocationHandler(Object iActivityManagerObject) {
            this.iActivityManagerObject = iActivityManagerObject;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
            if ("startActivity".contains(method.getName())) {
                Log.i("yezhou", "invoke: startActivity");
                Intent intent = null;
                int index = 0;
                for (int i = 0; i < args.length; i++) {
                    Object arg = args[i];
                    if (arg instanceof Intent) {
                        intent = (Intent) args[i];
                        index = i;
                        break;
                    }
                }
                if (!Constants.inLogin) {
                    Intent proxyIntent = new Intent();
                    ComponentName componentName = new ComponentName(context, LoginActivity.class);
                    proxyIntent.setComponent(componentName);
                    proxyIntent.putExtra("extraIntent", intent.getComponent().getClassName());
                    args[index] = proxyIntent;
                }
            }
            return method.invoke(iActivityManagerObject, args);
        }
    }

}

登录拦截测试

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AuthHookHelper.getInstance(this).hookAms();
    }

    public void firstActivity(View view) {
        Intent intent = new Intent(this, FirstActivity.class);
        startActivity(intent);
    }
}
public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
    }

}
public class LoginActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        Constants.inLogin = true;
    }

}

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/18/android-plugin-implementation-of-startactivity-hook-for-login-interception/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Android插件化之startActivity hook实现登录拦截
Android 26及以上:startActivity -> startActivityForResult -> mInstrumentation.execStartActivity -> ActivityManagerNative.getDefault().start……
<<上一篇
下一篇>>
文章目录
关闭
目 录