新浦京81707con > 首页 > 十分钟学会android,应用程序的入口

原标题:十分钟学会android,应用程序的入口

浏览次数:137 时间:2020-03-15

@酸菜个人站点Github如博客中有不合适的地方款待留言调换转发请评释原再次创下处

当客户导航、退出和重临您的施用时,应用中的 Activity 实例将要其生命周期中改动不一样意况。 举个例子,当你的Activity初次发轫时,它将现出在系统前台并摄取顾客核心。 在这里个历程中,Android 系统会对Activity调用一体系生命周期方法,通过那一个主意,您可以安装顾客分界面和别的构件。 即使客户施行起来另一Activity或切换至另一应用的操作,当其进去后台(在内部Activity不再可以见到,但实例及其状态完整保存),系统会对您的Activity调用此外一密密层层生命周期方法。

# 问题
一经你未来要花销三个 SDK,举例说广告SDK吧,你希望在使用的入口 Activity 早前插入你的 Activity,在您的 Activity 中展现广告, 如何是好? 笔者看过联通沃杂货店的做法, 供给接入方申明自身的 Ativity 为入口 Activity,这种做法明显不符合多个工夫人的追求的。那么我们能还是不可能在接入方无感知的情事把我们的 Activity 免强插入到入口 Activity创制前来展现呢? 

急需背景

多少个付加物线都急需达成开屏广告,大家付加物广告都以接的大家自身广告SDK,而SplashActivity只是几行代码央浼大家广告,广告SDK会把View封装好再次回到来,SplashActivity要做的政工只是获得响应结果,而且show出来.

在生命周期回调方法内,您能够申明客户间距和再度走入Activity时的Activity行为。举例,要是您正营造流摄像播放器,当客商切换至另一应用时,您或者要中断录像或终止互联网连接。当客商再次回到时,您能够再次连接网络并同意客户从同一职责一而再再而三播放录制。

**主题材料再简化一下:怎么着 hook 二个采用的入口 Activity,插入自个儿的Activity?**
# 思路
 大家先是要知道一个施用的入口Activiy是怎么被创设,然后被具体出来的?假设看过插件化的相关落到实处验小学说就轻便了然了,大家第一来探视客商点击运营Logo之后是怎么进来第一个Activity的:
