MBaaS徹底入門――Kii Cloudでスマホアプリ開発

第6回Kii Cloudを用いたチャットアプリケーションの開発 [その2] ―友達追加機能の実装

前回は、チャットアプリケーションの全体像/データフローを示し、その後に「サインアップ(サインイン⁠⁠」機能について解説しました。

第6回となる今回は、他のユーザを友達リストに追加する「友達追加」機能について解説します。ユーザは友達リストから話したい友達を選び、チャットを開始することになります。

なお前回と同様、今回使用したソースコードについては、GitHubで公開しています。

友達追加機能の実装

実装に入る前に、前回説明した友達追加機能について簡単に確認してみましょう。

友達追加機能は、次の2つのフローにより成り立ちます。

友達追加時のデータフロー
友達追加時のデータフロー

友達候補の取得

サインアップの際、アプリケーションスコープの⁠chat_users⁠バケットにユーザ情報を登録しているため、このバケットはアプリケーションに登録している全ユーザの情報を含んでいます。このバケットに対して検索をかけることで、友達候補を取得します。

友達リストへの追加

1で取得した友達候補から、友達リストに追加したいユーザを選択します。選択したユーザはユーザスコープの⁠chat_friends⁠バケットに追加され、チャットを開始する際に選択できます。

この2つのフローの実装について、以下で説明していきます。

①友達候補の取得

友達候補の取得処理をもう少し小さい処理に分割すると、以下のようになります。

  1. ユーザの入力から検索キーワードを取得する
  2. ユーザネームもしくはEmailが検索キーワードから始まるユーザを、⁠chat_users⁠バケットから取得する
  3. 取得したユーザのリストを表示する

この中で、Kii Cloudへのアクセスが含まれているのは、2つ目の「ユーザネームもしくはEmailが検索キーワードを含むユーザを取得する」です。この実装について見ていきましょう。

なお、以降では、前回同様、GitHubに掲載しているコードと少しコメントの内容・位置が異なっている場合があります。あらかじめご了承ください。

まず、UserListLoaderクラスを見ていきます。

このクラスではActivity側で入手したユーザ入力を検索キーワードとして、コンストラクタでセットします。セットした検索キーワードを用いて、友達候補を取得する処理をバックグラウンドで実行します。処理終了後、結果を元のActivityに渡します。

public class UserListLoader extends AbstractAsyncTaskLoader<List<ChatUser>> {
	
    private String keyword;
	
    public UserListLoader(Context context, String keyword) {
        super(context);
        
        // Activity側で取得した検索キーワードをセットする
        this.keyword = keyword;
    }

    @Override
    public List<ChatUser> loadInBackground() {
        List<ChatUser> users = new ArrayList<ChatUser>();
        try {
            
            // 友達候補(キーワードにマッチするユーザ)を取得する
            List<ChatUser> results = ChatUser.searchByKeyword(keyword);
            for (ChatUser user : results) {
                // サインイン中のユーザ(=検索実行中のユーザ自身)は検索結果から除外する
                if (!TextUtils.equals(user.getUri(), KiiUser.getCurrentUser().toUri().toString())) {
                    users.add(user);
                }
            }
        } catch (Exception e) {
            Logger.e("Unable to list users", e);
        }
        return users;
    }
}

UserListLoaderクラス内で、友達候補取得のために実行するメソッドはChatUser#searchByKeyword(String keyword)です。このメソッド内でAndroid Cloud SDKのAPIを実行しています。具体的には、KiiBucket#query(KiiQuery query)を実行して、⁠chat_users⁠バケット下にあるオブジェクトの内、条件にマッチしたオブジェクトを取得しています。

クエリ実行時の条件は、KiiClauseクラスにより指定します。

KiiQueryクラスの生成時に与えるKiiClauseクラスのインスタンスにより、⁠特定のフィールドの値が等しい」⁠あるフィールドの値が指定した値よりも大きい」などの条件を扱うことができます。KiiClauseクラスは論理演算子(and, or)をサポートしているため、複数の条件を組み合わせることも可能です。

以下の例では、⁠ "username" もしくは ⁠email⁠⁠ フィールドの値が検索キーワードで始まるオブジェクト」という条件を使っています。

public class ChatUser extends KiiObjectWrapper implements IUser {

    // “chat_users”バケット: アプリケーションの全ユーザの情報が登録されている
    private static final String BUCKET_NAME = "chat_users"; 

    private static final String FIELD_USERNAME = "username";
    private static final String FIELD_EMAIL = "email";

    public ChatUser(KiiObject user) {
        super(user);
    }
	
    public static KiiBucket getBucket() {
        return Kii.bucket(BUCKET_NAME);
    }

    public static List<ChatUser> searchByKeyword(String keyword) throws Exception {
        KiiQuery query = null;
        
        // *(アスタリスク)を指定した場合、全ユーザを取得する
        if (TextUtils.equals("*", keyword)) {
            query = new KiiQuery();
        } else {
            query = new KiiQuery(

    
                // 取得した検索キーワードから始まる”username”/”email”フィールドの値を検索する
                KiiClause.or(                    
                    KiiClause.startsWith(FIELD_USERNAME, keyword),
                    KiiClause.startsWith(FIELD_EMAIL, keyword)
                )
            );
        }
        List<ChatUser> users = new ArrayList<ChatUser>();
        List<KiiObject> objects = getBucket().query(query).getResult();

        // ChatUserはKiiObject(オブジェクトを表すAndroid Cloud SDKのクラス)から作成する
        for (KiiObject object : objects) {
            users.add(new ChatUser(object));
        }
        return users;
    }
    …
}

②友達リストへの追加

友達リストへの追加をもう少し小さい処理に分割すると、以下のようになります。

  1. 「①友達候補の取得」で取得した友達候補から、友達リストに追加したいユーザを選択する
  2. ユーザの意思を確認するダイアログを表示する
  3. 上記ダイアログで追加に同意するボタンをクリックした場合、友達リストにユーザを追加/表示する

この中で、Kii Cloudへのアクセスが含まれているのは、3番目の「友達リストにユーザを追加/表示する」です。この実装について見ていきましょう。

AddFriendActivityクラス内で定義するAsyncTask(AddingFriendTaskクラス)により,友達リストへの追加処理がバックグラウンドで実行されます。追加するユーザのインスタンス(ChatUserのインスタンス)は、ユーザ確認のダイアログからのクリックイベントを通して伝えられます。

public class AddFriendActivity extends ActionBarActivity implements 
    LoaderCallbacks<List<ChatUser>>, 
    OnItemClickListener, 
    OnAddFriendListener {

    …

    private class AddingFriendTask extends AsyncTask<Void, Void, Boolean> {
        private final ChatUser chatUser;

        private AddingFriendTask(ChatUser chatUser) {
            this.chatUser = chatUser;
        }

        @Override
        protected void onPreExecute() {
            ProgressDialogFragment.show(getSupportFragmentManager(), 
                "Adding Friend", "Processing...");
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                
                // 選択したユーザを友達リストに追加する
                ChatFriend friend = new ChatFriend(this.chatUser);
                friend.getKiiObject().save();

                return true;
            } catch (Exception e) {
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            ProgressDialogFragment.hide(getSupportFragmentManager());
            if (result) {
                setResult(RESULT_OK);
            } else {
                ToastUtils.showShort(AddFriendActivity.this, "Unable to add friend");
                setResult(RESULT_CANCELED);
            }
            finish();
        }
    }
}

AddingFriendTaskクラス内で、友達リストに登録されたユーザを表すChatFriendクラスのインスタンスを生成しています。このインスタンスは、⁠chat_friends⁠バケットの下にあるオブジェクト(Cloud SDKのKiiObject)をラップしたものです。ChatFriend#getObject()により、KiiObjectのインスタンスを取り出し、KiiObject#save()を呼ぶことでオブジェクトがサーバに保存されます。これにより、友達リストに選択したユーザの情報が登録されます。

public class ChatFriend extends KiiObjectWrapper implements IUser {

    // “chat_friends”バケット: 友達リスト内のユーザの情報が登録されている	
    private static final String BUCKET_NAME = "chat_friends";

    …

    // ログインユーザ(友達を追加する側)のユーザスコープ下の’chat_friends’バケットを返す
    public static KiiBucket getBucket() {
        return KiiUser.getCurrentUser().bucket(BUCKET_NAME);
    }

    ...

    public ChatFriend(ChatUser user) {

        // ‘chat_friends’バケット下にユーザを表すオブジェクトを作成する
        super(getBucket().object());
        setUsername(user.getUsername());
        setEmail(user.getEmail());
        setUri(user.getUri());
    }
    …
}

上記までに友達リストに登録されたユーザを一覧する処理は、FriendListLoaderクラスに定義しています。⁠chat_friends⁠バケット以下のオブジェクトを返すクエリを実行して、友達リストに登録している全ユーザの情報を取得します。取得された情報は、FriendListFragmentクラスに渡され一覧表示されます。

public class FriendListLoader extends AbstractAsyncTaskLoader<List<ChatFriend>> {

    public FriendListLoader(Context context) {
        super(context);
    }

    @Override
    public List<ChatFriend> loadInBackground() {
        List<ChatFriend> friends = new ArrayList<ChatFriend>();
        try {

            // ログインユーザのユーザスコープ下にある“chat_friends”バケットを返す
            KiiBucket friendsBucket = ChatFriend.getBucket();

            // new KiiQuery()はバケット下の全てのオブジェクトを返す
            List<KiiObject> results = friendsBucket.query(new KiiQuery()).getResult();
            for (KiiObject friend : results) {
                friends.add(new ChatFriend(friend));
            }
            return friends;
        } catch (Exception e) {
            Logger.e("Unable to list users", e);
            return friends;
        }
    }
}

以上で、友達追加機能についての解説を終えます。サーバへのアクセスが数回のメソッド呼び出しに抽象化されており、REST APIにアクセスする処理を自前で実装する必要がないことが見て取れます。

次回の第7回は、今回友達リストに登録したユーザとの間にチャットルームを作成する機能について解説していきます。

おすすめ記事

記事・ニュース一覧