SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

MBaaSと連携するAndroidアプリを作る

MBaaSのデータストアの高度な使い方~リレーショナルなデータを扱う

MBaaSと連携するAndroidアプリを作る 第4回


  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンロード StampTime_04.zip (2.3 MB)

選択したタスクの仕事をやめたときの処理

 赤くなっているボタンをタップしたら、計測を停止します。リスト2に戻ってください。

[再掲]リスト2 MainActivity.javaのonCreateメソッドと、createButtonsメソッド(前半)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // SDKの初期セットアップ(アプリで一回だけ)
    NCMB.initialize(getApplication(), getString(R.string.app_key), getString(R.string.client_key));
    currentUser = NCMBUser.getCurrentUser();
    if (currentUser == null) {
        // 未ログインのときは、
        Intent intent = new Intent(MainActivity.this,LoginActivity.class);
        startActivity(intent);  
    } else {
        createButtons();
    }

}
private void createButtons() {
    LinearLayout LLayout = (LinearLayout) findViewById(R.id.main_layout);
    LLayout.removeAllViews();
    Button btn0 = new Button(this);
    btn0.setText("タスクはまだ選択されていません");
    btn0.setId(0);
    btn0.setBackgroundColor(Color.GRAY);
    btn0.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            if (v.getTag() == null) {
            } else {
                // 計測中のタスクがあるとき
                finCurTask();(a)
            }

        }
    });

    Space spc = new Space(this);(1)
    LLayout.addView(spc,600,10);
    LLayout.addView(btn0,600,160);

    getCurTask();(b)

 btn0がクリックされてgetTag()がnullを返さないとき、つまり、btn0のタグにいずれかのタスクのオブジェクトIDがセットされているときは、finCurTaskメソッドを実行します(a)

 finCurTaskメソッドでは、ログインしているユーザーのユーザー名をwhereEqualToの抽出条件に指定して、クエリを実行します(1)

リスト6 finCurTask()以降の処理
private void finCurTask() {
    NCMBUser currentUser = NCMBUser.getCurrentUser();

    NCMBQuery<NCMBObject> query = NCMBQuery.getQuery("CurTaskClass");
    query.whereEqualTo("UserName", currentUser.getUsername());  (1)
    query.findInBackground(new FindCallback<NCMBObject>() {
        @Override
        public void done(List<NCMBObject> result, NCMBException e){
            // 1件しか存在しない
            if (result.size() > 0 ) {
                NCMBObject curTask = result.get(0);
                getRelatedFinTask(curTask);

            }
        }
    });
}
private void getRelatedFinTask(final NCMBObject curTask) {
    final String userName = curTask.getString("UserName");(1)
    final Date startTime = curTask.getDate("startTime");

    curTask.getNCMBObject("task").fetchIfNeededInBackground(new GetCallback<NCMBObject> () {(2)
        @Override
        public void done(NCMBObject task, NCMBException e) {
            // TODO 自動生成されたメソッド・スタブ
            createLog(userName,task,startTime);
            deleteCurTask(curTask);
        }
    });
}
private void createLog(String userName, NCMBObject task, Date startTime ) {
    // ログデータの作成
    NCMBObject log = new NCMBObject("LogClass");
    log.put("UserName", userName);
    log.put("task", task);
    log.put("startTime",startTime);
    log.put("endTime",new Date() );
    Date endTime = log.getDate("endTime");
    long datetime1 = startTime.getTime();
    long datetime2 = endTime.getTime();
    long one_min_time = 1000 * 60;  //  ミリ秒を分単位
    long elapsedTime = (datetime2 - datetime1) / one_min_time;
    log.put("elapsedTime",elapsedTime );
    log.saveInBackground();
}
private void deleteCurTask(NCMBObject curTask) {
    curTask.deleteInBackground(new DeleteCallback() {
        @Override
        public void done(NCMBException e) {
                if (e == null) {
                    // オブジェクト削除成功!
                    createButtons();
                } else {
                    Toast.makeText(getApplication(), "失敗!", Toast.LENGTH_SHORT).show();
                }
            }
        });
}

 一人のユーザーは同時に一つのタスクしか選択できないので、ユーザー名で抽出するとCurTaskClassには1件しかレコードが存在しません。それをcurTaskオブジェクトに代入して、getRelatedFinTaskメソッドを呼び出します。

 getRelatedFinTaskメソッドでは、まず、curTaskオブジェクトからUserNameとstartTimeを取り出しています(1)

 次にgetNCMBObjectメソッドは指定したキーのNCMBObjectを返すので、(2)でtaskオブジェクトを取得します。そのtaskオブジェクトとcurTaskオブジェクトから取得したUsernameとstartTimeを引数にcreateLogメソッド呼び出します。

 createLogメソッドはLogClassのレコードを追加します。LogClassには、誰(UserName)が、どのタスク(task)を、何時から何時まで(startTime、endTime)やったか、そして、経過時間(elapsedTime)を分単位で記録します。

