-
Notifications
You must be signed in to change notification settings - Fork 23
Application Manual for Android Studio 232
- 1. はじめに
- 2. Device Connect について
- 3. サンプルアプリケーションの作成
本ドキュメントは、Device Connect APIを用いてAndroidネイティブアプリケーションを開発する手法について解説します。Androidに関する一般的な知識と、Javaに関する一般的な知識を保持している事を前提に解説していきます。
本ドキュメントでは、開発環境としてAndroid Studioを使用します。
Android Studioは、こちらからダウンロードを行ってください。
Device Connectでは、RESTfulで、命令やデータの送受信が可能です。各処理は、Profileという形でURIが割り振られ、そのURIをJavaやJavaScriptなどで呼び出す事で、処理を行います。
Device Connect で提供される Profile は、DeviceConnect-Spec で定義しています。
上記のサイトとは別にデバイス毎に固有の Profile が定義されることもあります。その場合には、Service Information などの Profile で情報を取得して使用します。
定義されている一部のプロファイルを以下に示します。
| Profile名 | 説明 |
|---|---|
| Battery | バッテリーの状態を保持します |
| DeviceOrientation | デバイスの加速度等を取得します。 |
| File | デバイスとFileの送信、受信等を行います。 |
| Media Player | メディアの再生(音声, 音楽, 動画)を行います。 |
| MediaStream Recording | メディアの録音(音声,音楽,動画)を行います。 |
| Notification | デバイスに通知(Notification)を行います。 |
| Phone | デバイスに電話発信の命令を送ります。 |
| Proximity | デバイスと物体との近接状態を取得します。 |
| Service Discovery | デバイスの対応Profile一覧を取得します。 |
| Setting | デバイスの設定(音量, 画面輝度, 画面スリープ時間等)を行います。 |
| Vibration | デバイスをバイブレートする命令を送ります。 |
ただし、デバイスによって、使用出来る Profile は変わりますので、ご注意ください。
Android版Device Connectでは、端末内のローカルに起動しているHTTPサーバ(Device Connect Manager)に問い合わせを行う事で、ハードウェアの操作や、情報取得を行う事が可能です。
図1. Device Connect Managerへの問い合わせ
githubのDownload ZIPボタンを押下して、ダウンロードしてください。
もしくは、gitコマンドを用いてプロジェクトをチェックアウトしてください。
$ git clone https://github.com/DeviceConnect/DeviceConnect-Android.gitAndroid Studio で /DeviceConnect-Android/dConnectManager/dConnectManager にあるプロジェクトを開きます。
appを実行することで、Device Connect Manager がインストールされます。
Device Connect Managerのアイコンを押下して、アプリを起動します。
Device Connect Managerのスイッチを押下して、オンにすることでサーバを起動します。
Device Connect Manager の起動を行うとサービスのリストの中にHOSTが存在することを確認します。
以上で、Device Connectを使用するための準備が整いました。
次からサンプルの作成を説明します。
サンプルアプリケーションでは、Device Connect Managerに問い合わせを行い、結果のJSONを取得するサンプルを作成しながら解説をします。
Android Studio の[Start a new Android Studio project]を選択します。
Application Name, Company domain、Project locationを入力します。
Project locationはサンプルアプリケーションのソースコードを格納するパスを任意に指定してください。
| 項目 | 設定値 |
|---|---|
| Application Name | ExmapleApp |
| Campany domain | android.deviceconnect.org |
| Project location | プロジェクトのパス(任意) |
| Package Name | org.deviceconnect.android.exampleapp |
ターゲットとするAndroid SDKバージョンなどは、デフォルトのまま。
Empty Activityを選択します。
Finish ボタンを押下して、プロジェクトを作成します。
ビルドには、GitHubアカウントとトークンが必要になります。 以下の手順により、プロジェクトでGitHubアカウントとトークンの設定を行ってください。
- GitHubの[Settings] > [Developer settings] > [Personal access tokens] から作成します。
- scopeは
repo、write:packages、read:packagesにチェックを付けて生成してください。 - プロジェクトのルートディレクトリに
github.propertiesというファイルを作成して配置してください。 - github.propertiesにユーザ名とトークンを入力してください。
gpr.usr={ GitHubユーザ名 }
gpr.key={ トークン }
以下のように環境変数を設定することで、github.propertiesの追加を省略することができます。
$ export GPR_USER={ GitHubユーザ名 }
$ export GPR_API_KEY={ トークン }build.gradleに以下の記述をすることで、Device Connect SDK for Androidをインポートします。
android {
...
repositories {
maven {
name = "dConnectSDKForAndroid"
/** Configure path of your package repository on Github
* Replace GITHUB_USERID with your/organisation Github userID and REPOSITORY with the repository name on GitHub
*/
url = uri("https://maven.pkg.github.com/DeviceConnect/DeviceConnect-Android")
credentials {
/**Create github.properties in root project folder file with gpr.usr=GITHUB_USER_ID & gpr.key=PERSONAL_ACCESS_TOKEN**/
username = githubProperties['gpr.usr'] ?: System.getenv("GPR_USER")
password = githubProperties['gpr.key'] ?: System.getenv("GPR_API_KEY")
}
}
}
}
dependencies {
implementation 'org.deviceconnect:dconnect-sdk-for-android:2.3.2'
}Device Connect Managerを使用する前に、生存確認を行います。
Device Connect Managerの生存確認には以下のメソッドを使用します。
DConnectSDK#availability()
生存確認を行うためのボタンとログを表示するためのTextViewをUIに追加します。
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="org.deviceconnect.android.exampleapp.MainActivity">
<Button
android:id="@+id/btn_availability"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="availability"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_view_log"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
</LinearLayout>MainActivity.java
package org.deviceconnect.android.exampleapp;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import org.deviceconnect.message.DConnectMessage;
import org.deviceconnect.message.DConnectResponseMessage;
import org.deviceconnect.message.DConnectSDK;
import org.deviceconnect.message.DConnectSDKFactory;
public class MainActivity extends AppCompatActivity {
private DConnectSDK sdk;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sdk = DConnectSDKFactory.create(getApplicationContext(), DConnectSDKFactory.Type.HTTP);
findViewById(R.id.btn_availability).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sdk.availability(new DConnectSDK.OnResponseListener() {
@Override
public void onResponse(DConnectResponseMessage response) {
if (response.getResult() == DConnectMessage.RESULT_OK) {
log("Device Connect Manager is available.");
} else {
log("Device Connect Manager is unavailable.");
}
}
});
}
});
}
private void log(final String text) {
runOnUiThread(new Runnable() {
@Override
public void run() {
TextView textView = findViewById(R.id.text_view_log);
String log = textView.getText() + "\n" + text;
textView.setText(log);
}
});
}
}サンプルアプリケーションを実行すると以下のような画面が表示されます。
AVAILABILITYボタンを押下することでDevice Connect Managerの生存確認が行えます。
Device Connect Managerが起動している場合には、上記のようなログが表示されます。
もし、Managerが起動していない場合には、以下のAPIで起動します。
DConnectSDK#startManager(context)
- context: コンテキスト
sdk.startManager(context);このメソッドは、URIスキームを用いてDevice Connect Managerを起動します。
同じ端末にインストールされているDevice Connect Manager以外は起動できません。
Device Connect Managerを使用するためには、Managerから認可を行い、アクセストークンを取得する必要があります。
アクセストークンの取得には以下のメソッドを使用します。
DConnectSDK#authorization(appName, scopes)
- appName: アプリケーション名を指定します。
- scopes: 使用するプロファイルの一覧を指定します。
アプリケーション認可を実行するためのボタンを追加します。
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="org.deviceconnect.android.exampleapp.MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_availability"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="availability"/>
<Button
android:id="@+id/btn_authorization"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="authorization"/>
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_view_log"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
</LinearLayout>追加したボタンにアプリケーション認可を行う処理を追加します。
このサンプルアプリケーションでは、サービス一覧の取得・ライトの操作・加速度センサーの操作を行いますので、アプリケーション認可に渡すスコープには、以下の Profile を指定します。
- serviceDiscovery
- serviceInformation
- light
- deviceOrientation
MainActivity.java
findViewById(R.id.btn_authorization).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String appName = "ExampleApp";
String[] scopes = {
"serviceDiscovery",
"serviceInformation",
"light",
"deviceOrientation"
};
sdk.authorization(appName, scopes, new DConnectSDK.OnAuthorizationListener() {
@Override
public void onResponse(String clientId, String accessToken) {
// SDKにアクセストークンを設定
sdk.setAccessToken(accessToken);
log("AccessToken=" + accessToken);
}
@Override
public void onError(int errorCode, String errorMessage) {
log("Failed to authorization. message=" + errorMessage);
}
});
}
});DConnectSDK#authorization(appName, scopes, listener) を呼び出すと以下のようなダイアログが表示されます。
ここで、サンプルアプリケーションが使用する Profile の確認を行い、ユーザから使用許可の認可を受けます。
認可された場合には、以下のようにアクセストークンが取得できます。
取得したアクセストークンは、ストレージなどに保存しておき、DConnectSDKを作り直した時に、DConnectSDKに設定します。
DConnectSDKでは、設定されたアクセストークンで Device Connect Managerにアクセスします。
不正なアクセストークンでAPIにアクセスした場合には、以下のようなエラーが発生します。
DConnectResponseMessage response = sdk.serviceDiscovery();
if (response.getResult() != DConnectMessage.RESULT_OK) {
ErrorCode errorCode = DConnectMessage.ErrorCode.getInstance(response.getInt("errorCode"));
switch (errorCode) {
case AUTHORIZATION:
// 認可エラー
break;
case EXPIRED_ACCESS_TOKEN:
// 有効期限切れ
break;
case EMPTY_ACCESS_TOKEN:
// アクセストークンがない
break;
case SCOPE:
// スコープにないプロファイルにアクセスされた
break;
case NOT_FOUND_CLIENT_ID:
// クライアントIDが見つからない
break;
}
}これらのエラーが発生した場合には、アクセストークンを取得し直す必要があります。
Device Connect Managerに接続されているサービス(デバイス)の一覧を取得します。
サービス一覧の取得には、以下のメソッドを使用します。
DConnectSDK#serviceDiscovery()
サービス一覧を取得を実行するためのボタンを追加します。
res/layout/activity_main.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_sevice_discovery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="serviceDiscovery"/>
</LinearLayout>MainActivity.java
findViewById(R.id.btn_sevice_discovery).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sdk.serviceDiscovery(new DConnectSDK.OnResponseListener() {
@Override
public void onResponse(DConnectResponseMessage response) {
if (response.getResult() == DConnectMessage.RESULT_OK) {
for (Object obj : response.getList("services")) {
DConnectMessage service = (DConnectMessage) obj;
log("----");
log("serviceId: " + service.getString("id"));
log("name: " + service.getString("name"));
}
} else {
log("Failed to get a services. message=" + response.getString("errorMessage"));
}
}
});
}
});SERVICEDISCOVERYのボタンを押下することで、Device Connect Managerに接続されているサービスの一覧を取得することができます。
プラグインをインストールしていない状態では、HOSTのみが表示されます。
HOSTに搭載されているライトの操作を行う手順を説明します。
ライトを操作するために、点灯・消灯を行うボタンを追加します。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_light_on"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Light On"/>
<Button
android:id="@+id/btn_light_off"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Light Off"/>
</LinearLayout>
HOSTのライトを点灯します。
ここでは、lightIdを省略していますので、デフォルトのライトが点灯します。
ライト点灯には以下のメソッドを使用します。
DConnectSDK#post(uri, entity)
- uri: Device Connect ManagerへのリクエストURIを指定します。
- entity: POSTのBodyに送るエンティティを指定します。不要な場合にはnullを指定します。
MainActivity.java
findViewById(R.id.btn_light_on).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DConnectSDK.URIBuilder builder = sdk.createURIBuilder();
builder.setProfile("light");
builder.setServiceId("Host.f16efda156ed2d91b1a82b6fdbbd30.localhost.deviceconnect.org");
sdk.post(builder.toString(), null, new DConnectSDK.OnResponseListener() {
@Override
public void onResponse(DConnectResponseMessage response) {
if (response.getResult() == DConnectMessage.RESULT_OK) {
log("Success.");
} else {
log("Failed to turn on a light. message=" + response.getString("errorMessage"));
}
}
});
}
});LIGHT ONボタンを押下することで、Android端末のカメラについているライトが点灯します。
Android端末のライトは、カメラに付随していますので、他のカメラアプリなどとは同時に使用することができませんので、ご注意ください。
HOSTのライトを消灯します。
ライト消灯には以下のメソッドを使用します。
DConnectSDK#delete(uri)
- uri: Device Connect ManagerへのリクエストURIを指定します。
MainActivity.java
findViewById(R.id.btn_light_off).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DConnectSDK.URIBuilder builder = sdk.createURIBuilder();
builder.setProfile("light");
builder.setServiceId("Host.f16efda156ed2d91b1a82b6fdbbd30.localhost.deviceconnect.org");
sdk.delete(builder.toString(), new DConnectSDK.OnResponseListener() {
@Override
public void onResponse(DConnectResponseMessage response) {
if (response.getResult() == DConnectMessage.RESULT_OK) {
log("Success.");
} else {
log("Failed to turn off a light. message=" + response.getString("errorMessage"));
}
}
});
}
});LIGHT OFFボタンを押下することで、点灯していたライトが消灯します。
HOSTから加速度センサーのイベント受信するためには、WebSocketでDevice Connect Managerと接続する必要があります。
WebSocketを接続するには以下のメソッドを使用します。
DConnectSDK#connectWebSocket(listener)
- listener: WebSocketの接続・切断などのイベントを受け取るリスナーを指定します。
WebSocketの接続・切断を行うためのボタンを追加します。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_websocket_connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Connect"/>
<Button
android:id="@+id/btn_websocket_disconnect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Disconnect"/>
</LinearLayout>MainActivity.java
findViewById(R.id.btn_websocket_connect).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sdk.connectWebSocket(new DConnectSDK.OnWebSocketListener() {
@Override
public void onOpen() {
log("Websocket is open.");
}
@Override
public void onClose() {
log("Websocket is close.");
}
@Override
public void onError(Exception e) {
log("Websocket is error. e=" + e.getMessage());
}
});
}
});イベント開始後にWebSocketが切断された場合には、同じオリジンで登録されているイベントが全て解除されます。
WebSocketが切断された場合には、再開する場合には再度イベントを登録する必要があります。
オリジンは、デフォルトではアプリのパッケージ名が指定されています。
必要に応じて、DConnectSDK#setOrigin(origin)で変更することができます。
WebSocketを接続した際には、最後に必ずWebSocketを切断する必要があります。
WebSocketを切断するには以下のメソッドを使用します。
DConnectSDK#disconnectWebSocket()
MainActivity.java
findViewById(R.id.btn_websocket_disconnect).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sdk.disconnectWebSocket();
}
});WebSocketを切断せずに終了した場合にはメモリリークになる恐れがありますので、ご注意ください。
加速度センサーを受信するには加速度センサーの開始を行う必要があります。
イベントの開始には以下のメソッドを使用します。
DConnectSDK.addEventListener(uri, listener)
- uri: 開始するイベントへのURI
- listener: イベントの開始のレスポンス、イベントの受信を行うリスナー。
加速度センサーの開始・停止を行うボタンを追加します。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_sensor_on"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Sensor On"/>
<Button
android:id="@+id/btn_sensor_off"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Sensor Off"/>
</LinearLayout>MainActivity.java
findViewById(R.id.btn_sensor_on).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DConnectSDK.URIBuilder builder = sdk.createURIBuilder();
builder.setProfile("deviceOrientation");
builder.setAttribute("onDeviceOrientation");
builder.setServiceId("Host.f16efda156ed2d91b1a82b6fdbbd30.localhost.deviceconnect.org");
sdk.addEventListener(builder.build(), new DConnectSDK.OnEventListener() {
@Override
public void onMessage(DConnectEventMessage message) {
log("Event: " + message.toString());
}
@Override
public void onResponse(DConnectResponseMessage response) {
if (response.getResult() == DConnectMessage.RESULT_OK) {
log("Success to add event.");
} else {
log("Failed to add event. message=" + response.getString("errorMessage"));
}
}
});
}
});イベントが開始されると画面にログが表示されます。
イベントの停止には以下のメソッドを使用します。
DConnectSDK.removeEventListener(uri)
- uri: 停止するイベントへのURI
MainActivity.java
findViewById(R.id.btn_sensor_off).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DConnectSDK.URIBuilder builder = sdk.createURIBuilder();
builder.setProfile("deviceOrientation");
builder.setAttribute("onDeviceOrientation");
builder.setServiceId("Host.f16efda156ed2d91b1a82b6fdbbd30.localhost.deviceconnect.org");
sdk.removeEventListener(builder.toString());
}
});DConnectSDK#post(uri, entity)でデータを送信する際の第2引数のentityには以下のクラスが指定できます。
- StringEntity
- BinaryEntity
- MultipartEntity
文字列のデータをPOSTのBodyに指定できます。
StringEntity entity = new StringEntity("key=value");
DConnectResponseMessage response = sdk.post(uri, entity);バイト配列のデータをPOSTのBodyに指定できます。
byte[] value = { ... };
BinaryEntity entity = new BinaryEntity(value);
DConnectResponseMessage response = sdk.post(uri, entity);マルチパートのデータをPOSTのBodyに指定できます。
MultipartEntity data = new MultipartEntity();
data.add("key", new StringEntity("value"));
data.add("data", new FileEntity(new File(path)));
DConnectResponseMessage response = sdk.post(uri, entity);bodyを空で送りたい場合には、entityにnullを指定します。
findViewById(R.id.btn_draw_image).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DConnectSDK.URIBuilder builder = sdk.createURIBuilder();
builder.setProfile("canvas");
builder.setAttribute("drawImage");
builder.setServiceId("Host.f16efda156ed2d91b1a82b6fdbbd30.localhost.deviceconnect.org");
MultipartEntity entity = new MultipartEntity();
entity.add("data", new BinaryEntity(getImage()));
sdk.post(builder.toString(), entity, new DConnectSDK.OnResponseListener() {
@Override
public void onResponse(DConnectResponseMessage response) {
if (response.getResult() == DConnectMessage.RESULT_OK) {
log("Success to send image.");
} else {
log("Failed to send image. message=" + response.getString("errorMessage");
}
}
});
}
});assetsフォルダから画像のバイナリデータを取得します。
private byte[] getImage() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
int len;
InputStream in = getAssets().open("ic_launcher.png");
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
} catch (IOException e) {
// ignore.
}
return out.toByteArray();
}