android 获取栈顶activty的方法总结(兼容API 5.0)

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
简介:   声明:本文为Dujinyang CSDN原创投稿文章,未经许可,禁止任何形式的转载。  最近5.0\6.0\7.0 安卓系统都陆续上岗了,兼容性和代码更新是个很头疼的问题,这次我们来说下TASK的基础和API 4.

  声明:本文为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)   ... ... ... ...

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指令都没有比较全面详细而又系统的教程。只能靠在实践中慢慢摸索,从网上零星介绍中获得。



_______________________________________________________________________ _______________________ _______________________

  

_____________________________________________________________________________________________________________________





相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
相关文章
|
2月前
|
自然语言处理 算法 Java
地址描述转换为坐标点不使用API,有什么转换的方法?
地址描述转换为坐标点不使用API,有什么转换的方法?
275 64
|
28天前
|
测试技术 API 项目管理
API测试方法
【10月更文挑战第18天】API测试方法
45 1
|
3月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
78 2
基于Android P,自定义Android开机动画的方法
|
3月前
|
Android开发
基于android-11.0.0_r39,系统应用的手动签名方法和过程
本文介绍了基于Android 11.0.0_r39版本进行系统应用手动签名的方法和解决签名过程中遇到的错误,包括处理`no conscrypt_openjdk_jni-linux-x86_64`和`RegisterNatives failed`的问题。
185 2
|
25天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
48 15
Android 系统缓存扫描与清理方法分析
|
28天前
|
Java 大数据 API
别死脑筋,赶紧学起来!Java之Steam() API 常用方法使用,让开发简单起来!
分享Java Stream API的常用方法,让开发更简单。涵盖filter、map、sorted等操作,提高代码效率与可读性。关注公众号,了解更多技术内容。
|
1月前
|
JavaScript 前端开发 Java
多种语言请求API接口方法
每种语言和库的选择取决于具体需求、项目环境以及个人偏好。了解这些基本方法,开发者就可以根据项目需求选择合适的语言和库来高效地与API交互。
38 1
|
1月前
|
安全 测试技术 API
一图看懂API测试9种方法
一图看懂API测试九种方法:冒烟测试验证基本功能,功能测试确保符合规格,集成测试检查组件协同工作,回归测试防止新变更引入问题,负载测试评估性能稳定性,压力测试挑战极限负载,安全测试发现并修复漏洞,用户界面测试确保UI与API协调,模糊测试提升异常数据处理鲁棒性。
|
2月前
|
ARouter 测试技术 API
Android经典面试题之组件化原理、优缺点、实现方法?
本文介绍了组件化在Android开发中的应用,详细阐述了其原理、优缺点及实现方式,包括模块化、接口编程、依赖注入、路由机制等内容,并提供了具体代码示例。
47 2
|
3月前
|
Android开发
Android在rootdir根目录创建自定义目录和挂载点的方法
本文介绍了在Android高通平台的根目录下创建自定义目录和挂载点的方法,通过修改Android.mk文件并使用`LOCAL_POST_INSTALL_CMD`变量在编译过程中添加目录,最终在ramdisk.img的系统根路径下成功创建了`/factory/bin`目录。
207 1

热门文章

最新文章