最近在酷安看到的一个叫做’当前activity’的app,开启无障碍功能和悬浮窗权限之后,就能在手机左上角显示正在前台显示的activity的className和packageName,然后结合之前一直嫌某些操作比如支付宝转账,微信扫一扫在关键时刻还得先打开app再打开该功能很浪费时间,于是就想自己写个基于前者显示的className和PackageName做一个自定义一键打开第三方APP指定页面的应用。

前言

最近在酷安看到的一个叫做’当前activity’的app,开启无障碍功能和悬浮窗权限之后,就能在手机左上角显示正在前台显示的activity的className和packageName,然后结合之前一直嫌某些操作比如支付宝转账,微信扫一扫在关键时刻还得先打开app再打开该功能很浪费时间,于是就想自己写个基于前者显示的className和PackageName做一个自定义一键打开第三方APP指定页面的应用,当然,会内置几个常用的操作。

困难

在实际写代码的时候,用的是自己的android6.0版本的小米MAX,发现用最常用获取进程的方法失效了,只能在本APP在前台显示时能正确显示,其他情况都会显示系统桌面的信息,上网查了一下,Google出于安全考虑,对普通应用开发该接口可能会造成用户的隐私泄露,从Android L开始对getRunningTasks接口进行限制使用。默认情况下,普通的三方应用(非系统应用不能使用该接口),于是我想了另外一种解决办法。

解决方案

方案一: 之前说了,android5.0以下的系统还是可以用下面的代码的:

private AppInfo getAppInfo(){
        ActivityManager am= (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List runningTasks=am.getRunningTasks(1);
        String pkgName = runningTasks.get(0).topActivity.getPackageName();
        String clsName = runningTasks.get(0).topActivity.getClassName();
        return new AppInfo(pkgName, clsName);

    }

方案二:

了解adb shell 命令的应该都知道’dumsys’命令,它会输出系统信息,而’dumpsys activity’则会输出activity的信息,大概是这样的,我只截了关键的一部分。

我的思路就是通过’dumpsys activity | grep mFocusedActivity ‘命令来取到当前正在运行的activity,代码如下:

    public static AppInfo getAppInfo(){
        command = "dumpsys activity | grep mFocusedActivity";
        Process process = null;
        DataOutputStream outputStream=null;
        DataInputStream inPutStrem=null;
        try {
            //获取root权限并执行command命令
            process = Runtime.getRuntime().exec("su");
            outputStream = new DataOutputStream(process.getOutputStream());
            inPutStrem=new DataInputStream(process.getInputStream());
            outputStream.write(command.getBytes());
            outputStream.writeBytes("\n");
            outputStream.flush();
            outputStream.writeBytes("exit\n");
            outputStream.flush();
            //获取执行后的输出信息
            String line = null;
            String value="";
            while ((line = inPutStrem.readLine()) != null) {
                value += line;
            }
            //判断获取root是否成功
            int exitValue= process.waitFor();
            if(exitValue==0){
                //返回正则之后的AppInfo
                return patternValue(value);
            }else{
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (outputStream != null) { outputStream.close();   }
                if (process!=null       ) { process.destroy();      }
                if(inPutStrem!=null     ) { inPutStrem.close();     }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    //正则表达式获取正在前台界面的类名和包名
    private static AppInfo patternValue(String value) {
        String patternString="mFocusedActivity: ActivityRecord\\{([\\s\\S]*) ([\\s\\S]*)/.([\\s\\S]*) ([\\s\\S]*)";
        Pattern pattern=Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(value);
        if(matcher.find()){
            String pkgName=matcher.group(2);
            String clsName=pkgName+"."+matcher.group(3);
            AppInfo appInfo=new AppInfo(pkgName,clsName);
            return appInfo;
        }else{
            return null;
        }

    }

第二种方法应该是通用的但是需要root权限,而第一种只适合在android5.0以下的系统上运行,可以根据自己的需求来选择

引用来源

http://blog.csdn.net/hyhyl1990/article/details/45700447

https://developer.android.com/studio/command-line/shell.html#shellcommands