Démarrer une nouvelle activité

Transmission des données entre activités

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Le démarrage d'une nouvelle activité ressemble un peu à la navigation via les liens sur un site web où chaque clique affiche une nouvelle page. Sous Android chaque démarrage d'une activité va nous présenter un écran différent.A travers cet article on verra comment démarrer une nouvelle activité sous Android.

Commencer une nouvelle activité

Afin de garantir une navigation fluide, on doit totalement contrôler la navigation au sein de notre application. Le démarrage d'une nouvelle activité depuis une activité est assez banale. Elle consiste à créer l'instance de la classe Intent et ensuite d'appeler la méthode startActivity() de l'activité. L'exemple ci-dessous montre comment implémenter cette logique :

public class MainActivity extends BaseActivity {
    // ...
    public void goToMyAccount(View view) {
        Log.d(LOG_TAG, "Clicked on goToMyAccount");
        Intent intentMyAccount = new Intent(getApplicationContext(), SubscriberFragmentActivity.class);
        startActivity(intentMyAccount);
    }
}

On voit qu'il suffit de passer le contexte et la classe de l'activité à lancer au constructeur de la classe Intent. L'instance créée doit être ensuite transmise en paramètre dans la méthode startActivity.

La tâche se complique quand on ne se trouve pas au sein d'une activité. La complication peut s'illustrer par des exceptions du type android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity eecontext requires the FLAG_ACTIVITY_NEW_TASK flag.. Pour l'éviter, il faut joindre le flague FLAG_ACTIVITY_NEW_TASK à la méthode qui commence une nouvelle activité.

public class BookHelperView {
    private Activity activity;
    // ...
    public void setActivity(Activity activity) {
        this.activity = activity;
    }
    public void constructFooter(PlacementTextView placementView) {
        // ...
        textSms.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(activity.getBaseContext(), SendSmsActivity.class);
                // ...
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                activity.getBaseContext().startActivity(intent);
            }
        });
    }
}

L'ajout de la flague se fait via la méthode addFlags(). Ensuite le lancement d'une nouvelle activité, via l'instance Activity passée dans la méthode setActivity(), se fait de la même manière que dans l'exemple précédent.

Parfois lors du lancement d'une nouvelle activité on a besoin de passer les paramètres, comme dans le cas des requêtes HTTP. On a déjà mentionné la possibilité de faire cela avec Bundle. Cependant au même moment on a indiqué que l'on utilisera un autre moyen, celui avec Intent. Une méthode de cette classe, putExtra(), permet de spécifier le nom et la valeur d'un paramètre qui doit être transmis à l'activité suivante. Pour l'illustrer, on prendra le code précédent dans lequel on rajoutera le fragment chargé de placer les informations sur le livre chargé :

public class BookHelperView {
    private Activity activity;
    // ...
    public void setActivity(Activity activity) {
        this.activity = activity;
    }
    public void constructFooter(PlacementTextView placementView) {
        // ...
        textSms.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(activity.getBaseContext(), SendSmsActivity.class);
                intent.putExtra("bookId", book.getId());
                intent.putExtra("bookTitle", book.getTitle());
                intent.putExtra("bookUrl", book.getUrl());
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                activity.getBaseContext().startActivity(intent);
            }
        });
    }
}

La récupération des paramètres se fera avec les getters adaptés au type du paramètre (long, int, String...). Voici l'exemple avec getLongExtra() (récupère un long) et getStringExtra() (récupère un String) :

public class SendSmsActivity extends BaseActivity {
    // ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(LOG_TAG, "Creating ContactFormActivity");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.send_sms);

        Intent intent = getIntent();
        bookId = intent.getLongExtra("bookId", 0l);
        String bookTitle = intent.getStringExtra("bookTitle");
        // ...
    }
}

Une chose importante à noter est que chaque activité doit être définie dans le fichier de manifeste, AndroidManifest.xml. La définition indique le nom, la classe ainsi que l'action et la catégorie de l'activité, comme le montre l'exemple suivant :

        <activity
            android:name="com.example.library.MainActivity"
            android:label="@string/app_name">
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

TODO : expliquer la balise action

Les attributs android:name et android:label ne sont pas compliqués à comprendre. Le premier précise le nom de l'activité et l'autre le libellé. Concernant intent-filter, il spécifie les intentions auxquelles une activité, un service ou un broadcast receiver peuvent répondre.

En ce qui concerne la balise <category />, elle détermine la catégorie à laquelle appartient le filtre d'intention. En occurrence, on indique que l'activité peut être l'activité principale de l'application (elle s'affichera après le démarrage de l'application).

Bartosz KONIECZNY Activités

Une question ? Une remarque ?

*

*

Un conseil Symfony2

A quoi peut être lié le problème "Unknown Entity namespace alias" ?

Ce problème peut apparaître dans Symfony2 parce que le bundle de l'entité peut ne pas être défini dans AppKernel.