Android 如何关闭SDK中Activity

235 阅读3分钟

一 、背景

项目工程中有集成某业务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在栈顶,对用户的影响会比较大。