Multi-player Bomberman sample

with Chromecast

View project on GitHub

Outils

Google Cast API Reference : docs

Setup

Clonez le dépôt :

 $ git clone https://github.com/xebia-france/workshop-cast-maze.git

Coding party

Importer le projet gradle suivant dans votre IDE favori

sender/android

Ce projet contiendra tout le code nécessaire pour communiquer avec le serveur sur la chromecast.

Initialisation du mediaRouter

Dans le onCreate() de l'activité récupérer l'instance du MediaRouter. Ensuite créer un MediaRouteSelector et via la méthode addControlCategory, ajouter la catégorie suivante:

CastMediaControlIntent.categoryForCast(getString(R.string.app_id))

Cela va permettre d'identifier le receiver souhaité pour notre application.

Créer une classe interne MediaRouterCallback qui hérite de MediaRouter.Callback, pour être informé quand l'utilisateur aura choisi une route (i.e. un device). Laissez les méthodes onRouteSelected et onRouteUnselected vides pour le moment.

Pour finir dans le onResume() demarrer la recherche de devices grâce à la méthode addCallback avec comme flag MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN

Prérequis

Créer les méthodes :

public void launchReceiver() {
}
public void teardown() {
}

Nous les implémenterons un peu plus loin dans l'exercice.

Sélection de la route

Lorsque l'utilisateur choisit une route, le méthode onRouteSelected de votre MediaRouterCallback est appelée. Récupérer le device sélectionné grâce à :

mSelectedDevice = CastDevice.getFromBundle(info.getExtras());
Dans la foulée appeler la méthode launchReceiver(). A l'inverse dans le callback onRouteUnSelected déclencher la méthode teardown() afin de libérer les resources et réinitialiser la variable mSelectedDevice.

Connexion au play services

Avant de pouvoir communiquer avec la chromecast, il faut d'abord se connecter au play services. Utiliser le builder du GoogleApiClient utiliser la méthode addApi pour ajouter la feature Cast.API en n'oubliant pas de passer les CastOptions suivantes:

Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
    .builder(mSelectedDevice, new Cast.Listener() {
        @Override
        public void onApplicationDisconnected(int errorCode) {
            Log.d(TAG, "application has stopped");
            teardown();
        }
    });

Ajouter les listeners pour le ConnectionCallbacks et le OnConnectionFailed (une impélementation est fournie). Ensuite démarrer la connexion avec la méthode connect

Démarrage du receiver

La gestion de la reconnection étant quelque peu complexe, elle vous est fournie. Cependant, il vous faut maintenant démarrer le receiver. Utiliser la méthode launchApplication pour le démarrer (où rejoindre une session s'il est déjà lancé) puis enregistrer un ResultCallback.

Verification du status de la connexion

Dans le onResult du ResultCallback, vous pouvez vérifier le statut de votre connexion. C'est généralement ici que l'on enregistre un channel pour recevoir des messages du receiver. Dans notre cas nous ne n'utiliserons pas cette fonctionnalité. Un exemple est cependant fourni dans la solution de l'exercice.

Envoi d'un message

Le receiver n'accepte que 4 actions : left, up, right, down. Pour lui envoyer un message il ne reste plus qu'à utiliser la méthode Cast.CastApi.sendMessage. Le namespace de notre application est :

urn:x-cast:fr.xebia.workshop.cast.maze
Vous pouvez attacher un listener pour vérifier si votre message a bien été envoyé. Mapper le clic de vos boutons pour qu'il envoie l'action correspondante au receiver.

Teardown

Dans la méthode teardown quitter le receiver.

La touche finale

Vous aller bientôt pouvoir jouer! La dernière étape consiste à afficher le logo cast dans l'action bar. Créer un menu avec le code suivant :

<menu xmlns:android="http://schemas.android.com/apk/res/android"
                             xmlns:tools="http://schemas.android.com/tools"
                             xmlns:app="http://schemas.android.com/apk/res-auto"
                             tools:context="fr.xebia.workshop.cast.maze.MazeActivity">
       <item
               android:id="@+id/mediaroutemenuitem"
               android:title="@string/mediaroutemenutitle"
               app:actionProviderClass="android.support.v7.app.MediaRouteActionProvider"
               app:showAsAction="always"/>
</menu>

Utiliser le dans le onCreateOptionsMenu et ajouter le code suivant :

MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat.getActionProvider(mediaRouteMenuItem);
// Set the MediaRouteActionProvider selector for device discovery.
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);

Go

Essayer de trouver la sortie du labyrinthe!