From 2e1fe78fbf01a1e6f454df0f4065410cbbc868bd Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Fri, 31 Aug 2012 07:12:42 -0700 Subject: [PATCH] Add new sample for Presentation API. Change-Id: Ia31deb9ca6ad9a4db1dd6f852c00fa9a94caa4c3 --- samples/ApiDemos/AndroidManifest.xml | 8 + .../res/layout/presentation_activity.xml | 40 +++ .../res/layout/presentation_content.xml | 37 +++ samples/ApiDemos/res/values/strings.xml | 4 + .../apis/app/PresentationActivity.java | 289 ++++++++++++++++++ 5 files changed, 378 insertions(+) create mode 100644 samples/ApiDemos/res/layout/presentation_activity.xml create mode 100644 samples/ApiDemos/res/layout/presentation_content.xml create mode 100644 samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index 817b23ac1..7326170a6 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -254,6 +254,14 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/ApiDemos/res/layout/presentation_content.xml b/samples/ApiDemos/res/layout/presentation_content.xml new file mode 100644 index 000000000..7e9aaa04e --- /dev/null +++ b/samples/ApiDemos/res/layout/presentation_content.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml index a64de167c..778becaa3 100644 --- a/samples/ApiDemos/res/values/strings.xml +++ b/samples/ApiDemos/res/values/strings.xml @@ -112,6 +112,10 @@ Enter the text that will be used by the main activity. Press back to cancel. Apply + App/Activity/Presentation + This activity demonstrates how to use the Presentation activity to show content on other Displays. Try connecting a secondary display and watch what happens. + You\'re watching channel %1$d on display %2$d. + App/Fragment/Alert Dialog App/Fragment/Arguments diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java new file mode 100644 index 000000000..e7e043b73 --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.apis.app; + +// Need the following import to get access to the app resources, since this +// class is in a sub-package. +import com.example.android.apis.R; + +import android.app.Activity; +import android.app.Presentation; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.hardware.display.DisplayManager; +import android.os.Bundle; +import android.util.Log; +import android.util.SparseArray; +import android.view.Display; +import android.view.View; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +/** + *

Presentation Activity

+ * + *

+ * This demonstrates how to create an activity that shows some content + * on a secondary display using a {@link Presentation}. + *

+ * The activity automatically creates and displays a {@link Presentation} whenever + * a new non-default display is detected. You can try this out by using + * the "Simulate secondary displays" feature in Development Settings to create + * a few simulated secondary displays. + *

