Android 5.1.1及以上版本-getRunningAppProcises()仅返回我的应用程序包

似乎谷歌最终关闭了所有获得当前前台应用程序包的大门。

在 Lollipop 更新之后,它杀死了 getRunningTasks(int maxNum),多亏了 这个答案,我使用这段代码获得了 Lollipop 之后的前台应用程序包:

final int PROCESS_STATE_TOP = 2;
RunningAppProcessInfo currentInfo = null;
Field field = null;
try {
field = RunningAppProcessInfo.class.getDeclaredField("processState");
} catch (Exception ignored) {
}
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
for (RunningAppProcessInfo app : appList) {
if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
app.importanceReasonCode == 0 ) {
Integer state = null;
try {
state = field.getInt( app );
} catch (Exception ignored) {
}
if (state != null && state == PROCESS_STATE_TOP) {
currentInfo = app;
break;
}
}
}
return currentInfo;

Android 5.1.1及以上版本(6.0版棉花糖)似乎也杀死了 getRunningAppProcesses()。它现在返回您自己的应用程序包的列表。


UsageStatsManager

我们可以使用新的 UsageStatsManager API 作为 这里描述的,但它并不适用于所有应用程序。一些系统应用程序将返回相同的包

com.google.android.googlequicksearchbox

AccessibilityService (2017年12月: 将被谷歌禁用)

有些应用程序使用 AccessibilityService(作为 在这里见过) ,但它有一些缺点。


是否有其他获得当前正在运行的应用程序包的方法?

97195 次浏览
 private String printForegroundTask() {
String currentApp = "NULL";
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,  time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
} else {
ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
currentApp = tasks.get(0).processName;
}


Log.e("adapter", "Current App in foreground is: " + currentApp);
return currentApp;
}

Use this method for getting foreground task. U will need an System Permission "android:get_usage_stats"

public static boolean needPermissionForBlocking(Context context){
try {
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
return  (mode != AppOpsManager.MODE_ALLOWED);
} catch (PackageManager.NameNotFoundException e) {
return true;
}
}

IF user enable this in setting -> Security-> app with usage access. After that u will get foreground task. Similar process Clean matser by Cheetahamobile google play link

Google limited this functionality for system apps only. As been reported in a bug ticket, you will need the REAL_GET_TASKS permission to access there.

Applications must now have ...permission.REAL_GET_TASKS to be able to get process information for all applications. Only the process information for the calling application will be returned if the app doesn't have the permission. Privileges apps will temporarily be able to get process information for all applications if they don't have the new permission, but have deprecated ...permission.GET_TASKS Also,only system apps can acquire the REAL_GET_TASKS permission.

To get a list of running processes on Android 1.6 - Android 6.0 you can use this library I wrote: https://github.com/jaredrummler/AndroidProcesses The library reads /proc to get process info.

Google has significantly restricted access to /proc in Android Nougat. To get a list of running processes on Android Nougat you will need to use UsageStatsManager or have root access.

Click the edit history for previous alternative solutions.

Please try to use getRunningServices() instead of getRunningAppProcesses() method.

 ActivityManager mActivityManager = (ActivityManager) getSy stemService(Context.ACTIVITY_SERVICE);


List<ActivityManager.RunningServiceInfo> appProcessInfoList = mActivityManager.getRunningServices(Integer.MAX_VALUE);
public class AccessibilityDetectingService extends AccessibilityService {


@Override
protected void onServiceConnected() {
super.onServiceConnected();


//Configure these here for compatibility with API 13 and below.


AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;


if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;


setServiceInfo(config);
}


@Override
public void onAccessibilityEvent(final AccessibilityEvent event) {
if (event == null ) {
return;
} else if(event.getPackageName() == null && event.getClassName() == null){
return;
}


if (activityInfo != null){


Log.d("CurrentActivity", componentName.flattenToShortString());
}


}


private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public void onInterrupt() {
}
}
}//`enter code here`uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.GET_TASKS" />

Then start the service and app accessibility on in your device setting->accessibility->App on that service.

Take a look at https://github.com/ricvalerio/foregroundappchecker, it might be what you need. Provides sample code, and takes away the pain of having to implement cross version foreground detector.

Here are two samples:

AppChecker appChecker = new AppChecker();
String packageName = appChecker.getForegroundApp();

Or regularly check:

AppChecker appChecker = new AppChecker();
appChecker
.when("com.other.app", new AppChecker.Listener() {
@Override
public void onForeground(String packageName) {
// do something
}
)
.when("com.my.app", new AppChecker.Listener() {
@Override
public void onForeground(String packageName) {
// do something
}
)
.other(new AppChecker.Listener() {
@Override
public void onForeground(String packageName) {
// do something
}
)
.timeout(1000)
.start(this);

Just throwing out a potential optimization to what I imagine is a heavily copy-pasted bit of code for detecting the top-most application on Android M.

This

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,  time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
}

Can be simplified to this

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) context.getSystemService(
Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
time - 1000 * 1000, time);
if (appStatsList != null && !appStatsList.isEmpty()) {
currentApp = Collections.max(appStatsList, (o1, o2) ->
Long.compare(o1.getLastTimeUsed(), o2.getLastTimeUsed())).getPackageName();
}
}

I found myself using this code in a 2 second loop, and wondered why I was using a complex solution that was O(n*log(n)) when a more simple solution was available in Collections.max() which is O(n).