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推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
相关文章
|
7天前
|
JSON 安全 API
Microsoft邮箱API发送邮件的方法和步骤
Aoksend详解如何使用Microsoft邮箱API发送邮件:1. 在Azure创建应用并获取访问权限;2. 设置API请求头,含Authorization和Content-Type;3. 构建JSON格式的邮件内容;4. 使用POST方法发送至API端点;5. 检查响应处理发送结果。遵循最佳实践,安全集成邮件功能。
|
10天前
|
搜索推荐 JavaScript 前端开发
Gmail邮箱API发送邮件的方法有什么
使用Gmail API发送邮件,需先获取API访问权限,包括在Google Cloud Platform上创建项目,启用Gmail API,生成API密钥或OAuth 2.0凭据。然后,用Python等编程语言设置API请求,指定邮件详情。发送简单邮件涉及创建Base64编码的消息体,而带附件的邮件需编码为multipart格式。可添加邮件头信息,并处理发送结果以确保成功。Gmail API使应用能集成自动化、个性化的邮件发送功能,提升效率和体验。
|
26天前
|
人工智能 Java API
Google Gemini API 接口调用方法
Google 最近发布的 Gemini 1.0 AI 模型通过其升级版,Gemini,标志着公司迄今为止最为强大和多功能的人工智能技术的突破。
|
3月前
|
Android开发 Python
Python封装ADB获取Android设备wifi地址的方法
Python封装ADB获取Android设备wifi地址的方法
60 0
|
5月前
|
Linux Android开发 iOS开发
基于.Net开发的ChatGPT客户端,兼容Windows、IOS、安卓、MacOS、Linux
基于.Net开发的ChatGPT客户端,兼容Windows、IOS、安卓、MacOS、Linux
86 0
|
8天前
|
监控 安全 API
Office365邮箱API发送邮件有什么值得推荐的方法
使用Office365邮箱API发送邮件时,建议采用OAuth认证确保安全;利用RESTful API简化流程;借助官方客户端库加速集成;遵循最佳实践保障安全可靠;批量发送时使用异步方式提升效率;监控调试以解决问题;注意避免触发垃圾邮件过滤。AokSend提供高效发信服务,支持触发式接口和SMTP/API,独立IP确保高触达。
|
15天前
|
Android开发
Android调用相机与相册的方法2
Android调用相机与相册的方法
17 0
|
3月前
|
API Python Windows
python3应用windows api对后台程序窗口及桌面截图并保存的方法
python3应用windows api对后台程序窗口及桌面截图并保存的方法
88 1
|
26天前
|
Java API Maven
email api java编辑方法?一文教你学会配置步骤
在Java开发中,Email API是简化邮件功能的关键工具。本文指导如何配置和使用Email API Java:首先,在项目中添加javax.mail-api和javax.mail依赖;接着,配置SMTP服务器和端口;然后,创建邮件,设定收件人、发件人、主题和正文;最后,使用Transport.send()发送邮件。借助Email API Java,可为应用添加高效邮件功能。
|
30天前
|
JavaScript 前端开发 API
JavaScript循环遍历常用的7种方法以及常用的数组 API
JavaScript循环遍历常用的7种方法以及常用的数组 API
34 0