声明:本文为Dujinyang CSDN原创投稿文章,未经许可,禁止任何形式的转载。

最近5.0\6.0\7.0 安卓系统都陆续上岗了,兼容性和代码更新是个很头疼的问题,这次我们来说下TASK的基础和API 4.4以上解决方法;

* 必要权限:

<uses-permission android:name = “android.permission.GET_TASKS”/>

* 涉及的TASK()方法:

1. 当前应用是否为前台task
          2. 当前应用是否为后台task
          3. 当前activity是否是Top Activity
          4. 获取nums相应数量的activity

* 遇到问题:

android5.0新特性不能获取 getRunningTask() ?

* 有几个解决方案:
1. 手动打开,让用户授权实现;
2. 代码UsageStatsManager解决,Android官方提供的

3. 用ADB进入手机查看(对于开发只能是辅助功能)

下面我们就来仔细的深入吧~

首先我们先来看下调用Task相关的方法和使用:

1. 当前应用是否为前台task

* 判断当前应用的是否为前台task
* @author dujinyang
* @param context
* @return
*/
public static boolean isAppForgroud(Context context) {
if (context != null) {
String packName = context.getPackageName();
List<RunningTaskInfo> rTasks = getRunningTask(context, 1);
RunningTaskInfo task = rTasks.get(0);
return packName.equalsIgnoreCase(task.topActivity.getPackageName());
}
return false;
}

2. 当前应用是否为后台task

/
* 判断当前应用的是否为后台task
* @author dujinyang
* @param context
* @param packName
* @return
*/
public static boolean isAppBackgroud(Context context) {
if (context != null) {
String packName = context.getPackageName();
List<RunningTaskInfo> rTasks = getRunningTask(context, 1);
RunningTaskInfo task = rTasks.get(0);
return !packName.equalsIgnoreCase(task.topActivity.getPackageName());
}
return false;
}

3. 当前activity是否是Top Activity

/
* 判断当前的activity是否为top activity @author dujinyang
* @param context
* @param className
* @return
*/
public static boolean isTopActivity(Context context, String className) {
List<RunningTaskInfo> rTasks = getRunningTask(context, 1);
for (RunningTaskInfo task : rTasks) {
Log.d("SystemUtils", "isTopActivity:" + task.topActivity.getClassName()
+ "|" + className);
if (task.topActivity.getClassName().equals(className)) {
return true;
}
}
return false;
}

4. 获取nums相应数量的activity

public static List<RunningTaskInfo> getRunningTask(Context context, int num) {
if (context != null) {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> rTasks = am.getRunningTasks(1);
return rTasks;
}
return null;
}

然后问题出现了:~~~~(>_<)~~~~


在android 5.0 版本后 获取栈顶应用的方法 getRunningTask方法被google给屏蔽掉了!

在5.0之前获取的方法是:API (4.4以下)

         /**
* 获取activity
*/
protected void getTastInfos() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
RunningTaskInfo info = manager.getRunningTasks(1).get(0);
String shortClassName = info.topActivity.getShortClassName(); //类名
String className = info.topActivity.getClassName(); //完整类名
String packageName = info.topActivity.getPackageName(); //包名
Log.e("test","YYSDK className:"+className);
Log.e("test","YYSDK shortClassName :"+shortClassName);
Log.e("test","YYSDK packageName:"+packageName);
}

为啥?

原因是Android 5.0在API权限上作了修改:

Android L, Google has disabled getRunningTasks. Now it can only return own apps task and the home launcher.


处理方法:

解决办法之一:

其实就是使用UsageStatsManager获取,但是这种获取方法需要用户在手机上赋予APP权限才可以使用,就是在安全-高级-有权查看使用情况的应用在这个模块中勾选上指定APP就可以获取到栈顶的应用名。那么现在问题来了,如何调用系统提供的常量打开“有权查看使用权限的应用”界面。

其实是使用:

Settings.ACTION_USAGE_ACCESS_SETTINGS

