2015年8月7日金曜日

Android Wear アンビエントモードを実装する


■はじめに

Android Wear5.0からWatch Faceの作成が可能になり、
なんと5.1.1からは、アンビエントモードが通常のアプリでも実装できるようになりました!!
この機能を使用するとアプリを終了することなく、情報を表示し続けることができます。
Apple WatchにはないAndroid Wear独特の機能。
これを利用すれば、面白いアプリが作れるかもしれません!
早速仕組みをご紹介します。


■アンビエントモードって?

アンビエントモードは、液晶(IPSやVA方式の場合)の黒色表示時は、消費電力が減る事を利用し、背景を黒、情報を白色にすることで消費電力を減らす機能です。
特に有機ELパネルの場合は顕著な差がでます。
ブラック表示時に電力を消費しないを生かし、LGのG Watch Rの場合、通常消費電力が130mAなのに対し、アンビエントモードでは13mWと1/10になるそうです。


■アンビエントモードを実装する!

それでは実際に実装部分を見ていきます。
 ※今回はandroid-AlwaysOnのソースを使用しています。

AndroidManifestに以下の項目を追加します。

    <uses-permission android:name="android.permission.WAKE_LOCK" >


setAmbientEnabledを呼び出すことでアンビエントモードが有効になります。

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //アンビエントモードを有効にする
        setAmbientEnabled();
    }


アンビエントモードになると、onEnterAmbientが呼び出されますので
表示をアンビエントモード用に変更します。
アンビエントモード時の表示には、規則というか決まり事があります。
 ※詳しくは、DisplayModesをご覧ください。

今回は、文字の色を白くし、アンチエイリアスを無効にしています。

アンビエントモード中は、1分毎にonUpdateAmbientが呼ばれます。
画面の更新が必要な場合は、この処理内に記述します。

アンビエントモードが終了すると、onExitAmbientが呼ばれるので表示を元に戻しましょう。

    @Override
    public void onEnterAmbient(Bundle ambientDetails) {
        super.onEnterAmbient(ambientDetails);
        //文字を白くし、アンチエイリアスを無効にします。
        mStateTextView.setTextColor(Color.WHITE);
        mStateTextView.getPaint().setAntiAlias(false);
    }

    @Override
    public void onExitAmbient() {
        super.onExitAmbient();
        //表示を元に戻します
        mStateTextView.setTextColor(Color.GREEN);
        mStateTextView.getPaint().setAntiAlias(true);
    }

    @Override
    public void onUpdateAmbient() {
        super.onUpdateAmbient();
    }


・実行結果

動かすと以下のような表示になります。
電源ボタン、またはF7キー(Windowsの場合)を押すと、アンビエントモードになります。

実行画面 左が通常時、右がアンビエントモード時

・更新間隔

アンビエントモード時は、1分間隔で更新されますが
onEnterAmbient発生時から、1分ごとではなく00秒毎に呼び出されます。
そのため、初回時は1分以内に呼び出されることがあります。

onUpdateAmbientの呼び出しタイミング


・更新間隔を変えたい場合

AlarmManagerを利用すると更新の間隔を変えることができます。
 ※更新間隔が短い場合は、バッテリーの消費も激しくなるので注意が必要です

AndroidManifestに以下の項目を追加します。

    
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>


対象となるActivityのlaunchModeをsingleInstanceにします。

    <activity
        android:launchMode="singleInstance" />


AlarmMangerを生成します。

 
    private static final long ACTIVE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(1);
    private static final long AMBIENT_INTERVAL_MS = TimeUnit.SECONDS.toMillis(20);
    private AlarmManager mAmbientStateAlarmManager;
    private PendingIntent mAmbientStatePendingIntent;

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

        mAmbientStateAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent ambientStateIntent = new Intent(getApplicationContext(), MainActivity.class);

        mAmbientStatePendingIntent = PendingIntent.getActivity(
                getApplicationContext(),
                0 /* requestCode */,
                ambientStateIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }


アンビエントモード開始時に、Alarmをセットします。

    @Override
    public void onEnterAmbient(Bundle ambientDetails) {
        super.onEnterAmbient(ambientDetails);
        //Alarmを設定する
        setAlerm();
    }

    priavte void setAlerm(){
        long delayMs = AMBIENT_INTERVAL_MS - (timeMs % AMBIENT_INTERVAL_MS);
        long triggerTimeMs = timeMs + delayMs;

        //Alarmを利用し、20秒ごとに更新を行う
        mAmbientStateAlarmManager.setExact(
                AlarmManager.RTC_WAKEUP,
                triggerTimeMs,
                mAmbientStatePendingIntent);
    }


更新は、onUpdateAmbientではなく、onNewIntentが呼び出されます。
※ただし、初回時のみonUpdateAmbientも呼び出されているようです。

    @Override
    public void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        //次のAlarmを設定する
        setAlerm();
    }


onExitAmbientとonDestroyでAlarmの解除を忘れないように注意しましょう。

    @Override
    public void onExitAmbient() {
        super.onExitAmbient();
        //Alartの停止
        mAmbientStateAlarmManager.cancel(mAmbientStatePendingIntent);
    }

    @Override
    public void onDestroy() {
        //Alartを止めるのを忘れないように
        mAmbientStateAlarmManager.cancel(mAmbientStatePendingIntent);
        super.onDestroy();
    }


・5.1.1以降を対象するに場合

5.1.1以前のAndroid Wearにインストールされたくない場合は、AndroidManifestに以下の項目を追加してください。
    
    <uses-library android:name="com.google.android.wearable" android:required="true" />


■最後に

アンビエントモードどうでしょうか?
思いの外、実装は簡単な気がしませんか?
個人的には実装よりもアンビエントモード時のデザインをどうするか?のほうが難しいと思います。
それでも、この機能を追加することで、ユーザーにとってはかなり使いやすいアプリになるのではないでしょうか。
よかったら一度試してみてください。

ここで紹介しているソースは、Apache License, Version 2.0 のライセンスで配布されている成果物を含んでいます。




140 180 Android Wear

記載されている会社名、および商品名等は、各社の商標または登録商標です。

0 コメント:

コメントを投稿

Related Posts Plugin for WordPress, Blogger...