DayDream | Android 4.2 APIs | Android Developers
Daydream: Interactive Screen Savers | Android Developers Blog
DayDream が利用可能な状況は充電中、ドック接続中(車など)のみ(※)です。
(※ユーザーの設定により両方もしくはいずれか)
ユーザーの設定でスクリーンセーバーが有効になっていれば動作可能で、
画面がスリープする代わりに起動設定されているスクリーンセーバーが動作します。
詳しい設定方法は以下のサイトがわかりやすいです。
Android 4.2の新機能、Daydream(スクリーンセーバー)の使い方と設定方法。 - Android(アンドロイド)おすすめアプリ・カスタムニュース|AndroidLover.Net
DayDream の実装には DreamService という Service を継承したクラスを使用します。
DreamService は Activity のように扱うことができます。
その他にも onAttachedToWindow(), onDreamingStarted(), onDreamingStopped(), onDetachedFromWindow() という DreamService 特有のライフサイクルがあります。
詳しくは DreamService | Android Developers を見てください。
簡単なサンプルを作ってみました。wada811/AndroidLibrary@wada811
設定付き DayDream の作り方
<service android:name="at.wada811.android.library.demos.daydream.DayDreamDemo" android:exported="false" android:label="@string/DayDreamDemo" > <intent-filter> <action android:name="android.service.dreams.DreamService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.service.dream" android:resource="@xml/daydream" /> </service> <activity android:name="at.wada811.android.library.demos.daydream.DayDreamSettingsActivity" android:label="@string/app_name" > </activity>
<dream xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="at.wada811.android.library.demos/.daydream.DayDreamSettingsActivity" />
public class DayDreamDemo extends DreamService { @Override public void onAttachedToWindow(){ super.onAttachedToWindow(); LogUtils.d(); setInteractive(PreferenceUtils.getBoolean(getApplicationContext(), getString(R.string.setInteractive), true)); setFullscreen(PreferenceUtils.getBoolean(getApplicationContext(), getString(R.string.setFullscreen), true)); setScreenBright(PreferenceUtils.getBoolean(getApplicationContext(), getString(R.string.setScreenBright), true)); setContentView(R.layout.daydream); } @Override public void onDreamingStarted(){ super.onDreamingStarted(); LogUtils.d(); } @Override public void onDreamingStopped(){ super.onDreamingStopped(); LogUtils.d(); } @Override public void onDetachedFromWindow(){ super.onDetachedFromWindow(); LogUtils.d(); } }
public class DayDreamSettingsActivity extends FragmentActivity { final DayDreamSettingsActivity self = this; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_daydream_settings); Switch switchInteractive = (Switch)findViewById(R.id.setInteractive); switchInteractive.setChecked(PreferenceUtils.getBoolean(self, getString(R.string.setInteractive), true)); switchInteractive.setOnCheckedChangeListener(new OnCheckedChangeListener(){ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){ PreferenceUtils.putBoolean(self, getString(R.string.setInteractive), isChecked); } }); Switch switchFullscreen = (Switch)findViewById(R.id.setFullscreen); switchFullscreen.setChecked(PreferenceUtils.getBoolean(self, getString(R.string.setFullscreen), true)); switchFullscreen.setOnCheckedChangeListener(new OnCheckedChangeListener(){ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){ PreferenceUtils.putBoolean(self, getString(R.string.setFullscreen), isChecked); } }); Switch switchScreenBright = (Switch)findViewById(R.id.setScreenBright); switchScreenBright.setChecked(PreferenceUtils.getBoolean(self, getString(R.string.setScreenBright), true)); switchScreenBright.setOnCheckedChangeListener(new OnCheckedChangeListener(){ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){ PreferenceUtils.putBoolean(self, getString(R.string.setScreenBright), isChecked); } }); } }以上!実装はすごく簡単です。
DreamService#setScreenBright(boolean) | Android Developers の効果がいまいちわかりませんでした。
DreamService は WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED と
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD が設定されているので
KEYGUARD_LAYER にいるっぽいです。
参考
表示レイヤーについて - baroqueworksdevの日記
Y.A.M の 雑記帳: Android FLAG_DISMISS_KEYGUARD と FLAG_SHOW_WHEN_LOCKED を使う
Toast や DreamService から起動した Activity などは KEYGUARD_LAYER より下に表示されるので
見ることができません。
また、DreamService はあくまで「 Activity のように」、なので Fragment を扱うことができません。
面倒なので普通の Activity を使いたい場合は以下のように起動させてあげると良いです。
DayDream から Activity を起動する
<service android:name="at.wada811.android.library.demos.daydream.DayDreamLauncher" android:exported="false" android:label="@string/DayDreamLauncher" > <intent-filter> <action android:name="android.service.dreams.DreamService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> <activity android:name="at.wada811.android.library.demos.daydream.DayDreamActivity" android:label="@string/app_name" > </activity>
public class DayDreamLauncher extends DreamService { @Override public void onAttachedToWindow(){ super.onAttachedToWindow(); Intent intent = new Intent(this, DayDreamActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }
public class DayDreamActivity extends FragmentActivity { final DayDreamActivity self = this; @Override protected void onCreate(Bundle savedInstanceState){ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); super.onCreate(savedInstanceState); setContentView(R.layout.activity_daydream); LogUtils.d(); Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ AndroidUtils.showToast(self, R.string.touch); } }); } }DreamService と同じようにフラグを設定してあげれば
Activity も DreamService と同じレイヤーで表示することが可能です。
参考
JB 4.2 Daydreamの制約を乗り越えようとしてみる。 #androidadvent2012 | Mobile Dev Blog (by @korodroid)
ぺろぺろ会でのDaydreamまとめ #JB42 - ReDo
利用状況がかなり限られていますが競合が少なそうな分野なのでインストールされやすそうですね。
Android4.2 以上の端末の普及とユーザーへのスクリーンセーバーが使えるという認知が広まればの話ですが…。