根据此常量打开设置--“有权查看使用权限的应用”,不过在很多系统中被去掉了,如:小米、魅族等~

下面上代码:

判断当前设备中有没有“有权查看使用权限的应用”这个选项

       private boolean isNoOptions() {
PackageManager packageManager = getApplicationContext().getPackageManager();
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
List<ResolveInfo> list = packageManager.queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}

判断调用该设备中“有权查看使用权限的应用”这个选项的APP有没有打开

private boolean isNoSwitch() {
long dujinyang = System.currentTimeMillis();
UsageStatsManager usageStatsManager = (UsageStatsManager) getApplicationContext().getSystemService("usagestats");
ist<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_BEST, 0, dujinyang );
if (queryUsageStats == null || queryUsageStats.isEmpty()) {
return false;
}
return true;
}

然后定义一个Button跳转:

buttonViews.setOnClickListener(new OnClickListener() {  

	                @Override
public void onClick(View v) {
Intent intent = new Intent(
Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
}
});

最后添加权限:

<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />

解决办法之二:

参考文档:http://stackoverflow.com/questions/24625936/getrunningtasks-doesnt-work-in-android-l

上面的stackoverflow网址里面还有其它解决方法;

public void getTopActivtyFromLolipopOnwards(){
String topPackageName ;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
// We get usage stats for the last 10 seconds
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*10, time);
// Sort the stats by the last time used
if(stats != null) {
SortedMap<Long,UsageStats> mySortedMap = new TreeMap<Long,UsageStats>();
for (UsageStats usageStats : stats) {
mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
}
if(mySortedMap != null && !mySortedMap.isEmpty()) {
topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
Log.e("TopPackage Name",topPackageName);
}
}
}
}

调用:

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);

解决办法之三:用ADB进入手机查看(对于开发只能是辅助功能)

如果是代码层开发者可以忽略以下内容~

Android还为开发者提供了adb(Android Debug Bridge),这是非常强大的调试工具。最常用的自然是logcat来显示日志记录。另外一个很强大的指令就是这里要提到的dumpsys。dumpsys还可以添加不同的参数来指示需要输出哪一类Service的信息。对于本文提到的内容,需要查看的就是activity,指令就是:

adb shell dumpsys activity

输入上述指令,就能得到关于设备非常长的一段讯息,单是也能清晰看出它们比较详细的分类:

ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)
Process LRU list (sorted by oom_adj, 28 total, non-act at 3, non-svc at 3):
PERS #27: sys F/ /P trm: 0 605:system/1000 (fixed)
... ... ... ...

每一个类别都有一个括号内容,给出了更加详细的指令来查看该类别下更多具体内容。因此再来尝试指令:

db shell dumpsys activity activities

整个log显示了当前所有在运行的任务栈,它们的id分别是什么。对于每个Task,也有Activity数量等信息,同时也列出了其中的Activity列表,并且对于每个Activity也有比较详细的描述,比如启动它的Intent的内容。

如果觉得内容过多,只想看看栈的内容,也可以直接跳到”Running activities (most recent first)”那部分,比较简洁而又明了的列出了栈中得Activity列表,就能知道当按下返回键的时候会应该会回到哪个Activity以后是要退出程序。

对于”Running activitie”s的内容在dumpsys activity中就有,并不需要dumpsys activity activities,也可以用下边的指令来限制仅输出”Running activities”列表:

adb shell dumpsys activity activities | sed -En -e '/Running activities/,/Run #0/p'

缺点

很明显的看出,使用adb shell的相对于之前的方式的明显好处就是不需要添加额外的代码,而且任务栈的信息也更加详尽。但是同样的它只能输出Activity的类名,对于具体属性没有记录。

adb shell对于调试Android程序有很多的帮助,可惜对于adb指令都没有比较全面详细而又系统的教程。只能靠在实践中慢慢摸索,从网上零星介绍中获得。

_____________________________________________________________________________________________________________________

