Android,检测何时启动其他应用


92

我正在尝试开发一个应用程序,该应用程序可以防止用户在没有密码的情况下进入指定的应用程序。情况是...

  1. 用户点击“电子邮件”应用程序(例如)
  2. 我的应用检测到应用启动
  3. 我的应用程序确认它是“电子邮件”应用程序
  4. 我的应用在顶部打开一个视图,要求输入密码
  5. 用户输入密码,如果正确,我的应用程序消失,将“电子邮件”应用程序放在顶部

我可以做其余的事情,只是第2部分让我感到困惑,并且经过很多天阅读了《广播意图》等并尝试在我的试用项目中收听“ android.intent.action.MAIN”等之后,似乎可以检测到我的应用程序何时启动。

有人可以帮忙吗?我是否正在寻找正确的方法,寻找新的应用程序来广播启动意图,还是应该在系统日志中查找新的意图,还是应该使用本机代码来做一些事情?

任何指点都会有所帮助,即使您无法完全回答,我也可以做更多研究。非常感谢。伊恩


我不确定他们是如何做到的,但是诸如App Protector之类的应用程序确实可以满足您的要求,因此从技术上讲,这确实是可能的。
汉斯皮德

@lan您如何解决您的问题,请您分享您的知识
奈达(Nida)2015年

嗨,你有解决方案吗?
ask4solutions

Answers:


34

我认为我们可以使用logcat 和分析它的输出。

在所有类似的程序中,我都已获得此许可:

android.permission.READ_LOGS

这意味着他们所有人都使用它,但是似乎程序启动了,然后我们的程序(应用保护程序)就会启动并取得领先。

使用以下代码:

try
    {
        Process mLogcatProc = null;
        BufferedReader reader = null;
        mLogcatProc = Runtime.getRuntime().exec(new String[]{"logcat", "-d"});

        reader = new BufferedReader(new InputStreamReader(mLogcatProc.getInputStream()));

        String line;
        final StringBuilder log = new StringBuilder();
        String separator = System.getProperty("line.separator"); 

        while ((line = reader.readLine()) != null)
        {
            log.append(line);
            log.append(separator);
        }
        String w = log.toString();
        Toast.makeText(getApplicationContext(),w, Toast.LENGTH_LONG).show();
    }
    catch (Exception e) 
    {
        Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
    }

并且不要忘记在清单文件中添加它的权限。


请把我们的代码放在哪里?在服务中?在onStartCommand()中?
haythem souissi 2012年

56
在JellyBean及更高版本中将无法使用。READ_LOGS权限现在仅保留给系统应用程序。
2012年

5
您对此绝对确定吗?因为即使在JB设备上,Smart AppLock似乎也可以做到这一点。是因为应用程序将自身提升为设备管理员状态吗?play.google.com/store/apps/...
KARTHIK维文

1
@Torcellite,该应用程序具有“获取运行任务”权限,因此它可能正在使用该技术。
2015年

1
@Ran那么现在该怎么使用...现在有解决方案可以解决问题中所述的问题,因为我需要在软糖之上...请尽快提供您的反馈...
Shreyan Mehta

19

一个花哨的方法是通过定时循环检查服务

ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfo = am.getRunningAppProcesses();

您遍历该列表以查看电话上正在运行的内容。现在您可以使用id和processName来标识它们,因此对于标准活动而言,这对于自定义对象很容易实现,除非您停止所有难以区分的事情...

注意:这并不是屏幕上实际存在的内容的列表,只是正在运行的内容的列表...可能会使目标无效,但至少您会知道什么时候开始运行...它将一直存在即使在后台也列出。

对于密码,您可以在找到一个受保护的应用或其他应用后立即开始活动。


是否可以获取启动/恢复应用的时间?
0LLiena

4
在Android L中使用android.app.usagepackage代替。developer.android.com/reference/android/app/usage/...
Plo_Koon

12

我认为并希望这不可能。考虑恶意软件滥用此类功能的难易程度。您可以听取针对您的意图以及广播的意图,但是启动应用程序不应是广播事件。

您可能能够做的就是更换发射器。如果用户同意。


1
为什么不可能呢?这是我的设备,我决定在其上运行什么。与我们通常授予的其他权限相比,这有什么问题呢?替换启动器将不会捕获仅由其直接启动的所有应用程序的启动。关于这一点以及关于SO的类似主题有很多评论,声称能够简单地查看意图的通过将是一个巨大的问题,但是没有人解释这个问题是什么,以及为什么应该将其视为如此讨厌以至于现有特权系统无法解决用于向用户清楚说明正在发生的事情。
凯文·怀特福特

