关于activity前台后台切换

117 篇文章 0 订阅
[背景]
当一个业务流程涉及到多个task之间的交互,如一个Task_A中的Activity_1 startActivityForResult() 了一个Activity_2, Activity_2启动另一个Task_B并且期望利用Task_B运行的结果setResult()返回给Activity_1。
TaskRecord如下图所示:
Android中怎么切换task到前台。
[问题]
Task_B取得result之后,需要 把Task_A带到前台(active) ,这样Activity_1才能响应(onActivityResult)到Activity_2返回(setResult)的结果。
现在的问题就在于,Task_B并不一定能够退出(Activity_3其可能其他程序,如browser等),从而把Task_A带到前台;又或者Task_A和Task_B中又夹杂了其他的Task(你知道,长按home键你可以做得出来),以至于调用Task_B.moveTaskToBack()也不能解决问题。

[解决方案]
如果 你的平台是面向Android3.0(API level 11),那么恭喜你,一个函数就可以搞定:
moveTaskToFront 
Android中怎么切换task到前台。

 
如果你和我一样苦逼的在用2.2的平台,那么就要稍微麻烦点了,基本上是用 taskAffinity +FLAG_ACTIVITY_NEW_TASK  FLAG_ACTIVITY_SINGLE_TOP
先来看一下sdk怎么说的:
Android中怎么切换task到前台。
SDK说,如果用带FLAG_ACTIVITY_NEW_TASK标志来启动一个activity,并且这个activity与当前运行的另一个task(A)的affinity名字相同,那么就这个activity就会在那个task(A)里启动。
Ok,到这还不行,人家没说会把Task_A带到前台,接着看另一个Flag
 
Android中怎么切换task到前台。
好了,重点来了:如果Task_A中已经有了Activity_2,这时候如果以FLAG_ACTIVITY_NEW_TASK来start Activity_2,那么这个Task_A就会被 带到前台
好了,现在Task_A已经可以到前台了,剩下最后一步:Activity_2不能创建两次,这就要求同时使用下面这个flag:
 
3. FLAG_ACTIVITY_SINGLE_TOP
Android中怎么切换task到前台。
如果Activity_2在Task的顶端,那么这个Activity_2就不会被再此创建,而是走onNewIntent.
 
至此,结合上面3个特性,问题得以解决。结合代码,流程如下:
1. 在androdiManifest.xml中添加Activity_2的taskAffinity name与Task_A相同(也就是与Activity_1的taskAffinity名字相同),如android:taskAffinity = "android.task.calendar"。
2. 在Task_B启动前,Activity_1先启动Activity_2并要求返回结果,startActivityForResult().
3. Task_B中的Activity_4取得所需数据后,保存好(intent,或其他方法),然后startActivity(Activity_2),并带上(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_SINGLE_TOP)标志。
4. Task_A被带到前台,并且调用到Activity_2::onNewIntent().
5. Activity_2取得之前保存的信息(从Intent或其他地方),调用setResult(),然后finish().
6. Activity_1中的onActivityResult()响应,得到返回结果。
 
总结下:
Android中怎么切换task到前台。

Android 显示 Activity 到前台

Java代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<uses-permission android:name= "android.permission.REORDER_TASKS" />
 
public class SampleActivity extends Activity {
     private ActivityManager.RunningAppProcessInfo getRunningAppProcessInfo(String packageName) {
         ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
         List<ActivityManager.RunningAppProcessInfo> processList = am.getRunningAppProcesses();
         for (ActivityManager.RunningAppProcessInfo p : processList) {
             if (p.processName.equals(packageName)) {
                 return p;
             }
         }
         return null ;
     }
     
     private boolean isForeground(String packageName) {
         ActivityManager.RunningAppProcessInfo processInfo = getRunningAppProcessInfo(packageName);
         
         if (processInfo != null ) {
             return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND == processInfo.importance;
         }
         return false ;
     }
     
     private boolean moveTaskToFront() {
         ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
         
         am.moveTaskToFront(getTaskId(), 0 );
         return isForeground(getPackageName());
     }
}
描述:getRunningAppProcessInfo 获得当前进程的RunningAppProcessInfo; isForeground 判断是否在前台 moveTaskToFront 把Activity切换到前台

有一个Android应用包含包含一个后台程序,该程序会定期连接服务器来实现自定义信息的推送。但是,当这个应用处于前台的时候,后台程序就没有必要连接服务器了。这样可以节省网络资源,也更省电。

用什么方法知道该应用是否处于前台呢?

网上搜到的方法大多数都是使用下面的代码:

? View Code JAVA
1
2
3
4
5
6
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
//获得task列表
List<ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1); 
Log.d("topActivity", "CURRENT Activity ::"+ taskInfo.get(0).topActivity.getClassName());
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();

但是查阅Android文档后发现,google并不推荐使用这个方法:

This should never be used for core logic in an application, such as deciding between different behaviors based on the information found here. Such uses are not supported, and will likely break in the future. For example, if multiple applications can be actively running at the same time, assumptions made about the meaning of the data here for purposes of control flow will be incorrect.

而且,这个方法还要求设置android.permission.GET_TASKS权限。

因此,我必须寻找更加合适的方法来做这件事。最终,我找到这个方法getRunningAppProcesses(),它并不需要增加特殊的权限。

下面是范例代码:

? View Code JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 返回当前的应用是否处于前台显示状态
 * @param $packageName
 * @return
 */
private boolean isTopActivity(String $packageName) 
{
    //_context是一个保存的上下文
    ActivityManager __am = (ActivityManager) _context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> __list = __am.getRunningAppProcesses();
    if(__list.size() == 0) return false;
    for(ActivityManager.RunningAppProcessInfo __process:__list)
    {
        Log.d(getTAG(),Integer.toString(__process.importance));
        Log.d(getTAG(),__process.processName);
        if(__process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
                __process.processName.equals($packageName))
        {
            return true;
        }
    }
    return false;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值