[图表上传失利...(image-b0898e-1512827933284卡塔尔(قطر‎]

何以落实一行代码完成开屏广告

  1. 经过Hook Instrumentation监听到App主分界面运营而且回调出来,然后跳转到内置的多少个activity里面完成开屏广告广告甘休再finish。
  2. 哪些识别是还是不是是主LAUNCHE冠道(App第三个运维分界面State of Qatar
 <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>

intent-filter标签里面八个字段分别代表如下意思

  • android.intent.action.MAIN 决定应用程序最早运营的Activity

  • android.intent.category.LAUNCHER表示activity应该被列入系统的运行器。Launcher是安卓系统中的桌面运转器,是桌面UI的统称。

也正是说依据如上标签能够剖断是还是不是是App第三个入口Activity代码如下:

 if (Intent.ACTION_MAIN.equals(intent.getAction && intent.hasCategory(Intent.CATEGORY_LAUNCHER)) { }

我们在Activity调用的startActivity主意末了都会调用到Instrumentation的execStartActivity格局,而最终activity的创设会被回调到InstrumentationcallActivityOnCreate办法。猛烈推荐Activity的开发银行进程

也正是说只要求我们透过反射替换Instrumentation然后在callActivityOnCreate办法里面回调出来就可以。反射功底用法

代码如下:

/** * @author 黄兴伟 (xwd9989@gamil.com) * @since 2018/5/9 */public class ProxyInstrumentation extends Instrumentation { private OnActivityCreateListener mOnActivityCreateListener; public ProxyInstrumentation() { Log.e("TAG", "ProxyInstrumentation created"); } public void setActivityCreateListener(OnActivityCreateListener onActivityCreateListener) { this.mOnActivityCreateListener = onActivityCreateListener; } @Override public void callActivityOnCreate(Activity activity, Bundle icicle) { super.callActivityOnCreate(activity, icicle); final Intent intent = activity.getIntent(); if (Intent.ACTION_MAIN.equals(intent.getAction && intent.hasCategory(Intent.CATEGORY_LAUNCHER)) { //判断是否是住入口 回调 if (mOnActivityCreateListener != null) { mOnActivityCreateListener.onHookActivityCreated(activity, icicle); } } } /*回调接口*/ public interface OnActivityCreateListener { void onHookActivityCreated(Activity activity, Bundle icicle); }}

/** * @author 黄兴伟 (xwd9989@gamil.com) * @since 2018/5/9 */public class HookActivityHelper { private static final HookActivityHelper INSTANCE = new HookActivityHelper(); private ProxyInstrumentation mProxyInstrumentation; public static HookActivityHelper get() { return INSTANCE; } public void open() { mProxyInstrumentation.setActivityCreateListener(new ProxyInstrumentation.OnActivityCreateListener() { @Override public void onHookActivityCreated(Activity activity, Bundle icicle) { Intent intent = new Intent(activity, WelcomeActivity.class); activity.startActivity; } }); } private HookActivityHelper() { try { Class<?> clazz = Class.forName("android.app.ActivityThread"); Method currentActivityThread = clazz.getDeclaredMethod("currentActivityThread"); Object object = currentActivityThread.invoke; Field field = clazz.getDeclaredField("mInstrumentation"); field.setAccessible; mProxyInstrumentation = new ProxyInstrumentation(); field.set(object, mProxyInstrumentation); } catch (Exception e) { e.printStackTrace(); } }}

/** * 再这个内置的Activity实现开屏广告UI或请求广告SDK即可 * @author 黄兴伟 (xwd9989@gamil.com) * @since 2018/5/9 */public class WelcomeActivity extends AppCompatActivity { private TextView mTextView; private CountDownTimer mCountDownTimer = new CountDownTimer(6000, 1000) { @Override public void onTick(long millisUntilFinished) { mTextView.setText("Hook成功,欢迎来到酸菜个人站点 huangxingwei.cn 6秒后返回MainActivity = "   millisUntilFinished / 1000); } @Override public void onFinish() { finish(); Log.e("TAG", "WelcomeActivity finished"); } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e("TAG", "WelcomeActivity created success"); setContentView(R.layout.welcome_layout); mTextView = findViewById(R.id.text); mCountDownTimer.start(); }}

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:andro package="com.xwdz.simple"> <application android:name=".TestApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".hook.WelcomeActivity"/> </application></manifest>

public class TestApp extends Application { @Override public void onCreate() { super.onCreate(); HookActivityHelper.get; }}

Log如下

05-09 17:27:40.832 3997-3997/? E/TAG: ProxyInstrumentation created05-09 17:27:40.853 3997-3997/? E/TAG: MainActivity created success05-09 17:27:41.072 3997-3997/? E/TAG: WelcomeActivity created success05-09 17:27:51.091 3997-3997/com.xwdz.simple E/TAG: WelcomeActivity finished

测验效果如下

图片 1hook6.gif

本课陈说每种 Activity 实例选用的主要性生命周期回调方法以致你何以选拔这一个情势以使您的Activity根据顾客预期举办同期当你的Activity没有供给它们时不会消耗系统财富。

明亮了Activity的创造和办法调用流程大家就足以调节在哪个环节 hook 了,简单窥见,大家 hook  的精品时刻是 Activity 的 onCreate 方法被调用前, 也正是Instrumentation 的 callActivityOnCreate 方法,大家把它拦截掉, 如何做?
您供给掌握个知识点: **反射**和**代理**。小编假若读自己的稿子的人都熟稔反射和代办了。
## 反射获取 Instrumentation

总结

总体代码参照simple-code,其实HookActivity还足以做越来越多的事,比方插件Activity等,希望能给大家提供到思路,谢谢阅读。

 

首先通过反射获取使用进度的 Instrumentation 对象,再来看看 Instrumentation 相关的引用关系:
ActivityThread -> Instrumentation
见 ActivityThread.java 中代码:

初步与销毁Activity

不一致于使用 main() 方法运维应用的其他编制程序榜样,Android 系统会透过调用对应于其生命周期中一定阶段的一定回调方法在 Activity 实例中运营代码。 有一密密层层可运营Activity的回调方法,以至一雨后苦笋可分解Activity的回调方法。

本学科概述了最要害的生命周期方法,并向您出示如哪个地区理创制Activity新实例的首先个生命周期回调。

    Instrumentation mInstrumentation;
至今大家想方法取得 ActivityThread 的实例对象:

询问生命周期回调

在Activity的生命周期中,系统会按相像于阶梯金字塔的顺序调用一组基本的生命周期方法。也等于说,Activity生命周期的各类阶段就是金字塔上的一阶。 当系统创立新Activity实例时,各样回调方法会将Activity状态向上方移动一阶。金字塔的上边是Activity在前台运维而且客商能够与其交互作用的时间点。

当顾客起初偏离Activity时,系统会调用其余措施在金字塔上校Activity状态下移,进而销毁Activity。在有个别情状下,Activity将只在金字塔中一些下移并等待(比方,当顾客切换来别的使用时),Activity可从该点起头移回顶上部分(倘使客商重临到该Activity),并在客商甘休的岗位一而再。

图片 2

图 1.简化的Activity生命周期图示,以阶梯金字塔表示。此图示展现,对于用于将Activity朝顶上部分的“继续”状态移动一阶的各种回调,有一种将Activity下移一阶的回调方法。Activity还是可以从“暂停”和“甘休”状态回到继续状态。*

基于Activity的复杂程度,您或然无需落实全体生命周期方法。不过,理解各样方法并达成确定保障您的施用根据客商期望的章程运维的章程丰裕重大。准确贯彻您的Activity生命周期方法可确认保证您的选取遵照以下三种格局能够运行,饱含:

  • 只要客商在运用你的运用时接听来电或切换成另多个选取,它不会崩溃。
  • 在顾客未主动选用它时不会消耗宝贵的系统能源。
  • 假定客户间距你的运用并稍后重回,不会放弃顾客的速度。
  • 当显示器在横向和纵向之间旋转时,不会崩溃或错过客户的快慢。

正如你将在在以下课程中要学习的,有Activity会在图 1 所示分裂情状之间连接的二种情景。不过,那些景况中独有两种可以是静态。 也正是说,Activity只能在二种情状之一下留存非常短日子。

  • Resumed:在此种景观下,Activity处于前台,且顾客能够与其人机联作。(不常也称为“运维”状态。)
  • Paused:在这里种场地下,Activity被在前台南处于半透明状态或许未覆盖任何显示屏的另一个Activity—部分拦截。暂停的Activity不会接受客户输入何况无法实践别的轮代理公司码。
  • Stopped:在此种气象下,Activity被统统隐形况且对顾客不可以知道;它被视为处在后台。结束时,Activity实例及其诸如成员变量等有着情形消息将保留,但它不或然试行别的轮代理公司码。

任何情形(“制造”和“最初”)是瞬态,

别的意况(CreatedStarted卡塔尔都以短暂的须臾态,系统会通过调用下三个生命周期回调方法从这一个情状神速移到下三个动静。 也便是说,在系统调用 onCreate())之后,它会神速调用 onStart()卡塔尔(قطر‎,紧接焦急迅调用 onResume())。

主干生命周期部分到此截至。今后,您将起来攻读特定生命周期行为的一些学问。

    public static final ActivityThread currentActivityThread() {
     return sThreadLocal.get();
    }
于是大家得以先反射 currentActivityThread(State of Qatar 方法取得 ActivityThread 当前实例, 再反射 mInstrumentation 获得 Instrumentation 对象。

钦定程序第四回运维的Activity

当顾客从主分界面点击程序Logo时,系统会调用app中被声称为"launcher" (or "main"卡塔尔activity中的onCreate(卡塔尔方法。这些Activity被用来作为程序的最首要步入点。

我们得以在AndroidManifest.xml中定义作为主activity的activity。

其一main activity必得在manifest使用包含 MAIN action 与 LAUNCHER category 的<intent-filter>标签来声称。比方:

<activity android:name=".MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Note:当您利用Android SDK工具来创制Android工程时,工程中就包罗了一个暗许的宣示有其一filter的activity类。

一经程序中从不表明了MAIN action 或者LAUNCHER category的activity,那么在配备的主分界面列表里面不会显示appLogo。

          //获取当前的ActivityThread对象
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
            currentActivityThreadMethod.setAccessible(true);
            Object currentActivityThread = currentActivityThreadMethod.invoke(null);

本文由新浦京81707con发布于首页,转载请注明出处:十分钟学会android,应用程序的入口

关键词: 新浦京81707con 代码 开屏 广告

上一篇:新奥门蒲京娱乐场SpringMVC从入门到放弃之第二章

下一篇:没有了