一 、背景
项目工程中有集成某业务SDK,调用其接口后会弹出一个其内部实现的Activity。Activity本身有提供关闭按钮,但是我们的业务逻辑希望在执行某逻辑之后,可以自行关闭这个Activity,而不是等待用户主动关闭。
由于SDK本身没有提供关闭这个Activity的接口,协调业务方提供接口时间上来不及,所以就需要我们自行想办法解决了。
几年前的需求,整体过程比较有意思这里分享出来。
二 、那么如何做到关闭SDK中的Activity呢?
我们想到了两种方案:
1 、使用 ActivityLifecycleCallbacks
传统办法使用ActivityLifecycleCallbacks,具体代码如下:
public class ActivityManager implements Application.ActivityLifecycleCallbacks {
private Activity activity;
public void registerActivityLifecycleCallbacks() {
AdApplication.getApp().registerActivityLifecycleCallbacks(this);
}
public void closeActivity() {
if (activity != null) {
activity.finish();
}
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if(activity instanceof com.xxx.xxx.CustomActivity) {
this.activity = activity;
}
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if(activity instanceof com.xxx.xxx.CustomActivity) {
activity = null;
}
}
}
- 通过 ActivityLifecycleCallbacks 获取目标Activity对象
- 在create中保存目前Activity对象
- 在destroy将对象置为null
- 在业务逻辑需要时,调用closeActivity方法关闭对象
2 、第二种方案
利用Actvity launchMode。
我们都知道Activity 有四种 launchMode 。
- standard
- singleTop
- singleTask
- singleInstance
这里我们需要用到singleTask,简单来讲就是利用singleTask原理,将目标Activity关掉。
我们知道当我们将Activity的launchMode 设置为singleTask,启动这个Activity后 ,那么这个Activity在其所在的任务栈中,只会存在一个实例。
当 Activity A 的 launchMode 为 singleTask 时,如果 Activity A 上面还有 Activity B 在前台。这时再次启动Activity A 。并不会重新创建Activity A,而是会将Activity B 下面的 Activity A 重新调起,并且Activity B 会被排除任务栈。
而我们就是要利用这个特性来关闭目标Activity
重新声明目标Activity
先在manifest中声明目标Activity,并且指定其任务栈,launchMode为singleTask。
<activity
android:name=".TargetActivity"
android:singleTask="singleTask"
android:taskAffinity="com.xx.xx"/>
再声明一个EmptyActivity
然后我们声明一个空Activity,同样声明其launchMode为singleTask,并且让其与TargetActivity 在同一个任务栈:
<activity
android:name=".EmptyActivity"
android:launchMode="singleTask"
android:taskAffinity="com.xx.xx"/>
优先启动EmptyActivity
接下来在启动TargetActivity之前,先启动EmptyActivity。让EmptyActivity 先一步TargetActivity 启动起来。当需要关闭TargetActivity时,只需要再次启动EmptyActivity就可以了。
关闭EmptyActivity
这时EmptyActivity还在,但是EmptyActivity是空的,完全是为了配合关闭 TargetActivity 存在的,所以需要将其finish。只需要在 EmptyActivity 中,重写 onNewIntent() 方法,然后调用finish() 就可以了。
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
finish();
}
如果希望保险一点,可以设置EmptyActivity为透明的,不会出现白屏的情况。
三、总结
通过以上两个方案都可以实现我们的小需求,这里主要是介绍一下可以实现需求的两种方法,业务代码中我们最终选择了第一种方案。方案二虽然可以实现需求,但是引入新的Activity,整体实现会比较重一旦出现某些Bug,可能会遗留一个透明的Activity在栈顶,对用户的影响会比较大。