随着预期权限的发展,这真是个笨蛋。拥有安全模型的目的是启用大多数合法用例,同时防止大多数(理想情况下)利用。不仅需要保护的您(大概是知识渊博的用户),还包括幼稚的安装应用程序的用户,以及无需考虑其他攻击媒介的应用程序编写者。所有的安全性都是权衡:在这种情况下,是在公用事业和电力之间,还是在大规模利用之间。如果您确实想要自己的自由度,则可以克隆Android堆栈并为自己的系统编写代码。
Pontus Gagge,2015年

12
class CheckRunningActivity extends Thread{
    ActivityManager am = null;
    Context context = null;

    public CheckRunningActivity(Context con){
        context = con;
        am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    }

    public void run(){
        Looper.prepare();

        while(true){
            // Return a list of the tasks that are currently running,
            // with the most recent being first and older ones after in order.
            // Taken 1 inside getRunningTasks method means want to take only
            // top activity from stack and forgot the olders.
            List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);

            String currentRunningActivityName = taskInfo.get(0).topActivity.getClassName();

            if (currentRunningActivityName.equals("PACKAGE_NAME.ACTIVITY_NAME")) {
                // show your activity here on top of PACKAGE_NAME.ACTIVITY_NAME
            }
        }
        Looper.loop();
    }
}

您可以使当前运行Activity并检查它是否ActivityEmail 应用程序相对应。

运行CheckRunningActivity ThreadApplication启动(或在设备启动)。

new CheckRunningActivity().start();

更新: 此类需要android.permission.GET_TASKS权限,因此将下一行添加到清单中:

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

我正在使用这种方法,但是由于循环的原因,它会一次又一次地打开“ //在PACKAGE_NAME.ACTIVITY_NAME上显示您的活动”。有什么解决方法吗?
Anuj Sharma 2014年

得到所需结果时停止CheckRunningActivity线程
Veaceslav Gaidarji 2014年

感谢您的答复,然后如何/何时重新启动此线程?我正在使用即时贴服务。
Anuj Sharma 2014年

根据问题的具体情况,请更详细地描述您想要获得什么。
Veaceslav Gaidarji 2014年

2
在这里的代码中,Looper.loop()由于while(true)循环永远不会结束,因此该语句似乎永远不会执行。这是一个错误吗?
2014年

11

主要问题是,当启动器(主屏幕)通常使用显式意图时,您尝试侦听隐式意图。

隐式意图是当您想说“有人播放此视频”并且Android选择可以处理该意图的应用时。

当您单击主屏幕上的“电子邮件”图标时,将发生明确的意图。它专门告诉Android使用完全限定的名称(即com.android.mail或其他名称)打开该特定应用。

AFAIK无法拦截此类明确的意图。这是Android内置的一种安全措施,任何两个Activity都不能具有相同的完全合格的包名称。这样可以防止第三方克隆该应用程序并伪装成该应用程序。如果您想做的事情可行,那么从理论上讲,您可以安装一个应用程序,该应用程序可能会阻止您竞争对手的所有应用程序正常运行。

您尝试执行的操作违反了Android安全模型。

您可以做的一件事是与特定的应用程序开发人员合作,将意图转发到您的安全系统,但这可能不是您想要处理的。


7

getRunningTasks() 在Android L中已弃用。

要获取应用使用情况统计信息,您可以使用android.app.usage包中的UsageStats类。

新的应用程序使用情况统计信息API允许应用程序开发人员收集与应用程序使用情况有关的统计信息。与不推荐使用的getRecentTasks()方法相比,此API提供了更详细的用法信息。

要使用此API,您必须首先android.permission.PACKAGE_USAGE_STATS在清单中声明权限。用户还必须通过启用对此应用程序的访问Settings > Security > Apps with usage access

是一个基本的应用示例,显示了如何使用应用使用情况统计信息API来让用户收集与应用程序使用情况有关的统计信息。


使用情况统计信息如何帮助您了解哪个应用程序处于前台?
2015年

3

也许您需要一项服务,而这些服务将在后台不断运行。比起您所说的服务。还使用类别android.intent.category.LAUNCHER监听android.intent.action.MAIN。然后让广播接收器重写onReceive方法,并进行检查以查看应用程序的名称等。


2
这听起来似乎只是我正在考虑的方法,但是我正在努力使用基本的BroadcastReceiver来接收MAIN(目录发射器)广播。以前有人设法做到这一点吗?在这个阶段,我只是想检测一个应用程序已经启动或恢复。然后,我可以将包名称与包含我要查找的名称的字符串进行比较。
伊恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.