DaVinci/Emmet – Créer une application Android Wear en moins de 10 minutes 2/2

Exemple

J’ai placé un fichier JSON contenant la liste des versions d’android, ainsi que leur logo respectif, essayons de les afficher sur notre montre grâce à Emmet et DaVinci !

Nous utiliserons Retrofit pour récupérer les données du JSON : http://pastebin.com/raw.php?i=PHPXBsEf

Créons notre protocole

Le protocol Smartphone->Wear
wearprotocole/ WearProtocole.java

public interface WearProtocol {
    void onAndroidVersionsReceived(List<AndroidVersion> androidVersions);
}

Le protocol Wear->Smartphone
wearprotocole/ SmartphoneProtocol.java

public interface SmartphoneProtocol {
    void hello();
}

Puis nos objets models partagés

wearprotocole/ AndroidVersion.java

public class AndroidVersion {

    private String titre;
    private String description;
    private String url;

    //getters & setters
}

 

Coté Smartphone

mobile/build.gralde

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    wearApp project(':wear')
    compile 'com.android.support:appcompat-v7:22.0.0'
    compile 'com.squareup.retrofit:retrofit:1.9.0'

    compile project (":wearprotocol")
    compile ("com.github.florent37:davincidaemon:1.0.3@aar"){
        transitive=true
        exclude group:"com.google.android.gms" //davinci & emmet use different gms versions
    }
}

Dans notre module smartphone, créer un interface pour Retrofit

AndroidService.java

public interface AndroidService {

    public static final String ENDPOINT = "http://pastebin.com";

    @GET("/raw.php?i=PHPXBsEf")
    public void getElements(Callback<List<AndroidVersion>> callback);
}

Implémentons notre service Smartphone

mobile/ WearService.java

public class WearService extends EmmetWearableListenerService implements SmartphoneProtocol {

    WearProtocol wearProtocol;

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

        //initialise la récéption de données
        Emmet.registerReceiver(SmartphoneProtocol.class, this);

        //initialise l'envoie de données vers la montre
        wearProtocol = Emmet.createSender(WearProtocol.class);
    }

    //lorsque le smartphone reçois le message hello (envoyé depuis wear)
    @Override
    public void hello() {
        //Utilise Retrofit pour réaliser un appel REST
        AndroidService androidService = new RestAdapter.Builder()
                .setEndpoint(AndroidService.ENDPOINT)
                .build().create(AndroidService.class);

        //Récupère et deserialise le contenu de mon fichier JSON en objet List<AndroidVersion>
        androidService.getElements(new Callback<List<AndroidVersion>>() {
            @Override
            public void success(List<AndroidVersion> androidVersions, Response response) {

                //envoie cette liste à la montre
                wearProtocol.onAndroidVersionsReceived(androidVersions);
            }

            @Override
            public void failure(RetrofitError error) {
            }
        });
    }

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        super.onMessageReceived(messageEvent);

        //permet à DaVinciDaemon d'écouter les messages
        DaVinciDaemon.with(getApplicationContext()).handleMessage(messageEvent);
    }
}

Ne pas oublier de le déclarer dans notre mobile/androidManifest.xml

     <service android:name=".WearService">
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
            </intent-filter>
     </service>

Coté Wear

wear/build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.google.android.support:wearable:1.1.0'
    compile project(':wearprotocol')
    compile ('com.github.florent37:davinci:1.0.3@aar'){
        transitive=true
        exclude group:"com.google.android.gms" //if davinci & emmet use different gms versions
    }
}

wear/ layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.wearable.view.GridViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:keepScreenOn="true" />

    <android.support.wearable.view.DotsPageIndicator
        android:id="@+id/page_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom"
        android:layout_marginBottom="5dp"/>

</FrameLayout>

 

Utilisons Emmet afin de communiquer avec notre smartphone

Envoie :

SmartphoneProtocol smartphoneProtocol = Emmet.createSender(SmartphoneProtocol.class);
smartphoneProtocol.hello(); //envoie le message hello smartphone

Reception :

Emmet.registerReceiver(WearProtocol.class, this);

