コマンド画面の実装
次に、コマンド画面の実装を説明します。
コマンド画面は、レイアウトファイル fragment_command.xml で定義されており、クラス内の実装と次のように結びついています。
Butter Knife の利用 で示したように、これらはアノテーションによって関連付けています。
public class CommandFragment extends Fragment {
@BindView(R.id.checkBoxPowerOn) CheckBox mCheckBoxPowerOn;
@BindView(R.id.textViewBrightness) TextView mTextViewBrightness;
@BindView(R.id.seekBarBrightness) SeekBar mSeekBarBrightness;
@BindView(R.id.textViewCommandResult) TextView mCommandResult;
@BindView(R.id.textViewStatePower) TextView mTextViewStatePower;
@BindView(R.id.textViewStateBrightness) TextView mTextViewStateBrightness;
@BindView(R.id.textViewMotion) TextView mTextViewStateMotion;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_command, container, false);
mButterknifeUnbunder = ButterKnife.bind(this, view);
......
return view;
}
@OnClick(R.id.buttonSend)
void onSendCommand() {
......
}
@OnClick(R.id.buttonRefresh)
void onRefreshState() {
......
}
}
このページでは、SEND COMMAND ボタンによるコマンドの送信処理と REFRESH STATE ボタンによるステートの取得処理について解説します。
なお、onCreateView()
での画面の初期化方法や、SeekBar を操作したときに OnSeekBarChangeListener 経由でつまみの位置を数値化して表示する処理は、Android アプリの一般的なの処理のため説明を省略します。
コマンドの送信処理
コマンド画面に切り替わった後、SEND COMMAND ボタンをクリックすると、画面で設定されたパラメーターに従って、コマンドが Thing に送信されます。
ここでは以下の処理を行っています。
@OnClick(R.id.buttonSend)
void onSendCommand() {
mCommandResult.setText("");
List<Action> actions = new ArrayList<>();
TurnPower action1 = new TurnPower();
action1.power = mCheckBoxPowerOn.isChecked();
actions.add(action1);
if (action1.power) {
SetBrightness action2 = new SetBrightness();
action2.brightness = mSeekBarBrightness.getProgress();
actions.add(action2);
}
PromiseAPIWrapper api = new PromiseAPIWrapper(mAdm, mApi);
mAdm.when(api.postNewCommand(HelloThingIF.SCHEMA_NAME, HelloThingIF.SCHEMA_VERSION, actions)
).then(new DoneCallback<Command>() {
@Override
public void onDone(Command command) {
String commandID = command.getCommandID();
showToast("The command has been sent: " + commandID);
}
}).fail(new FailCallback<Throwable>() {
@Override
public void onFail(final Throwable tr) {
showToast("Failed to send the command: " + tr.getLocalizedMessage());
}
});
}
はじめに、mCommandResult
のコマンドリザルト表示領域をクリアします。この後送信するコマンドの結果を反映する前に、受信済みの結果を一旦リセットしています。
次に、送信するコマンドを構成するアクションの配列を actions
に用意します。TurnPower と SetBrightness はいずれも Action クラスのサブクラスであるため、List<Action>
が型名です。
TurnPower アクションでは、power
にチェックボックス Power ON の値を読み込んで設定します。SetBrightness アクションでは、brightness
に SeekBar の明るさの値を読み込んで設定します。SetBrightness アクションは、電源をオンにするときだけ設定します。
必要なアクションを actions
に設定後、postNewCommand()
メソッドを呼び出します。
- 成功時は
onDone()
メソッドに実行したコマンドが渡されます。ここではデバッグ用に、トーストでコマンド ID を表示します。 - 失敗時は
onFail()
メソッドが呼び出されます。ここではトーストでエラーメッセージを出力します。
ここでは電源と明るさを操作する 2 つのアクションを、それぞれ 1 個ずつのパラメーターで定義していますが、実際のプログラムではソリューションの仕様に合わせて複雑なコマンドを扱うことができます。独自のコマンドを定義する際、アクションを表現する Java のインスタンスが JSON に変換できることが要件です。
PromiseAPIWrapper での postNewCommand()
の実装は以下のとおりです。ThingIFAPI の postNewCommand()
を作業スレッドから呼び出す処理が Promise を使って記述されています。
public Promise<Command, Throwable, Void> postNewCommand(final String schemaName, final int schemaVersion, final List<Action> actions) {
return mAdm.when(new DeferredAsyncTask<Void, Void, Command>() {
@Override
protected Command doInBackgroundSafe(Void... voids) throws Exception {
return mApi.postNewCommand(schemaName, schemaVersion, actions);
}
});
}
ステートの取得処理
REFRESH STATE ボタンをクリックすると、Thing Interaction Framework から最新のステートを取得して画面に反映します。
ここでは以下の処理を行っています。
@OnClick(R.id.buttonRefresh)
void onRefreshState() {
PromiseAPIWrapper api = new PromiseAPIWrapper(mAdm, mApi);
mAdm.when(api.getTargetState()
).then(new DoneCallback<LEDState>() {
@Override
public void onDone(LEDState state) {
if (getActivity() == null) {
return;
}
if (state.power) {
mTextViewStatePower.setText("Power: ON");
} else {
mTextViewStatePower.setText("Power: OFF");
}
mTextViewStateBrightness.setText("Brightness: " + state.brightness);
mTextViewStateMotion.setText("Motion: " + state.motion);
showToast("The state has been refreshed.");
}
}).fail(new FailCallback<Throwable>() {
@Override
public void onFail(final Throwable tr) {
showToast("Failed to receive the state: " + tr.getLocalizedMessage());
}
});
}
ボタンがクリックされると、すぐに PromiseAPIWrapper の getTargetState()
メソッドが呼び出されます。このメソッドは作業スレッドでステートを取得し、成功時は取得したステートを LEDState クラスに格納して onDone()
メソッドが呼び出されます。
ステートは、初期登録 の際に指定した LEDState で取得できます。各フィールドに設定された値を画面に反映します。また、トーストで The state has been refreshed.
を表示します。
PromiseAPIWrapper での getTargetState()
の実装は以下のとおりです。postNewCommand
と同様に、ThingIFAPI の getTargetState()
を作業スレッドで呼び出す処理が記述されています。
public Promise<LEDState, Throwable, Void> getTargetState() {
return mAdm.when(new DeferredAsyncTask<Void, Void, LEDState>() {
@Override
protected LEDState doInBackgroundSafe(Void... voids) throws Exception {
return mApi.getTargetState(LEDState.class);
}
});
}
次は...
コマンドリザルトの受信方法について説明します。コマンドリザルトはプッシュ通知を契機に取得するため、プッシュ通知の実装を含めて解説します。
コマンドリザルトの取得 に移動してください。
より詳しく学びたい方へ
- コマンドの送信方法の詳細は、機能ガイドの アクションとコマンドの実行 または Thing-IF SDK ガイドの コマンドの実行 を参照してください。
- ステートの受信方法の詳細は、機能ガイドの ステートの登録と取得 または Thing-IF SDK ガイドの ステートの参照 を参照してください。
- トリガーを使うと、ステートや時間の設定に応じて、コマンドや Server Code を自動的に実行することができます。詳細は、機能ガイドの トリガーによる自動実行 または Thing-IF SDK ガイドの トリガー を参照してください。