選択したタスクの仕事をやめたときの処理
赤くなっているボタンをタップしたら、計測を停止します。リスト2に戻ってください。
@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)。
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)を分単位で記録します。
| フィールド名 | データ型 | 内容 | 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のレコードは作成されます。
getRelatedFinTaskメソッドに戻りましょう。createLogメソッドでLogClassのレコードを作成したあとは、curTaskを引数にdeleteCurTaskメソッドを呼び出します。
deleteCurTaskメソッドではNCMBObjectのdeleteInBackgroundメソッドで非同期にcurTaskオブジェクトを削除しています。これで、CurTaskClassの該当レコードが削除されるわけです。
スマホの画面にずっとタスクタイマが表示されているわけではありません
さて、最後はスマホの特性に関係する処理です。Windowsなら起動したアプリを小さなウィンドウサイズにして画面の隅っこに置いておくとか、最小化して実行しっぱなしにしておくということができますが、スマホの場合はそうは行きません。
タスクタイマを起動して、タスクを選んで仕事を開始した後は、どこかから電話が掛かってきたり、スマホでメールを送りたくなったり、他のアプリを使いたくなったりします。タスクタイマアプリはいつ終了されるかわかりません。
でも、一度、タスクを選択したら、NCMBのデータストアのCurTaskClassにレコードは残っています。再度、起動したときに計測中のタスクはないかと探す処理がリスト2で呼び出しているgetCurTaskメソッドです(b)。
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オブジェクトを取得して、一番上のボタンを計測中の状態(見た目)にします。
最後に
今回は関連オブジェクトとクエリについて説明しました。具体的な処理を多く説明したので、長くなりましたね。少し難しく感じられたかもしれませんが、関連オブジェクトの保存と取得やクエリの発行、取得したレコードの処理は対象のクラスが変わっても違いがないことがお分かりいただけと思います。
次回は各タスクに費やした時間の集計に進みます。

