ニフクラ mobile backend を使ったAndroidのサンプルアプリを作ってみる(2)

[ニフクラ mobile backend (NCMB)](https://mbaas.nifcloud.com/)のエバンジェリストをやってます小山です。

[前回](http://qiita.com/nifcloud_mb/items/0495b2f0076e8d2b8d5d)から引き続き、Android のサンプルアプリを作っていきます。

今回は[前回](http://qiita.com/nifcloud_mb/items/0495b2f0076e8d2b8d5d)作成した「掲示板もどきアプリ」のコードを修正して、次の2つの機能について NCMB を利用するように変更していきます。

* ユーザ認証
* 投稿メッセージの保存/読込

## ニフクラ mobile backend ダッシュボードでの設定

### アプリの作成

まずは[NCMB ダッシュボード](https://console.mbaas.nifcloud.com/)にログインして、NCMB 側のアプリの作成と設定をしましょう。

画面上部のナビゲーションバーの「+新しいアプリ」をクリックします。
![11.ncmb-console.png](https://qiita-image-store.s3.amazonaws.com/0/72656/ce15ed81-9df2-4c20-473e-83d346c8e2d6.png)

「アプリの新規作成」という画面が表示されますので、アプリ名に作りたいアプリ名を入力して「新規作成」ボタンを押します。今回はAndroidのアプリケーション名に合わせて「Ncmboard」にしました。
![12.ncmb_newapp.png](https://qiita-image-store.s3.amazonaws.com/0/72656/8d3e8f16-fb79-6855-b00a-42fd4ac4bc0e.png)

アプリが作成されると、「アプリケーションキー」と「クライアントキー」という2つの API キーが表示されます。この2つは Android アプリケーション側から NCMB にアクセスするのに必要なのでメモっておきます。

もしメモを忘れても、ダッシュボードの左端にある「アプリ設定」からいつでも参照できます。

### ユーザの登録

今回作成した Ncmboard アプリは、ユーザの新規作成機能は持っていないので、NCMB ダッシュボードでアプリで使用するユーザを登録します。

ダッシュボードの左側の「会員管理」ボタンを選択して表示される上部の「+新しい会員」メニューから「+新しい会員の新規作成」を選択します。
![13.newuser.png](https://qiita-image-store.s3.amazonaws.com/0/72656/962b252d-55e8-8b59-2646-b93b5160ffea.png)

ユーザ名とパスワードをクリックして、任意のものを登録します。

## アプリの変更

さて、それでは前回作成した Ncmboard アプリの「NCMB化」に入りましょう。

[前回](http://qiita.com/nifcloud_mb/items/0495b2f0076e8d2b8d5d)にも書きましたが、このサンプルアプリのコードは GitHub で公開されています。

https://github.com/koyhoge/ncmboard/

[non_ncmbrized](https://github.com/koyhoge/ncmboard/tree/non_ncmbrized) と [ncmbrized](https://github.com/koyhoge/ncmboard/tree/ncmbrized) の2つのブランチがあって、それぞれ NCMB 対応前、対応後を表しています。今回の記事では対応後である ncmbrized ブランチのコードについて解説していきます。

ソースコードの修正部分は以下の diff で確認できます。

https://github.com/koyhoge/ncmboard/commit/9494f5bf728a2c00753651ded8afc6c4959bd45d?diff=split

### ニフクラ mobile backend Android SDK のインストール

まず NCMB Android SDK である NCMB.jar を取得します。NCMB のクイックスタートのページの中ごろにある「Android SDKダウンロードはこちら」というボタンから、NCMB_latest.zip をダウンロードして下さい。

[クイックスタート (Android)](https://mbaas.nifcloud.com/doc/current/introduction/quickstart_android.html)

NCMB_latest.zip を展開すると NCMB.jar ファイルが現れますので、それを Android Studio で作成したプロジェクトディレクトリの app/libs にコピーします。

### AndroidManifest.xml の編集

アプリケーションにインターネットのアクセスを許可するため、AndroidManifest.xml の &lt;application&gt; タグの直前に以下を追加します。

```xml:AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
```

### ニフクラ mobile backend SDKの初期化

まずは MainActivity クラスの onCreate() メソッドで NCMB の初期化処理を行います。APP_KEY と CLIENT_KEY は、上記で取得したものに置き換えて下さい。

```java:MainActivity#onCreate()
        // initialize NCMB
        String app_key = "APP_KEY";
        String client_key = "CLIENT_KEY";
        NCMB.initialize(this.getApplicationContext(), app_key, client_key);
```

### プロパティの追加・変更

投稿されたメッセージを保存する NCMB オブジェクトのクラス名を messages という定数文字列として定義しておきます。

```java:MainActivity.java
    /** Object class name for messages */
    private static final String NCMB_CLASSNAME_MESSAGES = "messages";
```

現在のユーザを、ユーザ名という単なる文字列から NCMBUser オブジェクトで持つように変更します。

```java:MainActivity.java
    private String currentUserName = null;
```

↓

```java:MainActivity.java
    /** Current user object */
    public NCMBUser currentUser = null;
```

### ユーザ認証

入力されたユーザ名とパスワードを、NCMBUser.loginInBackground() メソッドに渡してユーザ認証を行います。メソッド名が xxxInBackground となっているものは非同期処理を行うもので、結果はコールバックに渡されます。ログインの場合は LoginCallback#done() メソッドに対して、

* ログインに成功した場合は、第1引数に該当する NCMBUser オブジェクト、第2引数は null
* ログインに失敗した場合は、第1引数は null、第2引数はエラーの内容が含まれる例外オブジェクト

がわたります。成功した場合は、プロパティ変数 currentUser にその結果を保持しておきます。

```java:MainActivity#showLoginDialog()
                             NCMBUser.loginInBackground(username, password, new LoginCallback() {
                                    @Override
                                    public void done(NCMBUser ncmbUser, NCMBException e) {
                                        if (e != null) {
                                            // Login failed
                                            Toast.makeText(MainActivity.this,
                                                    "Invalid username or passwrd",
                                                    Toast.LENGTH_LONG)
                                                    .show();
                                            showLoginDialog();
                                        } else {
                                            // Login successed
                                            currentUser = ncmbUser;
                                        }
                                    }
                                });
```

### メッセージの投稿

ユーザから投稿されたメッセージは、NCMBObject に入れてサーバ側に保存します。NCMBObject は NCMB のデータストアの読み書きをするためのクラスで、任意の「クラス名」を指定することで保存された一連のオブジェクトをグループ化します。今回投稿メッセージに対しては「messages」というクラス名を指定しています。

NCMBObject を作成した後、put() メソッドを用いてメッセージのデータを格納し、saveInBackground() メソッドを用いて保存を実行しています。

データの保存が成功したら、全体を再読込して表示リストを更新します。

```java:MainActivity.java
    NCMBObject messageObj = new NCMBObject(NCMB_CLASSNAME_MESSAGES);
        messageObj.put("userId", currentUser.getObjectId());
        messageObj.put("userName", currentUser.getUserName());
        messageObj.put("message", item.getMessage());

        messageObj.saveInBackground(e -> {
            if (e != null) {
                Toast.makeText(MainActivity.this,
                        "Message post failed",
                        Toast.LENGTH_LONG)
                        .show();
                return;
            }
            // update all messages
            loadMessages();
        });
```

NCMB のダッシュボードをみると、データストアの中に保存されたメッセージを確認することができます。

![14.datastore.png](https://qiita-image-store.s3.amazonaws.com/0/72656/fff26486-63b2-ab5a-061a-30322c4d0558.png)

### メッセージデータの読み込み

もし別端末から新しいメッセージが追加されていた場合も、このタイミングで手元に読み込まれて表示されることになります。

今回はとにかく全件読み込んでしまうので、メッセージの数が増えるととんでもないことになりますが(笑)、SDK としては一度の取得件数を制限することももちろん可能です。

```java:MainActivity.java
    protected void loadMessages() {
        NCMBQuery<NCMBObject> query = new NCMBQuery<>(NCMB_CLASSNAME_MESSAGES);
        query.findInBackground((list, e) -> {
            if (e != null) {
                Toast.makeText(MainActivity.this,
                        "Failed loading messages",
                        Toast.LENGTH_LONG)
                        .show();
            } else {
                List<MessageItem> tmpMessages = new ArrayList<>();
                for (NCMBObject obj : list) {
                    MessageItem item = new MessageItem();
                    item.setUserName(obj.getString("userName"));
                    item.setUserId(obj.getString("userId"));
                    item.setMessage(obj.getString("message"));
                    try {
                        item.setTimestamp(obj.getUpdateDate());
                    } catch (NCMBException ncmbException) {
                        ncmbException.printStackTrace();
                    }

                    tmpMessages.add(item);
                }

                // update messages
                messages.clear();
                messages.addAll(tmpMessages);
                messageAdapter.notifyDataSetChanged();
            }
        });
    }
```

対応はこれだけです。これで NCMB でユーザ認証を行い、投稿したメッセージを NCMB に保存し、保存されたメッセージを NCMB から読み込むことができるアプリに変更できました。

## おわりに

いかがでしたでしょうか。mBaaS と言ってもまったく難しいことはなく、既存のアプリの簡単な変更で対応ができることをお分かりいただけましたでしょうか。

NCMB には今回使用した機能の他にも、

* 大きめのデータ(画像など)を保存するファイルストレージ
* スマホへのプッシュ通知
* 位置情報検索

などの機能があります。これらの機能を利用することは、よりスマホらしいアプリを簡単に作ることに役立ってくれるでしょう。