webentwicklung-frage-antwort-db.com.de

Android 5.1.1 und höher - getRunningAppProcesses () gibt nur mein Anwendungspaket zurück

Offenbar hat Google endlich alle Türen geschlossen, um das aktuelle Anwendungspaket für den Vordergrund zu erhalten.

Nach dem Lollipop-Update, das getRunningTasks(int maxNum) und dank diese Antwort tötete, verwendete ich diesen Code, um das Vordergrund-Anwendungspaket seit Lollipop zu erhalten:

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 und höher (6.0 Marshmallow) scheint ebenfalls getötet zu sein getRunningAppProcesses() . Es wird nun eine Liste Ihres eigenen Anwendungspakets zurückgegeben.


UsageStatsManager

Wir können die neue UsageStatsManager -API als hier beschrieben verwenden, aber sie funktioniert nicht für alle Anwendungen. Einige Systemanwendungen geben das gleiche Paket zurück

com.google.Android.googlequicksearchbox

AccessibilityService (Dezember 2017: Wird für die Verwendung durch Google gesperrt)

Einige Anwendungen verwenden AccessibilityService (wie hier zu sehen ), aber es hat einige Nachteile.


Gibt es eine andere Möglichkeit, das aktuell ausgeführte Anwendungspaket abzurufen?

94
Lior Iluz

Um eine Liste der laufenden Prozesse auf Android 1.6 - Android 6.0) zu erhalten, können Sie diese Bibliothek verwenden, die ich geschrieben habe: https://github.com/jaredrummler/AndroidProcesses Die Bibliothek liest/proc, um Prozessinformationen abzurufen.

Google hat den Zugriff auf/proc in Android Nougat. Um eine Liste der ausgeführten Prozesse in Android Nougat zu erhalten, müssen Sie UsageStatsManager verwenden oder Root-Zugriff haben .

Klicken Sie auf den Bearbeitungsverlauf für frühere alternative Lösungen.

92
Jared Rummler
 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;
}

Verwenden Sie diese Methode, um die Vordergrundaufgabe abzurufen. Du benötigst eine Systemberechtigung "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;
    }
}

WENN Benutzer dies in Einstellung -> Sicherheit -> App mit Nutzungszugriff aktivieren. Danach bekommst du die Vordergrundaufgabe. Ähnliches Verfahren Clean matser von Cheetahamobile google play link

19
Tarun Sharma

Schauen Sie sich https://github.com/ricvalerio/foregroundappchecker an, es könnte das sein, was Sie brauchen. Enthält Beispielcode und erspart die Notwendigkeit, den Vordergrunddetektor in einer Cross-Version zu implementieren.

Hier sind zwei Beispiele:

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

Oder überprüfen Sie regelmäßig:

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);
6
rvalerio

Google hat diese Funktionalität nur für System-Apps eingeschränkt. Wie in einem Bug Ticket gemeldet, benötigen Sie die REAL_GET_TASKS Berechtigung, um dort zuzugreifen.

Anwendungen müssen jetzt ... permission.REAL_GET_TASKS haben, um Prozessinformationen für alle Anwendungen abrufen zu können. Nur die Prozessinformationen für die aufrufende Anwendung werden zurückgegeben, wenn die App nicht über die Berechtigung verfügt. Privilegien-Apps können vorübergehend Prozessinformationen für alle Anwendungen abrufen, wenn sie nicht über die neue Berechtigung verfügen, aber veraltet sind ... permission.GET_TASKS Außerdem können nur System-Apps die REAL_GET_TASKS-Berechtigung erwerben.

4
Ilya Gazman

Ich stelle mir nur eine mögliche Optimierung vor, die ein stark kopiert eingefügter Code zum Erkennen der obersten Anwendung auf Android M ist.

Diese

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

Kann dazu vereinfacht werden

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

Ich stellte fest, dass ich diesen Code in einer 2-Sekunden-Schleife verwendete, und fragte mich, warum ich eine komplexe Lösung mit dem Namen O (n * log (n)) verwendete, als in Collections.max () eine einfachere Lösung mit dem Namen O (n) verfügbar war ).

2
bstar55

// Dies funktioniert schneller als oben angegeben.

 String mforegoundPppPackageName;
 UsageStatsManager usage = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
 long time = System.currentTimeMillis();

 List<UsageStats> stats = usage.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, 0, time);
 Collections.sort(stats, usageStatsComparator);

      if (stats != null && stats.size() > 0) {
          if (stats.get(stats.size()).getPackageName().equals("Android")) {
              stats.remove(stats.size());
          }
          mforegoundPppPackageName = stats.get(stats.size()).getPackageName();
      } else {
          mforegoundPppPackageName = "";
      }

**//How to sort**

Comparator<UsageStats> usageStatsComparator = new Comparator<UsageStats>() {
        @Override
        public int compare(UsageStats o1, UsageStats o2) {
            if (o1.getLastTimeUsed() > o2.getLastTimeUsed()) {
                return 1;
            } else if (o1.getLastTimeUsed() < o2.getLastTimeUsed()) {
                return -1;
            } else {
                return 0;
            }
        }
    };
0
Dilavar M
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" />

Starten Sie dann den Dienst und die App-Barrierefreiheit in Ihrer Geräteeinstellung -> Barrierefreiheit -> App für diesen Dienst.

0
Ram Bhawan