问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

Android中判断app何时启动和关闭的技术研究

发布网友 发布时间:2022-04-23 00:41

我来回答

1个回答

热心网友 时间:2023-06-01 11:34

Android开发中不可避免的会遇到需要检查app何时进入前台,何时被用户关闭。奇怪的是,要达到这个目的并不容易。检查app第一次启动并不难,但要判断它何时重新打开和关闭就没有那么简单了。

这篇文章将介绍一种判断app打开,重新打开和关闭的技术。

让我们开始吧

判断一个app打开和关闭的关键在于判断它的activities是否正在前台显示。让我们先从简单的例子开始,一个只有一个activity的app,而且不支持水平模式。这样想要判断app是打开还是关闭只需要检查activity的onStart和onStop方法即可:

[Java] 纯文本查看 复制代码

@Override

protected void onStart() {

super.onStart();

// The Application has been opened!

}

@Override

protected void onStop() {

super.onStop();

// The Application has been closed!

}

上面例子的问题在于当需要支持水平模式时该方法就失效了。当我们旋转设备时activity将会重建,onStart方法将被再次调用,这时将会错误的判断为app第二次被打开。

为了处理设备旋转的情况,我们需要增加一个校验步骤。当activity退出时启动一个定时器,用于判断短时间内app的这个activity是否又被启动,如果没有,说明用户真的退出了这个app,如果重新启动了这个activity,说明用户还逗留在这个app中。

这种校验方式也适用于拥有多个activities的app,因为从app的一个activity跳转到另一个activity也可以用这种校验方式来处理。

使用这个技术我创建了一个管理类,所有的activities在可见和不可见时都会通知这个管理类。这个管理类为每个activity处理上述的校验步骤,从而避免错误的检测。它也提供了发布订阅(观察者)模式,任何对app启动和关闭感兴趣的模块都可以通过它来得到对应的通知。

这个管理类的使用分为三个步骤:

1)把它添加到你的工程中

2)Activities在可见性改变的需要发送通知

app中所有activities都要增加下面的代码,用于可见性改变时通知管理类。最好的实现方式是把这段代码加到工程的BaseActivity中。

[Java] 纯文本查看 复制代码

@Override

protected void onStart() {

super.onStart();

AppForegroundStateManager.getInstance().onActivityVisible(this);

}

@Override

protected void onStop() {

AppForegroundStateManager.getInstance().onActivityNotVisible(this);

super.onStop();

}

3)订阅app的前台可见性改变事件

在感兴趣的模块中订阅app前台可见性改变事件,application类的onCreate函数是一个不错的地方,它可以保证每次app启动和关闭,你都能得到通知。

public class MyApplication extends Application {

@Override

public void onCreate() {

super.onCreate();

AppForegroundStateManager.getInstance().addListener(this);

}

@Override

public void onAppForegroundStateChange(AppForegroundStateManager.AppForegroundState newState) {

if (AppForegroundStateManager.AppForegroundState.IN_FOREGROUND == newState) {

// App just entered the foreground. Do something here!

} else {

// App just entered the background. Do something here!

}

}

}

进一步的思考

有一些细节需要进一步讨论,下面讨论的几点针对具体的应用可以做微调。

校验时间

校验定时器检查app是否真的进入后台的时间间隔是多少合适呢?上面的代码设置为30秒,原因如下。

当你的app在运行时,可能存在第三方的activities会覆盖全屏幕,一些常见的例子是Google应用内购买和*登录注册页面。这些情况下你的app都会*进入后台,前台用于显示这些第三方页面。如果把这种情况当做用户离开了你的app,显然是不对的。30秒超时设置就是用来避免这种情况的。例如当用户在30秒内完成应用内购买,大部分用户都可以做得到,那么就不会当做用户突然离开app了。

如果你的app不存在上述这种情况,我建议可以把你的校验时间设置为4秒,这样对于低配设备当屏幕旋转重新创建activity的时间间隔是合适的。

CPU休眠

可能存在的问题是当用户关闭app或者app仍处于前台时用户锁屏了,这时CPU可能不会等到定时器检测就休眠了。为了保证这种情况下定时器能够正常检测用户退出app,我们需要持有wakelock防止CPU休眠直到app关闭事件被确认。实践中相比使用wakelock,这种情况并不算问题。

判断app是如何启动的

现在我们已经知道如何检测app何时启动和关闭,但我们不知道app是如何启动的。是用户点击通知栏消息?还是点击一个链接?亦或是他们直接通过桌面图标或最近使用启动?

跟踪启动机制

首先我们需要知道在哪里检测app是如何启动的。基于前面一个例子我们可以打印出app何时启动,以及如何启动。

