Utilisez une notification persistante pour permettre à l'utilisateur de revenir à l'exécution de l'application Android

StackOverflow https://stackoverflow.com/questions/3568250

Question

Je développe une application avec de nombreuses activités. Je voudrais créer une notification persistante (plus ou moins) dit: « AppName - Retour à AppName » qui sera présent à chaque fois que mes services de base sont en cours d'exécution. Création et élimination de la notification avait pas de problème.

Maintenant, l'utilisateur pourrait être sur l'un de plusieurs écrans / Activités, quitter l'application, veulent alors saisir à nouveau l'application via la notification. Le problème est , la notification doit avoir une intention, qui lance un Activité prédéterminée . Je veux que la notification à entrer de nouveau l'application quelle que soit l'activité est en haut de la pile historique .

Ma première tentative d'une solution laide était de faire une activité (permettent de faire appel de ce « returnFromNotify ») dont le seul travail était « fini » lui-même dans c'est « onCreate ». La notification ouvrirait « returnFromNotify » dans le cadre de l'histoire des applications, ce qui serait alors se retirer immédiatement, envoyer le dos de l'utilisateur à l'état de l'histoire précédente dans la pile d'applications. Cela semble fonctionner ... à moins que l'utilisateur a utilisé « retour » pour sauvegarder complètement hors de l'application. Puis, quand ils ont frappé la notification, « returnFromNotify » des charges, puis termine, de les renvoyer vers l'écran d'accueil (car il n'y a pas d'activité sur la pile d'histoire pour l'application).

Je considérais essayer de détecter s'il y avait quelque chose dans la pile de l'histoire avant « returnFromNotify », et sinon, le feu mon activité principale. Je ne peux pas sembler trouver une façon de faire, que ce soit.

Toute entrée ou suggestions pour un novice Java / Android? Pour votre information, mon histoire principale est avec les langues basées sur le script.

Était-ce utile?

La solution

Je aime votre idée originale de créer une activité « returnFromNotify » mieux que votre solution de contournement proposée, comme permet de détecter si le ResumeActivity est au bas de la pile (et donc la seule activité dans la pile).

Voici comment vous pouvez le faire:

Ajoutez votre ResumeActivity au manifeste et spécifiez le Nohistory attribut:

<activity android:name=".ResumeActivity" android:noHistory="true" />

Nohistory Spécifier fera que cette activité ne restera pas dans la pile dès qu'elle se termine. De cette façon, vous savez que seule une instance en cours d'exécution du ResumeActivity affichera dans la pile.

Afin de vérifier la pile d'applications, vous devrez également demander la permission GET_TASKS:

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

Maintenant, vous pouvez utiliser ActivityManager :: getRunningTasks () déterminer si ResumeActivity est la seule activité de la pile:

public class ResumeActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if(isOnlyActivityInStack()) { //check the application stack
            //This activity is the only activity in the application stack, so we need to launch the main activity
            Intent main = new Intent(this, MainActivity.class);
            main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(main);
        } else {
            //Return the user to the last activity they had open
            this.finish();
        }
    }

    /**
     * Checks the currently running tasks. If this activity is the base activity, we know it's the only activity in the stack
     *
     * @return  boolean  This activity is the only activity in the stack?
     **/
    private boolean isOnlyActivityInStack() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        boolean onlyActivityInStack = false;

        for(RunningTaskInfo tasks : manager.getRunningTasks(Integer.MAX_VALUE)) {
            if(tasks.baseActivity.getPackageName().equals(this.getPackageName())) { //find this package's application stack
                if(tasks.baseActivity.getClassName().equals(this.getClass().getName())) {
                    //If the ResumeActivity is the base activity, we know that it is the only activity in the stack
                    onlyActivityInStack = true;
                    break;
                }
            }
        }

        return onlyActivityInStack;
    }

}

Je sais que vous posé cette question il y a plus de 2 ans, mais je fournir cette réponse au cas où quelqu'un d'autre court dans cette situation particulière (comme je l'ai fait). Je pense que vous étiez sur la bonne voie avec la solution que vous travailliez à l'origine vers.

Autres conseils

D'accord, je crois que je l'ai trouvé un travail autour de pour mon cas spécifique satisfaisant . J'ai ajouté un entier statique à mon « MainActivity », et chaque fois qu'il est « onCreate » est tiré, il incrémente le nombre entier. Chaque fois qu'il est « OnDestroy » est tiré, il décrémente.

Dans mon « returnFromNotify », je regarde l'entier statique pour voir si elle est supérieure à 0. Si oui, je suppose qu'il ya un actif « MainActivity », et que l'exécution de « finition » à l'intérieur « returnFromNotify » retournerai là-bas . Dans le cas contraire, il suppose que les utilisateurs ont « soutenu » sur lui-même se termine, puis utilise « startActivity » pour tirer une nouvelle instance de « MainActivity ».

Ce n'est pas une solution universelle, mais pour mes fins, je pense qu'il suffira. Je suis toujours ouvert à d'autres réponses, et si quelqu'un peut percer un trou dans ma logique, s'il vous plaît le faire - constructive critiques sont les bienvenues . Merci.

Je suppose qu'il n'y a pas moyen facile de faire cela, mais au lieu d'ajouter un compteur dans le MainActivity j'étendrais application :

  

Classe de base pour ceux qui ont besoin de   maintenir l'état global de l'application. Vous   peut fournir votre propre mise en œuvre par   spécifiant son nom dans votre   AndroidManifest.xml de   étiquette, ce qui provoque cette classe à être   instancié pour vous lorsque le processus   pour votre application / package est   créé.

Je mantein la logique là et avoir une méthode comme:

public Intent getIntentForLastActivityShown();

à appeler lorsque l'élément de notification est cliqué.

Ma première approche serait d'utiliser SharedPreferences et stocker une paire de valeurs clé appelée quelque chose comme lastDisplayedActivity. Puis, dans la onResume de chaque activité (et éventuellement `onCreate ') vous auriez une ligne comme ceci:

sharedPreferences.edit().putInteger("lastDisplayedActivity", ReturnFromNotify.THIS_ACTIVITY_NAME);

En d'autres termes, vous stockez une variable à l'échelle indiquant l'application dont l'activité a été la dernière affichée. Ensuite, vous prenez simplement cette variable de SharedPreferences et de lancer l'activité correspondante.

I activité utilise habituellement appelé « lanceur » cet état de ma demande de contrôle modèle et démarre des activités (ou fait d'autres choses) selon les règles du modèle. Je mets Modèle objet dans ma classe d'application. Modèle peuvent utiliser Préférences pour stocker son état. Je le fais pour éviter les champs statiques dans les activités.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top