【问题标题】:Cannot get foreground activity name in Android Lollipop 5.0 only仅在 Android Lollipop 5.0 中无法获取前台活动名称
【发布时间】:2014-11-23 09:55:29
【问题描述】:

我使用以下代码在变量 foregroundTaskPackageName 中获取前台应用程序的活动名称。它适用于 4.1 到 4.4 之间的所有操作系统版本,但不适用于 Android 5.0 Lollipop。

任何人都可以帮助解决 5.0 Lollipop 中的变化吗?在 Lollipop 中 - 我为 foregroundTaskPackageName 获得的文本只是“Launcher3”。我正在使用 Genymotion 模拟器。

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0); // get
                                                                        // list
                                                                        // of
                                                                        // running
                                                                        // tasks
String foregroundTaskAppName = null;
String foregroundTaskPackageName = foregroundTaskInfo.topActivity
                .getPackageName();

【问题讨论】:

  • 我想知道您是否能够使用适用于 Android L 的新 UsageStatsManager 检索 topActivity。如果可以,请告诉我如何操作。示例代码也很有用。谢谢。
  • @user3144836 : 你能找到获取TopActivity的方法吗?
  • @venkat:不。还没想好如何在 Android 5.0 棒棒糖中做到这一点
  • 在这个帖子stackoverflow.com/questions/2166961/…回答了同样的问题请看一下。
  • 我解决了这个问题;在这里查看我的答案:stackoverflow.com/a/36086106/2217336

标签: android android-5.0-lollipop activity-manager


【解决方案1】:

这对我在 Lollipop (21) 上有效:

    ActivityManager manager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);

    List<ActivityManager.RunningAppProcessInfo> tasks = manager.getRunningAppProcesses();

    Log.i("current_app",tasks.get(0).processName);

【讨论】:

  • 有没有办法使用这种方法获得热门活动?
  • 因为我希望收到来自应用程序的确切活动的通知。
  • @venekat sry 但这只会获取当前正在运行的应用程序而不是活动
  • 仅供参考 API 中不保证此行为。请参阅有关未指定排序的注释。即使它现在有效,这种行为将来也可能会中断。 developer.android.com/reference/android/app/…
  • 这只返回你自己的包名,在摩托罗拉 MotoX 上测试过
【解决方案2】:

您需要使用新的UsageStatsManager 并调用其queryUsageStats 方法来获取已启动活动的历史记录。 请注意,用户将需要在安全->具有使用访问权限的应用程序中的设备设置中提供使用统计访问权限。

链接:

UsageStatsManager documentation

queryUsageStats method documentation

【讨论】:

    【解决方案3】:

    您可以使用下面的代码并获取当前的前台活动包名称。

     if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            // intentionally using string value as Context.USAGE_STATS_SERVICE was
            // strangely only added in API 22 (LOLLIPOP_MR1)
            @SuppressWarnings("WrongConstant")
            UsageStatsManager usm = (UsageStatsManager) getSystemService("usagestats");
            long time = System.currentTimeMillis();
            List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
                            time - 1000 * 1000, time);
                    if (appList != null && appList.size() > 0) {
                        SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
                        for (UsageStats usageStats : appList) {
                            mySortedMap.put(usageStats.getLastTimeUsed(),
                                    usageStats);
                        }
                        if (mySortedMap != null && !mySortedMap.isEmpty()) {
                            currentApp = mySortedMap.get(
                                    mySortedMap.lastKey()).getPackageName();
                        }
                    }
        } else {
            ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningAppProcessInfo> tasks = am
                            .getRunningAppProcesses();
                    currentApp = tasks.get(0).processName;
        }
    

    将这些权限添加到 Manifest 文件中(第一个用于 = API 21)。

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

    【讨论】:

    • 您是否在您的应用程序中运行了此代码?因为我无法找到 UsageStatsManager。你能分享你的java文件或代码吗?
    • @nitishpatel UsageStatsManager 仅存在于 API 21 及更高版本。
    • 这适用于前台包名,但是Activity类名呢?
    • @user1118764 你有没有找到获取活动类名的方法?请告诉我
    【解决方案4】:

    根据getRunningTasks() 文档:

    此方法在 API 级别 21 中已弃用。从 LOLLIPOP 开始,此 方法不再可用于第三方应用程序: 引入以文档为中心的最新消息意味着它可以泄露人员 给来电者的信息。为了向后兼容,它仍然会 返回其数据的一小部分:至少是调用者自己的任务, 可能还有一些其他的任务,比如家,已知不 敏感。

    【讨论】:

      【解决方案5】:

      一种可用但不是最好的方法是使用辅助功能。

      在 AndroidManifest xml 文件中声明无障碍服务

      <service
                  android:name=".MyAccessibilityService"
                  android:label="@string/accessibility_service_label"
                  android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
                  <intent-filter>
                      <action android:name="android.accessibilityservice.AccessibilityService" />
                  </intent-filter>
      
                  <meta-data
                      android:name="android.accessibilityservice"
                      android:resource="@xml/accessibility_service_config" />
              </service>
      

      accessibility_service_config.xml 文件

      <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
          android:description="@string/accessibility_service_desc"
          android:accessibilityEventTypes="typeAllMask"
          android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews"
          android:accessibilityFeedbackType="feedbackSpoken"
          android:notificationTimeout="100"
          android:canRetrieveWindowContent="true"
      />
      

      在窗口状态改变时存储活动名称

      public class MyAccessibilityService extends AccessibilityService{
          public static String sActivityName;
          @Override
          public void onAccessibilityEvent(AccessibilityEvent event) {
              // TODO Auto-generated method stub
              if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
                  Log.d("activitytest", "onAccessibilityEvent with window state changed");
                  sActivityName = event.getClassName().toString();
              }
          }
      
          @Override
          public void onInterrupt() {
              // TODO Auto-generated method stub
      
          }
      
      }
      

      缺点是你需要让用户在设置中启用你的无障碍服务。

      【讨论】:

        【解决方案6】:

        我创建了一个类,它使用/system/bin/toolbox 命令来识别进程,然后识别可见的应用程序。 需要添加识别系统应用,没有 UI 和 android 启动器。

        ProcessManager.java

        【讨论】:

          【解决方案7】:

          试试这个

          public static boolean isForeground(Context context) {
              ActivityManager manager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
              List<ActivityManager.RunningAppProcessInfo> tasks = manager.getRunningAppProcesses();
              if(tasks.isEmpty())
                  return false;
          
              for (ActivityManager.RunningAppProcessInfo task : tasks) {
                  if(context.getPackageName().equalsIgnoreCase(task.processName)){
                      return task.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
                  }
              }
              return false;
          }
          

          【讨论】:

            猜你喜欢
            • 2016-03-25
            • 2011-08-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-28
            • 2012-05-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多