【问题标题】:Get open activity of the foreground app获取前台应用的打开活动
【发布时间】:2017-06-05 12:31:20
【问题描述】:

我需要获取前台 App 的当前 Activity。我尝试关注this answer,后来又使用了this library(因为第一个解决方案只适用于 Lollipop),它们确实可以很好地告诉前台应用程序的包名称,但我需要知道打开了什么活动。

【问题讨论】:

    标签: android service foreground


    【解决方案1】:

    嘿@Capitan Luzzatto,

    • 在 LOLLIPOP(API 21) 之前,我们可以从 ActivityManager 获取正在运行的应用列表
    • 但是从 LOLLIPOP 我们应该只从 UsageStatsManager 获取

    首先您需要 2 个权限才能读取任务

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

    您应该首先检查用户 API 级别是否为 21 或更高,如果是,您应该可以访问以下使用访问设置

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP && !mIsChecked) {
            if (getUsageStatsList(getActivity()).isEmpty()) {
    
                Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
                startActivity(intent);
            }
     }
    

    获取使用情况统计列表

        public static List<UsageStats> getUsageStatsList(Context context){
        UsageStatsManager usm = (UsageStatsManager) context.getSystemService("usagestats");
        Calendar calendar = Calendar.getInstance();
        long endTime = calendar.getTimeInMillis();
        calendar.add(Calendar.DATE, -1);
        long startTime = calendar.getTimeInMillis();
    
        List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,startTime,endTime);
    
        return usageStatsList;
    }
    

    终于可以通过以下方法获取最新的Foreground app

    public String getRecentApps(Context context) {
        String topPackageName = "";
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
    
            long time = System.currentTimeMillis();
    
            UsageEvents usageEvents = mUsageStatsManager.queryEvents(time - 1000 * 30, System.currentTimeMillis() + (10 * 1000));
            UsageEvents.Event event = new UsageEvents.Event();
            while (usageEvents.hasNextEvent()) {
                usageEvents.getNextEvent(event);
            }
    
            if (event != null && !TextUtils.isEmpty(event.getPackageName()) && event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
                if (AndroidUtils.isRecentActivity(event.getClassName())) {
                    return event.getClassName();
                }
                return event.getPackageName();
            } else {
                topPackageName = "";
            }
        } else {
            ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
            ComponentName componentInfo = taskInfo.get(0).topActivity;
    
            if (AndroidUtils.isRecentActivity(componentInfo.getClassName())) {
                return componentInfo.getClassName();
            }
    
            topPackageName = componentInfo.getPackageName();
        }
    
    
        return topPackageName;
    }
    

    要获取前台活动,请使用这样的方法

    public String getRecentActivity(Context context) {
        String topActivityName = "";
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
    
            long time = System.currentTimeMillis();
    
            UsageEvents usageEvents = mUsageStatsManager.queryEvents(time - 1000 * 30, System.currentTimeMillis() + (10 * 1000));
            UsageEvents.Event event = new UsageEvents.Event();
            while (usageEvents.hasNextEvent()) {
                usageEvents.getNextEvent(event);
            }
    
            if (event != null && !TextUtils.isEmpty(event.getPackageName()) && event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
                return event.getClassName();
            } else {
                topActivityName = "";
            }
        } else {
            ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
            ComponentName componentInfo = taskInfo.get(0).topActivity;
    
            topActivityName = componentInfo.getClassName();
        }
    
    
        return topActivityName;
    }
    

    AndroidUtils.java - 要以 Hack 方式获取设备最近的屏幕,也许我们应该对此进行更多调查,不确定它是否适用于所有设备,但它适用于几乎所有设备

    public class AndroidUtils {
        private static final String RECENT_ACTIVITY;
    
        static {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
                RECENT_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
            } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
                RECENT_ACTIVITY = "com.android.systemui.recent.RecentsActivity";
            } else {
                RECENT_ACTIVITY = "com.android.internal.policy.impl.RecentApplicationDialog";
            }
        }
    
        /**
         * To get the Device recent screen activity
         *
         * @param className
         * @return activity
         */
        public static boolean isRecentActivity(String className) {
            if (RECENT_ACTIVITY.equalsIgnoreCase(className)) {
                return true;
            }
    
            return false;
        }
    }
    

    【讨论】:

    • 我做到了,但问题是 getRecentApps() 总是返回包名。例如,当我打开设置时,它总是返回 com.android.settings 当我在那里打开某些东西时。
    • 那么你想要应用程序名称吗..?
    • 不,我需要前台活动名称
    • 编辑答案以获得最近的活动名称
    • 什么是AndroidUtils类?
    【解决方案2】:

    由于安全问题,您应该无法执行此操作。您不希望其他应用知道您当前的打开活动。所以其他应用程序不希望您监视它们。这是操作系统限制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多