データストア LogClass
計測終了でLogClassのオブジェクトを作成する
フィールド名 データ型 内容 User/System
objectId 文字列 ID System
UserName 文字列 getCurrentUser()の戻り値 User
task 参照 taskClassオブジェクトへの参照 User
startTime 日付 開始日時 User
endTime 日付 終了日時 User
elapsedTime 数値 経過時間(分単位) User
createDate 日付 作成日時 System
updateDate 日付 更新日時 System

 LogClassのオブジェクトを作成して、各項目を編集しています。経過時間はミリ秒単位であるendTimeとstartTimeを引き算して、分単位に変換しています。

 次の画面のようにLogClassのレコードは作成されます。

LogClassのレコード
LogClassのレコード

 getRelatedFinTaskメソッドに戻りましょう。createLogメソッドでLogClassのレコードを作成したあとは、curTaskを引数にdeleteCurTaskメソッドを呼び出します。

 deleteCurTaskメソッドではNCMBObjectのdeleteInBackgroundメソッドで非同期にcurTaskオブジェクトを削除しています。これで、CurTaskClassの該当レコードが削除されるわけです。

スマホの画面にずっとタスクタイマが表示されているわけではありません

 さて、最後はスマホの特性に関係する処理です。Windowsなら起動したアプリを小さなウィンドウサイズにして画面の隅っこに置いておくとか、最小化して実行しっぱなしにしておくということができますが、スマホの場合はそうは行きません。

 タスクタイマを起動して、タスクを選んで仕事を開始した後は、どこかから電話が掛かってきたり、スマホでメールを送りたくなったり、他のアプリを使いたくなったりします。タスクタイマアプリはいつ終了されるかわかりません。

 でも、一度、タスクを選択したら、NCMBのデータストアのCurTaskClassにレコードは残っています。再度、起動したときに計測中のタスクはないかと探す処理がリスト2で呼び出しているgetCurTaskメソッドです(b)

リスト7 getCurTask()以降の処理
private void getCurTask() {
    NCMBUser currentUser = NCMBUser.getCurrentUser();

    NCMBQuery<NCMBObject> query = NCMBQuery.getQuery("CurTaskClass");
    query.whereEqualTo("UserName", currentUser.getUsername());
    query.findInBackground(new FindCallback<NCMBObject>() {
        @Override
        public void done(List<NCMBObject> result, NCMBException e){
            // 存在する
            if (result.size() > 0 ) {
                NCMBObject curTask = result.get(0);
                getRelatedTask(curTask);
            }
        }
    });
}
private void getRelatedTask(NCMBObject curTask) {
    curTask.getNCMBObject("task").fetchIfNeededInBackground(new GetCallback<NCMBObject> () {
        @Override
        public void done(NCMBObject task, NCMBException e) {
            // TODO 自動生成されたメソッド・スタブ
            Button btn0 = (Button) findViewById(0);
            btn0.setTag(task.getObjectId());
            btn0.setText(task.getString("taskName"));
            btn0.setBackgroundColor(Color.RED);
        }
    });
}

 getCurTaskメソッドでは、ログイン中のユーザー名でCurTaskClassに対してクエリを実行します。レコードが存在した場合は、getRelatedTaskメソッドを呼び出します。getRelatedTaskメソッドでは、CurTaskClassのオブジェクトからtaskオブジェクトを取得して、一番上のボタンを計測中の状態(見た目)にします。

最後に

 今回は関連オブジェクトとクエリについて説明しました。具体的な処理を多く説明したので、長くなりましたね。少し難しく感じられたかもしれませんが、関連オブジェクトの保存と取得やクエリの発行、取得したレコードの処理は対象のクラスが変わっても違いがないことがお分かりいただけと思います。

 次回は各タスクに費やした時間の集計に進みます。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
MBaaSと連携するAndroidアプリを作る連載記事一覧

もっと読む

この記事の著者

金宏 和實(カネヒロ カズミ)

 富山県高岡市出身で在住。ソフトウェア開発者兼ライター。株式会社イーザー関西学院大学文学部仏文科卒。第一種情報処理技術者(今で言うと、応用情報技術者。第一種→ソフ開→応用と変遷したようだ)主な著書『作ればわかる!Androidプログラミング第2版 -SDK4対応-』『VS 2010で作る Web-DB アプリ入門』『ベテランが丁寧に教えてくれるデータベースの知識と実務』『はじめてのAndroidアプリ作成 センサー活用とクラウド連携』『はじめてのAndroidアプリ作成 基本プログラミング』Web連載『VB2008で楽々Webプログラミング』『再発見!VB2005快適プログラミング』 『こうしろうのMindStroms日記』 個人的なブログはこちらです。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8167 2014/10/16 19:47

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング