美文网首页Android开发Android开发Android开发经验谈
保持Activity独立,SingleInstance、Sing

保持Activity独立,SingleInstance、Sing

作者: HarveyLegend | 来源:发表于2019-03-13 20:21 被阅读43次

项目中有VOIP的需求,类似微信语音聊天的界面。这种类型的界面通常会要求可以最小化并保持运行状态。最小化自然想到悬浮窗,悬浮窗的实现以及注意事项不在本文讨论范围,本文讨论的是怎样让Activity不可见但又不finish呢?

通过简单的搜索可以比较轻松的看到网上提供的实现方式:将Activity设置成singleTask,搭配taskAffinity属性使用,目的是让此Activity独立运行在一个task中。

说一下Task,我们知道Android中每个Activity运行在一个task中,由ActivityManager中的RunningTaskInfo统一管理。通常情况下,一个Application中的所有Activity都默认是同一个task,除非在AndroidManifest.xml文件中对某Activity设置了taskAffinity,可以使此Activity运行在指定名称的task中。

由于接手项目时已经是这种实现方式,大部分设备上也没有问题,达到了我们想要的效果,具体实现细节如下:

1、在AndroidManifest.xml中将ActivityVoip设置成singleTask,设置android:taskAffinity为"com.xx.xx.xx"。
2、加入属性android:excludeFromRecents,让该task不在最近任务列表中显示。此处强调一下,如果刚启动ActivityVoip,马上呼出最近任务界面还是能看到两个task,一个是ActivityVoip界面所属的task,一个是APP所在的默认task,这是没问题的,官方有说明。
3、点击ActivityVoip中的最小化按钮,生成悬浮窗的同时moveTaskToBack(true)将当前task退到后台。悬浮窗的权限注意控制。

        <activity
            android:name="ui.ActivityVoip"
            android:exported="false"
            android:launchMode="singleTask"
            android:excludeFromRecents="true"
            android:taskAffinity="com.xx.xx.xx"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />

以上,似乎完美实现了这个功能,可突然测试说华为手机最小化通话页面或者直接讲应用退到后台后,再冷启动任意一个其他app都会导致通话断开,悬浮窗消失!

此处吐槽一下国产系统特别是华为的UI,乱改什么Android,留下那么多坑。经过测试,华为在launcher冷启动一个app时会将设置为android:excludeFromRecents="true"的task干掉。。。可是想实现这个功能必须用到这个属性怎么办,经过几个小时的研究和尝试,将singleTask改为singleInstance,去掉taskAffinity和excludeFromRecents属性,也可以实现Activity独立运行的目的,但怎么可能没有其他问题呢?T_T 。当启动ActivityVoip后,退到后台,再从最近任务回到通话界面,点击结束finish()后并没有留在主app的界面上,给人的感觉像是app崩掉了,然而事实是并没有。原因也比较简单,ActivityManager最顶端的task并不是主APP的task,解决方案自然想到finish()通话界面前召唤主app的task回来。代码如下:

   private void moveAppToFront() {
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> recentList = am.getRunningTasks(30);
        recentList.remove(0); //去掉当前 Activity
        for (ActivityManager.RunningTaskInfo info : recentList) {
            if (info.topActivity.getPackageName().equals(getPackageName())) {
                am.moveTaskToFront(info.id, 0);
                return;
            }
        }
    }

还有没有坑有待观察,目前测试情况良好。

相关文章

网友评论

    本文标题:保持Activity独立,SingleInstance、Sing

    本文链接:https://www.haomeiwen.com/subject/gffxmqtx.html