JB 4.2 Daydreamの制約を乗り越えようとしてみる。 #androidadvent2012

 Android Advent Calendar 2012の14日目(表)担当の@korodroidです。裏は@ryosmsさんです。

Androidに出会ってから結構な年月が経ちましたが、いまだに新しいAndroidバージョンがリリースされるとわくわくしたりと、まだまだAndroidも大好きなアプリ開発者です:-)

@youten_redoさん主催のJB新味ぺろぺろ会に先日参加して、Android 4.2から追加されたDaydreamを学んできました。面白い機能なので、早速、自分のアプリにも適用しようと思って、さらに触ってみました。そこで得られた情報を紹介させていただきます。このエントリを読んでいただき、Daydream対応アプリが少しでも増えてくれたらうれしいなと思っています。

  • Daydreamって何?
    Android 4.2から追加された機能で、簡単に言えば、スクリーンセーバーです。ドックを接続したり充電を開始したりといったタイミングで自動的に起動します。ユーザが画面を触ると、自動的に終了してくれます。
    ただ、スクリーンセーバーとは言っても、インタラクティブモードを指定しておけば、画面を触っても自動終了せず、ユーザからのイベントを受け付けたりすることも可能です。

    成果物その1:JB時計セーバー

  • どうやって実装するの?
     公式サイトを見ると分かるように、2つのステップが必要です。
    (1)DreamServiceというServiceを継承したクラスを作成する。
     →画面に表示したい内容をレイアウトXMLとして定義しておき、本Service内でsetContentViewすると言った流れです。

    (2)Android Manifestに同Service+IntentFilterを定義する。
      →Daydreamの起動タイミングである「ドック接続」「充電開始」といったタイミングで、Intent(android.service.dreams.DreamService)があがってきますので、それをこのIntentFilterで拾うという仕組みです。

  • はまりポイントってないの?
    実際にやってみると分かりますが、幾つかはまりました。
    DreamService内でsetContentViewしたりと、findViewByIdでビューを取得してイベントリスナを設定したりできるので、Activity<のように>使えます。<のように>のところがポイントですorz

【★一般的なDaydream の実装】
public void onAttachedToWindow() {

    super.onAttachedToWindow();

   setInteractive(false);  // インタラクティブモードの無効化

   setFullscreen(true); // フルスクリーンの設定

   setContentView(R.layout.main); // レイアウトXMLファイルの設定

}

自分のアプリ(セカイフォン)をDaydream対応させようとしたところ、大きな問題にはまりました。セカイフォンは、Fragmentをたっぷりと使っているのですが、DreamServiceの中ではFragmentManagerなどFragmentを扱うのに必要なものを取得できない!!なんか手がないかと思って、ちょっとごにょごにょしましたが、だめでした。

どうしてもセカイフォンをDaydreamに対応させたい!と思いつつも、せっかくFragmentベースの実装からFragmentを除去するのは面倒くさい(あほらしい)ので、色々考えて試行錯誤しました。その結果、簡単な方法で対応することに成功しました!DaydreamでFragmentを使えなくて困ってしまった場合に役立つかもしれない方法です(大袈裟。。w)

成果物その2:セカイフォン

 

  • どうやって対応したの?
    まず、主に変更したのは以下2行です。

    【★今回のDaydream 部分の実装】
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        setInteractive(false);
        setFullscreen(true);
        // setContentView(R.layout.main); →Fragmentいっぱい。やめた。
     startActivity(new Intent(this, MainActivity.class));
    }

    しかし、これだけだとうまくいきません。実際にやってみると、MainActivityの画面は起動するものの裏に隠れたままの状態です(Daydreamの画面が最前面に表示されたままなので、見た目上は画面に変化がありません)。

    【★追加で行った対策】
    起動されるMainActivityの方で、画面を上位に表示するためのおまじないがあります。
    このあたりは、 JB新味ぺろぺろ会で教えてもらったものをそのまま使わせていただいただけなので、そちらの記事をご参照ください。
    ここまでやると、めでたく、Fragmentばりばりの画面のDaydream対応の完成です! 

ということで、2行+αで、Daydreamの制約を乗り越える(回避する)方法の紹介でした。
正直イレギュラーな方法な気がするので、仕様的な問題をかかえてしまうかもしれません。あらかじめ、その点にご注意ください!

■関連URL

明日15日目の表担当は”青空文庫ビューア”作者としても有名な@sys1yagiさん、裏担当は”Androidリファレンス書籍”でご一緒した@kenz_firespeedさんです。よろしくお願いします。

それではー! 

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です