Help us understand the problem. What is going on with this article?

Android端末にGetWildを歌わせる

More than 3 years have passed since last update.

GetWild Advent Calendar 2016の6日目です!!

はじめに

このカレンダーに参加を決めて何を書くか考えている時に、パッと浮かんだのはこちらの記事でした!

そこで、同じようにAndroid端末が盗まれそうになったらできないかなーと思い、Wearと連携させることで実現できるのではないかと開発を始めました。

概要

  • AndroidMobileに接続されているWearから歌をリクエストするとMobileが歌います
  • AndroidMobileがWearから離れすぎて接続が切れるとMobileが歌います

動画

pic.twitter.com/pwUvb6jc5G

— futabooo (@futabooo) 2016年12月4日

コード

Mobile側

Mobile側で特定のServiceを起動している状態でのみ歌うようにします。
ServiceがWearからのMessageを受け取れるようにManifestに下記を追加します。

AndroidManifest.xml
<service android:name=".GetWildListenerService">
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED"/>
        <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
            <data
                android:host="*"
                android:scheme="wear"/>
    </intent-filter>
</service>

dataタグの中ではoptionとしてandroid:pathPrefix="/prefix"も使えるので、もっと細かいことがしたい場合は使えそうです。
WearableListenerService

GetWildListenerServiceはこんな感じです。
歌うときだけ音量MAXにしています。
onPeerDisconnectedonMessageReceivedがそれぞれMobileとWearの接続が切れたとき、Messageを受け取った時に呼ばれるメソッドです。

GetWildListenerService.java
public class GetWildListenerService extends WearableListenerService {

    private TextToSpeech tts;

    private AudioManager audioManager;
    private int originalVol;
    private int maxVol;

    @Override
    public void onCreate() {
        super.onCreate();

        // 歌う時に音量MAXにするために
        audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        originalVol = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        maxVol = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

        tts = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                Log.d(TAG, "tts onInit");
            }
        });
    }

    @Override
    public void onDestroy() {
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, originalVol, 0);
        super.onDestroy();
    }

    @Override
    public void onPeerDisconnected(Node node) {
        super.onPeerDisconnected(node);
        Log.d(TAG, "onPeerDisconnected");
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxVol, 0);
        startSing();
    }

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        super.onMessageReceived(messageEvent);
        Log.d(TAG, "onMessageReceived");
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxVol, 0);
        startSing();
    }

    private void startSing() {
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        if (!sp.getBoolean("isEnable", false)) {
            return;
        }

        getWildAndTough(Locale.ENGLISH, getString(R.string.lyrics_get_wild_and_tough));
        getWildAndTough(Locale.JAPAN, getString(R.string.lyrics_1));
        getWildAndTough(Locale.ENGLISH, getString(R.string.lyrics_get_wild_and_tough));
        getWildAndTough(Locale.JAPAN, getString(R.string.lyrics_2));
        getWildAndTough(Locale.ENGLISH, getString(R.string.lyrics_get_chance_and_luck));
        getWildAndTough(Locale.JAPAN, getString(R.string.lyrics_3));
        getWildAndTough(Locale.ENGLISH, getString(R.string.lyrics_get_chance_and_luck));
        getWildAndTough(Locale.JAPAN, getString(R.string.lyrics_4));
    }

    private void getWildAndTough(Locale locale, String string) {
        // 日本語遅すぎなので歌っぽくするために
        if (locale == Locale.JAPAN) {
            tts.setSpeechRate(2.0f);
        } else if (locale == Locale.ENGLISH) {
            tts.setSpeechRate(1.0f);
        }

        tts.setLanguage(locale);
        tts.speak(string, TextToSpeech.QUEUE_ADD, null, "1");
    }
}

Wear側

Waer側からはMobileに対してメッセージを送る実装をします。
sendMessage"/get-wild"がAndroidManifestでoptionとして追加可能なprefix部分です。

WearMainActivity.java
public class WearMainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.wear_activity_main);

        WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
        stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
            @Override
            public void onLayoutInflated(WatchViewStub stub) {
                Button button = (Button) stub.findViewById(R.id.button);
                button.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                // Mobile側へメッセージを送る
                                GoogleApiClient client = new GoogleApiClient.Builder(getApplicationContext()).addApi(Wearable.API).build();
                                client.blockingConnect(100, TimeUnit.MILLISECONDS);
                                NodeApi.GetConnectedNodesResult result = Wearable.NodeApi.getConnectedNodes(client).await();
                                List<Node> nodes = result.getNodes();
                                if (nodes.size() > 0) {
                                    client.blockingConnect(100, TimeUnit.MILLISECONDS);
                                    Wearable.MessageApi.sendMessage(client, nodes.get(0).getId(), "/get-wild", null);
                                    client.disconnect();
                                }
                                client.disconnect();
                            }
                        }).start();
                    }
                });
            }
        });
    }
}

おわりに

どれぐらいの距離を離れると接続が切れるのか試すことができませんでしたorz
Bluetoothの接続可能な距離って結構長いんですねw
TextToSpeechのチューニングしだいでもっと歌っぽくできそうです。

今回作ったものはここに置いてあります
https://github.com/futabooo/getwild

参考

https://developer.android.com/reference/android/speech/tts/TextToSpeech.html
https://developer.android.com/training/wearables/data-layer/messages.html

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away