DayDreaming is simple, if you have written an application with an Activity i.e everybody! You should be able to implement a simple daydream with little extra effort.
We are going to run through creating one and it will look something like this at the end:
(much smoother on a device, this is a GIF representation)
To create a DayDream we need to:
- Create a DayDream *activity* to display our daydream
- Update our Manifest to inform the system we can dream
- Create a custom view that will perform something cool in our daydream
Ok here we go..
First we’ll create the DayDreamActivity, now technically it is not an Activity but a Service and in that idea we have to extend Service, but if you think of it as an Activity to display content with a lifecycle, I think it is a better concept.
In the DayDreamActivity we set a content view, this is the layout that will be shown if your day dream is being used. We also declare that we can handle user touch events, we don’t want the status bar shown when our day dream is shown and they can dim the screen.
DayDreamActivity.java:
package com.blundell.tutorial; import android.service.dreams.DreamService; import android.view.View; import android.widget.Toast; /** * Not really an Activity but just pretend it is one * <p/> * Where onCreate is onDreamingStarted * Where onPause is onDreamingStopped */ public class DayDreamActivity extends DreamService implements View.OnClickListener { @Override public void onDreamingStarted() { super.onDreamingStarted(); // Removed the status bar setFullscreen(true); // We want to know about clicks setInteractive(true); // Dull the screen setScreenBright(false); // Acts just like an Activity setContentView(R.layout.dream_main); findViewById(R.id.dream_main_image).setOnClickListener(this); } @Override public void onClick(View v) { startApp(); } private void startApp() { Toast.makeText(this, "Start your activity or another app on click", Toast.LENGTH_SHORT).show(); // This is where you would normally start an Intent // don't forget to add the new activity flag // Intent intent = new Intent(this, null); // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // startActivity(intent); } }
After your create your DayDream, you need to declare it in your AndroidManifest like any other service:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.blundell.tutorial" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> <application android:label="@string/app_name" android:icon="@drawable/ic_launcher"> <service android:name=".DayDreamActivity" android:label="@string/app_name" android:exported="true"> <intent-filter> <action android:name="android.service.dreams.DreamService" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </service> </application> </manifest>
That’s it, that would get you a basic daydream. However it doesn’t really do anything, so below I’m going to show you how to create a custom ImageView that will rotate any image you give it. For this example it is a spinning cloud daydream! We use a TimeAnimator to give us a callback on every frame for the system drawing. When we get this callback we change the Y rotation of the ImageView. You could do whatever you wanted for your daydream this is just one example.
SpinningImageView.java
package com.blundell.tutorial; import android.animation.TimeAnimator; import android.content.Context; import android.util.AttributeSet; import android.widget.ImageView; /** * Simple CustomView that will rotate whatever image source you set */ public class SpinningImageView extends ImageView implements TimeAnimator.TimeListener { public static final int ROTATION_DELTA = 10; // This will tick every frame so you can update the view private TimeAnimator animatorTick; public SpinningImageView(Context context) { this(context, null); } public SpinningImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SpinningImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); animatorTick = new TimeAnimator(); animatorTick.setTimeListener(this); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); animatorTick.start(); } @Override public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { setRotationY(getRotationY() + ROTATION_DELTA); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); animatorTick.cancel(); } }
Then you use your custom view in the layout for the DayDreamActivity and you are done.
dream_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/daydream_title" /> <com.blundell.tutorial.SpinningImageView android:id="@+id/dream_main_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/dd_cloud" android:contentDescription="@null" /> </LinearLayout>
Take a look at the GitRepo for the source. DayDream Source Here
Inspired by the Google IO 2013 Talk Androids Do DayDream, I would highly recommend you watch it.
Enjoy! and ask any questions you like.