{"id":1247,"date":"2023-03-18T09:38:47","date_gmt":"2023-03-18T01:38:47","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1247"},"modified":"2023-04-29T09:30:15","modified_gmt":"2023-04-29T01:30:15","slug":"android-plugin-implementation-of-startactivity-hook-for-login-interception","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/03\/18\/android-plugin-implementation-of-startactivity-hook-for-login-interception\/","title":{"rendered":"Android\u63d2\u4ef6\u5316\u4e4bstartActivity hook\u5b9e\u73b0\u767b\u5f55\u62e6\u622a"},"content":{"rendered":"<p>Android 26\u53ca\u4ee5\u4e0a\uff1a<code>startActivity<\/code> -&gt; <code>startActivityForResult<\/code> -&gt; <code>mInstrumentation.execStartActivity<\/code> -&gt; <code>ActivityManagerNative.getDefault().startActivity<\/code><br \/>\nAndroid 26\u4ee5\u4e0b\uff1a<code>startActivity<\/code> -&gt; <code>startActivityForResult<\/code> -&gt; <code>mInstrumentation.execStartActivity<\/code> -&gt; <code>ActivityManager.getService().startActivity<\/code><\/p>\n<p><!-- more --><\/p>\n<h2>startActivity hook<\/h2>\n<pre><code class=\"language-java\">public class AuthHookHelper {\n    private static AuthHookHelper mAuthHookHelper;\n    private Context context;\n\n    private AuthHookHelper(Context context) {\n        this.context = context;\n    }\n\n    public static AuthHookHelper getInstance(Context context) {\n        if (mAuthHookHelper == null) {\n            synchronized (AuthHookHelper.class) {\n                if (mAuthHookHelper == null) {\n                    mAuthHookHelper = new AuthHookHelper(context.getApplicationContext());\n                }\n            }\n        }\n        return mAuthHookHelper;\n    }\n\n    public void hookAms() {\n        try {\n            Class&lt;?&gt; activityManagerClass;\n            Field iActivityManagerSingleton;\n            if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {\n                activityManagerClass = Class.forName(&quot;android.app.ActivityManager&quot;);\n                iActivityManagerSingleton = activityManagerClass.getDeclaredField(&quot;IActivityManagerSingleton&quot;);\n            } else {\n                activityManagerClass = Class.forName(&quot;android.app.ActivityManagerNative&quot;);\n                iActivityManagerSingleton = activityManagerClass.getDeclaredField(&quot;gDefault&quot;);\n            }\n            iActivityManagerSingleton.setAccessible(true);\n            Object defaultValue = iActivityManagerSingleton.get(null);\n\n            Class&lt;?&gt; singletonClass = Class.forName(&quot;android.util.Singleton&quot;);\n            Field mInstance = singletonClass.getDeclaredField(&quot;mInstance&quot;);\n            mInstance.setAccessible(true);\n            Object iActivityManagerObject = mInstance.get(defaultValue);\n\n            Class&lt;?&gt; IActivityManager = Class.forName(&quot;android.app.IActivityManager&quot;);\n            Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),\n                    new Class[] {IActivityManager},\n                    new AmsInvocationHandler(iActivityManagerObject));\n            mInstance.set(defaultValue, proxy);\n\n        } catch (ClassNotFoundException e) {\n            e.printStackTrace();\n        } catch (NoSuchFieldException e) {\n            e.printStackTrace();\n        } catch (IllegalAccessException e) {\n            e.printStackTrace();\n        }\n    }\n\n    class AmsInvocationHandler implements InvocationHandler {\n        private Object iActivityManagerObject;\n\n        public AmsInvocationHandler(Object iActivityManagerObject) {\n            this.iActivityManagerObject = iActivityManagerObject;\n        }\n\n        @Override\n        public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {\n            if (&quot;startActivity&quot;.contains(method.getName())) {\n                Log.i(&quot;yezhou&quot;, &quot;invoke: startActivity&quot;);\n                Intent intent = null;\n                int index = 0;\n                for (int i = 0; i &lt; args.length; i++) {\n                    Object arg = args[i];\n                    if (arg instanceof Intent) {\n                        intent = (Intent) args[i];\n                        index = i;\n                        break;\n                    }\n                }\n                if (!Constants.inLogin) {\n                    Intent proxyIntent = new Intent();\n                    ComponentName componentName = new ComponentName(context, LoginActivity.class);\n                    proxyIntent.setComponent(componentName);\n                    proxyIntent.putExtra(&quot;extraIntent&quot;, intent.getComponent().getClassName());\n                    args[index] = proxyIntent;\n                }\n            }\n            return method.invoke(iActivityManagerObject, args);\n        }\n    }\n\n}<\/code><\/pre>\n<h2>\u767b\u5f55\u62e6\u622a\u6d4b\u8bd5<\/h2>\n<pre><code class=\"language-java\">public class MainActivity extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        AuthHookHelper.getInstance(this).hookAms();\n    }\n\n    public void firstActivity(View view) {\n        Intent intent = new Intent(this, FirstActivity.class);\n        startActivity(intent);\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">public class FirstActivity extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_first);\n    }\n\n}<\/code><\/pre>\n<pre><code class=\"language-java\">public class LoginActivity extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_login);\n        Constants.inLogin = true;\n    }\n\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Android 26\u53ca\u4ee5\u4e0a\uff1astartActivity -&gt; startActivityForResul [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[311],"tags":[310],"class_list":["post-1247","post","type-post","status-publish","format-standard","hentry","category-android-advance","tag-hook"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1247","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1247"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1247\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1247"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1247"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}