diff options
| author | Adam Cohen <adamcohen@google.com> | 2011-02-10 18:19:50 -0800 |
|---|---|---|
| committer | Adam Cohen <adamcohen@google.com> | 2011-02-11 15:11:43 -0800 |
| commit | 1ff28c7b12986856d8a975d4713d35093b831016 (patch) | |
| tree | 0ea2b8245f51bbf26a42a852eaab16db3d5d19f8 /samples/StackWidget | |
| parent | f8da117394bf87387fb71f3d8465edb558949c21 (diff) | |
| download | android_development-1ff28c7b12986856d8a975d4713d35093b831016.tar.gz android_development-1ff28c7b12986856d8a975d4713d35093b831016.tar.bz2 android_development-1ff28c7b12986856d8a975d4713d35093b831016.zip | |
Making StackWidget sample code stand alone as opposed to bundled with HoneycombGallery
Change-Id: I9da8433ee8a9710f5a5362a6f82fc96d4f456c88
Diffstat (limited to 'samples/StackWidget')
15 files changed, 457 insertions, 0 deletions
diff --git a/samples/StackWidget/Android.mk b/samples/StackWidget/Android.mk new file mode 100644 index 000000000..016a454ea --- /dev/null +++ b/samples/StackWidget/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +# Only compile source java files in this apk. +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := StackWidget + +LOCAL_SDK_VERSION := current + +include $(BUILD_PACKAGE) + +# Use the following include to make our test apk. +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/samples/StackWidget/AndroidManifest.xml b/samples/StackWidget/AndroidManifest.xml new file mode 100644 index 000000000..1fec1570e --- /dev/null +++ b/samples/StackWidget/AndroidManifest.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> + +<!-- Declare the contents of this Android application. The namespace + attribute brings in the Android platform namespace, and the package + supplies a unique name for the application. When writing your + own application, the package name must be changed from "com.example.*" + to come from a domain that you own or have control over. --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.android.stackwidget"> + <uses-sdk android:targetSdkVersion="11" android:minSdkVersion="11"/> + <application android:label="StackWidget"> + <receiver android:name="StackWidgetProvider"> + <intent-filter> + <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> + </intent-filter> + <meta-data android:name="android.appwidget.provider" + android:resource="@xml/stackwidgetinfo" /> + </receiver> + + <service android:name="StackWidgetService" + android:permission="android.permission.BIND_REMOTEVIEWS" + android:exported="false" /> + </application> +</manifest>
\ No newline at end of file diff --git a/samples/StackWidget/_index.html b/samples/StackWidget/_index.html new file mode 100644 index 000000000..e1af3179a --- /dev/null +++ b/samples/StackWidget/_index.html @@ -0,0 +1,31 @@ +<p> + This sample shows how to construct a simple collection widget. This particular example shows how + to create a widget containing a <a href="../../../reference/android/widget/StackView.html"><code>StackView</code></a> + ; however, only minimal changes are required to include + a <a href="../../../reference/android/widget/ListView.html"><code>ListView</code></a>, + <a href="../../../reference/android/widget/GridView.html"><code>GridView</code></a> or + <a href="../../../reference/android/widget/AdapterViewFlipper.html"><code>AdapterViewFlipper</code></a> instead. +</p> +<p> + The sample demonstrates the following: +</p> + <ul> + <li> + The pattern for creating and wiring a <a href="../../../reference/android/widget/RemoteViewsService.html"><code>RemoteViewsService</code></a> + and <a href="../../../reference/android/widget/RemoteViewsService.RemoteViewsFactory.html"><code>RemoteViewsFactory</code></a> which + serve the function of an adapter for the widget collection. + </li> + <li> + The pattern for setting an intent template and fill-in intents in order to + provide children of the collection with click behaviour. + </li> + <li> + How to make a widget with a <a href="../../../reference/android/widget/StackView.html"><code>StackView</code></a> + (or <a href="../../../reference/android/widget/AdapterViewFlipper.html"><code>AdapterViewFlipper</code></a>) auto-advance. + </li> + <li> + How to set a widget preview image. + </li> + </ul> +<img alt="The widget." + src="../images/StackWidget.png"/>
\ No newline at end of file diff --git a/samples/StackWidget/res/drawable-hdpi/icon.png b/samples/StackWidget/res/drawable-hdpi/icon.png Binary files differnew file mode 100644 index 000000000..8074c4c57 --- /dev/null +++ b/samples/StackWidget/res/drawable-hdpi/icon.png diff --git a/samples/StackWidget/res/drawable-ldpi/icon.png b/samples/StackWidget/res/drawable-ldpi/icon.png Binary files differnew file mode 100644 index 000000000..1095584ec --- /dev/null +++ b/samples/StackWidget/res/drawable-ldpi/icon.png diff --git a/samples/StackWidget/res/drawable-mdpi/icon.png b/samples/StackWidget/res/drawable-mdpi/icon.png Binary files differnew file mode 100644 index 000000000..a07c69fa5 --- /dev/null +++ b/samples/StackWidget/res/drawable-mdpi/icon.png diff --git a/samples/StackWidget/res/drawable-nodpi/preview.png b/samples/StackWidget/res/drawable-nodpi/preview.png Binary files differnew file mode 100644 index 000000000..f2f83a0ad --- /dev/null +++ b/samples/StackWidget/res/drawable-nodpi/preview.png diff --git a/samples/StackWidget/res/drawable-nodpi/widget_item_background.xml b/samples/StackWidget/res/drawable-nodpi/widget_item_background.xml new file mode 100644 index 000000000..c0b3843e8 --- /dev/null +++ b/samples/StackWidget/res/drawable-nodpi/widget_item_background.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> + <gradient android:startColor="#ff666666" android:endColor="#ff333333" android:angle="270" /> +</shape> diff --git a/samples/StackWidget/res/layout/widget_item.xml b/samples/StackWidget/res/layout/widget_item.xml new file mode 100644 index 000000000..75e31ab51 --- /dev/null +++ b/samples/StackWidget/res/layout/widget_item.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/widget_item" + android:layout_width="120dp" + android:layout_height="120dp" + android:gravity="center" + android:background="@drawable/widget_item_background" + android:textColor="#ffffff" + android:textStyle="bold" + android:textSize="44sp" /> diff --git a/samples/StackWidget/res/layout/widget_layout.xml b/samples/StackWidget/res/layout/widget_layout.xml new file mode 100644 index 000000000..11f9d3665 --- /dev/null +++ b/samples/StackWidget/res/layout/widget_layout.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <StackView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/stack_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:loopViews="true" /> + <TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/empty_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:background="@drawable/widget_item_background" + android:textColor="#ffffff" + android:textStyle="bold" + android:text="@string/empty_view_text" + android:textSize="20sp" /> +</FrameLayout> diff --git a/samples/StackWidget/res/values/strings.xml b/samples/StackWidget/res/values/strings.xml new file mode 100644 index 000000000..acb2f7fee --- /dev/null +++ b/samples/StackWidget/res/values/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> +<resources> + <string name="empty_view_text">This is the empty view</string> +</resources> diff --git a/samples/StackWidget/res/xml/stackwidgetinfo.xml b/samples/StackWidget/res/xml/stackwidgetinfo.xml new file mode 100644 index 000000000..8c2630f53 --- /dev/null +++ b/samples/StackWidget/res/xml/stackwidgetinfo.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> +<appwidget-provider + xmlns:android="http://schemas.android.com/apk/res/android" + android:minWidth="150dip" + android:minHeight="150dip" + android:updatePeriodMillis="3600000" + android:previewImage="@drawable/preview" + android:initialLayout="@layout/widget_layout" + android:autoAdvanceViewId="@id/stack_view"> +</appwidget-provider>
\ No newline at end of file diff --git a/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetProvider.java b/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetProvider.java new file mode 100644 index 000000000..e053c2103 --- /dev/null +++ b/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetProvider.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 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.stackwidget; + +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.widget.RemoteViews; +import android.widget.Toast; + +public class StackWidgetProvider extends AppWidgetProvider { + public static final String TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION"; + public static final String EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM"; + + @Override + public void onDeleted(Context context, int[] appWidgetIds) { + super.onDeleted(context, appWidgetIds); + } + + @Override + public void onDisabled(Context context) { + super.onDisabled(context); + } + + @Override + public void onEnabled(Context context) { + super.onEnabled(context); + } + + @Override + public void onReceive(Context context, Intent intent) { + AppWidgetManager mgr = AppWidgetManager.getInstance(context); + if (intent.getAction().equals(TOAST_ACTION)) { + int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID); + int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0); + Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show(); + } + super.onReceive(context, intent); + } + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // update each of the widgets with the remote adapter + for (int i = 0; i < appWidgetIds.length; ++i) { + + // Here we setup the intent which points to the StackViewService which will + // provide the views for this collection. + Intent intent = new Intent(context, StackWidgetService.class); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); + // When intents are compared, the extras are ignored, so we need to embed the extras + // into the data so that the extras will not be ignored. + intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); + RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout); + rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent); + + // The empty view is displayed when the collection has no items. It should be a sibling + // of the collection view. + rv.setEmptyView(R.id.stack_view, R.id.empty_view); + + // Here we setup the a pending intent template. Individuals items of a collection + // cannot setup their own pending intents, instead, the collection as a whole can + // setup a pending intent template, and the individual items can set a fillInIntent + // to create unique before on an item to item basis. + Intent toastIntent = new Intent(context, StackWidgetProvider.class); + toastIntent.setAction(StackWidgetProvider.TOAST_ACTION); + toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); + intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); + PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent); + + appWidgetManager.updateAppWidget(appWidgetIds[i], rv); + } + super.onUpdate(context, appWidgetManager, appWidgetIds); + } +}
\ No newline at end of file diff --git a/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetService.java b/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetService.java new file mode 100644 index 000000000..d53b0ea5d --- /dev/null +++ b/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetService.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2011 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.stackwidget; + +import java.util.ArrayList; +import java.util.List; + +import android.appwidget.AppWidgetManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.widget.RemoteViews; +import android.widget.RemoteViewsService; + +public class StackWidgetService extends RemoteViewsService { + @Override + public RemoteViewsFactory onGetViewFactory(Intent intent) { + return new StackRemoteViewsFactory(this.getApplicationContext(), intent); + } +} + +class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { + private static final int mCount = 10; + private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>(); + private Context mContext; + private int mAppWidgetId; + + public StackRemoteViewsFactory(Context context, Intent intent) { + mContext = context; + mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID); + } + + public void onCreate() { + // In onCreate() you setup any connections / cursors to your data source. Heavy lifting, + // for example downloading or creating content etc, should be deferred to onDataSetChanged() + // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR. + for (int i = 0; i < mCount; i++) { + mWidgetItems.add(new WidgetItem(i + "!")); + } + + // We sleep for 3 seconds here to show how the empty view appears in the interim. + // The empty view is set in the StackWidgetProvider and should be a sibling of the + // collection view. + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void onDestroy() { + // In onDestroy() you should tear down anything that was setup for your data source, + // eg. cursors, connections, etc. + mWidgetItems.clear(); + } + + public int getCount() { + return mCount; + } + + public RemoteViews getViewAt(int position) { + // position will always range from 0 to getCount() - 1. + + // We construct a remote views item based on our widget item xml file, and set the + // text based on the position. + RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item); + rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text); + + // Next, we set a fill-intent which will be used to fill-in the pending intent template + // which is set on the collection view in StackWidgetProvider. + Bundle extras = new Bundle(); + extras.putInt(StackWidgetProvider.EXTRA_ITEM, position); + Intent fillInIntent = new Intent(); + fillInIntent.putExtras(extras); + rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent); + + // You can do heaving lifting in here, synchronously. For example, if you need to + // process an image, fetch something from the network, etc., it is ok to do it here, + // synchronously. A loading view will show up in lieu of the actual contents in the + // interim. + try { + System.out.println("Loading view " + position); + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // Return the remote views object. + return rv; + } + + public RemoteViews getLoadingView() { + // You can create a custom loading view (for instance when getViewAt() is slow.) If you + // return null here, you will get the default loading view. + return null; + } + + public int getViewTypeCount() { + return 1; + } + + public long getItemId(int position) { + return position; + } + + public boolean hasStableIds() { + return true; + } + + public void onDataSetChanged() { + // This is triggered when you call AppWidgetManager notifyAppWidgetViewDataChanged + // on the collection view corresponding to this factory. You can do heaving lifting in + // here, synchronously. For example, if you need to process an image, fetch something + // from the network, etc., it is ok to do it here, synchronously. The widget will remain + // in its current state while work is being done here, so you don't need to worry about + // locking up the widget. + } +}
\ No newline at end of file diff --git a/samples/StackWidget/src/com/example/android/stackwidget/WidgetItem.java b/samples/StackWidget/src/com/example/android/stackwidget/WidgetItem.java new file mode 100644 index 000000000..aa822ca33 --- /dev/null +++ b/samples/StackWidget/src/com/example/android/stackwidget/WidgetItem.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 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.stackwidget; + +public class WidgetItem { + public String text; + + public WidgetItem(String text) { + this.text = text; + } +} |
