連載
» 2015年02月13日 18時00分 UPDATE

Androidで動く携帯Javaアプリ作成入門(57):腕時計から電話をかけるAndroid Wearアプリの作り方 (1/3)

ペアリングしているスマートフォン側で電話をかけるアプリを通じて、Android Wearとスマートフォン間のメッセージ送信の方法について解説します。

[緒方聡,株式会社イーフロー]
「Androidで動く携帯Javaアプリ開発入門」のインデックス

連載目次

Android Studio 1.0リリース

 2014年12月8日にAndroid Studioが1.0としてリリースされました。原稿執筆時点の2015年1月現在では1.0.2にアップデートされています。

 今後のAndroidアプリ開発は、本格的にAndroid Studioにシフトしていくことでしょう。Android Wearをはじめ、Android TV、Android Autoなどのスマートフォンやタブレット以外のターゲット向けのアプリの需要も増えていくことでしょうし、そうしたデバイス向けの開発環境はEclipseではなくAndroid Studioになっていきます。

 すぐにEclipseのサポートがなくなるわけではないと思いますが、正式版が出た今のタイミングで移行を計画しておいた方が良さそうです。

android57_1.jpg Android Studio 1.0のスプラッシュ画面

Android Wearからタクシーを呼ぼう

 今回は、連載第55回「スマホ連動音声認識Android Wearアプリの作り方」で作成したAndroid Wear用アプリに機能を追加し、ペアリングしているスマートフォン側で電話をかけるアプリを通じて、Android Wearとスマートフォン間のメッセージ送信の方法について解説します。Android Wear用アプリの作成方法に関しては、上記記事を参照ください。

 今回のサンプルアプリは以下よりダウンロードできます。

 連載第55回のサンプルはAndroid Studio 0.8で作成したのですが、その当時に作成したプロジェクトがAndroid Studio 1.0では期待通りに動作しなくなっていました。

 具体的には、ライブラリの依存関係が解決できなくなっていたこと、プロジェクトのディレクトリ構成が若干変わっていたことがあり、今回のサンプルはプロジェクトを新規に作り直して、ソースコードや設定を移植するという作業を行いました。

 また、Android Studioは自身でアップデートを行い、最新状態を保つことが可能なのですが、プレビュー版からのアップデートは、Android Studio自体の構成が大きく変わっているようなので、いったんプレビュー版をアンインストールして、正式版をクリーンインストールすることをお勧めします。

 さて、Android Wearとスマートフォンでデータ通信を行う方法は、大きく分類すると2通りあります。Android Wearとスマートフォンでデータを“自動同期”する方法、任意のデータを含むメッセージを“任意のタイミングで送受信”する方法です。

 今回はボタンをタップしたタイミングで電話をかけたいので、“任意のタイミングで送受信”する方法を使用します。

Android Wearからメッセージ送信

 送信側の処理を説明します。Android Wear用アプリのソースコードで今回修正したのは、CallFragment.javaだけです。

 メッセージを送信するにはGoogleApiClientのインスタンスをGoogle Play Servicesに接続しなければなりません。以下ソースコードは、GoogleApiClientのインスタンスを初期化するためのメソッドです。

