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

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



_______________________________________________________________________ _______________________ _______________________

  

_____________________________________________________________________________________________________________________





相关实践学习
使用CLup和iSCSI共享盘快速体验PolarDB for PostgtreSQL
在Clup云管控平台中快速体验创建与管理在iSCSI共享盘上的PolarDB for PostgtreSQL。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
相关文章
|
3天前
|
机器学习/深度学习 Java Shell
[RK3568][Android12.0]--- 系统自带预置第三方APK方法
[RK3568][Android12.0]--- 系统自带预置第三方APK方法
19 0
|
1天前
|
SQL Java 数据库连接
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
8 0
|
3天前
|
程序员 Android开发
Android亮度调节的几种实现方法
Android亮度调节的几种实现方法
8 0
|
3天前
|
Shell Android开发
Android Activity重写dump方法实现通过adb调试代码
Android Activity重写dump方法实现通过adb调试代码
10 0
|
3天前
|
Android开发
Android APP 隐藏系统软键盘的方法
Android APP 隐藏系统软键盘的方法
10 0
|
3天前
|
Android开发
Android中去掉ActionBar的几种方法
Android中去掉ActionBar的几种方法
10 0
|
12天前
|
JSON 安全 API
【专栏】四种REST API身份验证方法:基本认证、OAuth、JSON Web Token(JWT)和API密钥
【4月更文挑战第28天】本文探讨了四种REST API身份验证方法:基本认证、OAuth、JSON Web Token(JWT)和API密钥。基本认证简单但不安全;OAuth适用于授权第三方应用;JWT提供安全的身份验证信息传递;API密钥适合内部使用。选择方法时需平衡安全性、用户体验和开发复杂性。
|
15天前
|
Java API PHP
邮件发送API的方法和步骤
邮件发送API能便捷地自动化发送邮件,提高效率。步骤包括:1. 选择如aoksend、Mailgun或Amazon SES等适合的API;2. 注册并获取API密钥;3. 设置发件人、收件人、主题和内容等参数;4. 根据API文档用Python等语言编写调用代码;5. 调用API发送邮件并处理结果;6. 根据返回信息判断发送是否成功。适用于大量邮件发送场景。
|
16天前
|
API 开发者
邮件API接口使用的方法和步骤
AOKSEND指南:了解和使用邮件API接口,包括选择适合的接口(如AOKSEND、Mailgun、SMTP),获取访问权限,配置发件人、收件人及邮件内容,调用接口发送邮件,并处理返回结果,以高效集成邮件功能。
|
17天前
|
API
邮箱API发送邮件调试的方法和步骤
AokSend指南:调试邮箱API发送邮件涉及确认调试目的、检查参数设置、接口调用、异常处理、日志记录及结果验证。确保参数正确,关注接口返回,记录日志以分析问题,处理异常情况,最终验证邮件发送成功与内容准确性。AokSend提供高效发信服务,支持SMTP/API接口,适用于大量验证码发送。