美文网首页
Android跳转到第三方app,运行时长监听

Android跳转到第三方app,运行时长监听

作者: 独孤行者1992 | 来源:发表于2018-03-29 18:25 被阅读460次

    1. 问题描述

    需要实现从我们app跳转到第三方app,并统计第三方app在前台所待时长的功能。

    2. 问题分析

    大概过程如下:
    1)首先得有权限,我们这个需要实现允许查看应用使用情况悬浮窗两个权限。
    2)跳转到第三方app;
    3)启动一个服务监听;
    4)弹出一个悬浮窗
    5)监听第三方app是否在前台运行。实现思路是启动一个定时器,每隔1s去查看前台应用信息。
    6)预期时间完成,销毁悬浮窗,解绑Service。

    3. 实现过程

    3.1 悬浮窗
    • 悬浮窗权限
      当我们自己app在后台运行时,无法弹出一个Toast或者Dialog,所以得做一个类似于360安全卫士一样的悬浮窗。所以得要申请悬浮窗权限。6.0之前只需要在AndroidManifest文件中申请:
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
    

    6.0之后,代码中动态申请,需要跳转到系统设置中去获取:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        if (!Settings.canDrawOverlays(MainActivity.this)){
             Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
             startActivityForResult(intent, REQUESTCODE_OVER);
        }
    }
    
    • 显示一个悬浮窗
      显示一个悬浮窗,首先写一个布局文件,然后添加到WindowManager中。
        // LayoutInflater.from中Context用getApplicationContext()
        View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.layout_window,null);
        WindowManager mWindowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        //设置type.系统提示型窗口,一般都在应用程序窗口之上.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        }else{
            params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        }
        //设置效果为背景透明.
        params.format = PixelFormat.RGBA_8888;
        //设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    
        //设置窗口初始停靠位置.
        params.gravity = Gravity.LEFT | Gravity.TOP;
        params.x = 0;
        params.y = 0;
    
        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
    
        mWindowManager.addView(view,params);
    

    注意:在Android 8.0后 params.type变化。具体参考: Android 8.0 悬浮窗变动与用法

    3.2 监听app在前台运行

    Android检测app运行在前台,5.0以前是通过获取手机当前活跃进程列表,5.0后这种办法用不了了,5.0以后通过UsageStatsManager(统计服务类)来获取。

    1)5.0之前

    通过ActivityManager获取运行app进程来判断app是否处于前台。

    public boolean isRunningForeground(Context context,String packageName){
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> processes = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo processInfo: processes) {
    
            if (processInfo.processName.equals(context.getPackageName())) {
                if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    return true;
                }
            }
        }
        return false;
    }
    
    2)5.0之后

    Android5.0之后通过UsageStatsManager(统计服务类)

    • 申请“允许查看应用使用情况”。
      5.0以后查看应用使用情况
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
            tools:ignore="ProtectedPermissions"/>
    

    在代码中,我们也做一层判断,是否已经获取该权限,如果没有,则跳转到设置权限界面:

    Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
    startActivityForResult(intent,REQUESTCODE_USAGE);
    
    • 获取最近运行app
    public String getRunningPackageNameOver21(Context context){
        String topPackageName = "";
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
            return topPackageName;
        }
        // 1.获取统计服务类
        UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
        long currTime = System.currentTimeMillis();
        //2.获取从今天0点到现在的使用情况
        List<UsageStats> usageStatsList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, getStartTime(),currTime);
        //3.根据最后使用时间降序排列
        Collections.sort(usageStatsList,new UsageComparator());
    
        //获取前台应用,排除其他应用因通知栏而产生的统计信息
        Field mLastEventField = null;
        try {
            mLastEventField = UsageStats.class.getField("mLastEvent");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        for (UsageStats usageStats:usageStatsList){
            if (mLastEventField != null){
                int lastEvent = 0;
                try {
                    lastEvent =  mLastEventField.getInt(usageStats);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
    
                if (lastEvent == 1){
                    topPackageName = usageStats.getPackageName();
    //                        Log.i(TAG,"包名:" + usageStats.getPackageName() + ",:" + dateFormat.format(new Date(date)));
                    return topPackageName;
                }
            }
        }
        return topPackageName;
    }
    

    4. 最后效果

    device-2018-03-30-155006.gif

    源码:https://github.com/AnXy1218/AppRunTime

    相关文章

      网友评论

          本文标题:Android跳转到第三方app,运行时长监听

          本文链接:https://www.haomeiwen.com/subject/exwmcftx.html