private GoogleApiClient initClient() {
    GoogleApiClient.ConnectionCallbacks callbacks =
        new GoogleApiClient.ConnectionCallbacks() {
        @Override
        public void onConnected(Bundle bundle) {
            Log.d(TAG, "CallFragment#onConnected"); //【1】
        }
 
        @Override
        public void onConnectionSuspended(int i) {
            Log.d(TAG, "CallFragment#onConnectionSuspended"); //【2】
        }
    };
    GoogleApiClient.OnConnectionFailedListener listener =
            new GoogleApiClient.OnConnectionFailedListener() {
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            Log.d(TAG, "CallFragment#onConnectionFailed"); //【3】
        }
    };
    GoogleApiClient client = new GoogleApiClient.Builder(getActivity())
            .addApi(Wearable.API)
            .addConnectionCallbacks(callbacks)
            .addOnConnectionFailedListener(listener)
            .build(); //【4】
    return client;
}

 GoogleApiClientは、【4】のようにGoogleApiClient.BuilderにContextを渡し、Apiとコールバック2種類をセットして、ビルドして作成します。コールバックは、【1】のonConnectedが、Google Play Servicesに接続した後に呼び出され、【2】のonConnectionSuspendedが、スマートフォンとの接続が切れた場合、Google Play Servicesが終了された場合などの一時的に接続が切れた状態で呼び出されます。【3】のonConnectionFailedは、Google Play Servicesへの接続が失敗した際に呼び出されます。

 今回のアプリではコールバックで特に何かを行う必要はないので、ログ出力だけしています。

 このメソッドで作成したインスタンスは、以下のようにAndroid WearのActivityライフサイクルコールバックであるonCreateViewで初期化と接続を行い、onDestroyViewで切断を行っています。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    ...
    mClient = initClient();
    mClient.connect();
    ...
}
 
@Override
public void onDestroyView() {
    super.onDestroyView();
    if (mClient.isConnected()) {
        mClient.disconnect();
    }
}

 GoogleApiClientの準備ができたら、ボタンをタップされた際の処理でメッセージ送信を行います。以下がその処理です。

private void call() {
    AsyncTask.execute(this);
}

 AsyncTaskを使用して非同期で処理を実行しているのは、メッセージ送信時にPendingResult#awaitを使用する必要があり、UIスレッドで実行するとユーザーが操作できなくなってしまうためです。

 送信処理の実体はrunメソッドにあります。

@Override
public void run() {
    if (!mClient.isConnected()) { // 【1】
        mClient.blockingConnect(100, TimeUnit.MILLISECONDS);
    }
    if (!mClient.isConnected()) { // 【2】
        Log.i(TAG, "Failed to put phone number to phone - Client disconnected from Google Play Servicess");
        return;
    }
    String number = getPhoneNumber(); //【3】
    NodeApi.GetConnectedNodesResult nodes =
        Wearable.NodeApi.getConnectedNodes(mClient).await(); //【4】
    for (Node node : nodes.getNodes()) {
        MessageApi.SendMessageResult result =
            Wearable.MessageApi.sendMessage(
            mClient, node.getId(), "/calltaxi", number.getBytes()).await(); //【5】
        Log.i(TAG, "Result:" + result.getStatus());
        Log.i(TAG, "Canceled:" + result.getStatus().isCanceled());
        Log.i(TAG, "Success:" + result.getStatus().isSuccess());
        if (result.getStatus().isSuccess()) { //【6】
            Log.i(TAG, "Sent: " + number);
        }
    }
}

 GoogleApiClientがGoogle Play Servicesに接続されているかどうかを【1】のようにチェックし、されていなければここでは100msブロックしつつ接続を試みます。それでも接続されなかったら【2】のように処理を終了します。接続されていれば、送信する任意のデータとして、音声入力された電話番号を【3】のようにSharedPreferenceから取得します。【4】では、接続されている端末一覧を取得します。

 腕時計型のAndroid Wearは、コンパニオンとなるスマートフォン1台としか接続しないのですが、腕時計型以外の他のデバイスのための将来的な拡張を見据えて、一覧が取れるようになっているのだと思います。

 メッセージの送信は【5】のようにWearable.MessageApi.sendMessageを使用します。第一引数はGoogleApiClient、第二引数は送信先のID、第三引数は受信側で識別子となるパス、第四引数に任意のデータとしてバイト配列を渡します。第三引数のパスは、メッセージの種別が識別できれば何でもいいとは思いますが、名前が表すように、慣習としてスラッシュで始まるPOSIXパス形式が用いられるようです。送信に成功したかどうかは【6】のようにStatus#isSuccessで判定可能です。

       1|2|3 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。