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

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

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

剩下的部分我可以接受,只是第二部分让我很困惑,在阅读了几天 Broadcast Intents etc 和尝试在我的试用项目中听取“ android.intent.action.MAIN”等等之后,我似乎无法检测到除了我自己的应用程序之外的其他应用程序何时启动。

有人能帮忙吗?我在寻找新的应用程序来传播一个开始的意图,或者我应该阅读系统日志来获取新的意图,或者用本地代码做一些事情,这样做对吗?

任何指示都会有帮助,即使你不能完全回答它,我将能够做一些更多的研究。非常感谢。伊恩

80610 次浏览

The main issue is you are trying to listen for implicit intents when the Launcher (home screen) is typically using explicit intents.

An implicit intent is when you want to say "Somebody play this video" and Android picks an app that can handle that intent.

An explicit intent is what happens when you click the "Email" icon on the home screen. It is specifically telling Android to open that specific app by fully qualified name (i.e. com.android.mail or something).

There is no way AFAIK to intercept such explicit intents. It is a security measure built into Android that no two Activities can have the same fully qualified package name. This prevents a third party from cloning the app and masquerading as that app. If what you wish to do was possible, you could theoretically install an app that could block all of your competition's apps from working.

What you are trying to do goes against the Android security model.

One thing you could do is partner with specific app developers to forward the intents to your security system, but that's probably not something you want to deal with.

Perhaps you need a service, something that will run in the background constantly. Than have your service do what you said. Listen for the android.intent.action.MAIN also with the category android.intent.category.LAUNCHER. Then have that broadcast receiver override the onReceive method and do check to see the name of the application etc.

I think and hope this is not possible. Consider how easily such functionality could be abused by malicious software. You can listen to intents directed at you, and those that are broadcast, but application launching should not be a broadcast event.

What you may be able to do is replace the launcher. If the user agrees to it.

A gimmicky way to do it is have a service with a timed loop that checks

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

You run through that list to look at what is running on the phone. Now you can identify them with ids and processName, so for standard activity this is easy for custom ones well unless you stop them all its hard to discriminate...

Note: this isnt a list of whats is actually on the screen, just a list of whats is running...kinda nullifying your goal maybe but at least you will know when something is starting to run... it will keep being in that list even when in background though.

For the password thing you can just start your activity when you found an app thats protected or whatever.

I think we can use logcat and analyze it's output.

In all similar programs I have found this permission :

android.permission.READ_LOGS

It means all of them use it but it seems the program starts and after that our program (app protector) will start and bring front.

Use below code :

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();
}

And do not forget to add it's permission in Manifest file.

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();
}
}

You can get current running Activity and check if this Activity corresponds to Email application.

Run CheckRunningActivity Thread on Application start (or on device boot).

new CheckRunningActivity().start();

Update: This class need android.permission.GET_TASKS permission, so add next line to the Manifest:

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

getRunningTasks() is deprecated in Android L.

To obtain app usage statistics you can use UsageStats class from android.app.usage package.

The new App usage statistics API allows app developers to collect statistics related to usage of the applications. This API provides more detailed usage information than the deprecated getRecentTasks() method.

To use this API, you must first declare the android.permission.PACKAGE_USAGE_STATS permission in your manifest. The user must also enable access for this app through Settings > Security > Apps with usage access.

Here is a basic app example showing how to use App usage statistics API to let users collect statistics related to usage of the applications.

MORE MODERN ANSWER (Nov 2022):

This can be handled by the new app usage API

The system collects the usage data on a per-app basis, aggregating the data over daily, weekly, monthly, and yearly intervals. The maximum duration that the system keeps this data is as follows:

Daily data: 7 days Weekly data: 4 weeks Monthly data: 6 months Yearly data: 2 years For each app, the system records the following data:

The last time the app was used

The total length of time the app was in the foreground for that time interval (by > day, week, month, or year)

Timestamp capturing when a component (identified by a package and activity name) ?> moved to the foreground or background during a day

Timestamp capturing when a device configuration changed (such as when the device orientation changed because of rotation)

A background service can be used to constantly watch for updates to timestamps for specific apps regarding when they moved to the foreground with the API above.

note: It seems that starting from Android 5/6/7 and higher you cannot read info about other apps, including their status and logs. I believe this makes the accepted answer no longer work. If anyone can confirm this please comment below! Also, the getRunningTasks function suggested by @Veaceslav Gaidarji is now deprecated.