+ */ +public class PresentationActivity extends Activity { + private final String TAG = "PresentationActivity"; + + // The content that we want to show on the presentation. + private static final int[] CHANNELS = new int[] { + R.drawable.photo1, R.drawable.photo2, R.drawable.photo3, + R.drawable.photo4, R.drawable.photo5, R.drawable.photo6, + }; + + private DisplayManager mDisplayManager; + private ListView mDisplayList; + private DisplayListAdapter mDisplayListAdapter; + private int mNextChannelNumber; + + // All active presentations indexed by display id. + private final SparseArray mActivePresentations = + new SparseArray(); + + /** + * Initialization of the Activity after it is first created. Must at least + * call {@link android.app.Activity#setContentView setContentView()} to + * describe what is to be displayed in the screen. + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + // Be sure to call the super class. + super.onCreate(savedInstanceState); + + // Get the display manager service. + mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE); + + // See assets/res/any/layout/presentation_activity.xml for this + // view layout definition, which is being set here as + // the content of our screen. + setContentView(R.layout.presentation_activity); + + mDisplayListAdapter = new DisplayListAdapter(this); + + mDisplayList = (ListView)findViewById(R.id.display_list); + mDisplayList.setAdapter(mDisplayListAdapter); + mDisplayList.setOnItemClickListener(mOnItemClickListener); + } + + @Override + protected void onResume() { + // Be sure to call the super class. + super.onResume(); + + // Update our list of displays on resume. + mDisplayListAdapter.updateContents(); + + // Register to receive events from the display manager. + mDisplayManager.registerDisplayListener(mDisplayListener, null); + } + + @Override + protected void onPause() { + // Be sure to call the super class. + super.onPause(); + + // Unregister from the display manager. + mDisplayManager.unregisterDisplayListener(mDisplayListener); + + // Dismiss all of our presentations. + Log.d(TAG, "Activity is being paused. Dimissing all active presentation."); + for (int i = 0; i < mActivePresentations.size(); i++) { + Presentation presentation = mActivePresentations.valueAt(i); + presentation.dismiss(); + } + mActivePresentations.clear(); + } + + /** + * Shows a {@link Presentation} on the specified display. + */ + private void showPresentation(Display display) { + // Do nothing if there is already a presentation showing on the display. + if (mActivePresentations.get(display.getDisplayId()) != null) { + return; + } + + Log.d(TAG, "Showing presentation on display " + display.getDisplayId() + "."); + + int channelNumber = mNextChannelNumber; + mNextChannelNumber = (mNextChannelNumber + 1) % CHANNELS.length; + + final DemoPresentation presentation = new DemoPresentation(this, display, channelNumber); + mActivePresentations.put(display.getDisplayId(), presentation); + presentation.show(); + presentation.setOnDismissListener(mOnDismissListener); + } + + /** + * Shows a {@link Presentation} on the specified display, or dismisses it if one + * already showing there. + */ + private void showOrDismissPresentation(Display display) { + // Dismiss if already showing. + DemoPresentation presentation = mActivePresentations.get(display.getDisplayId()); + if (presentation != null) { + Log.d(TAG, "Dimissing presentation on display " + display.getDisplayId() + "."); + presentation.dismiss(); + return; + } + + // Otherwise show the presentation. + showPresentation(display); + } + + /** + * Listens for displays to be added, changed or removed. + * We use it to update the list and show a new {@link Presentation} when a + * display is connected. + * + * Note that we don't bother dismissing the {@link Presentation} when a + * display is removed, although we could. The presentation API takes care + * of doing that automatically for us. + */ + private final DisplayManager.DisplayListener mDisplayListener = + new DisplayManager.DisplayListener() { + @Override + public void onDisplayAdded(int displayId) { + Log.d(TAG, "Display " + displayId + " added."); + mDisplayListAdapter.updateContents(); + + Display display = mDisplayManager.getDisplay(displayId); + if (display != null) { + showPresentation(display); + } + } + + @Override + public void onDisplayChanged(int displayId) { + Log.d(TAG, "Display " + displayId + " changed."); + mDisplayListAdapter.updateContents(); + } + + @Override + public void onDisplayRemoved(int displayId) { + Log.d(TAG, "Display " + displayId + " removed."); + mDisplayListAdapter.updateContents(); + } + }; + + /** + * Listens for when presentations are dismissed. + */ + private final DialogInterface.OnDismissListener mOnDismissListener = + new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + DemoPresentation presentation = (DemoPresentation)dialog; + Display display = presentation.getDisplay(); + Log.d(TAG, "Presentation on display " + display.getDisplayId() + " was dismissed."); + mActivePresentations.remove(display.getDisplayId()); + } + }; + + /** + * List adapter. + * Shows information about all displays. + */ + private final class DisplayListAdapter extends ArrayAdapter { + public DisplayListAdapter(Context context) { + super(context, android.R.layout.simple_list_item_1); + } + + /** + * Update the contents of the display list adapter to show + * information about all current displays. + */ + public void updateContents() { + clear(); + + Display[] displays = mDisplayManager.getDisplays(); + addAll(displays); + + Log.d(TAG, "There are currently " + displays.length + " displays connected."); + for (Display display : displays) { + Log.d(TAG, " " + display); + } + } + } + + /** + * Called when an item in the display list is clicked. + * + * Causes a presentation to be shown or dismissed on that display if already showing. + */ + private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Display display = (Display)parent.getItemAtPosition(position); + showOrDismissPresentation(display); + } + }; + + /** + * The presentation to show on the secondary display. + * + * Note that this display may have different metrics from the display on which + * the main activity is showing so we must be careful to use the presentation's + * own {@link Context} whenever we load resources. + */ + private final class DemoPresentation extends Presentation { + // Specifies the content that we want to show in this presentation. + private final int mChannelNumber; + + public DemoPresentation(Context context, Display display, int channelNumber) { + super(context, display); + mChannelNumber = channelNumber; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + // Be sure to call the super class. + super.onCreate(savedInstanceState); + + // Get the resources for the context of the presentation. + // Notice that we are getting the resources from the context of the presentation. + Resources r = getContext().getResources(); + + // Inflate the layout. + setContentView(R.layout.presentation_content); + + // Show a text message to describe what's going on. + TextView text = (TextView)findViewById(R.id.text); + text.setText(r.getString(R.string.presentation_channel_text, mChannelNumber + 1, + getDisplay().getDisplayId())); + + // Show a n image for visual interest. + ImageView image = (ImageView)findViewById(R.id.image); + image.setImageDrawable(r.getDrawable(CHANNELS[mChannelNumber])); + } + } +}