public class MyApplication extends Application {

public final String TAG = MyApplication.class.getSimpleName();

public enum LaunchMechanism {

DIRECT,

NOTIFICATION,

URL;

}

private LaunchMechanism mLaunchMechanism = LaunchMechanism.DIRECT;

public void setLaunchMechanism(LaunchMechanism launchMechanism) {

mLaunchMechanism = launchMechanism;

}

@Override

public void onCreate() {

super.onCreate();

AppForegroundStateManager.getInstance().addListener(this);

}

@Override

public void onAppForegroundStateChange(AppForegroundStateManager.AppForegroundState newState) {

if (AppForegroundStateManager.AppForegroundState.IN_FOREGROUND.equals(newState)) {

// App just entered the foreground.

Log.i(TAG, "App Just Entered the Foreground with launch mechanism of: " + mLaunchMechanism);

} else {

// App just entered the background. Set our launch mode back to the default of direct.

mLaunchMechanism = LaunchMechanism.DIRECT;

}

}

}

设置启动机制

现在我们可以打印app何时启动的机制,但我们没有设置它。因此下一步就是在用户通过链接或者通知启动app时我们记下它。如果没有通过这两种方式设置过,说明用户是通过点击app图标启动的。

跟踪链接点击事件

为了跟踪用户点击链接打开app,你需要找到代码中处理链接的地方,并加入下面的代码来跟踪启动机制。要确保这些代码在activity的onStart()函数之前调用。在哪些地方加入下面的代码取决于你的app架构了。

getApplication().setLaunchMechanism(LaunchMechanism.URL);
1
跟踪通知事件

不幸的是跟踪通知点击需要更多技巧,通知显示后,点击它将会打开之前绑定好的一个PendingIntent,这里的技巧是为通知的所有PendingIntents添加一个标识表明是由通知发出的。

例如当为通知创建PendingIntent时为每个intent添加如下代码:

public static final String EXTRA_HANDLING_NOTIFICATION = "Notification.EXTRA_HANDLING_NOTIFICATION";

// Put an extra so we know when an activity launches if it is a from a notification

intent.putExtra(EXTRA_HANDLING_NOTIFICATION, true);

到这一步我们需要做的就是在每个activity(统一在BaseActivity中添加)中检查这个标识。当识别到这个标识时说明是从通知启动的,这时可以把启动机制设置为通过通知。这一步应该在onCreate中处理,这样在app启动到前台之前就设置好了(会触发启动机制的打印)。

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Intent intent = getIntent();

if (intent != null && intent.getExtras() != null) {

// Detect if the activity was launched by the user clicking on a notification

if (intent.getExtras().getBoolean(EXTRA_HANDLING_NOTIFICATION, false)) {

// Notify that the activity was opened by the user clicking on a notification.

getApplication().setLaunchMechanism(LaunchMechanism.NOTIFICATION);

}

}

}

本文接近尾声了,到这里你应该已经掌握了如何检测app何时启动和关闭,以及它是如何启动的。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
结核病是什么样的疾病? 曹丕17岁得了肺痨,明知自己命不长久,还要强争王位,是不是很自私呢?_百... 古代小说常出现的病名 急求一篇"生活小窍门"(500字)的作文 至今最有什么小妙招 健康的戒烟方法 笔记本电池锁死是什么原因引起的? 黑龙江债权转让合同纠纷该怎样取证 安徽债权转让合同纠纷应该怎么样取证 房产官司律师费多少 android onpause什么时候调用 Android中,我想在退出程序时,保存住当前的状态,当再次启动时,能回到退出时的状态,该怎么做呢? android什么 情况下activity的 会调用onpause不调用onstop android onPause方法的使用 onPause和onStop的区别 有过肺积水 能去青藏高原吗?麻烦谢谢 android程序中,我想让锁屏键调用程序的onStop(),应该怎么做?? android Activity调用onStop()前,成员变量会被保存吗 你经历过高原反应吗?什么感觉呢? android系统的activity的onPause()和onStop()会在什么时候调用?以及一些问题 请问一下android的onStop方法为什么要调用父类的onStop啊?super.onStop(); 肺积水会导致那些疾病呢? android中当一个Activity启动后什么情况下会被destroy,什么情况下onstop 重度高原反应为什么救不活? 在android中能否用onstop()退出activity 重度高原反应救不活吗? 长期进入高原生活、有没有危险??? 什么是肺积水为什么登山者易引发肺积水?是因为高海拔还是低温? 怎样松胯? 锻炼杨式太极拳的腰胯肩如何用劲? android快速(1秒内)锁屏解锁onPause方法会调用两次怎么破? 安卓开发中,如何实现点击返回键时,返回到上一个界面,而当前activity不销毁,只是onStop()。3Q, 3Q android fragemnt已经onstop为什么还能接受广播 安卓中Activity的onStart()和onResume()的区别是什么 如何理解Android中Activity的三个“生命周期”? android中 onResume()方法什么时候执行 ?? 适合给男朋友的备注有哪些? 男朋友备注特别的昵称有哪些? 甜到爆的男朋友备注有哪些? 给男朋友的备注有哪些? 给男朋友备注特殊含义有哪些? 给男朋友的备注(可爱)有哪些? 男朋友的昵称备注有哪些? 微信给男朋友独特备注有哪些? 微信里你是怎么备注男朋友的? 女生给男朋友的备注,你们备注的是什么呢? 给男朋友备注的特殊含义有哪些? 国产飞亚达的机械表质量怎么样?和日本的西铁城相比哪个质量好? 飞亚达手表质量如何 飞亚达和罗西尼怎么选择