wear/ MainActivity.java

public class MainActivity extends Activity implements WearProtocol {

    private final static String TAG = MainActivity.class.getCanonicalName();

    private GridViewPager pager;
    private DotsPageIndicator dotsPageIndicator;

    //la liste des éléments à afficher
    private List<AndroidVersion> elementList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        pager = (GridViewPager) findViewById(R.id.pager);
        dotsPageIndicator = (DotsPageIndicator) findViewById(R.id.page_indicator);
        dotsPageIndicator.setPager(pager);

        //initialise Emmet
        Emmet.onCreate(this);

        Emmet.registerReceiver(WearProtocol.class, this);
        SmartphoneProtocol smartphoneProtocol = Emmet.createSender(SmartphoneProtocol.class);

        smartphoneProtocol.hello(); //envoie le message hello smartphone
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Emmet.onDestroy(); //ne pas oublier
    }

    //envoyé depuis le smartphone
    @Override
    public void onAndroidVersionsReceived(List<AndroidVersion> androidVersions) {
        if (androidVersions != null && this.elementList != null && this.elementList.isEmpty()) {
            this.elementList.addAll(androidVersions);
            startMainScreen();
        }
    }

    public void startMainScreen() {
        //penser à effectuer les actions graphiques dans le UIThread
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //nous affichons ici dans notre viewpager

                if (pager != null && pager.getAdapter() == null)
                    pager.setAdapter(new ElementGridPagerAdapter(MainActivity.this, elementList, getFragmentManager()));
            }
        });
    }
}

 

Puis enfin créons notre adapter, qui affichera une cards pour chaque version d’android

et utilisons DaVinci pour afficher chaque logo en background de notre FragmentGridPagerAdapter

wear/ ElementGridPagerAdapter.java

public class ElementGridPagerAdapter extends FragmentGridPagerAdapter {

    private Context context;
    private List<AndroidVersion> androidVersions;
    private List<Row> mRows;

    public ElementGridPagerAdapter(Context context, List<AndroidVersion> androidVersions, FragmentManager fm) {
        super(fm);

        this.context = context;
        this.androidVersions = androidVersions;
        this.mRows = new ArrayList<Row>();

        //Construit le tableau des éléménts à afficher
        for (AndroidVersion version : androidVersions) {
            mRows.add(new Row(
                            //pour l'instant nous ne mettrons qu'un élément par ligne
                            CardFragment.create(version.getTitre(), version.getDescription())
                    )
            );
        }
    }

    //Le fragment à afficher
    @Override
    public Fragment getFragment(int row, int col) {
        Row adapterRow = mRows.get(row);
        return adapterRow.getColumn(col);
    }

    //le drawable affichée en background pour la ligne [row]
    @Override
    public Drawable getBackgroundForRow(final int row) {
        return DaVinci.with(context).load(this.androidVersions.get(row).getUrl()).into(this, row);
    }

    @Override
    public Drawable getBackgroundForPage(final int row, final int column) {
        //nous pouvons spécifier un drawable différent pour le swipe horizontal
        return getBackgroundForRow(row);
    }

    //Le nombre de lignes dans la grille
    @Override
    public int getRowCount() {
        return mRows.size();
    }

    //Le nombre de colonnes par ligne
    @Override
    public int getColumnCount(int rowNum) {
        return mRows.get(rowNum).getColumnCount();
    }

    /**
     * Représentation d'une ligne - Contient une liste de fragments
     */
    private class Row {
        final List<Fragment> columns = new ArrayList<Fragment>();

        public Row(Fragment... fragments) {
            for (Fragment f : fragments) {
                add(f);
            }
        }

        public void add(Fragment f) {
            columns.add(f);
        }

        Fragment getColumn(int i) {
            return columns.get(i);
        }

        public int getColumnCount() {
            return columns.size();
        }
    }

}

 

 

Vous pouvez remarquer qu’il est assez rapide et simple de créer une application wear grâce à Emmet et DaVinci, donc à utiliser sans modération !

 

Vous pouvez retrouver les sources de ce tutoriel sur github

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *