115 votes

La détermination de l'actuel premier plan d'applications à partir d'une tâche d'arrière-plan ou d'un service

Je souhaite avoir une application qui s'exécute en arrière-plan, qui sait quand l'un de l'intégré dans les applications (messagerie, contacts, etc) est en cours d'exécution.

Donc mes questions sont:

  1. Comment je dois exécuter mon application en arrière-plan.

  2. Comment mon application en arrière-plan peut savoir ce que l'application en cours d'exécution dans le premier plan.

Les réponses de personnes ayant de l'expérience serait grandement apprécié.

103voto

Oliver Pearmain Points 5096

En ce qui concerne "2. Comment mon application en arrière-plan peut savoir ce que l'application en cours d'exécution dans le premier plan."

Ne PAS utiliser l' getRunningAppProcesses() méthode, car cela renvoie à toutes sortes de système d'ordures à partir de mon expérience et vous obtiendrez plusieurs résultats qui ont RunningAppProcessInfo.IMPORTANCE_FOREGROUND. Utiliser getRunningTasks() au lieu

C'est le code que j'utilise dans mon service afin de déterminer l'application de premier plan, il est vraiment facile:

ActivityManager am = (ActivityManager) AppService.this.getSystemService(ACTIVITY_SERVICE);
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);

C'est elle, alors vous pouvez facilement accéder aux informations détaillées de l'avant-plan app/activité:

String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
PackageManager pm = AppService.this.getPackageManager();
PackageInfo foregroundAppPackageInfo = pm.getPackageInfo(foregroundTaskPackageName, 0);
String foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo.loadLabel(pm).toString();

Cela nécessite une permission supplémentaire dans l'activité menifest et fonctionne parfaitement.

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

38voto

Sven Dawitz Points 281

j'ai dû trouver la bonne solution à la dure. le code ci-dessous est une partie de cyanogenmod7 (la tablette de bricolage) et est testé sur android 2.3.3 / pain d'épices.

méthodes:

  • getForegroundApp - retourne l'application de premier plan.
  • getActivityForApp - renvoie à l'activité de l'application.
  • isStillActive - détermine si une antérieure trouvé l'application est toujours l'application active.
  • isRunningService - une fonction d'aide pour getForegroundApp

cela devrait répondre à cette question dans tous les étendre (:

private RunningAppProcessInfo getForegroundApp() {
    RunningAppProcessInfo result=null, info=null;

    if(mActivityManager==null)
        mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
    List <RunningAppProcessInfo> l = mActivityManager.getRunningAppProcesses();
    Iterator <RunningAppProcessInfo> i = l.iterator();
    while(i.hasNext()){
        info = i.next();
        if(info.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                && !isRunningService(info.processName)){
            result=info;
            break;
        }
    }
    return result;
}

private ComponentName getActivityForApp(RunningAppProcessInfo target){
    ComponentName result=null;
    ActivityManager.RunningTaskInfo info;

    if(target==null)
        return null;

    if(mActivityManager==null)
        mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
    List <ActivityManager.RunningTaskInfo> l = mActivityManager.getRunningTasks(9999);
    Iterator <ActivityManager.RunningTaskInfo> i = l.iterator();

    while(i.hasNext()){
        info=i.next();
        if(info.baseActivity.getPackageName().equals(target.processName)){
            result=info.topActivity;
            break;
        }
    }

    return result;
}

private boolean isStillActive(RunningAppProcessInfo process, ComponentName activity)
{
    // activity can be null in cases, where one app starts another. for example, astro
    // starting rock player when a move file was clicked. we dont have an activity then,
    // but the package exits as soon as back is hit. so we can ignore the activity
    // in this case
    if(process==null)
        return false;

    RunningAppProcessInfo currentFg=getForegroundApp();
    ComponentName currentActivity=getActivityForApp(currentFg);

    if(currentFg!=null && currentFg.processName.equals(process.processName) &&
            (activity==null || currentActivity.compareTo(activity)==0))
        return true;

    Slog.i(TAG, "isStillActive returns false - CallerProcess: " + process.processName + " CurrentProcess: "
            + (currentFg==null ? "null" : currentFg.processName) + " CallerActivity:" + (activity==null ? "null" : activity.toString())
            + " CurrentActivity: " + (currentActivity==null ? "null" : currentActivity.toString()));
    return false;
}

private boolean isRunningService(String processname){
    if(processname==null || processname.isEmpty())
        return false;

    RunningServiceInfo service;

    if(mActivityManager==null)
        mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
    List <RunningServiceInfo> l = mActivityManager.getRunningServices(9999);
    Iterator <RunningServiceInfo> i = l.iterator();
    while(i.hasNext()){
        service = i.next();
        if(service.process.equals(processname))
            return true;
    }

    return false;
}

37voto

Friedrich Bhaer Points 51

Essayez le code suivant:

ActivityManager activityManager = (ActivityManager) newContext.getSystemService( Context.ACTIVITY_SERVICE );
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for(RunningAppProcessInfo appProcess : appProcesses){
    if(appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
        Log.i("Foreground App", appProcess.processName);
    }
}

Nom du processus est le nom du package de l'application qui s'exécute en arrière plan. Comparer le nom du package de votre application. Si c'est la même chose, alors votre demande est en cours d'exécution sur le premier plan.

J'espère que cela répond à votre question.

5voto

Charles Duffy Points 34134

Le ActivityManager classe est l'outil approprié pour voir quels sont les processus en cours d'exécution.

Exécution en arrière-plan, il est généralement préférable d'utiliser un Service.

0voto

ChristianS Points 33

Faire quelque chose comme ceci:

int showLimit = 20;

/* Get all Tasks available (with limit set). */
ActivityManager mgr = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> allTasks = mgr.getRunningTasks(showLimit);
/* Loop through all tasks returned. */
for (ActivityManager.RunningTaskInfo aTask : allTasks) 
{                  
    Log.i("MyApp", "Task: " + aTask.baseActivity.getClassName()); 
    if (aTask.baseActivity.getClassName().equals("com.android.email.activity.MessageList")) 
        running=true;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X