_____________________________________________________________________________________________________________________

android 获取栈顶activty的方法总结(兼容API 5.0)的更多相关文章

  1. Android获取系统时间的多种方法

    Android中获取系统时间有多种方法,可分为Java中Calendar类获取,java.util.date类实现,还有android中Time实现. 现总结如下: 方法一: ? 1 2 3 4 5 ...

  2. Android获取ROOT权限的通用方法

    背景 自从Android问世以后,给手机获取ROOT权限变成了玩机爱好者老生常谈的话题.拥有手机,却不能拥有操作手机的最高权限,这对于手机爱好者而言,这怎么可以忍?所以无论Android升到什么什么版 ...

  3. 【Android】AppCompat V21:将 Materia Design 兼容到5.0之前的设备

    AppCompat V21:将 Materia Design 兼容到于5.0之前的设备 本篇文章翻译自Chris Banes(就职于Google,是Android-PullToRefresh,Phot ...

  4. Android 获取WIFI MAC地址的方法

    1. 经常用法,调用Android的API:WifiManager <uses-permission android:name="android.permission.ACCESS_W ...

  5. android获取各种系统路径的方法

    链接https://blog.csdn.net/qq_26296197/article/details/51909423 通过Environment获取的 Environment.getDataDir ...

  6. android获取设备屏幕大小的方法

    // 通过WindowManager获取 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay( ...

  7. android获取屏幕长宽的方法

    package com.kale.imageview02; import android.annotation.SuppressLint; import android.app.Activity; i ...

  8. android 获取sharedpreference的三种方法的区别

    1. public SharedPreferences getPreferences (int mode) 通过Activity对象获取,获取的是本Activity私有的Preference,保存在系 ...

  9. Android获取窗体信息的Util方法

    package com.wangyi.tools; import android.app.Activity; import android.util.DisplayMetrics; public cl ...

随机推荐

  1. POJ-2234 Matches Game---尼姆博奕裸题

    题目链接: https://vjudge.net/problem/POJ-2234 题目大意: 尼姆博奕裸题 思路: 直接异或 #include<iostream> #include< ...

  2. hdu-1237 简单计算器---中缀表达式转后缀表达式

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1237 题目大意: 读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值. 思路 ...

  3. bs4解析要获取被注掉的部分需先将注释符号去掉

    <div class="xzcf-content"> <div id="sfxz"> <div class="main- ...

  4. Vue 项目代理设置的优化

    Vue 项目代理设置的优化 Vue 类的项目开发中项目结构基本都是类似于 Vue-cli 生成的方式, 这种方式开发中,最常用到的模式是开启代理进行 mock 调试或远程调试, 也就是使用了 Vue- ...

  5. 深入解析浏览器的幕后工作原理(三) 呈现树和 DOM 树的关系

    呈现树和 DOM 树的关系 呈现器是和 DOM 元素相对应的,但并非一一对应.非可视化的 DOM 元素不会插入呈现树中,例如"head"元素.如果元素的 display 属性值为& ...

  6. java中的内部类概念

    内部类和外部类可以互相访问私有属性 1.普通内部类实例化方式 外部类.内部类 对象 = new 外部类().new 内部类(); class Outer{//外部类 private String ms ...

  7. [LeetCode] Special Binary String 特殊的二进制字符串

    Special binary strings are binary strings with the following two properties: The number of 0's is eq ...

  8. ftp爆破(python脚本)

    最近在乌云看到一份端口详解:为了锻炼自己,按照端口详解写脚本 #!/usr/local/bin/ python #-*- coding: UTF-8 -*- __author__ = '' from ...

  9. 区间(interval)

    [问题描述]给定 N 个区间, 要求选出若干个区间 A1, A2, A3... Am (m > 1), 使得:|A1∩A2∩A3...∩Am| * |A1∪A2∪A3...∪Am|最大.[输入格 ...

  10. bzoj 5248: [2018多省省队联测]一双木棋

    Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子 ...