auto import from //depot/cupcake/@135843
diff --git a/samples/AliasActivity/Android.mk b/samples/AliasActivity/Android.mk
new file mode 100644
index 0000000..a34e1bf
--- /dev/null
+++ b/samples/AliasActivity/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := AliasActivity
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/samples/AliasActivity/AndroidManifest.xml b/samples/AliasActivity/AndroidManifest.xml
new file mode 100644
index 0000000..33ad326
--- /dev/null
+++ b/samples/AliasActivity/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.aliasactivity">
+ <application android:hasCode="false">
+ <activity android:name="android.app.AliasActivity" android:label="@string/app_label">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <meta-data android:name="android.app.alias"
+ android:resource="@xml/alias" />
+ </activity>
+ </application>
+</manifest>
diff --git a/samples/AliasActivity/res/values/strings.xml b/samples/AliasActivity/res/values/strings.xml
new file mode 100644
index 0000000..dd746e3
--- /dev/null
+++ b/samples/AliasActivity/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="app_label">An Alias</string>
+</resources>
diff --git a/samples/AliasActivity/res/xml/alias.xml b/samples/AliasActivity/res/xml/alias.xml
new file mode 100644
index 0000000..3946333
--- /dev/null
+++ b/samples/AliasActivity/res/xml/alias.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+ <intent android:action="android.intent.action.VIEW"
+ android:data="http://www.google.com/">
+ </intent>
+</alias>
diff --git a/samples/ApiDemos/Android.mk b/samples/ApiDemos/Android.mk
new file mode 100644
index 0000000..5019c2f
--- /dev/null
+++ b/samples/ApiDemos/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples development
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += \
+ src/com/example/android/apis/app/IRemoteService.aidl \
+ src/com/example/android/apis/app/IRemoteServiceCallback.aidl \
+ src/com/example/android/apis/app/ISecondary.aidl \
+
+LOCAL_PACKAGE_NAME := ApiDemos
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# Use the folloing include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
new file mode 100644
index 0000000..afcfbc8
--- /dev/null
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -0,0 +1,1705 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.apis">
+
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.VIBRATE" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application android:name="ApiDemosApplication"
+ android:label="@string/activity_sample_code"
+ android:icon="@drawable/app_sample_code" >
+
+ <uses-library android:name="com.google.android.maps" />
+
+ <activity android:name="ApiDemos">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- APPLICATION PACKAGE SAMPLES -->
+ <!-- ************************************* -->
+
+ <!-- Activity Samples -->
+
+ <activity android:name=".app.HelloWorld" android:label="@string/activity_hello_world">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.DialogActivity"
+ android:label="@string/activity_dialog"
+ android:theme="@android:style/Theme.Dialog">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.CustomDialogActivity"
+ android:label="@string/activity_custom_dialog"
+ android:theme="@style/Theme.CustomDialog">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.TranslucentActivity"
+ android:label="@string/activity_translucent"
+ android:theme="@style/Theme.Translucent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.TranslucentBlurActivity"
+ android:label="@string/activity_translucent_blur"
+ android:theme="@style/Theme.Transparent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.SaveRestoreState"
+ android:label="@string/activity_save_restore"
+ android:windowSoftInputMode="stateVisible|adjustResize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.PersistentState"
+ android:label="@string/activity_persistent"
+ android:windowSoftInputMode="stateVisible|adjustResize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.ReceiveResult" android:label="@string/activity_receive_result">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.SendResult">
+ </activity>
+
+ <activity android:name=".app.Forwarding" android:label="@string/activity_forwarding">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.ForwardTarget">
+ </activity>
+
+ <activity android:name=".app.RedirectEnter" android:label="@string/activity_redirect">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.RedirectMain">
+ </activity>
+
+ <activity android:name=".app.RedirectGetter">
+ </activity>
+
+ <activity android:name=".app.CustomTitle"
+ android:label="@string/activity_custom_title"
+ android:windowSoftInputMode="stateVisible|adjustPan">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.ReorderOnLaunch"
+ android:label="@string/activity_reorder">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.ReorderTwo" />
+ <activity android:name=".app.ReorderThree" />
+ <activity android:name=".app.ReorderFour" />
+
+ <!-- Intent Samples -->
+
+ <activity android:name=".app.Intents" android:label="@string/activity_intents">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- Service Samples -->
+
+ <service android:name=".app.LocalService" />
+
+ <activity android:name=".app.LocalServiceController" android:label="@string/activity_local_service_controller">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.LocalServiceBinding" android:label="@string/activity_local_service_binding">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".app.RemoteService" android:process=":remote">
+ <intent-filter>
+ <!-- These are the interfaces supported by the service, which
+ you can bind to. -->
+ <action android:name="com.example.android.apis.app.IRemoteService" />
+ <action android:name="com.example.android.apis.app.ISecondary" />
+ <!-- This is an action code you can use to select the service
+ without explicitly supplying the implementation class. -->
+ <action android:name="com.example.android.apis.app.REMOTE_SERVICE" />
+ </intent-filter>
+ </service>
+
+ <activity android:name=".app.RemoteServiceController" android:label="@string/activity_remote_service_controller">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.RemoteServiceBinding" android:label="@string/activity_remote_service_binding">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".app.ServiceStartArguments" />
+
+ <activity android:name=".app.ServiceStartArgumentsController" android:label="@string/activity_service_start_arguments_controller">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- Alarm Samples -->
+
+ <receiver android:name=".app.OneShotAlarm" android:process=":remote" />
+
+ <receiver android:name=".app.RepeatingAlarm" android:process=":remote" />
+
+ <activity android:name=".app.AlarmController" android:label="@string/activity_alarm_controller">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".app.AlarmService_Service" android:process=":remote" />
+
+ <activity android:name=".app.AlarmService" android:label="@string/activity_alarm_service">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- Instrumentation Samples -->
+
+ <activity android:name=".app.LocalSample" android:label="@string/activity_local_sample">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <!-- category android:name="android.intent.category.SAMPLE_CODE" /-->
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.ContactsFilter" android:label="@string/activity_contacts_filter">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <!-- category android:name="android.intent.category.SAMPLE_CODE" /-->
+ </intent-filter>
+ </activity>
+
+
+ <!-- Notifications samples -->
+
+ <activity android:name=".app.NotifyWithText" android:label="App/Notification/NotifyWithText">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.IncomingMessage" android:label="App/Notification/IncomingMessage">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.IncomingMessageView" android:label="App/Notification/IncomingMessageView">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.EMBED" />
+ </intent-filter>
+ </activity>
+
+ <!-- This is used to display a notification selected by the user
+ from StatusBarNotifications. Note the configuration here so
+ that the activity layers on top of whatever the user is doing,
+ allowing them to press back to return. -->
+ <activity android:name=".app.NotificationDisplay"
+ android:theme="@style/Theme.Transparent"
+ android:taskAffinity=""
+ android:excludeFromRecents="true"
+ android:noHistory="true">
+ </activity>
+
+ <activity android:name=".app.StatusBarNotifications"
+ android:label="App/Notification/Status Bar"
+ android:launchMode="singleTop">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".app.NotifyingService" />
+
+ <activity android:name=".app.NotifyingController" android:label="App/Notification/Notifying Service Controller">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- Dialog samples -->
+ <activity android:name=".app.AlertDialogSamples" android:label="@string/activity_alert_dialog">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- Search Samples -->
+
+ <!-- This activity represents a "typical" activity in your application from which the -->
+ <!-- user would be allowed to invoke a search function. As noted below, the definition -->
+ <!-- of android.app.default_searchable is more typically handled at the application -->
+ <!-- level, where it can serve as a default for all of your activities. -->
+
+ <activity android:name=".app.SearchInvoke"
+ android:label="@string/search_invoke">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+
+ <!-- This metadata entry causes .app.SearchQueryResults to be the default context -->
+ <!-- whenever the user invokes search while in this Activity. -->
+ <meta-data android:name="android.app.default_searchable"
+ android:value=".app.SearchQueryResults" />
+
+ <!-- This is not the typical way to define android.app.default_searchable, -->
+ <!-- and we show it here only because we wish to confine the search demo to this -->
+ <!-- section of the ApiDemos application. -->
+
+ <!-- For typical applications, it's simpler to define android.app.default_searchable -->
+ <!-- just once, at the application level, where it serves as a default for all of -->
+ <!-- the Activities in your package. -->
+ </activity>
+
+ <!-- This activity represents the "search" activity in your application, in which -->
+ <!-- search results are gathered and displayed. -->
+
+ <activity android:name=".app.SearchQueryResults"
+ android:label="@string/search_query_results">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+
+ <!-- This intent-filter identifies this activity as "searchable" -->
+
+ <intent-filter>
+ <action android:name="android.intent.action.SEARCH" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+
+ <!-- This metadata entry provides further configuration details for searches -->
+ <!-- that are handled by this activity. -->
+
+ <meta-data android:name="android.app.searchable"
+ android:resource="@xml/searchable" />
+ </activity>
+
+ <!-- This provider declaration informs the Search Manager that you have a provider of -->
+ <!-- Search suggestions, and provides information about how to access it. -->
+
+ <provider android:name=".app.SearchSuggestionSampleProvider"
+ android:authorities="com.example.android.apis.SuggestionProvider" />
+
+ <!-- Shortcuts Samples -->
+
+ <!-- This section of sample code shows how your application can add shortcuts to -->
+ <!-- the launcher (home screen). Shortcuts have a three step life cycle. -->
+
+ <!-- 1. Your application offers to provide shortcuts to the launcher. When -->
+ <!-- the user installs a shortcut, an activity within your application -->
+ <!-- generates the actual shortcut and returns it to the launcher, where it -->
+ <!-- is shown to the user as an icon. -->
+
+ <!-- 2. Any time the user clicks on an installed shortcut, an intent is sent. -->
+ <!-- Typically this would then be handled as necessary by an activity within -->
+ <!-- your application. -->
+
+ <!-- 3. The shortcut is deleted. There is no notification to your application. -->
+
+ <!-- In order provide shortcuts from your application, you provide three things: -->
+
+ <!-- 1. An intent-filter declaring your ability to provide shortcuts -->
+ <!-- 2. Code within the activity to provide the shortcuts as requested -->
+ <!-- 3. Code elsewhere within your activity, if appropriate, to receive -->
+ <!-- intents from the shortcut itself. -->
+
+ <activity android:name=".app.LauncherShortcuts"
+ android:label="@string/shortcuts">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+
+ </activity>
+
+ <!-- It is recommended that you use an activity-alias to provide the "CREATE_SHORTCUT" -->
+ <!-- intent-filter. This gives you a way to set the text (and optionally the -->
+ <!-- icon) that will be seen in the launcher's create-shortcut user interface. -->
+
+ <activity-alias android:name=".app.CreateShortcuts"
+ android:targetActivity=".app.LauncherShortcuts"
+ android:label="@string/sample_shortcuts">
+
+ <!-- This intent-filter allows your shortcuts to be created in the launcher. -->
+ <intent-filter>
+ <action android:name="android.intent.action.CREATE_SHORTCUT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+
+ </activity-alias>
+
+ <!-- Menu Samples -->
+
+ <activity android:name=".app.MenuInflateFromXml" android:label="@string/menu_from_xml_title">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- Preferences Samples -->
+
+ <activity android:name=".app.PreferencesFromXml" android:label="@string/preferences_from_xml">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.PreferencesFromCode" android:label="@string/preferences_from_code">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.AdvancedPreferences" android:label="@string/advanced_preferences">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.LaunchingPreferences" android:label="@string/launching_preferences">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.PreferenceDependencies" android:label="@string/preference_dependencies">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.DefaultValues" android:label="@string/default_values">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+
+ <!-- Voice Recognition Samples -->
+
+ <activity android:name=".app.VoiceRecognition" android:label="@string/voice_recognition">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- CONTENT PACKAGE SAMPLES -->
+ <!-- ************************************* -->
+
+ <activity android:name=".content.StyledText" android:label="@string/activity_styled_text">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ <category android:name="android.intent.category.EMBED" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".content.ReadAsset" android:label="@string/activity_read_asset">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ <category android:name="android.intent.category.EMBED" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".content.ResourcesSample" android:label="@string/activity_resources">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- OS PACKAGE SAMPLES -->
+ <!-- ************************************* -->
+
+ <activity android:name=".os.MorseCode" android:label="OS/Morse Code">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".os.Sensors" android:label="OS/Sensors">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- ANIMATION PACKAGE SAMPLES -->
+ <!-- ************************************* -->
+
+ <activity android:name=".animation.Transition3d" android:label="Views/Animation/3D Transition">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- VIEW/WIDGET PACKAGE SAMPLES -->
+ <!-- ************************************* -->
+
+ <activity android:name=".view.ChronometerDemo" android:label="Views/Chronometer">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".view.WebView1" android:label="Views/WebView">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.RelativeLayout1" android:label="Views/Layouts/RelativeLayout/1. Vertical">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.RelativeLayout2" android:label="Views/Layouts/RelativeLayout/2. Simple Form">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout1" android:label="Views/Layouts/LinearLayout/1. Vertical">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout2" android:label="Views/Layouts/LinearLayout/2. Vertical (Fill Screen)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout3" android:label="Views/Layouts/LinearLayout/3. Vertical (Padded)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout4" android:label="Views/Layouts/LinearLayout/4. Horizontal">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout5" android:label="Views/Layouts/LinearLayout/5. Simple Form">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout6" android:label="Views/Layouts/LinearLayout/6. Uniform Size">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout7" android:label="Views/Layouts/LinearLayout/7. Fill Parent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout8" android:label="Views/Layouts/LinearLayout/8. Gravity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout9" android:label="Views/Layouts/LinearLayout/9. Layout Weight">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LinearLayout10" android:label="Views/Layouts/LinearLayout/10. Background Image">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+
+ <activity android:name=".view.RadioGroup1" android:label="Views/Radio Group">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ScrollView1" android:label="Views/Layouts/ScrollView/1. Short">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ScrollView2" android:label="Views/Layouts/ScrollView/2. Long">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Tabs1" android:label="Views/Tabs/Content By Id">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.SAMPLE_CODE"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Tabs2" android:label="Views/Tabs/Content By Factory">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.SAMPLE_CODE"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Tabs3" android:label="Views/Tabs/Content By Intent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.SAMPLE_CODE"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.InternalSelectionScroll" android:label="Views/Layouts/ScrollView/3. Internal Selection">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout1" android:label="Views/Layouts/TableLayout/01. Basic">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout2" android:label="Views/Layouts/TableLayout/02. Empty Cells">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout3" android:label="Views/Layouts/TableLayout/03. Long Content">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout4" android:label="Views/Layouts/TableLayout/04. Stretchable">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout5" android:label="Views/Layouts/TableLayout/05. Spanning and Stretchable">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout6" android:label="Views/Layouts/TableLayout/06. More Spanning and Stretchable">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout7" android:label="Views/Layouts/TableLayout/07. Column Collapse">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout8" android:label="Views/Layouts/TableLayout/08. Toggle Stretch">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout9" android:label="Views/Layouts/TableLayout/09. Toggle Shrink">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout10" android:label="Views/Layouts/TableLayout/10. Simple Form">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout11" android:label="Views/Layouts/TableLayout/11. Gravity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TableLayout12" android:label="Views/Layouts/TableLayout/12. Cell Spanning">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Tabs1" android:label="Views/Tabs/Content By Id">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.SAMPLE_CODE"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Tabs2" android:label="Views/Tabs/Content By Factory">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.SAMPLE_CODE"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Tabs3" android:label="Views/Tabs/Content By Intent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.SAMPLE_CODE"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Baseline1" android:label="Views/Layouts/Baseline/1. Top">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Baseline2" android:label="Views/Layouts/Baseline/2. Bottom">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Baseline3" android:label="Views/Layouts/Baseline/3. Center">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Baseline4" android:label="Views/Layouts/Baseline/4. Everywhere">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Baseline6" android:label="Views/Layouts/Baseline/5. Multi-line">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Baseline7" android:label="Views/Layouts/Baseline/6. Relative">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.BaselineNested1" android:label="Views/Layouts/Baseline/Nested Example 1">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.BaselineNested2" android:label="Views/Layouts/Baseline/Nested Example 2">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.BaselineNested3" android:label="Views/Layouts/Baseline/Nested Example 3">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ScrollBar1" android:label="Views/ScrollBars/1. Basic">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ScrollBar2" android:label="Views/ScrollBars/2. Fancy">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ScrollBar3" android:label="Views/ScrollBars/3. Style">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Visibility1" android:label="Views/Visibility">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List1" android:label="Views/Lists/1. Array">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List2" android:label="Views/Lists/2. Cursor (People)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List3" android:label="Views/Lists/3. Cursor (Phones)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List4" android:label="Views/Lists/4. ListAdapter">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List5" android:label="Views/Lists/5. Separators">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List6" android:label="Views/Lists/6. ListAdapter Collapsed">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List7" android:label="Views/Lists/7. Cursor (Phones)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List8" android:label="Views/Lists/8. Photos">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List9" android:label="Views/Lists/9. Array (Overlay)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List10" android:label="Views/Lists/10. Single choice list">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List11" android:label="Views/Lists/11. Multiple choice list">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List12" android:label="Views/Lists/12. Transcript">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List13" android:label="Views/Lists/13. Slow Adapter">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.List14" android:label="Views/Lists/14. Efficient Adapter">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ExpandableList1" android:label="Views/Expandable Lists/1. Custom Adapter">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ExpandableList2" android:label="Views/Expandable Lists/2. Cursor (People)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ExpandableList3" android:label="Views/Expandable Lists/3. Simple Adapter">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.CustomView1"
+ android:label="Views/Custom"
+ android:theme="@android:style/Theme.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Gallery1" android:label="Views/Gallery/1. Photos">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Gallery2" android:label="Views/Gallery/2. People">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Spinner1" android:label="Views/Spinner">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Grid1" android:label="Views/Grid/1. Icon Grid">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Grid2" android:label="Views/Grid/2. Photo Grid">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ImageView1"
+ android:label="Views/ImageView">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ImageSwitcher1"
+ android:label="Views/ImageSwitcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.TextSwitcher1"
+ android:label="Views/TextSwitcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ImageButton1"
+ android:label="Views/ImageButton">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Animation1" android:label="Views/Animation/Shake">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Animation2" android:label="Views/Animation/Push">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LayoutAnimation1" android:label="Views/Layout Animation/1. Grid Fade">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LayoutAnimation2" android:label="Views/Layout Animation/2. List Cascade">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LayoutAnimation3" android:label="Views/Layout Animation/3. Reverse Order">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LayoutAnimation4" android:label="Views/Layout Animation/4. Randomize">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LayoutAnimation5" android:label="Views/Layout Animation/5. Grid Direction">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LayoutAnimation6" android:label="Views/Layout Animation/6. Wave Scale">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.LayoutAnimation7" android:label="Views/Layout Animation/7. Nested Animations">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Controls1"
+ android:label="Views/Controls/1. Light Theme"
+ android:theme="@android:style/Theme.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Controls2" android:label="Views/Controls/2. Default Theme">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Buttons1"
+ android:label="Views/Buttons">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.AutoComplete1" android:label="Views/Auto Complete/1. Screen Top">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.AutoComplete2" android:label="Views/Auto Complete/2. Screen Bottom">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.AutoComplete3" android:label="Views/Auto Complete/3. Scroll">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.AutoComplete4" android:label="Views/Auto Complete/4. Contacts">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.AutoComplete5" android:label="Views/Auto Complete/5. Contacts with Hint">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.AutoComplete6" android:label="Views/Auto Complete/6. Multiple items">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ProgressBar1" android:label="Views/Progress Bar/1. Incremental">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ProgressBar2" android:label="Views/Progress Bar/2. Smooth">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ProgressBar3" android:label="Views/Progress Bar/3. Dialogs">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.ProgressBar4" android:label="Views/Progress Bar/4. In Title Bar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.SeekBar1" android:label="Views/Seek Bar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.RatingBar1" android:label="Views/Rating Bar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Focus1" android:label="Views/Focus/1. Vertical">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Focus2" android:label="Views/Focus/2. Horizontal">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.Focus3" android:label="Views/Focus/3. Circular">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.InternalSelectionFocus" android:label="Views/Focus/4. Internal Selection">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.DateWidgets1" android:label="Views/Date Widgets/1. Dialog">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.DateWidgets2" android:label="Views/Date Widgets/2. Inline">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.MapViewDemo" android:label="Views/MapView">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".view.MapViewCompassDemo" android:label="Views/MapView and Compass">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- GRAPHICS SAMPLES -->
+ <!-- ************************************* -->
+
+ <activity android:name=".graphics.kube.Kube" android:label="Graphics/OpenGL ES/Kube"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Compass" android:label="Graphics/Compass">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.CameraPreview" android:label="Graphics/CameraPreview" android:screenOrientation="landscape">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.GLSurfaceViewActivity"
+ android:label="Graphics/OpenGL ES/GLSurfaceView"
+ android:theme="@android:style/Theme.NoTitleBar"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.TranslucentGLSurfaceViewActivity"
+ android:label="Graphics/OpenGL ES/Translucent GLSurfaceView"
+ android:theme="@style/Theme.Translucent"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.TriangleActivity"
+ android:label="Graphics/OpenGL ES/Textured Triangle"
+ android:theme="@android:style/Theme.NoTitleBar"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.spritetext.SpriteTextActivity"
+ android:label="Graphics/OpenGL ES/Sprite Text"
+ android:theme="@android:style/Theme.NoTitleBar"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.TouchRotateActivity"
+ android:label="Graphics/OpenGL ES/Touch Rotate"
+ android:theme="@android:style/Theme.NoTitleBar"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.PolyToPoly" android:label="Graphics/PolyToPoly">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.ScaleToFit" android:label="Graphics/ScaleToFit">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.RoundRects" android:label="Graphics/RoundRects">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.ShapeDrawable1" android:label="Graphics/Drawable/ShapeDrawable">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.SurfaceViewOverlay"
+ android:label="Graphics/SurfaceView Overlay">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.TextAlign" android:label="Graphics/Text Align">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Arcs" android:label="Graphics/Arcs">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Patterns" android:label="Graphics/Patterns">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Clipping" android:label="Graphics/Clipping">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Layers" android:label="Graphics/Layers">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.UnicodeChart" android:label="Graphics/UnicodeChart">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.PathFillTypes" android:label="Graphics/PathFillTypes">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Pictures" android:label="Graphics/Pictures">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Vertices" android:label="Graphics/Vertices">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.AnimateDrawables" android:label="Graphics/AnimateDrawables">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.SensorTest" android:label="Graphics/SensorTest">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.AlphaBitmap" android:label="Graphics/AlphaBitmap">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Regions" android:label="Graphics/Regions">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Sweep" android:label="Graphics/Sweep">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.BitmapMesh" android:label="Graphics/BitmapMesh">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.MeasureText" android:label="Graphics/MeasureText">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Typefaces" android:label="Graphics/Typefaces">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.FingerPaint" android:label="Graphics/FingerPaint">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.ColorMatrixSample" android:label="Graphics/ColorMatrix">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.BitmapDecode" android:label="Graphics/BitmapDecode">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.CreateBitmap" android:label="Graphics/CreateBitmap">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.DrawPoints" android:label="Graphics/Points">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.TouchPaint" android:label="Graphics/Touch Paint"
+ android:theme="@style/Theme.Black"
+ android:configChanges="keyboard|keyboardHidden|navigation|orientation">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.BitmapPixels" android:label="Graphics/BitmapPixels">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.Xfermodes" android:label="Graphics/Xfermodes">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.PathEffects" android:label="Graphics/PathEffects">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".graphics.GradientDrawable1" android:label="Graphics/Drawable/GradientDrawable">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- MEDIA SAMPLES -->
+ <!-- ************************************* -->
+
+ <activity android:name=".media.MediaPlayerDemo" android:label="Media/MediaPlayer">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".media.MediaPlayerDemo_Audio" android:label="Media/MediaPlayer">
+ <intent-filter>
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".media.MediaPlayerDemo_Video" android:label="Media/MediaPlayer">
+ <intent-filter>
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".media.VideoViewDemo" android:label="Media/VideoView">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <!-- ************************************* -->
+ <!-- GADGET PACKAGE SAMPLES -->
+ <!-- ************************************* -->
+
+ <receiver android:name=".gadget.ExampleGadgetProvider">
+ <meta-data android:name="android.gadget.provider"
+ android:resource="@xml/gadget_provider" />
+ <intent-filter>
+ <action android:name="android.gadget.action.GADGET_UPDATE" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name=".gadget.ExampleBroadcastReceiver" android:enabled="false">
+ <intent-filter>
+ <action android:name="android.intent.ACTION_TIMEZONE_CHANGED" />
+ <action android:name="android.intent.ACTION_TIME" />
+ </intent-filter>
+ </receiver>
+
+ <!-- ************************************* -->
+ <!-- OTHER SAMPLES -->
+ <!-- ************************************* -->
+
+ <activity android:name=".text.Link" android:label="Text/Linkify">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".text.Marquee" android:label="Text/Marquee">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".text.LogTextBox1" android:label="Text/LogTextBox">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
+ </application>
+
+ <instrumentation android:name=".app.LocalSampleInstrumentation"
+ android:targetPackage="com.example.android.apis"
+ android:label="Local Sample" />
+
+</manifest>
diff --git a/samples/ApiDemos/_index.html b/samples/ApiDemos/_index.html
new file mode 100755
index 0000000..b0d1c7b
--- /dev/null
+++ b/samples/ApiDemos/_index.html
@@ -0,0 +1,19 @@
+<p>The API Demos include sample code for many aspects of the Android APIs, from screen layout to Intent resolution.
+</p>
+
+<dl>
+ <dt><a href="src/com/example/android/apis/app/index.html">App</a></dt>
+ <dd></dd>
+
+ <dt><a href="src/com/example/android/apis/content/index.html">Content</a></dt>
+ <dd></dd>
+
+ <dt><a href="src/com/example/android/apis/view/index.html">View</a></dt>
+ <dd></dd>
+
+ <dt><a href="src/com/example/android/apis/graphics/index.html">Graphics</a></dt>
+ <dd></dd>
+
+ <dt><a href="src/com/example/android/apis/text/index.html">Text</a></dt>
+ <dd></dd>
+</dl>
diff --git a/samples/ApiDemos/assets/fonts/samplefont.ttf b/samples/ApiDemos/assets/fonts/samplefont.ttf
new file mode 100644
index 0000000..49f1c62
--- /dev/null
+++ b/samples/ApiDemos/assets/fonts/samplefont.ttf
Binary files differ
diff --git a/samples/ApiDemos/assets/read_asset.txt b/samples/ApiDemos/assets/read_asset.txt
new file mode 100644
index 0000000..ff9c023
--- /dev/null
+++ b/samples/ApiDemos/assets/read_asset.txt
@@ -0,0 +1,3 @@
+This text is stored in a raw Asset.
+
+It was read and placed into the TextView here.
diff --git a/samples/ApiDemos/res/anim/cycle_7.xml b/samples/ApiDemos/res/anim/cycle_7.xml
new file mode 100644
index 0000000..02fb699
--- /dev/null
+++ b/samples/ApiDemos/res/anim/cycle_7.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="7" />
diff --git a/samples/ApiDemos/res/anim/fade.xml b/samples/ApiDemos/res/anim/fade.xml
new file mode 100644
index 0000000..78b193d
--- /dev/null
+++ b/samples/ApiDemos/res/anim/fade.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="100" />
diff --git a/samples/ApiDemos/res/anim/hyperspace_in.xml b/samples/ApiDemos/res/anim/hyperspace_in.xml
new file mode 100644
index 0000000..8d0cc56
--- /dev/null
+++ b/samples/ApiDemos/res/anim/hyperspace_in.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" android:startOffset="1200" />
diff --git a/samples/ApiDemos/res/anim/hyperspace_out.xml b/samples/ApiDemos/res/anim/hyperspace_out.xml
new file mode 100644
index 0000000..83fef33
--- /dev/null
+++ b/samples/ApiDemos/res/anim/hyperspace_out.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
+
+ <scale
+ android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+ android:fromXScale="1.0"
+ android:toXScale="1.4"
+ android:fromYScale="1.0"
+ android:toYScale="0.6"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillAfter="false"
+ android:duration="700" />
+
+
+ <set
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:startOffset="700">
+
+ <scale
+ android:fromXScale="1.4"
+ android:toXScale="0.0"
+ android:fromYScale="0.6"
+ android:toYScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:duration="400" />
+
+ <rotate
+ android:fromDegrees="0"
+ android:toDegrees="-45"
+ android:toYScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:duration="400" />
+ </set>
+
+</set>
+
diff --git a/samples/ApiDemos/res/anim/layout_animation_row_left_slide.xml b/samples/ApiDemos/res/anim/layout_animation_row_left_slide.xml
new file mode 100644
index 0000000..9c6a459
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_animation_row_left_slide.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:delay="10%"
+ android:animation="@anim/slide_left" />
diff --git a/samples/ApiDemos/res/anim/layout_animation_row_right_slide.xml b/samples/ApiDemos/res/anim/layout_animation_row_right_slide.xml
new file mode 100644
index 0000000..156f09a
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_animation_row_right_slide.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:delay="10%"
+ android:animationOrder="reverse"
+ android:animation="@anim/slide_right" />
diff --git a/samples/ApiDemos/res/anim/layout_animation_table.xml b/samples/ApiDemos/res/anim/layout_animation_table.xml
new file mode 100644
index 0000000..efebe84
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_animation_table.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:delay="50%"
+ android:animation="@anim/slide_top_to_bottom" />
diff --git a/samples/ApiDemos/res/anim/layout_bottom_to_top_slide.xml b/samples/ApiDemos/res/anim/layout_bottom_to_top_slide.xml
new file mode 100644
index 0000000..e7cb4bd
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_bottom_to_top_slide.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:delay="30%"
+ android:animationOrder="reverse"
+ android:animation="@anim/slide_right" />
diff --git a/samples/ApiDemos/res/anim/layout_grid_fade.xml b/samples/ApiDemos/res/anim/layout_grid_fade.xml
new file mode 100644
index 0000000..00d3584
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_grid_fade.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:rowDelay="50%"
+ android:directionPriority="column"
+ android:animation="@anim/fade" />
diff --git a/samples/ApiDemos/res/anim/layout_grid_inverse_fade.xml b/samples/ApiDemos/res/anim/layout_grid_inverse_fade.xml
new file mode 100644
index 0000000..0a68437
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_grid_inverse_fade.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:columnDelay="0.5"
+ android:directionPriority="row"
+ android:direction="right_to_left|bottom_to_top"
+ android:animation="@anim/fade" />
diff --git a/samples/ApiDemos/res/anim/layout_random_fade.xml b/samples/ApiDemos/res/anim/layout_random_fade.xml
new file mode 100644
index 0000000..0034676
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_random_fade.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:delay="0.5"
+ android:animationOrder="random"
+ android:animation="@anim/fade" />
diff --git a/samples/ApiDemos/res/anim/layout_wave_scale.xml b/samples/ApiDemos/res/anim/layout_wave_scale.xml
new file mode 100644
index 0000000..2cdd19d
--- /dev/null
+++ b/samples/ApiDemos/res/anim/layout_wave_scale.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:rowDelay="75%"
+ android:columnDelay="0%"
+ android:directionPriority="none"
+ android:animation="@anim/wave_scale" />
diff --git a/samples/ApiDemos/res/anim/push_left_in.xml b/samples/ApiDemos/res/anim/push_left_in.xml
new file mode 100644
index 0000000..894d222
--- /dev/null
+++ b/samples/ApiDemos/res/anim/push_left_in.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="300"/>
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
+</set>
diff --git a/samples/ApiDemos/res/anim/push_left_out.xml b/samples/ApiDemos/res/anim/push_left_out.xml
new file mode 100644
index 0000000..28802d2
--- /dev/null
+++ b/samples/ApiDemos/res/anim/push_left_out.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="300"/>
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="300" />
+</set>
diff --git a/samples/ApiDemos/res/anim/push_up_in.xml b/samples/ApiDemos/res/anim/push_up_in.xml
new file mode 100644
index 0000000..a2f47e9
--- /dev/null
+++ b/samples/ApiDemos/res/anim/push_up_in.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromYDelta="100%p" android:toYDelta="0" android:duration="300"/>
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
+</set>
diff --git a/samples/ApiDemos/res/anim/push_up_out.xml b/samples/ApiDemos/res/anim/push_up_out.xml
new file mode 100644
index 0000000..2803435
--- /dev/null
+++ b/samples/ApiDemos/res/anim/push_up_out.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromYDelta="0" android:toYDelta="-100%p" android:duration="300"/>
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="300" />
+</set>
diff --git a/samples/ApiDemos/res/anim/shake.xml b/samples/ApiDemos/res/anim/shake.xml
new file mode 100644
index 0000000..80eb451
--- /dev/null
+++ b/samples/ApiDemos/res/anim/shake.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0" android:toXDelta="10" android:duration="1000" android:interpolator="@anim/cycle_7" />
diff --git a/samples/ApiDemos/res/anim/slide_left.xml b/samples/ApiDemos/res/anim/slide_left.xml
new file mode 100644
index 0000000..8760491
--- /dev/null
+++ b/samples/ApiDemos/res/anim/slide_left.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator">
+ <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="150" />
+</set>
diff --git a/samples/ApiDemos/res/anim/slide_right.xml b/samples/ApiDemos/res/anim/slide_right.xml
new file mode 100644
index 0000000..7aaacdb
--- /dev/null
+++ b/samples/ApiDemos/res/anim/slide_right.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator">
+ <translate android:fromXDelta="-100%p" android:toXDelta="0" android:duration="150" />
+</set>
diff --git a/samples/ApiDemos/res/anim/slide_top_to_bottom.xml b/samples/ApiDemos/res/anim/slide_top_to_bottom.xml
new file mode 100644
index 0000000..a548181
--- /dev/null
+++ b/samples/ApiDemos/res/anim/slide_top_to_bottom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator">
+ <translate android:fromYDelta="-100%" android:toXDelta="0" android:duration="100" />
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="50" />
+</set>
diff --git a/samples/ApiDemos/res/anim/wave_scale.xml b/samples/ApiDemos/res/anim/wave_scale.xml
new file mode 100644
index 0000000..ea4eaf2
--- /dev/null
+++ b/samples/ApiDemos/res/anim/wave_scale.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator">
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:duration="100" />
+ <scale
+ android:fromXScale="0.5" android:toXScale="1.5"
+ android:fromYScale="0.5" android:toYScale="1.5"
+ android:pivotX="50%" android:pivotY="50%"
+ android:duration="200" />
+ <scale
+ android:fromXScale="1.5" android:toXScale="1.0"
+ android:fromYScale="1.5" android:toYScale="1.0"
+ android:pivotX="50%" android:pivotY="50%"
+ android:startOffset="200"
+ android:duration="100" />
+</set>
diff --git a/samples/ApiDemos/res/drawable/alert_dialog_icon.png b/samples/ApiDemos/res/drawable/alert_dialog_icon.png
new file mode 100644
index 0000000..0a7de04
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/alert_dialog_icon.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/animated_gif.gif b/samples/ApiDemos/res/drawable/animated_gif.gif
new file mode 100644
index 0000000..51baf15
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/animated_gif.gif
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/app_sample_code.png b/samples/ApiDemos/res/drawable/app_sample_code.png
new file mode 100644
index 0000000..5ae7701
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/app_sample_code.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/arrow_down_float.png b/samples/ApiDemos/res/drawable/arrow_down_float.png
new file mode 100644
index 0000000..bfe0ce6
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/arrow_down_float.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/arrow_up_float.png b/samples/ApiDemos/res/drawable/arrow_up_float.png
new file mode 100644
index 0000000..77673ef
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/arrow_up_float.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/balloons.jpg b/samples/ApiDemos/res/drawable/balloons.jpg
new file mode 100644
index 0000000..6a90b92
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/balloons.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/beach.jpg b/samples/ApiDemos/res/drawable/beach.jpg
new file mode 100644
index 0000000..ae9794f
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/beach.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/black_box.xml b/samples/ApiDemos/res/drawable/black_box.xml
new file mode 100644
index 0000000..7772d56
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/black_box.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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">
+ <solid android:color="#1e000000"/>
+ <padding android:left="1dp" android:top="1dp"
+ android:right="1dp" android:bottom="1dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/black_opaque_box.xml b/samples/ApiDemos/res/drawable/black_opaque_box.xml
new file mode 100644
index 0000000..ba43f01
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/black_opaque_box.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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">
+ <solid android:color="#56000000"/>
+ <padding android:left="1dp" android:top="1dp"
+ android:right="1dp" android:bottom="1dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/box.xml b/samples/ApiDemos/res/drawable/box.xml
new file mode 100644
index 0000000..825de84
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/box.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2007, 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">
+ <solid android:color="#00000000"/>
+ <stroke android:width="1dp" color="#ff000000"/>
+ <padding android:left="1dp" android:top="1dp"
+ android:right="1dp" android:bottom="1dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/button.9.png b/samples/ApiDemos/res/drawable/button.9.png
new file mode 100644
index 0000000..f6da7e5
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/button.9.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/circular_progress.xml b/samples/ApiDemos/res/drawable/circular_progress.xml
new file mode 100644
index 0000000..1d76f57
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/circular_progress.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:drawable="@drawable/progress_circular_background" />
+
+ <item><rotate
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fromDegrees="0"
+ android:toDegrees="360"
+ android:drawable="@drawable/progress_particle" />
+ </item>
+</layer-list>
+
diff --git a/samples/ApiDemos/res/drawable/filled_box.xml b/samples/ApiDemos/res/drawable/filled_box.xml
new file mode 100644
index 0000000..75d15a0
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/filled_box.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2007, 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">
+ <solid android:color="#f0600000"/>
+ <stroke android:width="3dp" color="#ffff8080"/>
+ <corners android:radius="3dp" />
+ <padding android:left="10dp" android:top="10dp"
+ android:right="10dp" android:bottom="10dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/frog.gif b/samples/ApiDemos/res/drawable/frog.gif
new file mode 100644
index 0000000..9c20748
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/frog.gif
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_background_1.xml b/samples/ApiDemos/res/drawable/gallery_background_1.xml
new file mode 100644
index 0000000..a82794e
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_background_1.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:drawable="@drawable/black_opaque_box" />
+ <item android:drawable="@drawable/black_box" />
+</selector>
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_1.jpg b/samples/ApiDemos/res/drawable/gallery_photo_1.jpg
new file mode 100644
index 0000000..a2581fe
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_1.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_2.jpg b/samples/ApiDemos/res/drawable/gallery_photo_2.jpg
new file mode 100644
index 0000000..82ba3a8
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_2.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_3.jpg b/samples/ApiDemos/res/drawable/gallery_photo_3.jpg
new file mode 100644
index 0000000..2a83021
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_3.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_4.jpg b/samples/ApiDemos/res/drawable/gallery_photo_4.jpg
new file mode 100644
index 0000000..70a1c55
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_4.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_5.jpg b/samples/ApiDemos/res/drawable/gallery_photo_5.jpg
new file mode 100644
index 0000000..dc3f677
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_5.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_6.jpg b/samples/ApiDemos/res/drawable/gallery_photo_6.jpg
new file mode 100644
index 0000000..2e113a0
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_6.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_7.jpg b/samples/ApiDemos/res/drawable/gallery_photo_7.jpg
new file mode 100644
index 0000000..bc30297
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_7.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/gallery_photo_8.jpg b/samples/ApiDemos/res/drawable/gallery_photo_8.jpg
new file mode 100644
index 0000000..dc3aa85
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/gallery_photo_8.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/ic_popup_reminder.png b/samples/ApiDemos/res/drawable/ic_popup_reminder.png
new file mode 100755
index 0000000..4f2b82c
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/ic_popup_reminder.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/icon48x48_1.png b/samples/ApiDemos/res/drawable/icon48x48_1.png
new file mode 100644
index 0000000..d3b8125
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/icon48x48_1.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/icon48x48_2.png b/samples/ApiDemos/res/drawable/icon48x48_2.png
new file mode 100755
index 0000000..84af2a2
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/icon48x48_2.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/line.xml b/samples/ApiDemos/res/drawable/line.xml
new file mode 100644
index 0000000..b3707ff
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/line.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="line">
+ <stroke android:width="1dp" android:color="#FF000000"
+ android:dashWidth="1dp" android:dashGap="2dp" />
+ <size android:height="5dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/photo1.jpg b/samples/ApiDemos/res/drawable/photo1.jpg
new file mode 100644
index 0000000..825682b
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/photo1.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/photo2.jpg b/samples/ApiDemos/res/drawable/photo2.jpg
new file mode 100644
index 0000000..a1c8b55
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/photo2.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/photo3.jpg b/samples/ApiDemos/res/drawable/photo3.jpg
new file mode 100644
index 0000000..44b671e
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/photo3.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/photo4.jpg b/samples/ApiDemos/res/drawable/photo4.jpg
new file mode 100644
index 0000000..2483bb9
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/photo4.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/photo5.jpg b/samples/ApiDemos/res/drawable/photo5.jpg
new file mode 100644
index 0000000..250b085
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/photo5.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/photo6.jpg b/samples/ApiDemos/res/drawable/photo6.jpg
new file mode 100644
index 0000000..6c3c956
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/photo6.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/picture_frame.png b/samples/ApiDemos/res/drawable/picture_frame.png
new file mode 100644
index 0000000..ba71570
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/picture_frame.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/progress_circular_background.png b/samples/ApiDemos/res/drawable/progress_circular_background.png
new file mode 100644
index 0000000..7c637fd
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/progress_circular_background.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/progress_particle.png b/samples/ApiDemos/res/drawable/progress_particle.png
new file mode 100644
index 0000000..9160108
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/progress_particle.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/robot.png b/samples/ApiDemos/res/drawable/robot.png
new file mode 100644
index 0000000..8a9e698
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/robot.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_0.jpg b/samples/ApiDemos/res/drawable/sample_0.jpg
new file mode 100644
index 0000000..9dd3bce
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_0.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_1.jpg b/samples/ApiDemos/res/drawable/sample_1.jpg
new file mode 100644
index 0000000..46d06e0
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_1.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_2.jpg b/samples/ApiDemos/res/drawable/sample_2.jpg
new file mode 100644
index 0000000..c23dd63
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_2.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_3.jpg b/samples/ApiDemos/res/drawable/sample_3.jpg
new file mode 100644
index 0000000..0f0d5b5
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_3.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_4.jpg b/samples/ApiDemos/res/drawable/sample_4.jpg
new file mode 100644
index 0000000..d28ce6f
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_4.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_5.jpg b/samples/ApiDemos/res/drawable/sample_5.jpg
new file mode 100644
index 0000000..2348c7d
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_5.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_6.jpg b/samples/ApiDemos/res/drawable/sample_6.jpg
new file mode 100644
index 0000000..a35fc0c
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_6.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_7.jpg b/samples/ApiDemos/res/drawable/sample_7.jpg
new file mode 100644
index 0000000..96a4879
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_7.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_0.jpg b/samples/ApiDemos/res/drawable/sample_thumb_0.jpg
new file mode 100644
index 0000000..5b641e8
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_0.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_1.jpg b/samples/ApiDemos/res/drawable/sample_thumb_1.jpg
new file mode 100644
index 0000000..630c3c5
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_1.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_2.jpg b/samples/ApiDemos/res/drawable/sample_thumb_2.jpg
new file mode 100644
index 0000000..fad840a
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_2.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_3.jpg b/samples/ApiDemos/res/drawable/sample_thumb_3.jpg
new file mode 100644
index 0000000..27e0359
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_3.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_4.jpg b/samples/ApiDemos/res/drawable/sample_thumb_4.jpg
new file mode 100644
index 0000000..4934f02
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_4.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_5.jpg b/samples/ApiDemos/res/drawable/sample_thumb_5.jpg
new file mode 100644
index 0000000..c9c7380
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_5.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_6.jpg b/samples/ApiDemos/res/drawable/sample_thumb_6.jpg
new file mode 100644
index 0000000..0e2f3e4
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_6.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/sample_thumb_7.jpg b/samples/ApiDemos/res/drawable/sample_thumb_7.jpg
new file mode 100644
index 0000000..bf82c5d
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/sample_thumb_7.jpg
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/scrollbar_state2.png b/samples/ApiDemos/res/drawable/scrollbar_state2.png
new file mode 100755
index 0000000..012f737
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/scrollbar_state2.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/scrollbar_vertical_thumb.xml b/samples/ApiDemos/res/drawable/scrollbar_vertical_thumb.xml
new file mode 100644
index 0000000..4d80454
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/scrollbar_vertical_thumb.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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">
+ <gradient android:startColor="#3333FF" android:endColor="#8080FF"
+ android:angle="0"/>
+ <corners android:radius="6dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/scrollbar_vertical_track.xml b/samples/ApiDemos/res/drawable/scrollbar_vertical_track.xml
new file mode 100644
index 0000000..b3ad842
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/scrollbar_vertical_track.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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">
+ <gradient android:startColor="#505050" android:endColor="#C0C0C0"
+ android:angle="0"/>
+ <corners android:radius="0dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/shape_1.xml b/samples/ApiDemos/res/drawable/shape_1.xml
new file mode 100644
index 0000000..ea30bcf
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/shape_1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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">
+ <solid android:color="#00000000"/>
+ <stroke android:width="2dp" android:color="#ff000000"/>
+ <padding android:left="1dp" android:top="1dp"
+ android:right="1dp" android:bottom="1dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/shape_2.xml b/samples/ApiDemos/res/drawable/shape_2.xml
new file mode 100644
index 0000000..23bcb36
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/shape_2.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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">
+ <solid android:color="#FF0000FF"/>
+ <stroke android:width="4dp" android:color="#FFFFFFFF"
+ android:dashWidth="1dp" android:dashGap="2dp" />
+ <padding android:left="7dp" android:top="7dp"
+ android:right="7dp" android:bottom="7dp" />
+ <corners android:radius="4dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/shape_3.xml b/samples/ApiDemos/res/drawable/shape_3.xml
new file mode 100644
index 0000000..6822037
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/shape_3.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="oval">
+ <solid android:color="#00000000"/>
+ <stroke android:width="4dp" android:color="#99000000"
+ android:dashWidth="4dp" android:dashGap="2dp" />
+ <padding android:left="7dp" android:top="7dp"
+ android:right="7dp" android:bottom="7dp" />
+ <corners android:radius="4dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/shape_4.xml b/samples/ApiDemos/res/drawable/shape_4.xml
new file mode 100644
index 0000000..0deb0d1
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/shape_4.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="line">
+ <stroke android:width="1dp" android:color="#FF000000"
+ android:dashWidth="1dp" android:dashGap="2dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/shape_5.xml b/samples/ApiDemos/res/drawable/shape_5.xml
new file mode 100644
index 0000000..edd1d6f
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/shape_5.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="#FFFF0000" android:endColor="#80FF00FF"
+ android:angle="270"/>
+ <padding android:left="7dp" android:top="7dp"
+ android:right="7dp" android:bottom="7dp" />
+ <corners android:radius="8dp" />
+</shape>
diff --git a/samples/ApiDemos/res/drawable/star_big_on.png b/samples/ApiDemos/res/drawable/star_big_on.png
new file mode 100644
index 0000000..510c8b2
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/star_big_on.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/stat_happy.png b/samples/ApiDemos/res/drawable/stat_happy.png
new file mode 100644
index 0000000..3a8791b
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/stat_happy.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/stat_neutral.png b/samples/ApiDemos/res/drawable/stat_neutral.png
new file mode 100644
index 0000000..1dc0594
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/stat_neutral.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/stat_sad.png b/samples/ApiDemos/res/drawable/stat_sad.png
new file mode 100644
index 0000000..17d26de
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/stat_sad.png
Binary files differ
diff --git a/samples/ApiDemos/res/drawable/stat_sample.png b/samples/ApiDemos/res/drawable/stat_sample.png
new file mode 100644
index 0000000..1733042
--- /dev/null
+++ b/samples/ApiDemos/res/drawable/stat_sample.png
Binary files differ
diff --git a/samples/ApiDemos/res/layout/alarm_controller.xml b/samples/ApiDemos/res/layout/alarm_controller.xml
new file mode 100644
index 0000000..9ce4d72
--- /dev/null
+++ b/samples/ApiDemos/res/layout/alarm_controller.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/alarm_controller"/>
+
+ <Button android:id="@+id/one_shot"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/one_shot_alarm">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/start_repeating"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start_repeating_alarm" />
+
+ <Button android:id="@+id/stop_repeating"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/stop_repeating_alarm" />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/alarm_service.xml b/samples/ApiDemos/res/layout/alarm_service.xml
new file mode 100644
index 0000000..e24369c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/alarm_service.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/alarm_service"/>
+
+ <Button android:id="@+id/start_alarm"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start_alarm_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/stop_alarm"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/stop_alarm_service" />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/alert_dialog.xml b/samples/ApiDemos/res/layout/alert_dialog.xml
new file mode 100644
index 0000000..ddd5cb6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/alert_dialog.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates different uses of the android.app.AlertDialog.
+ See corresponding Java code com.example.android.apis.app.AlertDialogSamples.java. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/screen"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <Button android:id="@+id/two_buttons"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/alert_dialog_two_buttons"/>
+ <Button android:id="@+id/two_buttons2"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/alert_dialog_two_buttons2"/>
+ <Button android:id="@+id/select_button"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/alert_dialog_select_button"/>
+ <Button android:id="@+id/progress_button"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/alert_dialog_progress_button"/>
+ <Button android:id="@+id/radio_button"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/alert_dialog_single_choice"/>
+ <Button android:id="@+id/checkbox_button"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/alert_dialog_multi_choice"/>
+ <Button android:id="@+id/text_entry_button"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/alert_dialog_text_entry"/>
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/alert_dialog_text_entry.xml b/samples/ApiDemos/res/layout/alert_dialog_text_entry.xml
new file mode 100644
index 0000000..adec305
--- /dev/null
+++ b/samples/ApiDemos/res/layout/alert_dialog_text_entry.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/username_view"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:text="@string/alert_dialog_username"
+ android:gravity="left"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <EditText
+ android:id="@+id/username_edit"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:scrollHorizontally="true"
+ android:autoText="false"
+ android:capitalize="none"
+ android:gravity="fill_horizontal"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/password_view"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:text="@string/alert_dialog_password"
+ android:gravity="left"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <EditText
+ android:id="@+id/password_edit"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:scrollHorizontally="true"
+ android:autoText="false"
+ android:capitalize="none"
+ android:gravity="fill_horizontal"
+ android:password="true"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/animation_1.xml b/samples/ApiDemos/res/layout/animation_1.xml
new file mode 100644
index 0000000..cd25e04
--- /dev/null
+++ b/samples/ApiDemos/res/layout/animation_1.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:padding="10dip"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dip"
+ android:text="@string/animation_1_instructions"
+ />
+
+ <EditText android:id="@+id/pw"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:singleLine="true"
+ android:password="true"
+ />
+
+ <Button android:id="@+id/login"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/googlelogin_login"
+ />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/animation_2.xml b/samples/ApiDemos/res/layout/animation_2.xml
new file mode 100644
index 0000000..9f37920
--- /dev/null
+++ b/samples/ApiDemos/res/layout/animation_2.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:padding="10dip"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ViewFlipper android:id="@+id/flipper"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:flipInterval="2000"
+ android:layout_marginBottom="20dip" >
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textSize="26sp"
+ android:text="@string/animation_2_text_1"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textSize="26sp"
+ android:text="@string/animation_2_text_2"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textSize="26sp"
+ android:text="@string/animation_2_text_3"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textSize="26sp"
+ android:text="@string/animation_2_text_4"/>
+ </ViewFlipper>
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="5dip"
+ android:text="@string/animation_2_instructions"
+ />
+
+ <Spinner android:id="@+id/spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/animations_main_screen.xml b/samples/ApiDemos/res/layout/animations_main_screen.xml
new file mode 100644
index 0000000..ee9e339
--- /dev/null
+++ b/samples/ApiDemos/res/layout/animations_main_screen.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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:id="@+id/container"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ListView
+ android:id="@android:id/list"
+ android:persistentDrawingCache="animation|scrolling"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutAnimation="@anim/layout_bottom_to_top_slide" />
+
+ <ImageView
+ android:id="@+id/picture"
+ android:scaleType="fitCenter"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:visibility="gone" />
+
+</FrameLayout>
diff --git a/samples/ApiDemos/res/layout/autocomplete_1.xml b/samples/ApiDemos/res/layout/autocomplete_1.xml
new file mode 100644
index 0000000..3c41926
--- /dev/null
+++ b/samples/ApiDemos/res/layout/autocomplete_1.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_1_instructions" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_1_country" />
+
+ <AutoCompleteTextView android:id="@+id/edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ </LinearLayout>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_1_focus" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/autocomplete_2.xml b/samples/ApiDemos/res/layout/autocomplete_2.xml
new file mode 100644
index 0000000..6d4ee75
--- /dev/null
+++ b/samples/ApiDemos/res/layout/autocomplete_2.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="bottom">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_2_focus" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_2_country" />
+
+ <AutoCompleteTextView android:id="@+id/edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/autocomplete_3.xml b/samples/ApiDemos/res/layout/autocomplete_3.xml
new file mode 100644
index 0000000..e97535a
--- /dev/null
+++ b/samples/ApiDemos/res/layout/autocomplete_3.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_1" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_2" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_3" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_4" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_5" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_6" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_7" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_8" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_1" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_2" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_3" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_4" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_5" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_6" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_7" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button_8" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_country" />
+
+ <AutoCompleteTextView android:id="@+id/edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_button" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_3_country" />
+
+ <AutoCompleteTextView android:id="@+id/edit2"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/autocomplete_4.xml b/samples/ApiDemos/res/layout/autocomplete_4.xml
new file mode 100644
index 0000000..97e5eb9
--- /dev/null
+++ b/samples/ApiDemos/res/layout/autocomplete_4.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_4_instructions" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_4_name" />
+
+ <AutoCompleteTextView android:id="@+id/edit"
+ android:completionThreshold="1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_4_message" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/autocomplete_5.xml b/samples/ApiDemos/res/layout/autocomplete_5.xml
new file mode 100644
index 0000000..34f68c6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/autocomplete_5.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_5_instructions" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_5_name" />
+
+ <AutoCompleteTextView android:id="@+id/edit"
+ android:completionThreshold="1"
+ android:completionHint="@string/autocomplete_5_hint"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/autocomplete_6.xml b/samples/ApiDemos/res/layout/autocomplete_6.xml
new file mode 100644
index 0000000..24fbda1
--- /dev/null
+++ b/samples/ApiDemos/res/layout/autocomplete_6.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_7_instructions" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_7_country" />
+
+ <MultiAutoCompleteTextView android:id="@+id/edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ </LinearLayout>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autocomplete_7_focus" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_1.xml b/samples/ApiDemos/res/layout/baseline_1.xml
new file mode 100644
index 0000000..0f1c9f6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_1.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:text="@string/baseline_1_label" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:text="@string/baseline_1_button" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:text="@string/baseline_1_bigger" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_2.xml b/samples/ApiDemos/res/layout/baseline_2.xml
new file mode 100644
index 0000000..8e323b6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="bottom"
+ android:text="@string/baseline_2_label" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="bottom"
+ android:text="@string/baseline_2_button" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:textSize="20sp"
+ android:text="@string/baseline_2_bigger" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_3.xml b/samples/ApiDemos/res/layout/baseline_3.xml
new file mode 100644
index 0000000..c251703
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_3.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/baseline_3_explanation" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_weight="1.0"
+ android:layout_height="0dip">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_3_label" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_3_button" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textSize="20sp"
+ android:text="@string/baseline_3_bigger" />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_4.xml b/samples/ApiDemos/res/layout/baseline_4.xml
new file mode 100644
index 0000000..5faa9da
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_4.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:text="@string/baseline_4_label" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_4_button" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:textSize="20sp"
+ android:text="@string/baseline_4_bigger" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:text="@string/baseline_4_label_2" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="bottom"
+ android:text="@string/baseline_4_label_3" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_6.xml b/samples/ApiDemos/res/layout/baseline_6.xml
new file mode 100644
index 0000000..5418afb
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_6.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <EditText android:id="@+id/anchor"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:textSize="20sp"
+ android:text="@string/baseline_6_multi_line" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@id/anchor"
+ android:layout_alignRight="@id/anchor"
+ android:text="@string/baseline_6_baseline" />
+
+</RelativeLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_7.xml b/samples/ApiDemos/res/layout/baseline_7.xml
new file mode 100644
index 0000000..2dc9439
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_7.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView android:id="@+id/anchor"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:textStyle="bold"
+ android:text="@string/baseline_7_fat" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignBaseline="@id/anchor"
+ android:layout_height="wrap_content"
+ android:text="@string/baseline_7_lean" />
+
+</RelativeLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_nested_1.xml b/samples/ApiDemos/res/layout/baseline_nested_1.xml
new file mode 100644
index 0000000..b940239
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_nested_1.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_nested_1_label" />
+
+ <!-- We want the middle textview of this vertical linear layout to
+ be baseline aligned with the others.-->
+ <LinearLayout
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dip"
+ android:text="@string/baseline_nested_1_label" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_down_float"/>
+ </LinearLayout>
+
+
+ <!-- We want the third index textview of this vertical linear layout to
+ be baseline aligned with the others.-->
+ <LinearLayout
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="2"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_height="wrap_content">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dip"
+ android:text="@string/baseline_nested_1_label" />
+ </LinearLayout>
+
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_nested_1_label" />
+
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_nested_2.xml b/samples/ApiDemos/res/layout/baseline_nested_2.xml
new file mode 100644
index 0000000..5bc8361
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_nested_2.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_nested_1_label" />
+
+ <!-- We want the middle textview of this vertical linear layout to
+ be baseline aligned with the others.-->
+ <LinearLayout
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dip"
+ android:text="@string/baseline_nested_1_label" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_down_float"/>
+ </LinearLayout>
+
+
+ <!-- We want the third index textview of this vertical linear layout to
+ be baseline aligned with the others.-->
+ <LinearLayout
+ android:orientation="horizontal"
+ android:baselineAlignedChildIndex="2"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_height="wrap_content">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dip"
+ android:text="@string/baseline_nested_1_label" />
+ </LinearLayout>
+
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_nested_1_label" />
+
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/baseline_nested_3.xml b/samples/ApiDemos/res/layout/baseline_nested_3.xml
new file mode 100644
index 0000000..c01c947
--- /dev/null
+++ b/samples/ApiDemos/res/layout/baseline_nested_3.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_nested_1_label" />
+
+ <!-- We want the middle textview of this vertical linear layout to
+ be baseline aligned with the others.-->
+ <LinearLayout
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dip"
+ android:text="@string/baseline_nested_1_label" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_down_float"/>
+ </LinearLayout>
+
+
+ <!-- We'll point to the linear layout to baseline align by, which
+ in turn will point to a text view inside of it -->
+ <LinearLayout
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="1"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_height="wrap_content">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <LinearLayout
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="2"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_height="wrap_content">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/arrow_up_float"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dip"
+ android:text="@string/baseline_nested_1_label"/>
+ </LinearLayout>
+ </LinearLayout>
+
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:layout_gravity="center_vertical"
+ android:text="@string/baseline_nested_1_label" />
+
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/buttons_1.xml b/samples/ApiDemos/res/layout/buttons_1.xml
new file mode 100644
index 0000000..dc657ef
--- /dev/null
+++ b/samples/ApiDemos/res/layout/buttons_1.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- Lots of buttons = need scrolling -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- Regular sized buttons -->
+ <Button android:id="@+id/button_normal"
+ android:text="@string/buttons_1_normal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- Small buttons -->
+ <Button android:id="@+id/button_small"
+ style="?android:attr/buttonStyleSmall"
+ android:text="@string/buttons_1_small"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ToggleButton android:id="@+id/button_toggle"
+ android:text="@string/buttons_1_toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/chronometer.xml b/samples/ApiDemos/res/layout/chronometer.xml
new file mode 100644
index 0000000..b38c2b6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/chronometer.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Chronometer android:id="@+id/chronometer"
+ android:format="@string/chronometer_initial_format"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="30dip"
+ android:paddingTop="30dip"
+ />
+
+ <Button android:id="@+id/start"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/chronometer_start">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/stop"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/chronometer_stop">
+ </Button>
+
+ <Button android:id="@+id/reset"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/chronometer_reset">
+ </Button>
+
+ <Button android:id="@+id/set_format"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/chronometer_set_format">
+ </Button>
+
+ <Button android:id="@+id/clear_format"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/chronometer_clear_format">
+ </Button>
+
+</LinearLayout>
+
+
diff --git a/samples/ApiDemos/res/layout/contacts_filter.xml b/samples/ApiDemos/res/layout/contacts_filter.xml
new file mode 100644
index 0000000..e8d1615
--- /dev/null
+++ b/samples/ApiDemos/res/layout/contacts_filter.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Front-end for running application instrumentation demonstration.
+ See corresponding Java code com.android.sdk.app.ContactsFilter.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/contacts_filter"/>
+
+ <Button android:id="@+id/go"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/go">
+ <requestFocus />
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/controls_1.xml b/samples/ApiDemos/res/layout/controls_1.xml
new file mode 100644
index 0000000..29658d7
--- /dev/null
+++ b/samples/ApiDemos/res/layout/controls_1.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/button"
+ android:text="@string/controls_1_save"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <EditText android:id="@+id/edit"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+
+ <CheckBox android:id="@+id/check1"
+ android:paddingBottom="24sp"
+ android:paddingTop="24sp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/controls_1_checkbox_1" />
+
+ <CheckBox android:id="@+id/check2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/controls_1_checkbox_2" />
+
+ <RadioGroup
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton android:id="@+id/radio1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/controls_1_radiobutton_1" />
+
+ <RadioButton android:id="@+id/radio2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/controls_1_radiobutton_2" />
+
+ </RadioGroup>
+
+ <CheckBox android:id="@+id/star"
+ style="?android:attr/starStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/controls_1_star" />
+
+ <ToggleButton android:id="@+id/toggle1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ToggleButton android:id="@+id/toggle2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <Spinner android:id="@+id/spinner1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:drawSelectorOnTop="true"
+ />
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dip"
+ android:text="@string/textColorPrimary"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:focusable="true"
+ />
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dip"
+ android:text="@string/textColorSecondary"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorSecondary"
+ android:focusable="true"
+ />
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dip"
+ android:text="@string/textColorTertiary"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorTertiary"
+ android:focusable="true"
+ />
+
+ <TextView
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:text="@string/listSeparatorTextViewStyle"
+ android:layout_marginTop="5dip"
+ />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/custom_dialog_activity.xml b/samples/ApiDemos/res/layout/custom_dialog_activity.xml
new file mode 100644
index 0000000..d706018
--- /dev/null
+++ b/samples/ApiDemos/res/layout/custom_dialog_activity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- Demonstrates an activity with a custom dialog theme.
+ See corresponding Java code com.android.sdk.app.CustomDialogActivity.java. -->
+
+<!-- This screen consists of a single text field that displays some text. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:gravity="center_vertical|center_horizontal"
+ android:text="@string/custom_dialog_activity_text"/>
diff --git a/samples/ApiDemos/res/layout/custom_title.xml b/samples/ApiDemos/res/layout/custom_title.xml
new file mode 100644
index 0000000..dbe8cb6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/custom_title.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- Demonstrates how to use a custom title.
+ See corresponding Java code com.example.android.apis.app.CustomTitle.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/screen"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <LinearLayout android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:baselineAligned="false">
+ <EditText android:id="@+id/left_text_edit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxEms="10"
+ android:minEms="10"
+ android:layout_gravity="center_vertical"
+ android:text="@string/custom_title_left" />
+ <Button android:id="@+id/left_text_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/custom_title_left_button"/>
+ </LinearLayout>
+ <LinearLayout android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:baselineAligned="false">
+ <EditText android:id="@+id/right_text_edit"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxEms="10"
+ android:minEms="10"
+ android:layout_gravity="center_vertical"
+ android:text="@string/custom_title_right" />
+ <Button android:id="@+id/right_text_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/custom_title_right_button"/>
+ </LinearLayout>
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/custom_title_1.xml b/samples/ApiDemos/res/layout/custom_title_1.xml
new file mode 100644
index 0000000..f794332
--- /dev/null
+++ b/samples/ApiDemos/res/layout/custom_title_1.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- Demonstrates how to use a custom title.
+ See corresponding Java code com.example.android.apis.app.CustomTitle.java. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/screen"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <TextView android:id="@+id/left_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:text="@string/custom_title_left" />
+ <TextView android:id="@+id/right_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:text="@string/custom_title_right" />
+</RelativeLayout>
diff --git a/samples/ApiDemos/res/layout/custom_view_1.xml b/samples/ApiDemos/res/layout/custom_view_1.xml
new file mode 100644
index 0000000..cac91ad
--- /dev/null
+++ b/samples/ApiDemos/res/layout/custom_view_1.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates defining custom views in a layout file. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <com.example.android.apis.view.LabelView
+ android:background="@drawable/red"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ app:text="Red"/>
+
+ <com.example.android.apis.view.LabelView
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ app:text="Blue" app:textSize="20dp"/>
+
+ <com.example.android.apis.view.LabelView
+ android:background="@drawable/green"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ app:text="Green" app:textColor="#ffffffff" />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/date_widgets_example_1.xml b/samples/ApiDemos/res/layout/date_widgets_example_1.xml
new file mode 100644
index 0000000..b9db6a0
--- /dev/null
+++ b/samples/ApiDemos/res/layout/date_widgets_example_1.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/dateDisplay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/date_widgets_example_dateDisplay_text"/>
+ </LinearLayout>
+
+ <Button android:id="@+id/pickDate"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/date_widgets_example_pickDate_text"/>
+
+ <Button android:id="@+id/pickTime"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/date_widgets_example_pickTime_text"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/date_widgets_example_2.xml b/samples/ApiDemos/res/layout/date_widgets_example_2.xml
new file mode 100644
index 0000000..50b182d
--- /dev/null
+++ b/samples/ApiDemos/res/layout/date_widgets_example_2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- example of using the time changed callback, with now visible 'set' button-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TimePicker android:id="@+id/timePicker"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+
+ <TextView android:id="@+id/dateDisplay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="4dip"
+ android:text="@string/date_widgets_example_dateDisplay_text"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/dialog_activity.xml b/samples/ApiDemos/res/layout/dialog_activity.xml
new file mode 100644
index 0000000..88c4b07
--- /dev/null
+++ b/samples/ApiDemos/res/layout/dialog_activity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- Demonstrates an activity with a dialog theme.
+ See corresponding Java code com.android.sdk.app.DialogActivity.java. -->
+
+<!-- This screen consists of a single text field that displays some text. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:gravity="center_vertical|center_horizontal"
+ android:text="@string/dialog_activity_text"/>
diff --git a/samples/ApiDemos/res/layout/focus_1.xml b/samples/ApiDemos/res/layout/focus_1.xml
new file mode 100644
index 0000000..12af0a9
--- /dev/null
+++ b/samples/ApiDemos/res/layout/focus_1.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/txtStatus"
+ android:text="@string/focus_1_message"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content" />
+
+ <ListView android:id="@+id/rssListView"
+ android:background="#7700CC00"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent" />
+
+ <WebView android:id="@+id/rssWebView"
+ android:background="#77CC0000"
+ android:layout_height="50dip"
+ android:layout_width="fill_parent"
+ android:focusable="false" />
+
+ <Button android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/focus_1_placeholder" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/focus_2.xml b/samples/ApiDemos/res/layout/focus_2.xml
new file mode 100644
index 0000000..6351de2
--- /dev/null
+++ b/samples/ApiDemos/res/layout/focus_2.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:orientation="horizontal">
+
+ <Button android:id="@+id/leftButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:text="@string/focus_2_left"
+ android:nextFocusRight="@+id/rightButton"/> <!-- jump over middle! -->
+
+ <Button android:id="@+id/centerButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:text="@string/focus_2_jump" />
+
+ <Button android:id="@+id/rightButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dip"
+ android:text="@string/focus_2_right"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/focus_3.xml b/samples/ApiDemos/res/layout/focus_3.xml
new file mode 100644
index 0000000..f08c3f8
--- /dev/null
+++ b/samples/ApiDemos/res/layout/focus_3.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates using nextLeft, nextRight, nextUp and nextDown to get
+ focus behavior that would be difficult with default focus calculation alg.-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dip">
+
+ <Button android:id="@+id/top"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:nextFocusDown="@+id/bottom"
+ android:text="@string/focus_3_top"/>
+
+ <Button android:id="@+id/right"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:nextFocusLeft="@+id/left"
+ android:text="@string/focus_3_right"/>
+
+ <Button android:id="@+id/bottom"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:nextFocusUp="@+id/top"
+ android:text="@string/focus_3_bottom"/>
+
+ <Button android:id="@+id/left"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:nextFocusRight="@+id/right"
+ android:text="@string/focus_3_left"/>
+
+</RelativeLayout>
+
+
+
+
+
+
+
diff --git a/samples/ApiDemos/res/layout/forward_target.xml b/samples/ApiDemos/res/layout/forward_target.xml
new file mode 100644
index 0000000..6d56ae2
--- /dev/null
+++ b/samples/ApiDemos/res/layout/forward_target.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates receiving activity results.
+ See corresponding Java code com.android.sdk.app.ReceiveResult.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:text="@string/forward_target"/>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/forwarding.xml b/samples/ApiDemos/res/layout/forwarding.xml
new file mode 100644
index 0000000..a860d88
--- /dev/null
+++ b/samples/ApiDemos/res/layout/forwarding.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates receiving activity results.
+ See corresponding Java code com.android.sdk.app.ReceiveResult.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/forwarding"/>
+
+ <Button android:id="@+id/go"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/go">
+ <requestFocus />
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/gadget_configure.xml b/samples/ApiDemos/res/layout/gadget_configure.xml
new file mode 100644
index 0000000..bc9f40d
--- /dev/null
+++ b/samples/ApiDemos/res/layout/gadget_configure.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/gadget_configure_instructions"
+ />
+
+ <EditText
+ android:id="@+id/gadget_prefix"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ />
+
+ <Button
+ android:id="@+id/save_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@android:string/ok"
+ />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/gadget_provider.xml b/samples/ApiDemos/res/layout/gadget_provider.xml
new file mode 100644
index 0000000..49cf42f
--- /dev/null
+++ b/samples/ApiDemos/res/layout/gadget_provider.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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/gadget_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#ff000000"
+/>
+
diff --git a/samples/ApiDemos/res/layout/gallery_1.xml b/samples/ApiDemos/res/layout/gallery_1.xml
new file mode 100644
index 0000000..40f3443
--- /dev/null
+++ b/samples/ApiDemos/res/layout/gallery_1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<Gallery xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gallery"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+/>
+
diff --git a/samples/ApiDemos/res/layout/gallery_2.xml b/samples/ApiDemos/res/layout/gallery_2.xml
new file mode 100644
index 0000000..37e5d11
--- /dev/null
+++ b/samples/ApiDemos/res/layout/gallery_2.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginBottom="10dip"
+ android:text="@string/gallery_2_text"
+ />
+
+ <Gallery android:id="@+id/gallery"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:spacing="16dp"
+ />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/google_login.xml b/samples/ApiDemos/res/layout/google_login.xml
new file mode 100644
index 0000000..9ab2f62
--- /dev/null
+++ b/samples/ApiDemos/res/layout/google_login.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates styled string resources.
+ See corresponding Java code com.android.sdk.content.StyledText -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/login"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/googlelogin_login"
+ />
+
+ <Button
+ android:id="@+id/bad_login"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/googlelogin_bad_login"
+ />
+
+ <Button
+ android:id="@+id/clear"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/googlelogin_clear"
+ />
+
+ <TextView
+ android:id="@+id/username_label"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/googlelogin_user"/>
+
+ <TextView
+ android:id="@+id/username"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/google_login_username_text"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/grid_1.xml b/samples/ApiDemos/res/layout/grid_1.xml
new file mode 100644
index 0000000..ca60320
--- /dev/null
+++ b/samples/ApiDemos/res/layout/grid_1.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/myGrid"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:verticalSpacing="10dp"
+
+ android:horizontalSpacing="10dp"
+ android:numColumns="auto_fit"
+ android:columnWidth="60dp"
+ android:stretchMode="columnWidth"
+
+ android:gravity="center"
+ />
diff --git a/samples/ApiDemos/res/layout/grid_2.xml b/samples/ApiDemos/res/layout/grid_2.xml
new file mode 100644
index 0000000..4640ab6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/grid_2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/myGrid"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:verticalSpacing="10dp"
+
+ android:horizontalSpacing="10dp"
+ android:numColumns="auto_fit"
+ android:columnWidth="60dp"
+ android:stretchMode="columnWidth"
+
+ android:gravity="center"
+ />
diff --git a/samples/ApiDemos/res/layout/hello_world.xml b/samples/ApiDemos/res/layout/hello_world.xml
new file mode 100644
index 0000000..364a83a
--- /dev/null
+++ b/samples/ApiDemos/res/layout/hello_world.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates basic application screen.
+ See corresponding Java code com.android.sdk.app.HelloWorld.java. -->
+
+<!-- This screen consists of a single text field that
+ displays our "Hello, World!" text. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:gravity="center_vertical|center_horizontal"
+ android:text="@string/hello_world"/>
diff --git a/samples/ApiDemos/res/layout/image_button_1.xml b/samples/ApiDemos/res/layout/image_button_1.xml
new file mode 100644
index 0000000..114163e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/image_button_1.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <ImageButton
+ android:layout_width="100dip"
+ android:layout_height="50dip"
+ android:src="@android:drawable/sym_action_call" />
+
+ <ImageButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@android:drawable/sym_action_chat" />
+
+ <ImageButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@android:drawable/sym_action_email" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/image_switcher_1.xml b/samples/ApiDemos/res/layout/image_switcher_1.xml
new file mode 100644
index 0000000..d9cd080
--- /dev/null
+++ b/samples/ApiDemos/res/layout/image_switcher_1.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ImageSwitcher android:id="@+id/switcher"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ />
+
+ <Gallery android:id="@+id/gallery"
+ android:background="#55000000"
+ android:layout_width="fill_parent"
+ android:layout_height="60dp"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+
+ android:gravity="center_vertical"
+ android:spacing="16dp"
+ />
+
+</RelativeLayout>
+
diff --git a/samples/ApiDemos/res/layout/image_view_1.xml b/samples/ApiDemos/res/layout/image_view_1.xml
new file mode 100644
index 0000000..36b926d
--- /dev/null
+++ b/samples/ApiDemos/res/layout/image_view_1.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <!-- The following four examples use a large image -->
+ <!-- 1. Non-scaled view, for reference -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_large_normal"/>
+ <ImageView
+ android:src="@drawable/sample_1"
+ android:adjustViewBounds="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- 2. Limit to at most 50x50 -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_large_at_most"/>
+ <ImageView
+ android:src="@drawable/sample_1"
+ android:adjustViewBounds="true"
+ android:maxWidth="50dip"
+ android:maxHeight="50dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- 3. Limit to at most 70x70, with 10 pixels of padding all around -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_large_at_most_padded"/>
+ <ImageView
+ android:src="@drawable/sample_1"
+ android:background="#66FFFFFF"
+ android:adjustViewBounds="true"
+ android:maxWidth="70dip"
+ android:maxHeight="70dip"
+ android:padding="10dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- 4. Limit to exactly 70x70, with 10 pixels of padding all around -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_large_exactly_padded"/>
+ <ImageView
+ android:src="@drawable/sample_1"
+ android:background="#66FFFFFF"
+ android:scaleType="centerInside"
+ android:padding="10dip"
+ android:layout_width="70dip"
+ android:layout_height="70dip" />
+
+ <!-- Repeating the previous four examples with small image -->
+ <!-- 1. Non-scaled view, for reference -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_small_normal"/>
+ <ImageView
+ android:src="@drawable/stat_happy"
+ android:background="#FFFFFFFF"
+ android:adjustViewBounds="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- 2. Limit to at most 50x50 -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_small_at_most"/>
+ <ImageView
+ android:src="@drawable/stat_happy"
+ android:background="#FFFFFFFF"
+ android:adjustViewBounds="true"
+ android:maxWidth="50dip"
+ android:maxHeight="50dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- 3. Limit to at most 70x70, with 10 pixels of padding all around -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_small_at_most_padded"/>
+ <ImageView
+ android:src="@drawable/stat_happy"
+ android:background="#FFFFFFFF"
+ android:adjustViewBounds="true"
+ android:maxWidth="70dip"
+ android:maxHeight="70dip"
+ android:padding="10dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <!-- 4. Limit to exactly 70x70, with 10 pixels of padding all around -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="10dip"
+ android:text="@string/image_view_small_exactly_padded"/>
+ <ImageView
+ android:src="@drawable/stat_happy"
+ android:background="#FFFFFFFF"
+ android:scaleType="centerInside"
+ android:padding="10dip"
+ android:layout_width="70dip"
+ android:layout_height="70dip" />
+
+
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/incoming_message.xml b/samples/ApiDemos/res/layout/incoming_message.xml
new file mode 100644
index 0000000..01ea04a
--- /dev/null
+++ b/samples/ApiDemos/res/layout/incoming_message.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Button
+ android:id="@+id/notify"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/incoming_message_notify_text" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/incoming_message_info.xml b/samples/ApiDemos/res/layout/incoming_message_info.xml
new file mode 100644
index 0000000..723a4da
--- /dev/null
+++ b/samples/ApiDemos/res/layout/incoming_message_info.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/sample_thumb_2"
+ />
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="6dip"
+ android:text="@string/incoming_message_info_message_text"
+ />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/incoming_message_panel.xml b/samples/ApiDemos/res/layout/incoming_message_panel.xml
new file mode 100644
index 0000000..3120e4e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/incoming_message_panel.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:drawable/toast_frame">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/sample_thumb_2"
+ />
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="6dip"
+ />
+
+ </LinearLayout>
+</FrameLayout>
diff --git a/samples/ApiDemos/res/layout/incoming_message_view.xml b/samples/ApiDemos/res/layout/incoming_message_view.xml
new file mode 100644
index 0000000..b286e6e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/incoming_message_view.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:paddingLeft="4dip"
+ android:paddingRight="4dip"
+ android:paddingTop="4dip"
+ >
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ >
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/sample_thumb_2"
+ />
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="6dip"
+ android:text="@string/incoming_message_view_message_text"
+ />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="12dip"
+ android:text="@string/imcoming_message_view_message2_text"
+ />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/intents.xml b/samples/ApiDemos/res/layout/intents.xml
new file mode 100644
index 0000000..023e4e8
--- /dev/null
+++ b/samples/ApiDemos/res/layout/intents.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- Demonstrates launching various intents.
+ See corresponding Java code com.example.android.apis.app.Intents.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/intents"/>
+
+ <Button android:id="@+id/get_music"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/get_music">
+ <requestFocus />
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/launcher_shortcuts.xml b/samples/ApiDemos/res/layout/launcher_shortcuts.xml
new file mode 100644
index 0000000..c8fbb2a
--- /dev/null
+++ b/samples/ApiDemos/res/layout/launcher_shortcuts.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This activity provides information about launcher shortcuts -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <!-- Section: Information -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dip"
+ android:text="@string/msg_launcher_shortcuts" />
+
+ <!-- Section: The intent that launched this Activity -->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_intent" />
+ <TextView android:id="@+id/txt_shortcut_intent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
diff --git a/samples/ApiDemos/res/layout/layout_animation_1.xml b/samples/ApiDemos/res/layout/layout_animation_1.xml
new file mode 100644
index 0000000..2b25485
--- /dev/null
+++ b/samples/ApiDemos/res/layout/layout_animation_1.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/grid"
+ android:layoutAnimation="@anim/layout_grid_fade"
+
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:verticalSpacing="10dp"
+
+ android:horizontalSpacing="10dp"
+ android:numColumns="auto_fit"
+ android:columnWidth="60dp"
+ android:stretchMode="columnWidth"
+
+ android:gravity="center" />
diff --git a/samples/ApiDemos/res/layout/layout_animation_3.xml b/samples/ApiDemos/res/layout/layout_animation_3.xml
new file mode 100644
index 0000000..051fa8e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/layout_animation_3.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutAnimation="@anim/layout_bottom_to_top_slide" />
diff --git a/samples/ApiDemos/res/layout/layout_animation_4.xml b/samples/ApiDemos/res/layout/layout_animation_4.xml
new file mode 100644
index 0000000..73b99b0
--- /dev/null
+++ b/samples/ApiDemos/res/layout/layout_animation_4.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/grid"
+ android:layoutAnimation="@anim/layout_random_fade"
+
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:verticalSpacing="10dp"
+
+ android:horizontalSpacing="10dp"
+ android:numColumns="auto_fit"
+ android:columnWidth="60dp"
+ android:stretchMode="columnWidth"
+
+ android:gravity="center" />
diff --git a/samples/ApiDemos/res/layout/layout_animation_5.xml b/samples/ApiDemos/res/layout/layout_animation_5.xml
new file mode 100644
index 0000000..602fb18
--- /dev/null
+++ b/samples/ApiDemos/res/layout/layout_animation_5.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/grid"
+ android:layoutAnimation="@anim/layout_grid_inverse_fade"
+
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:verticalSpacing="10dp"
+
+ android:horizontalSpacing="10dp"
+ android:numColumns="auto_fit"
+ android:columnWidth="60dp"
+ android:stretchMode="columnWidth"
+
+ android:gravity="center" />
diff --git a/samples/ApiDemos/res/layout/layout_animation_6.xml b/samples/ApiDemos/res/layout/layout_animation_6.xml
new file mode 100644
index 0000000..026797e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/layout_animation_6.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/grid"
+ android:layoutAnimation="@anim/layout_wave_scale"
+
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:verticalSpacing="10dp"
+
+ android:horizontalSpacing="10dp"
+ android:numColumns="auto_fit"
+ android:columnWidth="60dp"
+ android:stretchMode="columnWidth"
+
+ android:gravity="center" />
diff --git a/samples/ApiDemos/res/layout/layout_animation_7.xml b/samples/ApiDemos/res/layout/layout_animation_7.xml
new file mode 100644
index 0000000..38260c7
--- /dev/null
+++ b/samples/ApiDemos/res/layout/layout_animation_7.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layoutAnimation="@anim/layout_animation_table"
+ android:animationCache="false"
+ android:clipToPadding="false"
+ android:padding="12dp"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:stretchColumns="1">
+
+ <TableRow
+ android:layoutAnimation="@anim/layout_animation_row_right_slide">
+ <TextView
+ android:gravity="right"
+ android:text="@string/layout_animation_name" />
+ <EditText />
+ </TableRow>
+
+ <TableRow
+ android:layoutAnimation="@anim/layout_animation_row_left_slide">
+ <TextView
+ android:gravity="right"
+ android:text="@string/layout_animation_lastname" />
+ <EditText />
+ </TableRow>
+
+ <TableRow
+ android:layoutAnimation="@anim/layout_animation_row_right_slide">
+ <TextView
+ android:gravity="right"
+ android:text="@string/layout_animation_phone" />
+ <EditText />
+ </TableRow>
+
+ <TableRow
+ android:layoutAnimation="@anim/layout_animation_row_left_slide">
+ <TextView
+ android:gravity="right"
+ android:text="@string/layout_animation_address" />
+ <EditText android:lines="3" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_1.xml b/samples/ApiDemos/res/layout/linear_layout_1.xml
new file mode 100644
index 0000000..ef01ced
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_1.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates a simple linear layout. The height of the layout is the sum of its children. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <!-- view1 goes on top -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_1_top"/>
+
+ <!-- view2 goes in the middle -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_1_middle"/>
+
+ <!-- view3 goes on the bottom -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_1_bottom"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_10.xml b/samples/ApiDemos/res/layout/linear_layout_10.xml
new file mode 100644
index 0000000..eb793fd
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_10.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- Demonstrates using a LinearLayout background to group related
+ TextViews, EditTexts, and Buttons. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- Top label/button text field. -->
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:addStatesFromChildren="true"
+ android:gravity="center_vertical"
+ android:paddingRight="0dip"
+ android:background="@android:drawable/edit_text">
+
+ <!--
+ TextView label goes at the left.
+ -->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_10_from"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ />
+
+ <!--
+ EditText goes in between.
+ -->
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="true"
+ android:background="@null"
+ />
+
+ <!--
+ The button goes at the right.
+ -->
+ <ImageButton
+ style="@android:style/Widget.Button.Inset"
+ android:src="@android:drawable/star_big_on"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dip"
+ android:layout_marginRight="2dip"
+ android:layout_marginBottom="2dip"
+ android:padding="10dip"
+ />
+
+ </LinearLayout>
+
+ <!-- Bottom label/button text field. (Identical to the top one
+ except for the label.) -->
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:addStatesFromChildren="true"
+ android:gravity="center_vertical"
+ android:paddingRight="0dip"
+ android:background="@android:drawable/edit_text">
+
+ <!--
+ TextView label goes at the left.
+ -->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_10_to"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ />
+
+ <!--
+ EditText goes in between.
+ -->
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="true"
+ android:background="@null"
+ />
+
+ <!--
+ The button goes at the right.
+ -->
+ <ImageButton
+ style="@android:style/Widget.Button.Inset"
+ android:src="@android:drawable/star_big_on"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dip"
+ android:layout_marginRight="2dip"
+ android:layout_marginBottom="2dip"
+ android:padding="10dip"
+ />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_2.xml b/samples/ApiDemos/res/layout/linear_layout_2.xml
new file mode 100644
index 0000000..3cacccc
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_2.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates a simple linear layout. The layout fills the screen, with the children stacked from the top. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- view1 goes on top -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_2_top"/>
+
+ <!-- view2 goes in the middle -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_2_middle"/>
+
+ <!-- view3 goes on the bottom -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_2_bottom"/>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/linear_layout_3.xml b/samples/ApiDemos/res/layout/linear_layout_3.xml
new file mode 100644
index 0000000..2b9b327
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_3.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates a simple linear layout. The layout fills the screen, with the
+ children stacked from the top. The middle child gets allocated any extra
+ space.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- view1 goes on top -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_3_top"/>
+
+ <!-- view2 goes in the middle -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/linear_layout_3_middle"/>
+
+ <!-- view3 goes on the bottom -->
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_3_bottom"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_4.xml b/samples/ApiDemos/res/layout/linear_layout_4.xml
new file mode 100644
index 0000000..139fb57
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_4.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates a horizontal linear layout with equally sized columns
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:background="@drawable/red"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+
+ <TextView
+ android:background="@drawable/green"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+
+ <TextView
+ android:background="@drawable/blue"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+
+ <TextView
+ android:background="@drawable/yellow"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_5.xml b/samples/ApiDemos/res/layout/linear_layout_5.xml
new file mode 100644
index 0000000..832a103
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_5.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates a nesting layouts to make a form
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dip">
+
+ <!--
+ TextView goes on top...
+ -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_5_instructions"/>
+
+ <!--
+ Followed by the EditText field...
+
+ Also give it a standard background (the "android:"
+ part in @android:drawable/editbox_background
+ means it is system resource rather than
+ an application resource.
+ -->
+ <EditText
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:drawable/editbox_background"/>
+
+ <!--
+ Use a horizontal layout to hold the two buttons.
+ This item has layout_gravity="right". This means the whole
+ horizontal LinearLayout is right aligned, not the individual
+ items within it. The horizontal LinearLayout's width is set to
+ wrap_content. (If it was fill_parent it would not have any
+ room to slide to the right.)
+ -->
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right" >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_5_cancel"/>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dip"
+ android:text="@string/linear_layout_5_ok" />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_6.xml b/samples/ApiDemos/res/layout/linear_layout_6.xml
new file mode 100644
index 0000000..f4bb6a7
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_6.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ LinearLayout which uses a combination of wrap_content on itself and
+ fill_parent on its children to get every item to be the same width.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:background="@drawable/blue"
+ android:padding="20dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_6_one"/>
+
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_6_two"/>
+
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_6_three"/>
+
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_6_four"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_7.xml b/samples/ApiDemos/res/layout/linear_layout_7.xml
new file mode 100644
index 0000000..19b22e5
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_7.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates a horizontal linear layout with equally sized columns.
+ Some columns force their height to match the parent.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:background="@drawable/red"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:text="@string/linear_layout_7_small"/>
+
+ <TextView
+ android:background="@drawable/green"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:text="@string/linear_layout_7_big"/>
+
+ <TextView
+ android:background="@drawable/blue"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:text="@string/linear_layout_7_small" />
+
+ <TextView
+ android:background="@drawable/yellow"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/linear_layout_7_wrap"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_8.xml b/samples/ApiDemos/res/layout/linear_layout_8.xml
new file mode 100644
index 0000000..f226043
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_8.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates a simple linear layout. The layout fills the screen, with the
+ children stacked from the top.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="30dip">
+ <LinearLayout
+ android:id="@+id/layout"
+ android:orientation="vertical"
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="30dip">
+
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_8_c"/>
+
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_8_b"/>
+
+ <TextView
+ android:background="@drawable/box"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_8_c"/>
+
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/samples/ApiDemos/res/layout/linear_layout_9.xml b/samples/ApiDemos/res/layout/linear_layout_9.xml
new file mode 100644
index 0000000..eb91147
--- /dev/null
+++ b/samples/ApiDemos/res/layout/linear_layout_9.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates a simple linear layout. The layout fills the screen, with the
+ children stacked from the top.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ListView android:id="@+id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1.0" />
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/linear_layout_9_button" />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/link.xml b/samples/ApiDemos/res/layout/link.xml
new file mode 100644
index 0000000..a65d000
--- /dev/null
+++ b/samples/ApiDemos/res/layout/link.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <!-- Four TextView widgets, each one displaying text containing links. -->
+
+ <!-- text1 automatically linkifies things like URLs and phone numbers. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:autoLink="all"
+ android:text="@string/link_text_auto"
+ />
+
+ <!-- text2 uses a string resource containing explicit <a> tags to
+ specify links. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text2"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/link_text_manual"
+ />
+
+ <!-- text3 builds the text in the Java code using HTML. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text3"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ />
+
+ <!-- text4 builds the text in the Java code without using HTML. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/text4"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/list_12.xml b/samples/ApiDemos/res/layout/list_12.xml
new file mode 100644
index 0000000..7f19b58
--- /dev/null
+++ b/samples/ApiDemos/res/layout/list_12.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip">
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:stackFromBottom="true"
+ android:transcriptMode="normal"/>
+
+ <EditText android:id="@+id/userText"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/list_13.xml b/samples/ApiDemos/res/layout/list_13.xml
new file mode 100644
index 0000000..681b46e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/list_13.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:drawSelectorOnTop="false"/>
+
+ <TextView android:id="@+id/status"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/list_7.xml b/samples/ApiDemos/res/layout/list_7.xml
new file mode 100644
index 0000000..2dc7777
--- /dev/null
+++ b/samples/ApiDemos/res/layout/list_7.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip">
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:drawSelectorOnTop="false"/>
+
+ <TextView android:id="@+id/phone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/blue"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/list_8.xml b/samples/ApiDemos/res/layout/list_8.xml
new file mode 100644
index 0000000..a88b67c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/list_8.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/add"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/list_8_new_photo"/>
+
+ <Button android:id="@+id/clear"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/list_8_clear_photos"/>
+
+ </LinearLayout>
+
+ <!-- The frame layout is here since we will be showing either
+ the empty view or the list view. -->
+ <FrameLayout
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" >
+ <!-- Here is the list. Since we are using a ListActivity, we
+ have to call it "@android:id/list" so ListActivity will
+ find it -->
+ <ListView android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:drawSelectorOnTop="false"/>
+
+ <!-- Here is the view to show if the list is emtpy -->
+ <TextView android:id="@+id/empty"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/list_8_no_photos"/>
+
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/list_item_checkbox.xml b/samples/ApiDemos/res/layout/list_item_checkbox.xml
new file mode 100644
index 0000000..fa1d2d8
--- /dev/null
+++ b/samples/ApiDemos/res/layout/list_item_checkbox.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+/>
diff --git a/samples/ApiDemos/res/layout/list_item_icon_text.xml b/samples/ApiDemos/res/layout/list_item_icon_text.xml
new file mode 100644
index 0000000..7206c04
--- /dev/null
+++ b/samples/ApiDemos/res/layout/list_item_icon_text.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ImageView android:id="@+id/icon"
+ android:layout_width="48dip"
+ android:layout_height="48dip" />
+
+ <TextView android:id="@+id/text"
+ android:layout_gravity="center_vertical"
+ android:layout_width="0dip"
+ android:layout_weight="1.0"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/list_position.xml b/samples/ApiDemos/res/layout/list_position.xml
new file mode 100644
index 0000000..a82f6bc
--- /dev/null
+++ b/samples/ApiDemos/res/layout/list_position.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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:textSize="50sp"
+ android:textColor="#99FFFFFF"
+ android:background="#BB000000"
+ android:minWidth="70dip"
+ android:maxWidth="70dip"
+ android:padding="10dip"
+ android:gravity="center"
+/>
diff --git a/samples/ApiDemos/res/layout/local_sample.xml b/samples/ApiDemos/res/layout/local_sample.xml
new file mode 100644
index 0000000..e662921
--- /dev/null
+++ b/samples/ApiDemos/res/layout/local_sample.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Front-end for running application instrumentation demonstration.
+ See corresponding Java code com.android.sdk.app.LocalSample.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/local_sample"/>
+
+ <Button android:id="@+id/go"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/go">
+ <requestFocus />
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/local_service_binding.xml b/samples/ApiDemos/res/layout/local_service_binding.xml
new file mode 100644
index 0000000..775b8fb
--- /dev/null
+++ b/samples/ApiDemos/res/layout/local_service_binding.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/local_service_binding"/>
+
+ <Button android:id="@+id/bind"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/bind_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/unbind"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/unbind_service">
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/local_service_controller.xml b/samples/ApiDemos/res/layout/local_service_controller.xml
new file mode 100644
index 0000000..7bb02ca
--- /dev/null
+++ b/samples/ApiDemos/res/layout/local_service_controller.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/local_service_controller"/>
+
+ <Button android:id="@+id/start"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/stop"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/stop_service">
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/log_text_box_1.xml b/samples/ApiDemos/res/layout/log_text_box_1.xml
new file mode 100644
index 0000000..f06619d
--- /dev/null
+++ b/samples/ApiDemos/res/layout/log_text_box_1.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Button
+ android:id="@+id/add"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/log_text_box_1_add_text"/>
+
+ <com.example.android.apis.text.LogTextBox
+ android:id="@+id/text"
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:scrollbars="vertical"/>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/log_text_box_1_do_nothing_text"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/mapview.xml b/samples/ApiDemos/res/layout/mapview.xml
new file mode 100644
index 0000000..97ef7ff
--- /dev/null
+++ b/samples/ApiDemos/res/layout/mapview.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates use of the com.google.android.maps.MapView.
+ See corresponding Java code com.example.android.apis.view.MapViewDemo.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <com.google.android.maps.MapView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:enabled="true"
+ android:clickable="true"
+ android:apiKey="apisamples"
+ />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/marquee.xml b/samples/ApiDemos/res/layout/marquee.xml
new file mode 100644
index 0000000..6d40c84
--- /dev/null
+++ b/samples/ApiDemos/res/layout/marquee.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Button
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:text="@string/marquee_default"
+ android:singleLine="true"
+ android:ellipsize="marquee"/>
+
+ <Button
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:text="@string/marquee_once"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="1"/>
+
+ <Button
+ android:layout_width="150dip"
+ android:layout_height="wrap_content"
+ android:text="@string/marquee_forever"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/mediaplayer_1.xml b/samples/ApiDemos/res/layout/mediaplayer_1.xml
new file mode 100644
index 0000000..16ae61b
--- /dev/null
+++ b/samples/ApiDemos/res/layout/mediaplayer_1.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+ <Button android:id="@+id/localvideo"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:text="@string/local_video"
+ />
+
+ <Button android:id="@+id/streamvideo"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:text="@string/stream_video"
+ />
+
+ <Button android:id="@+id/localaudio"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:text="@string/local_audio"
+ />
+
+ <Button android:id="@+id/resourcesaudio"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:text="@string/res_audio"
+ />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/mediaplayer_2.xml b/samples/ApiDemos/res/layout/mediaplayer_2.xml
new file mode 100644
index 0000000..e1e49dd
--- /dev/null
+++ b/samples/ApiDemos/res/layout/mediaplayer_2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <SurfaceView android:id="@+id/surface"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center">
+ </SurfaceView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/ApiDemos/res/layout/morse_code.xml b/samples/ApiDemos/res/layout/morse_code.xml
new file mode 100644
index 0000000..f536da2
--- /dev/null
+++ b/samples/ApiDemos/res/layout/morse_code.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This activity exercises search invocation options -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <EditText
+ android:id="@+id/text"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dip"
+ />
+
+ <Button
+ android:id="@+id/button"
+ android:text="@string/vibrate"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/notify_with_text.xml b/samples/ApiDemos/res/layout/notify_with_text.xml
new file mode 100644
index 0000000..6cba90d
--- /dev/null
+++ b/samples/ApiDemos/res/layout/notify_with_text.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Button
+ android:id="@+id/short_notify"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/notify_with_text_short_notify_text" />
+
+ <Button
+ android:id="@+id/long_notify"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/notify_with_text_long_notify_text" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/notifying_controller.xml b/samples/ApiDemos/res/layout/notifying_controller.xml
new file mode 100644
index 0000000..54cef17
--- /dev/null
+++ b/samples/ApiDemos/res/layout/notifying_controller.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/notifying_service_controller"/>
+
+ <Button android:id="@+id/notifyStart"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/notifyStop"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/stop_service">
+ </Button>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/preference_widget_mypreference.xml b/samples/ApiDemos/res/layout/preference_widget_mypreference.xml
new file mode 100644
index 0000000..20c0d56
--- /dev/null
+++ b/samples/ApiDemos/res/layout/preference_widget_mypreference.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- Custom preference type using a text view. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/mypreference_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginRight="6sp"
+ android:focusable="false"
+ android:clickable="false" />
diff --git a/samples/ApiDemos/res/layout/progressbar_1.xml b/samples/ApiDemos/res/layout/progressbar_1.xml
new file mode 100644
index 0000000..0383de9
--- /dev/null
+++ b/samples/ApiDemos/res/layout/progressbar_1.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ProgressBar android:id="@+id/progress_horizontal"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="200dip"
+ android:layout_height="wrap_content"
+ android:max="100"
+ android:progress="50"
+ android:secondaryProgress="75" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_1_default_progress" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/decrease"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_1_minus" />
+
+ <Button android:id="@+id/increase"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_1_plus" />
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_1_secondary_progress" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/decrease_secondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_1_minus" />
+
+ <Button android:id="@+id/increase_secondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_1_plus" />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/progressbar_2.xml b/samples/ApiDemos/res/layout/progressbar_2.xml
new file mode 100644
index 0000000..2d43622
--- /dev/null
+++ b/samples/ApiDemos/res/layout/progressbar_2.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ProgressBar android:id="@+android:id/progress_large"
+ style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ProgressBar android:id="@+android:id/progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ProgressBar android:id="@+android:id/progress_small"
+ style="?android:attr/progressBarStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ProgressBar android:id="@+android:id/progress_small_title"
+ style="?android:attr/progressBarStyleSmallTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/progressbar_3.xml b/samples/ApiDemos/res/layout/progressbar_3.xml
new file mode 100644
index 0000000..ac10a30
--- /dev/null
+++ b/samples/ApiDemos/res/layout/progressbar_3.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/showIndeterminate"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_3_indeterminate" />
+
+ <Button android:id="@+id/showIndeterminateNoTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_3_indeterminate_no_title" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/progressbar_4.xml b/samples/ApiDemos/res/layout/progressbar_4.xml
new file mode 100644
index 0000000..5e577a0
--- /dev/null
+++ b/samples/ApiDemos/res/layout/progressbar_4.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/progressbar_4_toggle" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/radio_group_1.xml b/samples/ApiDemos/res/layout/radio_group_1.xml
new file mode 100644
index 0000000..3029207
--- /dev/null
+++ b/samples/ApiDemos/res/layout/radio_group_1.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <RadioGroup
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:checkedButton="@+id/lunch"
+ android:id="@+id/menu">
+ <RadioButton
+ android:text="@string/radio_group_1_breakfast"
+ android:id="@+id/breakfast"
+ />
+ <RadioButton
+ android:text="@string/radio_group_1_lunch"
+ android:id="@id/lunch" />
+ <RadioButton
+ android:text="@string/radio_group_1_dinner"
+ android:id="@+id/dinner" />
+ <RadioButton
+ android:text="@string/radio_group_1_all"
+ android:id="@+id/all" />
+ <TextView
+ android:text="@string/radio_group_1_selection"
+ android:id="@+id/choice" />
+ </RadioGroup>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/radio_group_1_clear"
+ android:id="@+id/clear" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/ratingbar_1.xml b/samples/ApiDemos/res/layout/ratingbar_1.xml
new file mode 100644
index 0000000..3256d3c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/ratingbar_1.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:paddingLeft="10dip"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <RatingBar android:id="@+id/ratingbar1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:numStars="3"
+ android:rating="2.5" />
+
+ <RatingBar android:id="@+id/ratingbar2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:numStars="5"
+ android:rating="2.25" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dip">
+
+ <TextView android:id="@+id/rating"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <RatingBar android:id="@+id/small_ratingbar"
+ style="?android:attr/ratingBarStyleSmall"
+ android:layout_marginLeft="5dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" />
+
+ </LinearLayout>
+
+ <RatingBar android:id="@+id/indicator_ratingbar"
+ style="?android:attr/ratingBarStyleIndicator"
+ android:layout_marginLeft="5dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/read_asset.xml b/samples/ApiDemos/res/layout/read_asset.xml
new file mode 100644
index 0000000..79b8bb6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/read_asset.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates styled string resources.
+ See corresponding Java code com.android.sdk.content.StyledText -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textStyle="normal"/>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/receive_result.xml b/samples/ApiDemos/res/layout/receive_result.xml
new file mode 100644
index 0000000..461be6c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/receive_result.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates receiving activity results.
+ See corresponding Java code com.android.sdk.app.ReceiveResult.java.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/receive_result_instructions"/>
+
+ <TextView android:id="@+id/results"
+ android:layout_width="fill_parent" android:layout_height="10dip"
+ android:layout_weight="1"
+ android:paddingBottom="4dip"
+ android:background="@drawable/green">
+ </TextView>
+
+ <Button android:id="@+id/get"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:text="@string/receive_result_result">
+ <requestFocus />
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/redirect_enter.xml b/samples/ApiDemos/res/layout/redirect_enter.xml
new file mode 100644
index 0000000..f73d999
--- /dev/null
+++ b/samples/ApiDemos/res/layout/redirect_enter.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates redirection between activities.
+ See corresponding Java code com.android.sdk.app.RedirectEnter.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/redirect_enter"/>
+
+ <Button android:id="@+id/go"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/go">
+ <requestFocus />
+ </Button>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/redirect_getter.xml b/samples/ApiDemos/res/layout/redirect_getter.xml
new file mode 100644
index 0000000..9879b78
--- /dev/null
+++ b/samples/ApiDemos/res/layout/redirect_getter.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates redirection between activities.
+ See corresponding Java code com.android.sdk.app.RedirectEnter.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/redirect_getter"/>
+
+ <EditText android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip">
+ <requestFocus />
+ </EditText>
+
+ <Button android:id="@+id/apply"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/apply" />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/redirect_main.xml b/samples/ApiDemos/res/layout/redirect_main.xml
new file mode 100644
index 0000000..74de502
--- /dev/null
+++ b/samples/ApiDemos/res/layout/redirect_main.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates redirection between activities.
+ See corresponding Java code com.android.sdk.app.RedirectEnter.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/redirect_main"/>
+
+ <TextView android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip" />
+
+ <Button android:id="@+id/clear"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/clear_text">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/newView"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/new_text">
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/relative_layout_1.xml b/samples/ApiDemos/res/layout/relative_layout_1.xml
new file mode 100644
index 0000000..122e718
--- /dev/null
+++ b/samples/ApiDemos/res/layout/relative_layout_1.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates stretching a view to fill the space between two other views
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- view1 goes on top -->
+ <TextView
+ android:id="@+id/view1"
+ android:background="@drawable/red"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:text="@string/relative_layout_1_top"/>
+
+ <!-- view2 goes on the bottom -->
+ <TextView
+ android:id="@+id/view2"
+ android:background="@drawable/green"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:text="@string/relative_layout_1_bottom"/>
+
+ <!-- view3 stretches betweeen view1 and view2 -->
+ <TextView
+ android:id="@+id/view3"
+ android:background="@drawable/yellow"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_above="@id/view2"
+ android:layout_below="@id/view1"
+ android:text="@string/relative_layout_1_center"/>
+
+</RelativeLayout>
+
diff --git a/samples/ApiDemos/res/layout/relative_layout_2.xml b/samples/ApiDemos/res/layout/relative_layout_2.xml
new file mode 100644
index 0000000..dc613e6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/relative_layout_2.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates using a relative layout to create a form -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/blue"
+ android:padding="10dip">
+
+ <!--
+ TextView goes at the top left by default .
+ -->
+ <TextView
+ android:id="@+id/label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/relative_layout_2_instructions"/>
+
+ <!--
+ Put the EditText field under the TextView
+ Also give it a standard background (the "android:"
+ part in @android:drawable/editbox_background
+ means it is system resource rather than
+ an application resource.
+ -->
+ <EditText
+ android:id="@+id/entry"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:drawable/editbox_background"
+ android:layout_below="@id/label"/>
+
+ <!--
+ The OK button goes below the EditText field.
+ It is also aligned to the right edge of the parent
+ (respecting the parent's padding).
+ The OK button comes first so the Cancel button
+ can be specified relative to the OK button.
+ -->
+ <Button
+ android:id="@+id/ok"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/entry"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="10dip"
+ android:text="@string/relative_layout_2_ok" />
+
+ <!--
+ The Cancel button is aligned with the top of
+ the OK button and positioned to the left of it.
+ Since the OK button has a left margin of 10, there
+ is some space between the two buttons.
+ -->
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toLeftOf="@id/ok"
+ android:layout_alignTop="@id/ok"
+ android:text="@string/relative_layout_2_cancel" />
+
+</RelativeLayout>
+
diff --git a/samples/ApiDemos/res/layout/remote_service_binding.xml b/samples/ApiDemos/res/layout/remote_service_binding.xml
new file mode 100644
index 0000000..a353efb
--- /dev/null
+++ b/samples/ApiDemos/res/layout/remote_service_binding.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/remote_service_binding"/>
+
+ <Button android:id="@+id/bind"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/bind_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/unbind"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/unbind_service">
+ </Button>
+
+ <Button android:id="@+id/kill"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/kill_process">
+ </Button>
+
+ <TextView android:id="@+id/callback"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:gravity="center_horizontal" android:paddingTop="4dip"/>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/remote_service_controller.xml b/samples/ApiDemos/res/layout/remote_service_controller.xml
new file mode 100644
index 0000000..48e4c95
--- /dev/null
+++ b/samples/ApiDemos/res/layout/remote_service_controller.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/remote_service_controller"/>
+
+ <Button android:id="@+id/start"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/stop"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/stop_service">
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/reorder_four.xml b/samples/ApiDemos/res/layout/reorder_four.xml
new file mode 100644
index 0000000..45f13a3
--- /dev/null
+++ b/samples/ApiDemos/res/layout/reorder_four.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Demonstrates using Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.
+ See corresponding Java code com.example.android.apis.app.ReorderOnLaunch.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/reorder_four_text"/>
+
+ <Button android:id="@+id/reorder_second_to_front"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/reorder_second_to_front">
+ </Button>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/reorder_on_launch.xml b/samples/ApiDemos/res/layout/reorder_on_launch.xml
new file mode 100644
index 0000000..850a2f5
--- /dev/null
+++ b/samples/ApiDemos/res/layout/reorder_on_launch.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Demonstrates using Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.
+ See corresponding Java code com.android.sdk.app.ReorderOnLaunch.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/reorder_on_launch"/>
+
+ <Button android:id="@+id/reorder_launch_two"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/reorder_launch_two">
+ </Button>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/reorder_three.xml b/samples/ApiDemos/res/layout/reorder_three.xml
new file mode 100644
index 0000000..30ef41b
--- /dev/null
+++ b/samples/ApiDemos/res/layout/reorder_three.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Demonstrates using Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.
+ See corresponding Java code com.example.android.apis.app.ReorderOnLaunch.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/reorder_three_text"/>
+
+ <Button android:id="@+id/reorder_launch_four"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/reorder_launch_four">
+ </Button>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/reorder_two.xml b/samples/ApiDemos/res/layout/reorder_two.xml
new file mode 100644
index 0000000..7132561
--- /dev/null
+++ b/samples/ApiDemos/res/layout/reorder_two.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Demonstrates using Intent.FLAG_ACTIVITY_REORDER_TO_FRONT.
+ See corresponding Java code com.example.android.apis.app.ReorderOnLaunch.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/reorder_two_text"/>
+
+ <Button android:id="@+id/reorder_launch_three"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/reorder_launch_three">
+ </Button>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/resources.xml b/samples/ApiDemos/res/layout/resources.xml
new file mode 100644
index 0000000..60ec581
--- /dev/null
+++ b/samples/ApiDemos/res/layout/resources.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!--
+ Demonstrates resources.
+
+ See corresponding Java code:
+ com.example.android.apis.content.ResourcesSample
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/styled_text"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textStyle="normal"
+ />
+
+ <TextView
+ android:id="@+id/plain_text"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textStyle="normal"
+ />
+
+ <TextView
+ android:id="@+id/res1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textStyle="normal"
+ />
+
+</LinearLayout>
+
+
diff --git a/samples/ApiDemos/res/layout/save_restore_state.xml b/samples/ApiDemos/res/layout/save_restore_state.xml
new file mode 100644
index 0000000..4f3f8ee
--- /dev/null
+++ b/samples/ApiDemos/res/layout/save_restore_state.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates saving and restoring activity state.
+ See corresponding Java code com.android.sdk.app.SaveRestoreState.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView android:id="@+id/msg"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip" />
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/saves_state"/>
+
+ <EditText android:id="@+id/saved"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:background="@drawable/green"
+ android:text="@string/initial_text"
+ android:freezesText="true">
+ <requestFocus />
+ </EditText>
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingTop="8dip"
+ android:paddingBottom="4dip"
+ android:text="@string/no_saves_state"/>
+
+ <EditText
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:background="@drawable/red"
+ android:text="@string/initial_text">
+ </EditText>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/scroll_view_1.xml b/samples/ApiDemos/res/layout/scroll_view_1.xml
new file mode 100644
index 0000000..0552807
--- /dev/null
+++ b/samples/ApiDemos/res/layout/scroll_view_1.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="none">
+
+ <LinearLayout
+ android:id="@+id/layout"
+ android:orientation="vertical"
+ android:layout_width="fill_parent" android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_text_1"/>
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_button_1"/>
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_text_2"/>
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_button_2"/>
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_text_3"/>
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_button_3"/>
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_text_4"/>
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_button_4"/>
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_text_5"/>
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_button_5"/>
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_text_6"/>
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_1_button_6"/>
+
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/scroll_view_2.xml b/samples/ApiDemos/res/layout/scroll_view_2.xml
new file mode 100644
index 0000000..0107e46
--- /dev/null
+++ b/samples/ApiDemos/res/layout/scroll_view_2.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="none">
+
+ <LinearLayout
+ android:id="@+id/layout"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_2_text_1"/>
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_view_2_button_1"/>
+
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/scrollbar1.xml b/samples/ApiDemos/res/layout/scrollbar1.xml
new file mode 100644
index 0000000..7221b3e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/scrollbar1.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_1_text"/>
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/scrollbar2.xml b/samples/ApiDemos/res/layout/scrollbar2.xml
new file mode 100644
index 0000000..4882a72
--- /dev/null
+++ b/samples/ApiDemos/res/layout/scrollbar2.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:scrollbarTrackVertical="@drawable/scrollbar_vertical_track"
+ android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb"
+ android:scrollbarSize="12dip">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text"/>
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/scrollbar3.xml b/samples/ApiDemos/res/layout/scrollbar3.xml
new file mode 100644
index 0000000..c272e45
--- /dev/null
+++ b/samples/ApiDemos/res/layout/scrollbar3.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <ScrollView
+ android:layout_width="100dip"
+ android:layout_height="120dip"
+ android:background="#FF0000">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_2_text" />
+ </LinearLayout>
+ </ScrollView>
+
+ <ScrollView
+ android:layout_width="100dip"
+ android:layout_height="120dip"
+ android:background="#00FF00"
+ android:paddingRight="12dip">
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/scrollbar_3_text"
+ android:textColor="#000000"
+ android:background="#60AA60" />
+ </ScrollView>
+
+ <ScrollView
+ android:id="@+id/view3"
+ android:layout_width="100dip"
+ android:layout_height="120dip"
+ android:background="@android:drawable/edit_text">
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textColor="#000000"
+ android:text="@string/scrollbar_3_text" />
+ </ScrollView>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <ScrollView
+ android:id="@+id/view4"
+ android:layout_width="100dip"
+ android:layout_height="120dip"
+ android:scrollbarStyle="outsideOverlay"
+ android:background="@android:drawable/edit_text">
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textColor="#000000"
+ android:text="@string/scrollbar_3_text" />
+ </ScrollView>
+ <ScrollView
+ android:id="@+id/view5"
+ android:layout_width="100dip"
+ android:layout_height="120dip"
+ android:scrollbarStyle="outsideInset"
+ android:background="@android:drawable/edit_text">
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textColor="#000000"
+ android:text="@string/scrollbar_3_text" />
+ </ScrollView>
+ </LinearLayout>
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/search_invoke.xml b/samples/ApiDemos/res/layout/search_invoke.xml
new file mode 100644
index 0000000..b78a616
--- /dev/null
+++ b/samples/ApiDemos/res/layout/search_invoke.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This activity exercises search invocation options -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <!-- Section: Information -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dip"
+ android:text="@string/msg_search" />
+
+ <!-- Section: Invocation -->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/search_sect_invocation" />
+
+ <Button android:id="@+id/btn_start_search"
+ android:text="@string/label_onsearchrequested"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <Spinner android:id="@+id/spinner_menu_mode"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:drawSelectorOnTop="true" />
+
+ <!-- Section: Options -->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/search_sect_options" />
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_search_query_prefill" />
+ <EditText android:id="@+id/txt_query_prefill"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxEms="10"
+ android:minEms="10" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_search_query_appdata" />
+ <EditText android:id="@+id/txt_query_appdata"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxEms="10"
+ android:minEms="10" />
+ </LinearLayout>
+ </LinearLayout>
+
+
+ </LinearLayout>
diff --git a/samples/ApiDemos/res/layout/search_query_results.xml b/samples/ApiDemos/res/layout/search_query_results.xml
new file mode 100644
index 0000000..03f1ae6
--- /dev/null
+++ b/samples/ApiDemos/res/layout/search_query_results.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This activity displays search queries and "results" -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <!-- Section: Information -->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dip"
+ android:text="@string/msg_search_results" />
+
+ <!-- Section: Search Query String -->
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_search_query" />
+ <TextView android:id="@+id/txt_query"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <!-- Section: Search Query application context data -->
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_search_appdata" />
+ <TextView android:id="@+id/txt_appdata"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <!-- Section: How the query was delivered -->
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_search_deliveredby" />
+ <TextView android:id="@+id/txt_deliveredby"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ </LinearLayout>
diff --git a/samples/ApiDemos/res/layout/seekbar_1.xml b/samples/ApiDemos/res/layout/seekbar_1.xml
new file mode 100644
index 0000000..513114e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/seekbar_1.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <SeekBar android:id="@+id/seek"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:max="100"
+ android:progress="50"
+ android:secondaryProgress="75" />
+
+ <TextView android:id="@+id/progress"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+ <TextView android:id="@+id/tracking"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/select_dialog.xml b/samples/ApiDemos/res/layout/select_dialog.xml
new file mode 100644
index 0000000..ad826af
--- /dev/null
+++ b/samples/ApiDemos/res/layout/select_dialog.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates different uses of the android.app.SelectDialog.
+ See corresponding Java code com.android.sdk.app.SelectDialogSamples.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/screen"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <Button android:id="@+id/show_dialog"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:text="@string/select_dialog_show"/>
+ <TextView android:id="@+id/message"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/send_result.xml b/samples/ApiDemos/res/layout/send_result.xml
new file mode 100644
index 0000000..386c3fc
--- /dev/null
+++ b/samples/ApiDemos/res/layout/send_result.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates receiving activity results.
+ See corresponding Java code com.android.sdk.app.ReceiveResult.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="8dip"
+ android:text="@string/pick_result"/>
+
+ <Button android:id="@+id/corky"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/corky">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/violet"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/violet">
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/service_start_arguments_controller.xml b/samples/ApiDemos/res/layout/service_start_arguments_controller.xml
new file mode 100644
index 0000000..f10a2c3
--- /dev/null
+++ b/samples/ApiDemos/res/layout/service_start_arguments_controller.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates starting and stopping a local service.
+ See corresponding Java code com.android.sdk.app.ServiceStartArguments.java. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent" android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingBottom="4dip"
+ android:text="@string/service_start_arguments_controller"/>
+
+ <Button android:id="@+id/start1"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start1_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/start2"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start2_service">
+ </Button>
+
+ <Button android:id="@+id/start3"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:text="@string/start3_service">
+ </Button>
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/shape_drawable_1.xml b/samples/ApiDemos/res/layout/shape_drawable_1.xml
new file mode 100644
index 0000000..037e844
--- /dev/null
+++ b/samples/ApiDemos/res/layout/shape_drawable_1.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates scrolling with a ScrollView. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="50dip"
+ android:src="@drawable/shape_1" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:src="@drawable/line" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="50dip"
+ android:src="@drawable/shape_2" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:src="@drawable/line" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="50dip"
+ android:src="@drawable/shape_3" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:src="@drawable/line" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="50dip"
+ android:src="@drawable/shape_4" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:src="@drawable/line" />
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="50dip"
+ android:src="@drawable/shape_5" />
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/spinner_1.xml b/samples/ApiDemos/res/layout/spinner_1.xml
new file mode 100644
index 0000000..3d5f3c1
--- /dev/null
+++ b/samples/ApiDemos/res/layout/spinner_1.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:padding="10dip"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/spinner_1_color"
+ />
+
+ <Spinner android:id="@+id/spinner1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:drawSelectorOnTop="true"
+ android:prompt="@string/spinner_1_color_prompt"
+ />
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dip"
+ android:text="@string/spinner_1_planet"
+ />
+
+ <Spinner android:id="@+id/spinner2"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:drawSelectorOnTop="true"
+ android:prompt="@string/spinner_1_planet_prompt"
+ />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/layout/status_bar_balloon.xml b/samples/ApiDemos/res/layout/status_bar_balloon.xml
new file mode 100644
index 0000000..58f1bbb
--- /dev/null
+++ b/samples/ApiDemos/res/layout/status_bar_balloon.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:baselineAligned="false"
+ android:gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="10dip" />
+ <TextView android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#ffffffff" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/status_bar_notifications.xml b/samples/ApiDemos/res/layout/status_bar_notifications.xml
new file mode 100644
index 0000000..11f3c96
--- /dev/null
+++ b/samples/ApiDemos/res/layout/status_bar_notifications.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_icons_only" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/happy"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_happy" />
+
+ <Button
+ android:id="@+id/neutral"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_ok" />
+
+ <Button
+ android:id="@+id/sad"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_sad" />
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dip"
+ android:text="@string/status_bar_notifications_icons_and_marquee" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/happyMarquee"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_happy" />
+
+ <Button
+ android:id="@+id/neutralMarquee"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_ok" />
+
+ <Button
+ android:id="@+id/sadMarquee"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_sad" />
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dip"
+ android:text="@string/status_bar_notifications_remote_views" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/happyViews"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_happy" />
+
+ <Button
+ android:id="@+id/neutralViews"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_ok" />
+
+ <Button
+ android:id="@+id/sadViews"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_sad" />
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dip"
+ android:text="@string/status_bar_notifications_defaults" />
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/defaultSound"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_default_sound" />
+
+ <Button
+ android:id="@+id/defaultVibrate"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_default_vibrate" />
+
+ <Button
+ android:id="@+id/defaultAll"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/status_bar_notifications_default_all" />
+
+ </LinearLayout>
+
+ <Button android:id="@+id/clear"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dip"
+ android:text="@string/status_bar_notifications_clear" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/styled_text.xml b/samples/ApiDemos/res/layout/styled_text.xml
new file mode 100644
index 0000000..610ea64
--- /dev/null
+++ b/samples/ApiDemos/res/layout/styled_text.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates styled string resources.
+ See corresponding Java code com.android.sdk.content.StyledText -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:text="@string/styled_text_rsrc"/>
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textStyle="normal"
+ android:text="@string/styled_text"/>
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ />
+
+ <TextView
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:text="@string/styled_text_prog"/>
+
+ <TextView android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textStyle="normal"/>
+
+</LinearLayout>
+
+
diff --git a/samples/ApiDemos/res/layout/surface_view_overlay.xml b/samples/ApiDemos/res/layout/surface_view_overlay.xml
new file mode 100644
index 0000000..a557e22
--- /dev/null
+++ b/samples/ApiDemos/res/layout/surface_view_overlay.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates changing view visibility. See corresponding Java code. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- Here is where we put the SurfaceView, in a frame so that we can
+ stack other views on top of it. -->
+ <FrameLayout
+ android:layout_width="fill_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <android.opengl.GLSurfaceView android:id="@+id/glsurfaceview"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+ <LinearLayout android:id="@+id/hidecontainer"
+ android:orientation="vertical"
+ android:visibility="gone"
+ android:background="@drawable/translucent_background"
+ android:gravity="center"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <Button android:id="@+id/hideme1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:visibility="gone"
+ android:text="@string/hide_me"/>
+
+ <Button android:id="@+id/hideme2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:visibility="gone"
+ android:text="@string/hide_me"/>
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center">
+
+ <Button android:id="@+id/vis"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_vis"/>
+
+ <Button android:id="@+id/invis"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_invis"/>
+
+ <Button android:id="@+id/gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_gone"/>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_1.xml b/samples/ApiDemos/res/layout/table_layout_1.xml
new file mode 100644
index 0000000..8d95e82
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_1.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_1_star"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_1_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_1_open_shortcut"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_1_triple_star"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_1_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_1_save_shortcut"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_1_star"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_1_quit"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_1_quit_shortcut"
+ android:padding="3dip" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_10.xml b/samples/ApiDemos/res/layout/table_layout_10.xml
new file mode 100644
index 0000000..6c558e7
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_10.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:stretchColumns="1">
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_10_user"
+ android:textStyle="bold"
+ android:gravity="right"
+ android:padding="3dip" />
+
+ <EditText android:id="@+id/username"
+ android:text="@string/table_layout_10_username_text"
+ android:padding="3dip"
+ android:scrollHorizontally="true" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_10_password"
+ android:textStyle="bold"
+ android:gravity="right"
+ android:padding="3dip" />
+
+ <EditText android:id="@+id/password"
+ android:text="@string/table_layout_10_password_text"
+ android:password="true"
+ android:padding="3dip"
+ android:scrollHorizontally="true" />
+ </TableRow>
+
+ <TableRow
+ android:gravity="right">
+
+ <Button android:id="@+id/cancel"
+ android:text="@string/table_layout_10_cancel" />
+
+ <Button android:id="@+id/login"
+ android:text="@string/table_layout_10_login" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_11.xml b/samples/ApiDemos/res/layout/table_layout_11.xml
new file mode 100644
index 0000000..e40e28a
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_11.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:stretchColumns="1">
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_7_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_open_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_7_save"
+ android:background="#FF00FF00"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_save_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <!-- Horizontally centers the content of the cell -->
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_7_save_as"
+ android:background="#FFFF0000"
+ android:layout_gravity="center_horizontal"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_save_as_shortcut"
+ android:background="#FFFF00FF"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_7_x"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_import"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <View
+ android:layout_height="68dip"
+ android:background="#FF909090" />
+ <!-- Aligns the content of the cell to the bottom right -->
+ <TextView
+ android:text="@string/table_layout_7_export"
+ android:background="#FFFF0000"
+ android:layout_gravity="right|bottom"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_export_shortcut"
+ android:background="#FF00FFFF"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_12.xml b/samples/ApiDemos/res/layout/table_layout_12.xml
new file mode 100644
index 0000000..423e34e
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_12.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_12_a"
+ android:background="#FFFF0000"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_12_b"
+ android:background="#FF00FF00"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_12_c"
+ android:background="#FF0000FF"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_12_d"
+ android:layout_span="2"
+ android:gravity="center_horizontal"
+ android:background="#FF0000FF"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_12_e"
+ android:background="#FF00FF00"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_12_f"
+ android:background="#FFFF00FF"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_12_g"
+ android:background="#FF00FF00"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_12_h"
+ android:background="#FFFF0000"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_12_a"
+ android:background="#FF00FF00"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_12_b"
+ android:layout_span="2"
+ android:gravity="center_horizontal"
+ android:background="#FF0000FF"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_12_g"
+ android:layout_span="3"
+ android:gravity="center_horizontal"
+ android:background="#FFC0C0C0"
+ android:padding="3dip" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_2.xml b/samples/ApiDemos/res/layout/table_layout_2.xml
new file mode 100644
index 0000000..c5134d3
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_2.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TableRow>
+ <Button
+ android:text="@string/table_layout_2_open" />
+ <TextView
+ android:text="@string/table_layout_2_path_1"
+ android:padding="3dip" />
+ </TableRow>
+ <TableRow>
+ <Button
+ android:text="@string/table_layout_2_save_all"/>
+ </TableRow>
+ <TableRow>
+ <Button
+ android:text="@string/table_layout_2_save"
+ android:visibility="invisible" />
+ <TextView
+ android:text="@string/table_layout_2_path_2"
+ android:padding="3dip" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_3.xml b/samples/ApiDemos/res/layout/table_layout_3.xml
new file mode 100644
index 0000000..44415fc
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_3.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:shrinkColumns="2, 3">
+
+ <!-- Rows have different number of columns and content doesn't fit on
+ screen: column 4 of row 2 shrinks all of the other columns -->
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_3_star"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_3_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_3_open_shortcut"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_3_triple_star"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_3_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_3_save_shortcut"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_3_too_long"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_3_star"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_3_quit"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_3_quit_shortcut"
+ android:padding="3dip" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_4.xml b/samples/ApiDemos/res/layout/table_layout_4.xml
new file mode 100644
index 0000000..a9b7b42
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_4.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Stretch some columns -->
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:stretchColumns="1">
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_4_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_4_open_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_4_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_4_save_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_5.xml b/samples/ApiDemos/res/layout/table_layout_5.xml
new file mode 100644
index 0000000..773d729
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_5.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Stretch some columns -->
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:stretchColumns="1">
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_5_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_5_open_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_5_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_5_save_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_5_save_as"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_5_save_as_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_5_import"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_5_export"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_5_export_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_5_quit"
+ android:padding="3dip" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_6.xml b/samples/ApiDemos/res/layout/table_layout_6.xml
new file mode 100644
index 0000000..9607f1c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_6.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Stretch some columns -->
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:stretchColumns="1">
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_6_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_6_open_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_6_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_6_save_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_6_save_as"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_6_save_as_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_6_x"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_6_import"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_6_x"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_6_export"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_6_export_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_6_quit"
+ android:padding="3dip" />
+ </TableRow>
+</TableLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_7.xml b/samples/ApiDemos/res/layout/table_layout_7.xml
new file mode 100644
index 0000000..88c4910
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_7.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TableLayout
+ android:id="@+id/menu"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:stretchColumns="1"
+ android:collapseColumns="2">
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_7_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_open_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_7_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_save_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_7_save_as"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_save_as_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_7_x"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_import"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_7_x"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_export"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_7_export_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <View
+ android:layout_height="2dip"
+ android:background="#FF909090" />
+ </TableLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <Button
+ android:id="@+id/toggle2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/table_layout_7_toggle_checkmarks" />
+ <Button
+ android:id="@+id/toggle1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/table_layout_7_toggle_shortcuts" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_8.xml b/samples/ApiDemos/res/layout/table_layout_8.xml
new file mode 100644
index 0000000..a63a8e8
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_8.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TableLayout
+ android:id="@+id/menu"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_8_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_8_open_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_8_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_8_save_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:layout_column="1"
+ android:text="@string/table_layout_8_save_as"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_8_save_as_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_8_x"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_8_import"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_8_x"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_8_export"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_8_export_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+ </TableLayout>
+
+ <Button
+ android:id="@+id/toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/table_layout_8_toggle_stretch" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/table_layout_9.xml b/samples/ApiDemos/res/layout/table_layout_9.xml
new file mode 100644
index 0000000..a2d6564
--- /dev/null
+++ b/samples/ApiDemos/res/layout/table_layout_9.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TableLayout
+ android:id="@+id/menu"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_9_open"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_9_open_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_9_save"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_9_save_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_9_save_as"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_9_save_as_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_9_save_all"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_9_save_all_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_9_import"
+ android:padding="3dip" />
+ </TableRow>
+
+ <TableRow>
+ <TextView
+ android:text="@string/table_layout_9_export"
+ android:padding="3dip" />
+ <TextView
+ android:text="@string/table_layout_9_export_shortcut"
+ android:gravity="right"
+ android:padding="3dip" />
+ </TableRow>
+ </TableLayout>
+
+ <Button
+ android:id="@+id/toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/table_layout_9_toggle_shrink" />
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/ApiDemos/res/layout/tabs1.xml b/samples/ApiDemos/res/layout/tabs1.xml
new file mode 100644
index 0000000..5a17693
--- /dev/null
+++ b/samples/ApiDemos/res/layout/tabs1.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView android:id="@+id/view1"
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/tabs_1_tab_1"/>
+
+ <TextView android:id="@+id/view2"
+ android:background="@drawable/red"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/tabs_1_tab_2"/>
+
+ <TextView android:id="@+id/view3"
+ android:background="@drawable/green"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/tabs_1_tab_3"/>
+
+</FrameLayout>
diff --git a/samples/ApiDemos/res/layout/text_switcher_1.xml b/samples/ApiDemos/res/layout/text_switcher_1.xml
new file mode 100644
index 0000000..d7be743
--- /dev/null
+++ b/samples/ApiDemos/res/layout/text_switcher_1.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <Button android:id="@+id/next"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/text_switcher_1_next_text" />
+
+ <TextSwitcher android:id="@+id/switcher"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/translucent_background.xml b/samples/ApiDemos/res/layout/translucent_background.xml
new file mode 100644
index 0000000..6b6e1cf
--- /dev/null
+++ b/samples/ApiDemos/res/layout/translucent_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates an activity with a fancy translucent background.
+ See corresponding Java code com.android.sdk.app.TranslucentBackground.java. -->
+
+<!-- This screen consists of a single text field that displays some text. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:gravity="center_vertical|center_horizontal"
+ android:text="@string/translucent_background"/>
diff --git a/samples/ApiDemos/res/layout/videoview.xml b/samples/ApiDemos/res/layout/videoview.xml
new file mode 100644
index 0000000..4f35ace
--- /dev/null
+++ b/samples/ApiDemos/res/layout/videoview.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+
+ <VideoView
+ android:id="@+id/surface_view"
+ android:layout_width="320px"
+ android:layout_height="240px"
+ />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/visibility_1.xml b/samples/ApiDemos/res/layout/visibility_1.xml
new file mode 100644
index 0000000..ad94602
--- /dev/null
+++ b/samples/ApiDemos/res/layout/visibility_1.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- Demonstrates changing view visibility. See corresponding Java code. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:background="@drawable/box"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:background="@drawable/red"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_view_1"/>
+
+ <TextView android:id="@+id/victim"
+ android:background="@drawable/green"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_view_2"/>
+
+ <TextView
+ android:background="@drawable/blue"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_view_3"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <Button android:id="@+id/vis"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_vis"/>
+
+ <Button android:id="@+id/invis"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_invis"/>
+
+ <Button android:id="@+id/gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/visibility_1_gone"/>
+
+ </LinearLayout>
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/voice_recognition.xml b/samples/ApiDemos/res/layout/voice_recognition.xml
new file mode 100644
index 0000000..2db4a72
--- /dev/null
+++ b/samples/ApiDemos/res/layout/voice_recognition.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.
+ -->
+
+<!-- This activity displays UI for launching voice recognition -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dip"
+ android:text="@string/voice_recognition_prompt" />
+
+ <Button android:id="@+id/btn_speak"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/speak_button" />
+
+ <ListView android:id="@+id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" />
+
+ </LinearLayout>
diff --git a/samples/ApiDemos/res/layout/webview_1.xml b/samples/ApiDemos/res/layout/webview_1.xml
new file mode 100644
index 0000000..91fca39
--- /dev/null
+++ b/samples/ApiDemos/res/layout/webview_1.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <WebView android:id="@+id/wv1"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv2"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv3"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv4"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv5"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv6"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv7"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv8"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv9"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+
+ <WebView android:id="@+id/wv10"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ />
+ </LinearLayout>
+
+ </ScrollView>
diff --git a/samples/ApiDemos/res/menu/category_order.xml b/samples/ApiDemos/res/menu/category_order.xml
new file mode 100644
index 0000000..cb2dde9
--- /dev/null
+++ b/samples/ApiDemos/res/menu/category_order.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- This group uses the default category. -->
+ <group android:id="@+id/most_used_items">
+
+ <item android:id="@+id/last_most_item"
+ android:orderInCategory="10"
+ android:title="@string/last_most_often" />
+
+ <item android:id="@+id/middle_most_item"
+ android:orderInCategory="7"
+ android:title="@string/middle_most_often" />
+
+ <item android:id="@+id/first_most_item"
+ android:orderInCategory="4"
+ android:title="@string/first_most_often" />
+
+ </group>
+
+ <!-- This group uses the secondary category, which is used for less oftenly used items.
+ Notice these items will show up after the above items.
+ (Furthermore, notice how the orders in each category are independent from the other
+ category.) -->
+ <group android:id="@+id/least_used_items"
+ android:menuCategory="secondary">
+
+ <item android:id="@+id/last_least_item"
+ android:orderInCategory="3"
+ android:title="@string/last_least_often" />
+
+ <item android:id="@+id/middle_least_item"
+ android:orderInCategory="2"
+ android:title="@string/middle_least_often" />
+
+ <item android:id="@+id/first_least_item"
+ android:orderInCategory="0"
+ android:title="@string/first_least_often" />
+
+ </group>
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/checkable.xml b/samples/ApiDemos/res/menu/checkable.xml
new file mode 100644
index 0000000..17fae65
--- /dev/null
+++ b/samples/ApiDemos/res/menu/checkable.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Checkable items appear only in submenus or context menus. -->
+
+ <!-- Carefully look at the attribute name checkableBehavior on groups, but
+ the attribute name checkable on items. The checkableBehavior encompasses
+ the number of items that will be checkable within that group. -->
+
+ <item android:title="None">
+ <menu>
+ <!-- The none checkableBehavior is default, but we explicitly show it here. -->
+ <group android:id="@+id/noncheckable_group"
+ android:checkableBehavior="none">
+ <!-- Notice how these items inherit from the group. -->
+ <item android:id="@+id/noncheckable_item_1"
+ android:title="@string/item_1" />
+ <item android:id="@+id/noncheckable_item_2"
+ android:title="@string/item_2" />
+ <item android:id="@+id/noncheckable_item_3"
+ android:title="@string/item_3" />
+ </group>
+ </menu>
+ </item>
+
+ <item android:title="All">
+ <menu>
+ <group android:id="@+id/checkable_group"
+ android:checkableBehavior="all">
+ <!-- Notice how these items inherit from the group. -->
+ <item android:id="@+id/checkable_item_1"
+ android:title="@string/item_1" />
+ <item android:id="@+id/checkable_item_2"
+ android:title="@string/item_2"
+ android:checked="true" />
+ <item android:id="@+id/checkable_item_3"
+ android:title="@string/item_3"
+ android:checked="true" />
+ </group>
+ </menu>
+ </item>
+
+ <item android:title="Single">
+ <menu>
+ <group android:id="@+id/exclusive_checkable_group"
+ android:checkableBehavior="single">
+ <!-- Notice how these items inherit from the group. -->
+ <item android:id="@+id/exclusive_checkable_item_1"
+ android:title="@string/item_1" />
+ <item android:id="@+id/exclusive_checkable_item_2"
+ android:title="@string/item_2" />
+ <item android:id="@+id/exclusive_checkable_item_3"
+ android:title="@string/item_3"
+ android:checked="true" />
+ </group>
+ </menu>
+ </item>
+
+ <item android:title="All without group">
+ <menu>
+ <!-- Notice how these items have each set. -->
+ <item android:id="@+id/nongroup_checkable_item_1"
+ android:title="@string/item_1"
+ android:checkable="true" />
+ <item android:id="@+id/nongroup_checkable_item_2"
+ android:title="@string/item_2"
+ android:checkable="true"
+ android:checked="true" />
+ <item android:id="@+id/nongroup_checkable_item_3"
+ android:title="@string/item_3"
+ android:checkable="true"
+ android:checked="true" />
+ </menu>
+ </item>
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/disabled.xml b/samples/ApiDemos/res/menu/disabled.xml
new file mode 100644
index 0000000..647ec2e
--- /dev/null
+++ b/samples/ApiDemos/res/menu/disabled.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@+id/enabled_item"
+ android:title="Enabled"
+ android:icon="@drawable/stat_happy" />
+
+ <item android:id="@+id/disabled_item"
+ android:title="Disabled"
+ android:enabled="false"
+ android:icon="@drawable/stat_sad" />
+
+ <item android:id="@+id/enabled_item_2"
+ android:title="Enabled"
+ android:icon="@drawable/stat_happy" />
+
+ <item android:id="@+id/disabled_item_2"
+ android:title="Disabled"
+ android:enabled="false"
+ android:icon="@drawable/stat_sad" />
+
+ <item android:id="@+id/enabled_item_3"
+ android:title="Enabled"
+ android:icon="@drawable/stat_happy" />
+
+ <item android:id="@+id/disabled_item_3"
+ android:title="Disabled"
+ android:enabled="false"
+ android:icon="@drawable/stat_sad" />
+
+ <item android:id="@+id/enabled_item_4"
+ android:title="Enabled"
+ android:icon="@drawable/stat_happy" />
+
+ <item android:id="@+id/disabled_item_4"
+ android:title="Disabled"
+ android:enabled="false"
+ android:icon="@drawable/stat_sad" />
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/groups.xml b/samples/ApiDemos/res/menu/groups.xml
new file mode 100644
index 0000000..46c04f5
--- /dev/null
+++ b/samples/ApiDemos/res/menu/groups.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@+id/browser_visibility"
+ android:title="@string/browser_visibility" />
+
+ <group android:id="@+id/browser">
+
+ <item android:id="@+id/refresh"
+ android:title="@string/browser_refresh" />
+
+ <item android:id="@+id/bookmark"
+ android:title="@string/browser_bookmark" />
+
+ </group>
+
+ <item android:id="@+id/email_visibility"
+ android:title="@string/email_visibility" />
+
+ <group android:id="@+id/email">
+
+ <item android:id="@+id/reply"
+ android:title="@string/email_reply" />
+
+ <item android:id="@+id/forward"
+ android:title="@string/email_forward" />
+
+ </group>
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/order.xml b/samples/ApiDemos/res/menu/order.xml
new file mode 100644
index 0000000..c73121f
--- /dev/null
+++ b/samples/ApiDemos/res/menu/order.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- These are in reverse order in this resource, but the orderInCategory attribute will
+ order them for the menu (they all have the same default category). -->
+
+ <item android:id="@+id/fourth_item"
+ android:orderInCategory="3"
+ android:title="Fourth" />
+
+ <item android:id="@+id/third_item"
+ android:orderInCategory="2"
+ android:title="Third" />
+
+ <item android:id="@+id/second_item"
+ android:orderInCategory="1"
+ android:title="Second" />
+
+ <item android:id="@+id/first_item"
+ android:orderInCategory="0"
+ android:title="First" />
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/shortcuts.xml b/samples/ApiDemos/res/menu/shortcuts.xml
new file mode 100644
index 0000000..b5e938a
--- /dev/null
+++ b/samples/ApiDemos/res/menu/shortcuts.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@+id/invisible_item"
+ android:visible="false"
+ android:alphabeticShortcut="i"
+ android:title="Invisible item" />
+
+ <item android:id="@+id/a_item"
+ android:alphabeticShortcut="a"
+ android:title="Alvin" />
+
+ <item android:id="@+id/b_item"
+ android:alphabeticShortcut="b"
+ android:title="Bart" />
+
+ <item android:id="@+id/c_item"
+ android:alphabeticShortcut="c"
+ android:title="Chris" />
+
+ <item android:id="@+id/d_item"
+ android:alphabeticShortcut="d"
+ android:title="David" />
+
+ <item android:id="@+id/e_item"
+ android:alphabeticShortcut="e"
+ android:title="Eric" />
+
+ <item android:id="@+id/f_item"
+ android:alphabeticShortcut="f"
+ android:title="Frank" />
+
+ <item android:id="@+id/g_item"
+ android:alphabeticShortcut="g"
+ android:title="Gary" />
+
+ <item android:id="@+id/h_item"
+ android:alphabeticShortcut="h"
+ android:title="Henry" />
+
+ <item android:id="@+id/excl_item"
+ android:alphabeticShortcut="!"
+ android:title="Exclamation" />
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/submenu.xml b/samples/ApiDemos/res/menu/submenu.xml
new file mode 100644
index 0000000..24eff76
--- /dev/null
+++ b/samples/ApiDemos/res/menu/submenu.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:title="Normal 1" />
+
+ <item android:id="@+id/submenu"
+ android:title="Emotions">
+
+ <menu>
+
+ <item android:id="@+id/happy"
+ android:title="Happy"
+ android:icon="@drawable/stat_happy" />
+
+ <item android:id="@+id/neutral"
+ android:title="Neutral"
+ android:icon="@drawable/stat_neutral" />
+
+ <item android:id="@+id/sad"
+ android:title="Sad"
+ android:icon="@drawable/stat_sad" />
+
+ </menu>
+
+ </item>
+
+ <item android:title="Normal 2" />
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/title_icon.xml b/samples/ApiDemos/res/menu/title_icon.xml
new file mode 100644
index 0000000..72030a9
--- /dev/null
+++ b/samples/ApiDemos/res/menu/title_icon.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@+id/happy"
+ android:title="Happy"
+ android:icon="@drawable/stat_happy" />
+
+ <item android:id="@+id/neutral"
+ android:title="Neutral"
+ android:icon="@drawable/stat_neutral" />
+
+ <item android:id="@+id/sad"
+ android:title="Sad"
+ android:icon="@drawable/stat_sad" />
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/title_only.xml b/samples/ApiDemos/res/menu/title_only.xml
new file mode 100644
index 0000000..44162b1
--- /dev/null
+++ b/samples/ApiDemos/res/menu/title_only.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@+id/jump"
+ android:title="@string/jump" />
+
+ <item android:id="@+id/dive"
+ android:title="@string/dive" />
+
+</menu>
diff --git a/samples/ApiDemos/res/menu/visible.xml b/samples/ApiDemos/res/menu/visible.xml
new file mode 100644
index 0000000..b41698d
--- /dev/null
+++ b/samples/ApiDemos/res/menu/visible.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@+id/visible_item"
+ android:title="Visible"
+ android:alphabeticShortcut="a" />
+
+ <item android:id="@+id/hidden_item"
+ android:title="Hidden"
+ android:visible="false"
+ android:alphabeticShortcut="b" />
+
+ <group android:id="@+id/hidden_group"
+ android:visible="false">
+
+ <item android:id="@+id/hidden_by_group"
+ android:title="Hidden by group"
+ android:alphabeticShortcut="c" />
+
+ </group>
+
+</menu>
diff --git a/samples/ApiDemos/res/raw/test_cbr.mp3 b/samples/ApiDemos/res/raw/test_cbr.mp3
new file mode 100755
index 0000000..7204d27
--- /dev/null
+++ b/samples/ApiDemos/res/raw/test_cbr.mp3
Binary files differ
diff --git a/samples/ApiDemos/res/values/arrays.xml b/samples/ApiDemos/res/values/arrays.xml
new file mode 100644
index 0000000..ca3003f
--- /dev/null
+++ b/samples/ApiDemos/res/values/arrays.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <!-- Used in View/Spinner1.java -->
+ <string-array name="colors">
+ <item>red</item>
+ <item>orange</item>
+ <item>yellow</item>
+ <item>green</item>
+ <item>blue</item>
+ <item>violet</item>
+ </string-array>
+
+ <!-- Used in View/Spinner1.java -->
+ <string-array name="planets">
+ <item>Mercury</item>
+ <item>Venus</item>
+ <item>Earth</item>
+ <item>Mars</item>
+ <item>Jupiter</item>
+ <item>Saturn</item>
+ <item>Uranus</item>
+ <item>Neptune</item>
+ <item>Pluto</item>
+ </string-array>
+
+ <!-- Used in App/SearchInvoke.java -->
+ <string-array name="search_menuModes">
+ <item>Search Key</item>
+ <item>Menu Item</item>
+ <item>Type-To-Search</item>
+ <item>Disabled</item>
+ </string-array>
+
+ <!-- Used in app/dialog examples -->
+ <string-array name="select_dialog_items">
+ <item>Command one</item>
+ <item>Command two</item>
+ <item>Command three</item>
+ <item>Command four</item>
+ </string-array>
+
+ <string-array name="select_dialog_items2">
+ <item>Map</item>
+ <item>Satellite</item>
+ <item>Traffic</item>
+ <item>Street view</item>
+ </string-array>
+
+ <string-array name="select_dialog_items3">
+ <item>Every Monday</item>
+ <item>Every Tuesday</item>
+ <item>Every Wednesday</item>
+ <item>Every Thursday</item>
+ <item>Every Friday</item>
+ <item>Every Saturday</item>
+ <item>Every Sunday</item>
+ </string-array>
+
+ <!-- Used in app/menu examples -->
+ <string-array name="entries_list_preference">
+ <item>Alpha Option 01</item>
+ <item>Beta Option 02</item>
+ <item>Charlie Option 03</item>
+ </string-array>
+
+ <!-- Used in app/menu examples -->
+ <string-array name="entryvalues_list_preference">
+ <item>alpha</item>
+ <item>beta</item>
+ <item>charlie</item>
+ </string-array>
+
+</resources>
diff --git a/samples/ApiDemos/res/values/attrs.xml b/samples/ApiDemos/res/values/attrs.xml
new file mode 100644
index 0000000..53f0034
--- /dev/null
+++ b/samples/ApiDemos/res/values/attrs.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <!-- These are the attributes that we want to retrieve from the theme
+ in app/PreferencesFromCode.java -->
+ <declare-styleable name="TogglePrefAttrs">
+ <attr name="android:preferenceLayoutChild" />
+ </declare-styleable>
+
+ <!-- These are the attributes that we want to retrieve from the theme
+ in view/Gallery1.java -->
+ <declare-styleable name="Gallery1">
+ <attr name="android:galleryItemBackground" />
+ </declare-styleable>
+
+ <declare-styleable name="LabelView">
+ <attr name="text" format="string" />
+ <attr name="textColor" format="color" />
+ <attr name="textSize" format="dimension" />
+ </declare-styleable>
+</resources>
diff --git a/samples/ApiDemos/res/values/colors.xml b/samples/ApiDemos/res/values/colors.xml
new file mode 100644
index 0000000..f2534d1
--- /dev/null
+++ b/samples/ApiDemos/res/values/colors.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <drawable name="red">#7f00</drawable>
+ <drawable name="blue">#770000ff</drawable>
+ <drawable name="green">#7700ff00</drawable>
+ <drawable name="yellow">#77ffff00</drawable>
+
+ <drawable name="screen_background_black">#ff000000</drawable>
+ <drawable name="translucent_background">#e0000000</drawable>
+ <drawable name="transparent_background">#00000000</drawable>
+
+ <color name="solid_red">#f00</color>
+ <color name="solid_blue">#0000ff</color>
+ <color name="solid_green">#f0f0</color>
+ <color name="solid_yellow">#ffffff00</color>
+
+</resources>
diff --git a/samples/ApiDemos/res/values/ids.xml b/samples/ApiDemos/res/values/ids.xml
new file mode 100644
index 0000000..17a3895
--- /dev/null
+++ b/samples/ApiDemos/res/values/ids.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <item type="id" name="snack" />
+</resources>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
new file mode 100644
index 0000000..bd1b0a3
--- /dev/null
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -0,0 +1,824 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="activity_sample_code">API Demos</string>
+
+ <!-- =============================== -->
+ <!-- app/activity examples strings -->
+ <!-- =============================== -->
+
+ <string name="tabs_1_tab_1">tab1</string>
+ <string name="tabs_1_tab_2">tab2</string>
+ <string name="tabs_1_tab_3">tab3</string>
+
+ <string name="activity_hello_world">App/Activity/<b>Hello <i>World</i></b></string>
+ <string name="hello_world"><b>Hello, <i>World!</i></b></string>
+
+ <string name="activity_dialog">App/Activity/Dialog</string>
+ <string name="dialog_activity_text">Example of how you can use the
+ Theme.Dialog theme to make an activity that looks like a
+ dialog.</string>
+
+ <string name="activity_custom_dialog">App/Activity/Custom Dialog</string>
+ <string name="custom_dialog_activity_text">Example of how you can use a
+ custom Theme.Dialog theme to make an activity that looks like a
+ customized dialog, here with an ugly frame.</string>
+
+ <string name="activity_translucent">App/Activity/Translucent</string>
+ <string name="translucent_background">Example of how you can make an
+ activity have a translucent background, compositing over
+ whatever is behind it.</string>
+
+ <string name="activity_translucent_blur">App/Activity/Translucent Blur</string>
+
+ <string name="activity_save_restore">App/Activity/Save & Restore State</string>
+ <string name="save_restore_msg">Demonstration of saving and restoring activity state in onSaveInstanceState() and onCreate().</string>
+ <string name="saves_state">This text field saves its state:</string>
+ <string name="no_saves_state">This text field does not save its state:</string>
+ <string name="initial_text">Initial text.</string>
+
+ <string name="activity_persistent">App/Activity/Persistent State</string>
+ <string name="persistent_msg">Demonstration of persistent activity state with getPreferences(0).edit() and getPreferences(0).</string>
+
+ <string name="activity_receive_result">App/Activity/Receive Result</string>
+ <string name="pick_result">Pick a result to send, or BACK to cancel.</string>
+ <string name="corky">Corky</string>
+ <string name="violet">Violet</string>
+
+ <string name="activity_forwarding">App/Activity/Forwarding</string>
+ <string name="forwarding">Press the button to go forward to the next activity. This activity will stop, so you will no longer see it when going back.</string>
+ <string name="go">Go</string>
+ <string name="forward_target">Press back button and notice we don\'t see the previous activity.</string>
+
+ <string name="activity_redirect">App/Activity/Redirection</string>
+ <string name="redirect_enter">Press the button to start the example. The next activity will conditionally redirect to another activity to collect data from the user.</string>
+ <string name="redirect_main">You now see the main activity running normally because the user text has been set to:</string>
+ <string name="clear_text">Clear and Exit</string>
+ <string name="new_text">New Text</string>
+ <string name="redirect_getter">Enter the text that will be used by the main activity. Press back to cancel.</string>
+ <string name="apply">Apply</string>
+
+ <string name="activity_menu">App/Activity/Menu</string>
+ <string name="open_menu">Open menu</string>
+ <string name="close_menu">Close menu</string>
+ <string name="toggle_scenery">Toggle scenery</string>
+ <string name="toggle_dogs">Toggle dogs</string>
+ <string name="long_click_for_context_menu">Long click for context menu</string>
+
+ <string name="local_service_started">Local service has started</string>
+ <string name="local_service_stopped">Local service has stopped</string>
+ <string name="local_service_label">Sample Local Service</string>
+
+ <string name="activity_local_service_controller">App/Service/Local Service Controller</string>
+ <string name="local_service_controller">This demonstrates how you can implement persistent services that
+ may be started and stopped as desired.</string>
+ <string name="start_service">Start Service</string>
+ <string name="stop_service">Stop Service</string>
+
+ <string name="activity_local_service_binding">App/Service/Local Service Binding</string>
+ <string name="local_service_binding">This demonstrates how you can connect with a persistent
+ service. Notice how it automatically starts for you, and play around with the
+ interaction between this and Local Service Controller.</string>
+ <string name="bind_service">Bind Service</string>
+ <string name="unbind_service">Unbind Service</string>
+ <string name="local_service_connected">Connected to local service</string>
+ <string name="local_service_disconnected">Disconnected from local service</string>
+
+ <string name="remote_service_started">Remote service has started</string>
+ <string name="remote_service_stopped">Remote service has stopped</string>
+ <string name="remote_service_label">Sample Remote Service</string>
+
+ <string name="activity_remote_service_controller">App/Service/Remote Service Controller</string>
+ <string name="remote_service_controller">This demonstrates how you can implement persistent services
+ running in a separate process that may be started and stopped as desired.</string>
+
+ <string name="activity_remote_service_binding">App/Service/Remote Service Binding</string>
+ <string name="remote_service_binding">This demonstrates how you can connect with a persistent
+ service running in another process. Use the kill button to see what happens when
+ the process crashes.</string>
+ <string name="kill_process">Kill Process</string>
+ <string name="remote_service_connected">Connected to remote service</string>
+ <string name="remote_service_disconnected">Disconnected from remote service</string>
+ <string name="remote_call_failed">Failure calling remote service</string>
+
+ <string name="service_arguments_started">"Started with arguments: "</string>
+ <string name="service_arguments_stopped">Finished arguments,
+ stopping.</string>
+ <string name="service_start_arguments_label">Sample Service Start Arguments
+ </string>
+
+ <string name="activity_service_start_arguments_controller">App/Service/Service
+ Start Arguments Controller
+ </string>
+ <string name="service_start_arguments_controller">This demonstrates how
+ service can be started with arguments, and run until all arguments are
+ processed.
+ </string>
+ <string name="start1_service">Start with \"One\"</string>
+ <string name="start2_service">Start with \"Two\"</string>
+ <string name="start3_service">Start with \"Three\"</string>
+
+ <string name="one_shot_received">The one-shot alarm has gone off</string>
+ <string name="repeating_received">The repeating alarm has gone off</string>
+
+ <string name="activity_alarm_controller">App/Alarm/Alarm Controller</string>
+ <string name="alarm_controller">This demonstrates how to schedule and handle
+ one-shot and repeating alarms.</string>
+ <string name="one_shot_alarm">One Shot Alarm</string>
+ <string name="start_repeating_alarm">Start Repeating Alarm</string>
+ <string name="stop_repeating_alarm">Stop Repeating Alarm</string>
+ <string name="one_shot_scheduled">One-shot alarm will go off in 30 seconds based on
+ the real time clock. Try changing the current time before then!</string>
+ <string name="repeating_scheduled">Repeating alarm will go off in 15 seconds and
+ every 15 seconds after based on the elapsed realtime clock</string>
+ <string name="repeating_unscheduled">Repeating alarm has been unscheduled</string>
+
+ <string name="alarm_service_started">The alarm service has started running</string>
+ <string name="alarm_service_finished">The alarm service has finished running</string>
+ <string name="alarm_service_label">Sample Alarm Service</string>
+
+ <string name="activity_alarm_service">App/Alarm/Alarm Service</string>
+ <string name="alarm_service">This demonstrates how to schedule a repeating
+ alarm that will initiate a long-lived operation through a service.</string>
+ <string name="start_alarm_service">Start Alarm Service</string>
+ <string name="stop_alarm_service">Stop Alarm Service</string>
+ <string name="alarm_service_scheduled">Alarm service will run now, and then every
+ 30 seconds for 15 seconds</string>
+ <string name="alarm_service_unscheduled">Alarm service has been unscheduled</string>
+
+ <string name="activity_local_sample">App/Instrumentation/Local Sample</string>
+ <string name="local_sample">This demonstrates an Instrumentation that runs against
+ one of our own classes. Note that this activity will be killed as
+ a side-effect of starting instrumentation on its own application.</string>
+
+ <string name="activity_contacts_filter">App/Instrumentation/Contacts Filter</string>
+ <string name="contacts_filter">This demonstrates an Instrumentation package that
+ launches the contacts list and simulates user events to filter it.</string>
+
+ <string name="pick_image_label">App/Activity/PickImage</string>
+ <string name="pick_image">Pick Image</string>
+
+ <string name="short_notification_text">Short notification</string>
+ <string name="long_notification_text">This is a long notification. See, you might need a second more to read it.</string>
+ <string name="status_bar_notification_title">Sample Notification</string>
+
+ <string name="notifying_service_controller">This service will update a status bar notification
+ every 5 seconds for a minute</string>
+
+ <string name="activity_custom_title">App/Activity/Custom Title</string>
+ <string name="custom_title_left">Left is best</string>
+ <string name="custom_title_right">Right is always right</string>
+ <string name="custom_title_left_button">Change Left</string>
+ <string name="custom_title_right_button">Change Right</string>
+
+ <string name="activity_reorder">App/Activity/Reorder Activities</string>
+ <string name="reorder_on_launch">This is the first of a sequence of four Activities. A button on the fourth will use the Intent.FLAG_ACTIVITY_REORDER_TO_FRONT flag to bring the second of the activities to the front of the history stack. After that, proceeding back through the history should begin with the newly-frontmost second reorder activity, then the fourth, the third, and finally the first.</string>
+ <string name="reorder_launch_two">Go to the second</string>
+ <string name="reorder_two_text">This is the second in a sequence of four Activities.</string>
+ <string name="reorder_launch_three">Go to the third</string>
+ <string name="reorder_three_text">This is the third of a sequence of four Activities.</string>
+ <string name="reorder_launch_four">Go to the fourth</string>
+ <string name="reorder_four_text">This is the last in a sequence of four Activities.</string>
+ <string name="reorder_second_to_front">Bring the second in front</string>
+
+ <string name="menu_from_xml_title">App/Menu/Inflate from XML</string>
+ <string name="menu_from_xml_instructions_press_menu">Select a menu resource and press the menu key.</string>
+ <string name="menu_from_xml_instructions_go_back">If you want to choose another menu resource, go back and re-run this activity.</string>
+
+ <string name="voice_recognition">App/Voice Recognition</string>
+
+ <!-- ============================== -->
+ <!-- app/content examples strings -->
+ <!-- ============================== -->
+
+ <string name="activity_styled_text">Content/Resources/<i>Styled</i> <b>Text</b></string>
+ <string name="styled_text_rsrc">Initialized from a resource:</string>
+ <string name="styled_text">Plain, <b>bold</b>, <i>italic</i>, <b><i>bold-italic</i></b></string>
+ <string name="styled_text_prog">Assigned programmatically:</string>
+
+ <string name="activity_read_asset">Content/Assets/Read Asset</string>
+
+ <string name="activity_themes">Content/Resources/Themes</string>
+ <string name="activity_resources">Content/Resources/Resources</string>
+
+ <!-- ============================== -->
+ <!-- app/intents examples strings -->
+ <!-- ============================== -->
+
+ <string name="activity_intents">App/Intents</string>
+ <string name="intents">Example of launching various Intents.</string>
+ <string name="get_music">Get Music</string>
+
+ <!-- =================================== -->
+ <!-- app/notification examples strings -->
+ <!-- =================================== -->
+
+ <string name="short_notification">Short notification.</string>
+ <string name="long_notification">Long notification.</string>
+ <string name="short_top_notification">Short top.</string>
+ <string name="short_bottom_notification">Short bottom.</string>
+ <string name="short_center_notification">Short center.</string>
+ <string name="short_left_notification">Short left.</string>
+ <string name="short_right_notification">Short right.</string>
+ <string name="custom_notification">Custom Notification:</string>
+ <string name="custom_notification_button">With a Button</string>
+
+ <string name="status_bar_notifications_icons_only">Icons only</string>
+ <string name="status_bar_notifications_icons_and_marquee">Icons and marquee</string>
+ <string name="status_bar_notifications_remote_views">Use remote views in balloon</string>
+ <string name="status_bar_notifications_defaults">Use default values where applicable</string>
+ <string name="status_bar_notifications_happy">:-)</string>
+ <string name="status_bar_notifications_ok">:-|</string>
+ <string name="status_bar_notifications_sad">:-(</string>
+ <string name="status_bar_notifications_happy_message">I am happy</string>
+ <string name="status_bar_notifications_ok_message">I am ok</string>
+ <string name="status_bar_notifications_sad_message">I am sad</string>
+ <string name="status_bar_notifications_clear">Clear notification</string>
+ <string name="status_bar_notifications_mood_title">Mood ring</string>
+ <string name="status_bar_notifications_default_sound">Sound</string>
+ <string name="status_bar_notifications_default_vibrate">Vibrate</string>
+ <string name="status_bar_notifications_default_all">All</string>
+
+ <!-- ============================== -->
+ <!-- app/dialog examples strings -->
+ <!-- ============================== -->
+
+ <string name="activity_alert_dialog">App/Dialog</string>
+ <string name="alert_dialog_two_buttons">OK Cancel dialog with a message</string>
+ <string name="alert_dialog_two_buttons2">OK Cancel dialog with a long message</string>
+ <string name="alert_dialog_select_button">List dialog</string>
+ <string name="alert_dialog_single_choice">Single choice list</string>
+ <string name="alert_dialog_multi_choice">Repeat alarm</string>
+ <string name="alert_dialog_progress_button">Progress dialog</string>
+ <string name="alert_dialog_text_entry">Text Entry dialog</string>
+ <string name="alert_dialog_username">Name:</string>
+ <string name="alert_dialog_password">Password:</string>
+ <string name="alert_dialog_two_buttons_title">
+ Lorem ipsum dolor sit aie consectetur adipiscing\nPlloaso mako nuto
+ siwuf cakso dodtos anr koop.
+ </string>
+ <string name="alert_dialog_two_buttons_msg">Header title</string>
+ <string name="alert_dialog_two_buttons2_msg">
+ Plloaso mako nuto siwuf cakso dodtos anr koop a
+ cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
+ ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
+ Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
+ kipg naar mixent phona. Cak pwico siructiun
+ ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg
+ </string>
+ <string name="alert_dialog_ok">OK</string>
+ <string name="alert_dialog_hide">Hide</string>
+ <string name="alert_dialog_something">Something</string>
+ <string name="alert_dialog_cancel">Cancel</string>
+ <string name="alert_dialog_progress_text1">34<xliff:g id="percent">%</xliff:g></string>
+ <string name="alert_dialog_progress_text2">145/305 KB</string>
+
+ <string name="select_dialog">Header title</string>
+ <string name="select_dialog_show">List dialog</string>
+
+ <!-- ============================== -->
+ <!-- app/menu examples strings -->
+ <!-- ============================== -->
+
+ <string name="last_most_often">Last most often</string>
+ <string name="middle_most_often">Middle most often</string>
+ <string name="first_most_often">First most often</string>
+ <string name="last_least_often">Last least often</string>
+ <string name="middle_least_often">Middle least often</string>
+ <string name="first_least_often">First least often</string>
+ <string name="item_1">Item 1</string>
+ <string name="item_2">Item 2</string>
+ <string name="item_3">Item 3</string>
+ <string name="browser_visibility">Browser visibility</string>
+ <string name="browser_refresh">Refresh</string>
+ <string name="browser_bookmark">Bookmark</string>
+ <string name="email_visibility">Email visibility</string>
+ <string name="email_reply">Reply</string>
+ <string name="email_forward">Forward</string>
+ <string name="jump">Jump</string>
+ <string name="dive">Dive</string>
+
+ <!-- ============================== -->
+ <!-- app/menu examples strings -->
+ <!-- ============================== -->
+
+ <string name="preferences_from_xml">App/Preferences/1. Preferences from XML</string>
+ <string name="launching_preferences">App/Preferences/2. Launching preferences</string>
+ <string name="preference_dependencies">App/Preferences/3. Preference dependencies</string>
+ <string name="default_values">App/Preferences/4. Default values</string>
+ <string name="preferences_from_code">App/Preferences/5. Preferences from code</string>
+ <string name="advanced_preferences">App/Preferences/6. Advanced preferences</string>
+
+ <string name="launch_preference_activity">Launch PreferenceActivity</string>
+ <string name="counter_value_is">The counter value is</string>
+
+ <string name="inline_preferences">In-line preferences</string>
+ <string name="dialog_based_preferences">Dialog-based preferences</string>
+ <string name="launch_preferences">Launch preferences</string>
+ <string name="preference_attributes">Preference attributes</string>
+
+ <string name="title_toggle_preference">Toggle preference</string>
+ <string name="summary_toggle_preference">This is a toggle button</string>
+
+ <string name="title_checkbox_preference">Checkbox preference</string>
+ <string name="summary_checkbox_preference">This is a checkbox</string>
+
+ <string name="title_yesno_preference">Yes or no preference</string>
+ <string name="summary_yesno_preference">An example that uses a yes/no dialog</string>
+ <string name="dialog_title_yesno_preference">Do you like bananas?</string>
+
+ <string name="title_edittext_preference">Edit text preference</string>
+ <string name="summary_edittext_preference">An example that uses an edit text dialog</string>
+ <string name="dialog_title_edittext_preference">Enter your favorite animal</string>
+
+ <string name="title_list_preference">List preference</string>
+ <string name="summary_list_preference">An example that uses a list dialog</string>
+ <string name="dialog_title_list_preference">Choose one</string>
+
+ <string name="title_screen_preference">Screen preference</string>
+ <string name="summary_screen_preference">Shows another screen of preferences</string>
+
+ <string name="title_next_screen_toggle_preference">Toggle preference</string>
+ <string name="summary_next_screen_toggle_preference">Preference that is on the next screen but same hierarchy</string>
+
+ <string name="title_intent_preference">Intent preference</string>
+ <string name="summary_intent_preference">Launches an Activity from an Intent</string>
+
+ <string name="title_my_preference">My preference</string>
+ <string name="summary_my_preference">This is a custom counter preference</string>
+
+ <string name="title_advanced_toggle_preference">Haunted preference</string>
+ <string name="summary_on_advanced_toggle_preference">I'm on! :)</string>
+ <string name="summary_off_advanced_toggle_preference">I'm off! :(</string>
+
+ <string name="title_parent_preference">Parent toggle</string>
+ <string name="summary_parent_preference">This is visually a parent</string>
+ <string name="title_child_preference">Child toggle</string>
+ <string name="summary_child_preference">This is visually a child</string>
+
+ <string name="example_preference_dependency">Example preference dependency</string>
+ <string name="title_wifi">WiFi</string>
+ <string name="title_wifi_settings">WiFi settings</string>
+
+ <string name="default_value_list_preference">beta</string>
+ <string name="default_value_edittext_preference">Default value</string>
+
+ <!-- ============================== -->
+ <!-- app/search examples strings -->
+ <!-- ============================== -->
+
+ <string name="search_invoke">App/Search/Invoke Search</string>
+ <string name="msg_search">This activity shows a few different ways to invoke search, and inserts context-specific data for use by the search activity.</string>
+ <string name="search_sect_invocation">Ways to invoke search</string>
+ <string name="label_onsearchrequested">onSearchRequested()</string>
+ <string name="search_sect_options">Optional search parameters</string>
+ <string name="label_search_query_prefill">"Prefill query: "</string>
+ <string name="label_search_query_appdata">"App Data: "</string>
+
+ <string name="search_query_results">App/Search/Query Search Results</string>
+ <string name="msg_search_results">This activity accepts query strings via the ACTION_SEARCH intent. In a full implementation, you would use the query string to select results from your data source, and present a list of those results to the user.</string>
+ <string name="label_search_query">"Query String: "</string>
+ <string name="label_search_appdata">"Query App Data: "</string>
+ <string name="label_search_deliveredby">"Activity Method: "</string>
+
+ <string name="search_label">Search Demo</string>
+ <string name="search_hint">Search Demo Hint</string>
+
+ <!-- ================================ -->
+ <!-- app/shortcuts examples strings -->
+ <!-- ================================ -->
+
+ <string name="shortcuts">App/Launcher Shortcuts</string>
+ <string name="sample_shortcuts">ApiDemos</string>
+ <string name="shortcut_name">Sample</string>
+
+ <string name="msg_launcher_shortcuts">This activity creates shortcuts for the launcher (home screen), and receives intents from those shortcuts. To try it, return to the launcher and long-press to create a shortcut.</string>
+ <string name="label_intent">Intent:</string>
+
+ <!-- ============================== -->
+ <!-- app/voice recognition examples strings -->
+ <!-- ============================== -->
+
+ <string name="voice_recognition_prompt">This activity demonstrates the voice recognition APIs.</string>
+ <string name="speak_button">Speak!</string>
+ <string name="voice_recognition_results">Results:</string>
+
+ <!-- ============================ -->
+ <!-- graphics examples strings -->
+ <!-- ============================ -->
+
+ <string name="hide_me">Hide Me!</string>
+
+ <!-- ============================ -->
+ <!-- media examples strings -->
+ <!-- ============================ -->
+
+ <string name="local_video">Play Video from Local File</string>
+ <string name="stream_video">Play Streaming Video</string>
+ <string name="local_audio">Play Audio from Local File</string>
+ <string name="res_audio">Play Audio from Resources</string>
+
+ <!-- ============================ -->
+ <!-- views examples strings -->
+ <!-- ============================ -->
+
+ <string name="linear_layout_8_vertical">Vertical</string>
+ <string name="linear_layout_8_horizontal">Horizontal</string>
+ <string name="linear_layout_8_top">Top</string>
+ <string name="linear_layout_8_middle">Middle</string>
+ <string name="linear_layout_8_bottom">Bottom</string>
+ <string name="linear_layout_8_left">Left</string>
+ <string name="linear_layout_8_center">Center</string>
+ <string name="linear_layout_8_right">Right</string>
+ <string name="linear_layout_10_from">From:</string>
+ <string name="linear_layout_10_to">To:</string>
+ <string name="list_7_nothing">Nothing\u2026</string>
+ <string name="radio_group_snack">Snack</string>
+ <string name="radio_group_selection">"You have selected: "</string>
+ <string name="radio_group_none">(none)</string>
+ <string name="table_layout_7_quit">Quit</string>
+ <string name="table_layout_7_ctrlq">Ctrl-Q</string>
+ <string name="table_layout_8_quit">Quit</string>
+ <string name="table_layout_8_ctrlq">Ctrl-Q</string>
+
+ <string name="seekbar_tracking_on">Tracking on</string>
+ <string name="seekbar_tracking_off">Tracking off</string>
+ <string name="seekbar_from_touch">from touch</string>
+
+ <string name="ratingbar_rating">Rating:</string>
+
+ <!-- ============================== -->
+ <!-- GoogleLogin examples strings -->
+ <!-- ============================== -->
+ <string name="googlelogin_err">Use a better username and password, please.</string>
+
+
+ <!-- ================================== -->
+ <!-- initial strings for layout files -->
+ <!-- ================================== -->
+ <string name="animation_1_instructions">Please enter your password:</string>
+ <string name="animation_2_text_1">Freedom</string>
+ <string name="animation_2_text_2">is nothing else but</string>
+ <string name="animation_2_text_3">a chance to be better.</string>
+ <string name="animation_2_text_4">— Albert Camus</string>
+ <string name="animation_2_instructions">Select an animation:</string>
+ <string name="autocomplete_1_instructions">Type in the text field for auto-completion.</string>
+ <string name="autocomplete_1_country">Country:</string>
+ <string name="autocomplete_1_focus">Give me Focus</string>
+ <string name="autocomplete_2_country">Country:</string>
+ <string name="autocomplete_2_focus">Give me Focus</string>
+ <string name="autocomplete_3_button_1">Scroll</string>
+ <string name="autocomplete_3_button_2">Down</string>
+ <string name="autocomplete_3_button_3">To</string>
+ <string name="autocomplete_3_button_4">See</string>
+ <string name="autocomplete_3_button_5">Auto</string>
+ <string name="autocomplete_3_button_6">Complete</string>
+ <string name="autocomplete_3_button_7">Text</string>
+ <string name="autocomplete_3_button_8">View</string>
+ <string name="autocomplete_3_button">Button</string>
+ <string name="autocomplete_3_country">Country:</string>
+ <string name="autocomplete_4_instructions">Type in the text field for auto-completion.</string>
+ <string name="autocomplete_4_name">Name:</string>
+ <string name="autocomplete_4_message">You must have contacts in your address book. Typing * will show all of your contacts.</string>
+ <string name="autocomplete_5_instructions">Type in the text field for auto-completion.</string>
+ <string name="autocomplete_5_hint">Typing * will show all of your contacts.</string>
+ <string name="autocomplete_5_name">Name:</string>
+ <string name="autocomplete_6_to">To:</string>
+ <string name="autocomplete_6_to_hint">To</string>
+ <string name="autocomplete_6_subject">Subject:</string>
+ <string name="autocomplete_7_instructions">Type in the text field for auto-completion by words.</string>
+ <string name="autocomplete_7_country">Country:</string>
+ <string name="autocomplete_7_focus">Give me Focus</string>
+ <string name="baseline_1_label">Label:</string>
+ <string name="baseline_1_button">Button</string>
+ <string name="baseline_1_bigger">Bigger</string>
+ <string name="baseline_2_label">Label:</string>
+ <string name="baseline_2_button">Button</string>
+ <string name="baseline_2_bigger">Bigger</string>
+ <string name="baseline_3_label">Label:</string>
+ <string name="baseline_3_button">Button</string>
+ <string name="baseline_3_bigger">Bigger</string>
+ <string name="baseline_3_explanation">This example shows that baseline alignment has no effect when the layout gravity is set to center_vertical.</string>
+ <string name="baseline_4_label">Label:</string>
+ <string name="baseline_4_button">Button</string>
+ <string name="baseline_4_bigger">Bigger</string>
+ <string name="baseline_4_label_2">Label Again</string>
+ <string name="baseline_4_label_3">Label Me</string>
+ <string name="baseline_6_multi_line">This is a\nmulti-line field.</string>
+ <string name="baseline_6_baseline">Baseline Aligned</string>
+ <string name="baseline_7_fat">Big and bold</string>
+ <string name="baseline_7_lean">Slim and slick.</string>
+ <string name="baseline_nested_1_label">label</string>
+ <string name="controls_1_save">Save</string>
+ <string name="controls_1_checkbox_1">Checkbox 1</string>
+ <string name="controls_1_checkbox_2">Checkbox 2</string>
+ <string name="controls_1_radiobutton_1">RadioButton 1</string>
+ <string name="controls_1_radiobutton_2">RadioButton 2</string>
+ <string name="controls_1_star">Star</string>
+ <string name="focus_1_message">Service not running</string>
+ <string name="focus_1_placeholder">placeholder</string>
+ <string name="focus_2_left">left</string>
+ <string name="focus_2_jump">jump over me from L to R</string>
+ <string name="focus_2_right">right</string>
+ <string name="focus_3_left">left</string>
+ <string name="focus_3_right">right</string>
+ <string name="focus_3_top">top</string>
+ <string name="focus_3_bottom">bottom</string>
+ <string name="gallery_2_text">Testing</string>
+ <string name="googlelogin_login">Login</string>
+ <string name="googlelogin_bad_login">Bad Login</string>
+ <string name="googlelogin_clear">Clear Credentials</string>
+ <string name="googlelogin_user">Username:</string>
+ <string name="layout_animation_name">Name:</string>
+ <string name="layout_animation_lastname">Last Name:</string>
+ <string name="layout_animation_phone">Phone:</string>
+ <string name="layout_animation_address">Address:</string>
+ <string name="linear_layout_1_top">This is the top view.</string>
+ <string name="linear_layout_1_middle">This is the middle view. It has more text in it than either the top view or the bottom view.</string>
+ <string name="linear_layout_1_bottom">This is the bottom view.</string>
+ <string name="linear_layout_2_top">This is the top view.</string>
+ <string name="linear_layout_2_middle">This is the middle view. It has more text in it than either the top view or the bottom view.</string>
+ <string name="linear_layout_2_bottom">This is the bottom view.</string>
+ <string name="linear_layout_3_top">This is the top view.</string>
+ <string name="linear_layout_3_middle">This is the middle view. It has more text in it than either the top view or the bottom view.</string>
+ <string name="linear_layout_3_bottom">This is the bottom view.</string>
+ <string name="linear_layout_5_instructions">Type Here:</string>
+ <string name="linear_layout_5_cancel">Cancel</string>
+ <string name="linear_layout_5_ok">OK</string>
+ <string name="linear_layout_6_one">One</string>
+ <string name="linear_layout_6_two">Two</string>
+ <string name="linear_layout_6_three">This is the third one</string>
+ <string name="linear_layout_6_four">Four</string>
+ <string name="linear_layout_7_small">Not much text</string>
+ <string name="linear_layout_7_big">A lot more text than any of the other columns. This column should set the height of the linear layout.</string>
+ <string name="linear_layout_7_wrap">wrap_content</string>
+ <string name="linear_layout_8_a">A</string>
+ <string name="linear_layout_8_b">B</string>
+ <string name="linear_layout_8_c">C</string>
+ <string name="linear_layout_9_button">Button</string>
+ <string name="link_text_auto"><b>text1:</b> This is some text. In
+ this text are some things that are actionable. For instance,
+ you can click on http://www.google.com and it will launch the
+ web browser. You can click on google.com too. And, if you
+ click on (415) 555-1212 it should dial the phone.
+ </string>
+ <string name="link_text_manual"><b>text2:</b> This is some other
+ text, with a <a href="http://www.google.com">link</a> specified
+ via an <a> tag. Use a \"tel:\" URL
+ to <a href="tel:4155551212">dial a phone number</a>.
+ </string>
+ <string name="list_8_new_photo">New photo</string>
+ <string name="list_8_clear_photos">Clear photos</string>
+ <string name="list_8_no_photos">No photos</string>
+ <string name="progressbar_1_plus">+</string>
+ <string name="progressbar_1_minus">-</string>
+ <string name="progressbar_1_default_progress">Default progress:</string>
+ <string name="progressbar_1_secondary_progress">Secondary progress:</string>
+ <string name="progressbar_3_progress">Show Progress</string>
+ <string name="progressbar_3_indeterminate">Show Indeterminate</string>
+ <string name="progressbar_3_indeterminate_no_title">Show Indeterminate No Title</string>
+ <string name="progressbar_4_toggle">Toggle Indeterminate</string>
+ <string name="radio_group_1_breakfast">Breakfast</string>
+ <string name="radio_group_1_lunch">Lunch</string>
+ <string name="radio_group_1_dinner">Dinner</string>
+ <string name="radio_group_1_all">All of them</string>
+ <string name="radio_group_1_selection">You have selected: (none)</string>
+ <string name="radio_group_1_clear">Clear</string>
+ <string name="receive_result_instructions">Press the button to get an activity result, which will be displayed here:</string>
+ <string name="receive_result_result">Get Result</string>
+ <string name="relative_layout_1_top">Top</string>
+ <string name="relative_layout_1_bottom">Bottom</string>
+ <string name="relative_layout_1_center">center_vertical</string>
+ <string name="relative_layout_2_instructions">Type here:</string>
+ <string name="relative_layout_2_ok">Ok</string>
+ <string name="relative_layout_2_cancel">Cancel</string>
+ <string name="scroll_view_1_text_1">Text View 1</string>
+ <string name="scroll_view_1_button_1">Button 1</string>
+ <string name="scroll_view_1_text_2">Text View 2</string>
+ <string name="scroll_view_1_button_2">Button 2</string>
+ <string name="scroll_view_1_text_3">Text View 3</string>
+ <string name="scroll_view_1_button_3">Button 3</string>
+ <string name="scroll_view_1_text_4">Text View 4</string>
+ <string name="scroll_view_1_button_4">Button 4</string>
+ <string name="scroll_view_1_text_5">Text View 5</string>
+ <string name="scroll_view_1_button_5">Button 5</string>
+ <string name="scroll_view_1_text_6">Text View 6</string>
+ <string name="scroll_view_1_button_6">Button 6</string>
+ <string name="scroll_view_2_text_1">Text View 1</string>
+ <string name="scroll_view_2_button_1">Button 1</string>
+ <string name="scrollbar_1_text">Lorem ipsum dolor sit amet.</string>
+ <string name="scrollbar_2_text">Lorem ipsum dolor sit amet.</string>
+ <string name="scrollbar_3_text">
+ The Android platform is a software stack for mobile devices including an
+ operating system, middleware and key applications. Developers can create
+ applications for the platform using the Android SDK. Applications are written
+ using the Java programming language and run on Dalvik, a custom virtual
+ machine designed for embedded use which runs on top of a Linux kernel.
+
+ If you want to know how to develop applications for Android, you're in the
+ right place. This site provides a variety of documentation that will help you
+ learn about Android and develop mobile applications for the platform.
+
+ An early look at the the Android SDK is also available. It includes sample
+ projects with source code, development tools, an emulator, and of course all
+ the libraries you'll need to build an Android application. What would it take
+ to build a better mobile phone?
+ </string>
+ <string name="spinner_1_color">Color:</string>
+ <string name="spinner_1_planet">Planet:</string>
+ <string name="spinner_1_color_prompt">Choose a color</string>
+ <string name="spinner_1_planet_prompt">Choose a planet</string>
+ <string name="table_layout_1_star">*</string>
+ <string name="table_layout_1_triple_star">***</string>
+ <string name="table_layout_1_open">Open\u2026</string>
+ <string name="table_layout_1_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_1_save">Save As\u2026</string>
+ <string name="table_layout_1_save_shortcut">(Save Document)</string>
+ <string name="table_layout_1_quit">Quit Application</string>
+ <string name="table_layout_1_quit_shortcut">Ctrl-Shift-Q</string>
+ <string name="table_layout_2_path_1">~/path/to/file/to/open</string>
+ <string name="table_layout_2_path_2">~/.profile</string>
+ <string name="table_layout_2_open">Open</string>
+ <string name="table_layout_2_save">Save</string>
+ <string name="table_layout_2_save_all">Save All</string>
+ <string name="table_layout_3_star">*</string>
+ <string name="table_layout_3_triple_star">***</string>
+ <string name="table_layout_3_open">Open\u2026</string>
+ <string name="table_layout_3_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_3_save">Save As\u2026</string>
+ <string name="table_layout_3_save_shortcut">(Save Document)</string>
+ <string name="table_layout_3_too_long">Too Long</string>
+ <string name="table_layout_3_quit">Quit Application</string>
+ <string name="table_layout_3_quit_shortcut">Ctrl-Shift-Q</string>
+ <string name="table_layout_4_open">Open\u2026</string>
+ <string name="table_layout_4_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_4_save">Save As\u2026</string>
+ <string name="table_layout_4_save_shortcut">Ctrl-Shift-S</string>
+ <string name="table_layout_5_open">Open\u2026</string>
+ <string name="table_layout_5_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_5_save">Save\u2026</string>
+ <string name="table_layout_5_save_shortcut">Ctrl-S</string>
+ <string name="table_layout_5_save_as">Save As\u2026</string>
+ <string name="table_layout_5_save_as_shortcut">Ctrl-Shift-S</string>
+ <string name="table_layout_5_import">Import\u2026</string>
+ <string name="table_layout_5_export">Export\u2026</string>
+ <string name="table_layout_5_export_shortcut">Ctrl-E</string>
+ <string name="table_layout_5_quit">Quit\u2026</string>
+ <string name="table_layout_6_x">X</string>
+ <string name="table_layout_6_open">Open\u2026</string>
+ <string name="table_layout_6_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_6_save">Save\u2026</string>
+ <string name="table_layout_6_save_shortcut">Ctrl-S</string>
+ <string name="table_layout_6_save_as">Save As\u2026</string>
+ <string name="table_layout_6_save_as_shortcut">Ctrl-Shift-S</string>
+ <string name="table_layout_6_import">Import\u2026</string>
+ <string name="table_layout_6_export">Export\u2026</string>
+ <string name="table_layout_6_export_shortcut">Ctrl-E</string>
+ <string name="table_layout_6_quit">Quit\u2026</string>
+ <string name="table_layout_7_x">X</string>
+ <string name="table_layout_7_open">Open\u2026</string>
+ <string name="table_layout_7_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_7_save">Save\u2026</string>
+ <string name="table_layout_7_save_shortcut">Ctrl-S</string>
+ <string name="table_layout_7_save_as">Save As\u2026</string>
+ <string name="table_layout_7_save_as_shortcut">Ctrl-Shift-S</string>
+ <string name="table_layout_7_import">Import\u2026</string>
+ <string name="table_layout_7_export">Export\u2026</string>
+ <string name="table_layout_7_export_shortcut">Ctrl-E</string>
+ <string name="table_layout_7_toggle_checkmarks">Toggle Checkmarks</string>
+ <string name="table_layout_7_toggle_shortcuts">Toggle Shortcuts</string>
+ <string name="table_layout_8_x">X</string>
+ <string name="table_layout_8_open">Open\u2026</string>
+ <string name="table_layout_8_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_8_save">Save\u2026</string>
+ <string name="table_layout_8_save_shortcut">Ctrl-S</string>
+ <string name="table_layout_8_save_as">Save As\u2026</string>
+ <string name="table_layout_8_save_as_shortcut">Ctrl-Shift-S</string>
+ <string name="table_layout_8_import">Import\u2026</string>
+ <string name="table_layout_8_export">Export\u2026</string>
+ <string name="table_layout_8_export_shortcut">Ctrl-E</string>
+ <string name="table_layout_8_toggle_stretch">Toggle Stretch</string>
+ <string name="table_layout_9_open">Open\u2026</string>
+ <string name="table_layout_9_open_shortcut">Ctrl-O</string>
+ <string name="table_layout_9_save">Save\u2026</string>
+ <string name="table_layout_9_save_shortcut">Ctrl-S</string>
+ <string name="table_layout_9_save_as">Save As\u2026</string>
+ <string name="table_layout_9_save_as_shortcut">Ctrl-Shift-S</string>
+ <string name="table_layout_9_save_all">Save All And Do A Lot Of Stuff Just To Be Too Long For This Screen Because It Is A Test After All</string>
+ <string name="table_layout_9_save_all_shortcut">Ctrl-E</string>
+ <string name="table_layout_9_import">Import\u2026</string>
+ <string name="table_layout_9_export">Export\u2026</string>
+ <string name="table_layout_9_export_shortcut">Ctrl-E</string>
+ <string name="table_layout_9_toggle_shrink">Toggle Shrink</string>
+ <string name="table_layout_10_user">User</string>
+ <string name="table_layout_10_password">Password</string>
+ <string name="table_layout_10_cancel">Cancel</string>
+ <string name="table_layout_10_login">Login</string>
+ <string name="table_layout_12_a">A</string>
+ <string name="table_layout_12_b">BB</string>
+ <string name="table_layout_12_c">CCCC</string>
+ <string name="table_layout_12_d">D</string>
+ <string name="table_layout_12_e">E</string>
+ <string name="table_layout_12_f">F</string>
+ <string name="table_layout_12_g">G</string>
+ <string name="table_layout_12_h">H</string>
+ <string name="visibility_1_view_1">View A</string>
+ <string name="visibility_1_view_2">View B</string>
+ <string name="visibility_1_view_3">View C</string>
+ <string name="visibility_1_vis">Vis</string>
+ <string name="visibility_1_invis">Invis</string>
+ <string name="visibility_1_gone">Gone</string>
+
+
+ <string name="google_login_username_text"></string>
+
+ <string name="incoming_message_notify_text">Show Notification</string>
+
+ <string name="incoming_message_info_message_text">this is the text of a previous message.\nkthx. meet u for dinner. cul8r</string>
+
+ <string name="incoming_message_view_message_text">this is the text of a previous message.\nkthx. meet u for dinner. cul8r</string>
+ <string name="imcoming_message_view_message2_text">Did you notice that the status bar icon disappeared?</string>
+ <string name="imcoming_message_ticker_text">New text message: <xliff:g id="text">%0$s</xliff:g></string>
+
+ <string name="log_text_box_1_do_nothing_text">Do nothing</string>
+ <string name="log_text_box_1_add_text">Add</string>
+
+ <string name="notify_with_text_long_notify_text">Show Long Notification</string>
+ <string name="notify_with_text_short_notify_text">Show Short Notification</string>
+
+ <string name="marquee_default">This use the default marquee animation limit of 3</string>
+ <string name="marquee_once">This will run the marquee animation once</string>
+ <string name="marquee_forever">This will run the marquee animation forever</string>
+
+ <string name="table_layout_10_password_text"></string>
+ <string name="table_layout_10_username_text"></string>
+
+ <string name="text_switcher_1_next_text">Next</string>
+
+ <string name="date_widgets_example_dateDisplay_text"></string>
+ <string name="date_widgets_example_pickTime_text">change the time</string>
+ <string name="date_widgets_example_pickDate_text">change the date</string>
+
+ <string name="buttons_1_normal">Normal</string>
+ <string name="buttons_1_right">Right</string>
+ <string name="buttons_1_small">Small</string>
+ <string name="buttons_1_small_right">S R</string>
+ <string name="buttons_1_small_left">S L</string>
+ <string name="buttons_1_small_up">S U</string>
+ <string name="buttons_1_small_down">S D</string>
+ <string name="buttons_1_toggle">Toggle</string>
+
+ <string name="expandable_list_sample_action">Sample action</string>
+
+ <string name="chronometer_start">Start</string>
+ <string name="chronometer_stop">Stop</string>
+ <string name="chronometer_reset">Reset</string>
+ <string name="chronometer_set_format">Set format string</string>
+ <string name="chronometer_clear_format">Clear format string</string>
+ <string name="chronometer_initial_format">Initial format: <xliff:g id="initial-format">%s</xliff:g></string>
+
+ <!-- ============================ -->
+ <!-- vibrator examples strings -->
+ <!-- ============================ -->
+
+ <string name="vibrate">Vibrate</string>
+
+
+ <string name="image_view_large_normal">Large image at normal size</string>
+ <string name="image_view_large_at_most">Large image scaled to at most 50x50</string>
+ <string name="image_view_large_at_most_padded">Large image scaled to at most 70x70 with padding</string>
+ <string name="image_view_large_exactly_padded">Large image scaled to exactly 70x70 with padding</string>
+ <string name="image_view_small_normal">Small image at normal size</string>
+ <string name="image_view_small_at_most">Small image scaled to at most 50x50</string>
+ <string name="image_view_small_at_most_padded">Small image scaled to at most 70x70 with padding</string>
+ <string name="image_view_small_exactly_padded">Small image scaled to exactly 70x70 with padding</string>
+
+ <!-- Shouldn't be localized -->
+ <string name="textColorPrimary">textColorPrimary</string>
+ <string name="textColorSecondary">textColorSecondary</string>
+ <string name="textColorTertiary">textColorTertiary</string>
+ <string name="listSeparatorTextViewStyle">listSeparatorTextViewStyle</string>
+
+ <!-- ============================ -->
+ <!-- gadget examples strings -->
+ <!-- ============================ -->
+
+ <string name="gadget_configure_instructions">This text will be shown before the date in our example gadget.</string>
+ <string name="gadget_prefix_default">Oh hai</string>
+ <string name="gadget_text_format"><xliff:g id="prefix">%1$s</xliff:g>: <xliff:g id="time">%2$s</xliff:g></string>
+</resources>
+
diff --git a/samples/ApiDemos/res/values/styles.xml b/samples/ApiDemos/res/values/styles.xml
new file mode 100644
index 0000000..40e934e
--- /dev/null
+++ b/samples/ApiDemos/res/values/styles.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <!-- Base application theme is the default theme. -->
+ <style name="Theme" parent="android:Theme">
+ </style>
+
+ <!-- Variation on our application theme that forces a plain
+ text style. -->
+ <style name="Theme.PlainText">
+ <item name="android:textAppearance">@style/TextAppearance.Theme.PlainText</item>
+ </style>
+
+ <!-- Variation on our application theme that has a black
+ background. -->
+ <style name="Theme.Black">
+ <item name="android:windowBackground">@drawable/screen_background_black</item>
+ </style>
+
+ <!-- A theme for a custom dialog appearance. Here we use an ugly
+ custom frame. -->
+ <style name="Theme.CustomDialog" parent="android:style/Theme.Dialog">
+ <item name="android:windowBackground">@drawable/filled_box</item>
+ </style>
+
+ <!-- A theme that has a translucent background. Here we explicitly specify
+ that this theme is to inherit from the system's translucent theme,
+ which sets up various attributes correctly.. -->
+ <style name="Theme.Translucent" parent="android:style/Theme.Translucent">
+ <item name="android:windowBackground">@drawable/translucent_background</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:colorForeground">#fff</item>
+ </style>
+
+ <!-- Variation on our application theme that has a transparent
+ background; this example completely removes the background,
+ allowing the activity to decide how to composite. Also here we
+ force the translucency ourself rather than making use of the built-in
+ translucent theme. -->
+ <style name="Theme.Transparent">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
+ <item name="android:windowBackground">@drawable/transparent_background</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:colorForeground">#fff</item>
+ </style>
+
+ <style name="TextAppearance.Theme.PlainText" parent="android:TextAppearance.Theme">
+ <item name="android:textStyle">normal</item>
+ </style>
+
+</resources>
diff --git a/samples/ApiDemos/res/xml/advanced_preferences.xml b/samples/ApiDemos/res/xml/advanced_preferences.xml
new file mode 100644
index 0000000..c362297
--- /dev/null
+++ b/samples/ApiDemos/res/xml/advanced_preferences.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This is an advanced example showing the custom preference types and manually handling
+ preference clicks. -->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- My custom preference type. This just replaces the actual widget
+ portion of the preference, if the whole preference wanted to be
+ replaced we would use the layout attribute instead of the widgetLayout
+ attribute. -->
+ <com.example.android.apis.app.MyPreference
+ android:key="my_preference"
+ android:title="@string/title_my_preference"
+ android:summary="@string/summary_my_preference"
+ android:defaultValue="100" />
+
+ <CheckBoxPreference
+ android:key="advanced_checkbox_preference"
+ android:title="@string/title_advanced_toggle_preference"
+ android:summaryOn="@string/summary_on_advanced_toggle_preference"
+ android:summaryOff="@string/summary_off_advanced_toggle_preference" />
+
+</PreferenceScreen>
diff --git a/samples/ApiDemos/res/xml/default_values.xml b/samples/ApiDemos/res/xml/default_values.xml
new file mode 100644
index 0000000..da15a62
--- /dev/null
+++ b/samples/ApiDemos/res/xml/default_values.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This is a primitive example showing how to set default values for preferences.
+ See DefaultValues.java for more information. -->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <CheckBoxPreference
+ android:key="default_toggle"
+ android:defaultValue="true"
+ android:title="@string/title_checkbox_preference"
+ android:summary="@string/summary_checkbox_preference" />
+
+ <EditTextPreference
+ android:key="default_edittext"
+ android:defaultValue="@string/default_value_edittext_preference"
+ android:title="@string/title_edittext_preference"
+ android:summary="@string/summary_edittext_preference"
+ android:dialogTitle="@string/dialog_title_edittext_preference" />
+
+ <ListPreference
+ android:key="default_list"
+ android:defaultValue="@string/default_value_list_preference"
+ android:title="@string/title_list_preference"
+ android:summary="@string/summary_list_preference"
+ android:entries="@array/entries_list_preference"
+ android:entryValues="@array/entryvalues_list_preference"
+ android:dialogTitle="@string/dialog_title_list_preference" />
+
+</PreferenceScreen>
diff --git a/samples/ApiDemos/res/xml/gadget_provider.xml b/samples/ApiDemos/res/xml/gadget_provider.xml
new file mode 100644
index 0000000..9ad6845
--- /dev/null
+++ b/samples/ApiDemos/res/xml/gadget_provider.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<gadget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="60dp"
+ android:minHeight="30dp"
+ android:updatePeriodMillis="86400000"
+ android:initialLayout="@layout/gadget_provider"
+ android:configure="com.example.android.apis.gadget.ExampleGadgetConfigure"
+ >
+</gadget-provider>
+
+<!-- 86400000 is the value of AlarmManager.INTERVAL_DAY - or once per day. -->
+
diff --git a/samples/ApiDemos/res/xml/preference_dependencies.xml b/samples/ApiDemos/res/xml/preference_dependencies.xml
new file mode 100644
index 0000000..5eae580
--- /dev/null
+++ b/samples/ApiDemos/res/xml/preference_dependencies.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This is a primitive example showing how some preferences can depend on other preferences. -->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceCategory
+ android:title="@string/example_preference_dependency">
+
+ <CheckBoxPreference
+ android:key="wifi"
+ android:title="@string/title_wifi" />
+
+ <EditTextPreference
+ android:layout="?android:attr/preferenceLayoutChild"
+ android:title="@string/title_wifi_settings"
+ android:dependency="wifi" />
+
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/samples/ApiDemos/res/xml/preferences.xml b/samples/ApiDemos/res/xml/preferences.xml
new file mode 100644
index 0000000..59b23f1
--- /dev/null
+++ b/samples/ApiDemos/res/xml/preferences.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This is a primitive example showing the different types of preferences available. -->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceCategory
+ android:title="@string/inline_preferences">
+
+ <CheckBoxPreference
+ android:key="checkbox_preference"
+ android:title="@string/title_toggle_preference"
+ android:summary="@string/summary_toggle_preference" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/dialog_based_preferences">
+
+ <EditTextPreference
+ android:key="edittext_preference"
+ android:title="@string/title_edittext_preference"
+ android:summary="@string/summary_edittext_preference"
+ android:dialogTitle="@string/dialog_title_edittext_preference" />
+
+ <ListPreference
+ android:key="list_preference"
+ android:title="@string/title_list_preference"
+ android:summary="@string/summary_list_preference"
+ android:entries="@array/entries_list_preference"
+ android:entryValues="@array/entryvalues_list_preference"
+ android:dialogTitle="@string/dialog_title_list_preference" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/launch_preferences">
+
+ <!-- This PreferenceScreen tag serves as a screen break (similar to page break
+ in word processing). Like for other preference types, we assign a key
+ here so it is able to save and restore its instance state. -->
+ <PreferenceScreen
+ android:key="screen_preference"
+ android:title="@string/title_screen_preference"
+ android:summary="@string/summary_screen_preference">
+
+ <!-- You can place more preferences here that will be shown on the next screen. -->
+
+ <CheckBoxPreference
+ android:key="next_screen_checkbox_preference"
+ android:title="@string/title_next_screen_toggle_preference"
+ android:summary="@string/summary_next_screen_toggle_preference" />
+
+ </PreferenceScreen>
+
+ <PreferenceScreen
+ android:title="@string/title_intent_preference"
+ android:summary="@string/summary_intent_preference">
+
+ <intent android:action="android.intent.action.VIEW"
+ android:data="http://www.android.com" />
+
+ </PreferenceScreen>
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/preference_attributes">
+
+ <CheckBoxPreference
+ android:key="parent_checkbox_preference"
+ android:title="@string/title_parent_preference"
+ android:summary="@string/summary_parent_preference" />
+
+ <!-- The visual style of a child is defined by this styled theme attribute. -->
+ <CheckBoxPreference
+ android:key="child_checkbox_preference"
+ android:dependency="parent_checkbox_preference"
+ android:layout="?android:attr/preferenceLayoutChild"
+ android:title="@string/title_child_preference"
+ android:summary="@string/summary_child_preference" />
+
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/samples/ApiDemos/res/xml/searchable.xml b/samples/ApiDemos/res/xml/searchable.xml
new file mode 100644
index 0000000..df4ef7a
--- /dev/null
+++ b/samples/ApiDemos/res/xml/searchable.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Search Manager. -->
+
+<searchable xmlns:android="http://schemas.android.com/apk/res/android"
+ android:label="@string/search_label"
+ android:hint="@string/search_hint"
+ android:searchMode="showSearchLabelAsBadge"
+
+ android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
+ android:voiceLanguageModel="free_form"
+ android:voicePromptText="@string/search_invoke"
+
+ android:searchSuggestAuthority="com.example.android.apis.SuggestionProvider"
+ android:searchSuggestSelection=" ? "
+/>
diff --git a/samples/ApiDemos/src/com/example/android/apis/ApiDemos.java b/samples/ApiDemos/src/com/example/android/apis/ApiDemos.java
new file mode 100644
index 0000000..78b1fd7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/ApiDemos.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ApiDemos extends ListActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ String path = intent.getStringExtra("com.example.android.apis.Path");
+
+ if (path == null) {
+ path = "";
+ }
+
+ setListAdapter(new SimpleAdapter(this, getData(path),
+ android.R.layout.simple_list_item_1, new String[] { "title" },
+ new int[] { android.R.id.text1 }));
+ getListView().setTextFilterEnabled(true);
+ }
+
+ protected List getData(String prefix) {
+ List<Map> myData = new ArrayList<Map>();
+
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
+
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+ if (null == list)
+ return myData;
+
+ String[] prefixPath;
+
+ if (prefix.equals("")) {
+ prefixPath = null;
+ } else {
+ prefixPath = prefix.split("/");
+ }
+
+ int len = list.size();
+
+ Map<String, Boolean> entries = new HashMap<String, Boolean>();
+
+ for (int i = 0; i < len; i++) {
+ ResolveInfo info = list.get(i);
+ CharSequence labelSeq = info.loadLabel(pm);
+ String label = labelSeq != null
+ ? labelSeq.toString()
+ : info.activityInfo.name;
+
+ if (prefix.length() == 0 || label.startsWith(prefix)) {
+
+ String[] labelPath = label.split("/");
+
+ String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+ if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+ addItem(myData, nextLabel, activityIntent(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name));
+ } else {
+ if (entries.get(nextLabel) == null) {
+ addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel));
+ entries.put(nextLabel, true);
+ }
+ }
+ }
+ }
+
+ Collections.sort(myData, sDisplayNameComparator);
+
+ return myData;
+ }
+
+ private final static Comparator<Map> sDisplayNameComparator = new Comparator<Map>() {
+ private final Collator collator = Collator.getInstance();
+
+ public int compare(Map map1, Map map2) {
+ return collator.compare(map1.get("title"), map2.get("title"));
+ }
+ };
+
+ protected Intent activityIntent(String pkg, String componentName) {
+ Intent result = new Intent();
+ result.setClassName(pkg, componentName);
+ return result;
+ }
+
+ protected Intent browseIntent(String path) {
+ Intent result = new Intent();
+ result.setClass(this, ApiDemos.class);
+ result.putExtra("com.example.android.apis.Path", path);
+ return result;
+ }
+
+ protected void addItem(List<Map> data, String name, Intent intent) {
+ Map<String, Object> temp = new HashMap<String, Object>();
+ temp.put("title", name);
+ temp.put("intent", intent);
+ data.add(temp);
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Map map = (Map) l.getItemAtPosition(position);
+
+ Intent intent = (Intent) map.get("intent");
+ startActivity(intent);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/ApiDemosApplication.java b/samples/ApiDemos/src/com/example/android/apis/ApiDemosApplication.java
new file mode 100644
index 0000000..92460e5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/ApiDemosApplication.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.app.DefaultValues;
+
+import android.app.Application;
+import android.preference.PreferenceManager;
+
+/**
+ * This is an example of a {@link android.app.Application} class. Ordinarily you would use
+ * a class like this as a central repository for information that might be shared between multiple
+ * activities.
+ *
+ * In this case, we have not defined any specific work for this Application.
+ *
+ * See samples/ApiDemos/tests/src/com.example.android.apis/ApiDemosApplicationTests for an example
+ * of how to perform unit tests on an Application object.
+ */
+public class ApiDemosApplication extends Application {
+
+ public void onCreate() {
+ /*
+ * This populates the default values from the preferences XML file. See
+ * {@link DefaultValues} for more details.
+ */
+ PreferenceManager.setDefaultValues(this, R.xml.default_values, false);
+ }
+
+ public void onTerminate() {
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/_package.html b/samples/ApiDemos/src/com/example/android/apis/_package.html
new file mode 100644
index 0000000..307c136
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/_package.html
@@ -0,0 +1,26 @@
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="assets/style.css" />
+<script type="text/javascript" src="http://www.corp.google.com/style/prettify.js"></script>
+<script src="http://www.corp.google.com/eng/techpubs/include/navbar.js" type="text/javascript"></script>
+
+
+
+</head>
+
+<body>
+
+<p>
+Examples of how to use the android platform APIs. See:
+
+<ol>
+ <li> <a href="com.android.sdk.app">sdk.app</a> for examples
+ of using the android.app APIs.
+ <li> <a href="com.android.sdk.view">sdk.view</a> for examples
+ of using the android.view APIs.
+</ol>
+</p>
+
+
+</body>
+</html>
diff --git a/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.java b/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.java
new file mode 100644
index 0000000..61ee828
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007 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.animation;
+
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+import android.graphics.Camera;
+import android.graphics.Matrix;
+
+/**
+ * An animation that rotates the view on the Y axis between two specified angles.
+ * This animation also adds a translation on the Z axis (depth) to improve the effect.
+ */
+public class Rotate3dAnimation extends Animation {
+ private final float mFromDegrees;
+ private final float mToDegrees;
+ private final float mCenterX;
+ private final float mCenterY;
+ private final float mDepthZ;
+ private final boolean mReverse;
+ private Camera mCamera;
+
+ /**
+ * Creates a new 3D rotation on the Y axis. The rotation is defined by its
+ * start angle and its end angle. Both angles are in degrees. The rotation
+ * is performed around a center point on the 2D space, definied by a pair
+ * of X and Y coordinates, called centerX and centerY. When the animation
+ * starts, a translation on the Z axis (depth) is performed. The length
+ * of the translation can be specified, as well as whether the translation
+ * should be reversed in time.
+ *
+ * @param fromDegrees the start angle of the 3D rotation
+ * @param toDegrees the end angle of the 3D rotation
+ * @param centerX the X center of the 3D rotation
+ * @param centerY the Y center of the 3D rotation
+ * @param reverse true if the translation should be reversed, false otherwise
+ */
+ public Rotate3dAnimation(float fromDegrees, float toDegrees,
+ float centerX, float centerY, float depthZ, boolean reverse) {
+ mFromDegrees = fromDegrees;
+ mToDegrees = toDegrees;
+ mCenterX = centerX;
+ mCenterY = centerY;
+ mDepthZ = depthZ;
+ mReverse = reverse;
+ }
+
+ @Override
+ public void initialize(int width, int height, int parentWidth, int parentHeight) {
+ super.initialize(width, height, parentWidth, parentHeight);
+ mCamera = new Camera();
+ }
+
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ final float fromDegrees = mFromDegrees;
+ float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
+
+ final float centerX = mCenterX;
+ final float centerY = mCenterY;
+ final Camera camera = mCamera;
+
+ final Matrix matrix = t.getMatrix();
+
+ camera.save();
+ if (mReverse) {
+ camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
+ } else {
+ camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
+ }
+ camera.rotateY(degrees);
+ camera.getMatrix(matrix);
+ camera.restore();
+
+ matrix.preTranslate(-centerX, -centerY);
+ matrix.postTranslate(centerX, centerY);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/animation/Transition3d.java b/samples/ApiDemos/src/com/example/android/apis/animation/Transition3d.java
new file mode 100644
index 0000000..38e69d0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/animation/Transition3d.java
@@ -0,0 +1,175 @@
+package com.example.android.apis.animation;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ListView;
+import android.widget.ArrayAdapter;
+import android.widget.AdapterView;
+import android.widget.ImageView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+
+/**
+ * This sample application shows how to use layout animation and various
+ * transformations on views. The result is a 3D transition between a
+ * ListView and an ImageView. When the user clicks the list, it flips to
+ * show the picture. When the user clicks the picture, it flips to show the
+ * list. The animation is made of two smaller animations: the first half
+ * rotates the list by 90 degrees on the Y axis and the second half rotates
+ * the picture by 90 degrees on the Y axis. When the first half finishes, the
+ * list is made invisible and the picture is set visible.
+ */
+public class Transition3d extends Activity implements
+ AdapterView.OnItemClickListener, View.OnClickListener {
+ private ListView mPhotosList;
+ private ViewGroup mContainer;
+ private ImageView mImageView;
+
+ // Names of the photos we show in the list
+ private static final String[] PHOTOS_NAMES = new String[] {
+ "Lyon",
+ "Livermore",
+ "Tahoe Pier",
+ "Lake Tahoe",
+ "Grand Canyon",
+ "Bodie"
+ };
+
+ // Resource identifiers for the photos we want to display
+ private static final int[] PHOTOS_RESOURCES = new int[] {
+ R.drawable.photo1,
+ R.drawable.photo2,
+ R.drawable.photo3,
+ R.drawable.photo4,
+ R.drawable.photo5,
+ R.drawable.photo6
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.animations_main_screen);
+
+ mPhotosList = (ListView) findViewById(android.R.id.list);
+ mImageView = (ImageView) findViewById(R.id.picture);
+ mContainer = (ViewGroup) findViewById(R.id.container);
+
+ // Prepare the ListView
+ final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, PHOTOS_NAMES);
+
+ mPhotosList.setAdapter(adapter);
+ mPhotosList.setOnItemClickListener(this);
+
+ // Prepare the ImageView
+ mImageView.setClickable(true);
+ mImageView.setFocusable(true);
+ mImageView.setOnClickListener(this);
+
+ // Since we are caching large views, we want to keep their cache
+ // between each animation
+ mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);
+ }
+
+ /**
+ * Setup a new 3D rotation on the container view.
+ *
+ * @param position the item that was clicked to show a picture, or -1 to show the list
+ * @param start the start angle at which the rotation must begin
+ * @param end the end angle of the rotation
+ */
+ private void applyRotation(int position, float start, float end) {
+ // Find the center of the container
+ final float centerX = mContainer.getWidth() / 2.0f;
+ final float centerY = mContainer.getHeight() / 2.0f;
+
+ // Create a new 3D rotation with the supplied parameter
+ // The animation listener is used to trigger the next animation
+ final Rotate3dAnimation rotation =
+ new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
+ rotation.setDuration(500);
+ rotation.setFillAfter(true);
+ rotation.setInterpolator(new AccelerateInterpolator());
+ rotation.setAnimationListener(new DisplayNextView(position));
+
+ mContainer.startAnimation(rotation);
+ }
+
+ public void onItemClick(AdapterView parent, View v, int position, long id) {
+ // Pre-load the image then start the animation
+ mImageView.setImageResource(PHOTOS_RESOURCES[position]);
+ applyRotation(position, 0, 90);
+ }
+
+ public void onClick(View v) {
+ applyRotation(-1, 180, 90);
+ }
+
+ /**
+ * This class listens for the end of the first half of the animation.
+ * It then posts a new action that effectively swaps the views when the container
+ * is rotated 90 degrees and thus invisible.
+ */
+ private final class DisplayNextView implements Animation.AnimationListener {
+ private final int mPosition;
+
+ private DisplayNextView(int position) {
+ mPosition = position;
+ }
+
+ public void onAnimationStart(Animation animation) {
+ }
+
+ public void onAnimationEnd(Animation animation) {
+ mContainer.post(new SwapViews(mPosition));
+ }
+
+ public void onAnimationRepeat(Animation animation) {
+ }
+ }
+
+ /**
+ * This class is responsible for swapping the views and start the second
+ * half of the animation.
+ */
+ private final class SwapViews implements Runnable {
+ private final int mPosition;
+
+ public SwapViews(int position) {
+ mPosition = position;
+ }
+
+ public void run() {
+ final float centerX = mContainer.getWidth() / 2.0f;
+ final float centerY = mContainer.getHeight() / 2.0f;
+ Rotate3dAnimation rotation;
+
+ if (mPosition > -1) {
+ mPhotosList.setVisibility(View.GONE);
+ mImageView.setVisibility(View.VISIBLE);
+ mImageView.requestFocus();
+
+ rotation = new Rotate3dAnimation(90, 180, centerX, centerY, 310.0f, false);
+ } else {
+ mImageView.setVisibility(View.GONE);
+ mPhotosList.setVisibility(View.VISIBLE);
+ mPhotosList.requestFocus();
+
+ rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f, false);
+ }
+
+ rotation.setDuration(500);
+ rotation.setFillAfter(true);
+ rotation.setInterpolator(new DecelerateInterpolator());
+
+ mContainer.startAnimation(rotation);
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/animation/_index.html b/samples/ApiDemos/src/com/example/android/apis/animation/_index.html
new file mode 100644
index 0000000..cd2ea53
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/animation/_index.html
@@ -0,0 +1,48 @@
+
+<h3>Drawable</h3>
+<dl>
+ <dt><a href="ShapeDrawable1.html">ShapeDrawable</a></dt>
+ <dd>Demonstrates creating Drawables in XML.</dd>
+</dl>
+
+<h3>OpenGL|ES</h3>
+<dl>
+ <dt><a href="CameraPreview.html">CameraPreview</a></dt>
+ <dd> Demonstrates capturing the image stream from the camera, drawing to a surface (extending SurfaceView) on a separate thread (extending Thread).</dd>
+
+ <dt><a href="GLSurfaceViewActivity.html">GL SurfaceView</a></dt>
+ <dd>Demonstrates how to perform OpenGL rendering in to a SurfaceView.
+ <dl>
+ <dt>Code:
+ <dd> <a href="GLSurfaceViewActivity.html">GLSurfaceViewActivity.java</a>,
+ <a href="GLSurfaceView.html">GLSurfaceView.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/hello_world.html">
+ hello_world.xml</a>
+ </dl>
+ </dd>
+
+ <dt><a href="PolyToPoly.html">PolyToPoly</a></dt>
+ <dd>Demonstrates calling the <a href="@{docRoot}reference/android/graphics/Matrix.html#setPolyToPoly(float[],%20int,%20float[],%20int,%20int)">Matrix.setPolyToPoly()</a> method to translate coordinates on a canvas to a new perspective (used to simulate perspective). </dd>
+
+ <dt><a href="DrawPoints.html">DrawPoints</a></dt>
+ <dd>Demonstrates using the <a href="android.graphics.Paint">Paint</a> and <a href="android.graphics.Canvas">Canvas</a> objects to draw random points on the screen, with different colors and strokes. </dd>
+
+ <dt><a href="PathEffects.html">PathEffects</a></dt>
+ <dd> Demonstrates the use of <a href="android.graphics.Path">Path</a> and various <a href="android.graphics.PathEffect">PathEffect</a> subclasses. </dd>
+
+ <dt><a href="SurfaceViewOverlay.html">SurfaceView Overlay</a></dt>
+ <dd>Shows how you can place overlays on top of a SurfaceView.
+ <dl>
+ <dt>Code:
+ <dd> <a href="SurfaceViewOverlay.html">SurfaceViewOverlay.java</a>,
+ <a href="GLSurfaceView.html">GLSurfaceView.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/surface_view_overlay.html">
+ surface_view_overlay.xml</a>
+ </dl>
+ </dd>
+
+ <dt><a href="TouchPaint.html">TouchPaint</a></dt>
+ <dd> Demonstrates the handling of touch screen events to implement a simple painting app. </dd>
+</dl>
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/AdvancedPreferences.java b/samples/ApiDemos/src/com/example/android/apis/app/AdvancedPreferences.java
new file mode 100644
index 0000000..2dbbc45
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/AdvancedPreferences.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceActivity;
+import android.preference.CheckBoxPreference;
+import android.widget.Toast;
+
+/**
+ * Example that shows finding a preference from the hierarchy and a custom preference type.
+ */
+public class AdvancedPreferences extends PreferenceActivity implements OnSharedPreferenceChangeListener {
+ public static final String KEY_MY_PREFERENCE = "my_preference";
+ public static final String KEY_ADVANCED_CHECKBOX_PREFERENCE = "advanced_checkbox_preference";
+
+ private CheckBoxPreference mCheckBoxPreference;
+ private Handler mHandler = new Handler();
+
+ /**
+ * This is a simple example of controlling a preference from code.
+ */
+ private Runnable mForceCheckBoxRunnable = new Runnable() {
+ public void run() {
+ if (mCheckBoxPreference != null) {
+ mCheckBoxPreference.setChecked(!mCheckBoxPreference.isChecked());
+ }
+
+ // Force toggle again in a second
+ mHandler.postDelayed(this, 1000);
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the XML preferences file
+ addPreferencesFromResource(R.xml.advanced_preferences);
+
+ // Get a reference to the checkbox preference
+ mCheckBoxPreference = (CheckBoxPreference)getPreferenceScreen().findPreference(
+ KEY_ADVANCED_CHECKBOX_PREFERENCE);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // Start the force toggle
+ mForceCheckBoxRunnable.run();
+
+ // Set up a listener whenever a key changes
+ getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ // Unregister the listener whenever a key changes
+ getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
+
+ mHandler.removeCallbacks(mForceCheckBoxRunnable);
+ }
+
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ // Let's do something when my counter preference value changes
+ if (key.equals(KEY_MY_PREFERENCE)) {
+ Toast.makeText(this, "Thanks! You increased my count to "
+ + sharedPreferences.getInt(key, 0), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/AlarmController.java b/samples/ApiDemos/src/com/example/android/apis/app/AlarmController.java
new file mode 100644
index 0000000..2ba5735
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/AlarmController.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2007 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.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+import java.util.Calendar;
+
+/**
+ * Example of scheduling one-shot and repeating alarms. See
+ * {@link OneShotAlarm} for the code run when the one-shot alarm goes off, and
+ * {@link RepeatingAlarm} for the code run when the repeating alarm goes off.
+ * <h4>Demo</h4>
+App/Service/Alarm Controller
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn">src/com.example.android.apis/app/AlarmController.java</td>
+ <td class="DescrColumn">The activity that lets you schedule alarms</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">src/com.example.android.apis/app/OneShotAlarm.java</td>
+ <td class="DescrColumn">This is an intent receiver that executes when the
+ one-shot alarm goes off</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">src/com.example.android.apis/app/RepeatingAlarm.java</td>
+ <td class="DescrColumn">This is an intent receiver that executes when the
+ repeating alarm goes off</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">/res/any/layout/alarm_controller.xml</td>
+ <td class="DescrColumn">Defines contents of the screen</td>
+ </tr>
+</table>
+
+ */
+public class AlarmController extends Activity {
+ Toast mToast;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.alarm_controller);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.one_shot);
+ button.setOnClickListener(mOneShotListener);
+ button = (Button)findViewById(R.id.start_repeating);
+ button.setOnClickListener(mStartRepeatingListener);
+ button = (Button)findViewById(R.id.stop_repeating);
+ button.setOnClickListener(mStopRepeatingListener);
+ }
+
+ private OnClickListener mOneShotListener = new OnClickListener() {
+ public void onClick(View v) {
+ // When the alarm goes off, we want to broadcast an Intent to our
+ // BroadcastReceiver. Here we make an Intent with an explicit class
+ // name to have our own receiver (which has been published in
+ // AndroidManifest.xml) instantiated and called, and then create an
+ // IntentSender to have the intent executed as a broadcast.
+ Intent intent = new Intent(AlarmController.this, OneShotAlarm.class);
+ PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,
+ 0, intent, 0);
+
+ // We want the alarm to go off 30 seconds from now.
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(System.currentTimeMillis());
+ calendar.add(Calendar.SECOND, 30);
+
+ // Schedule the alarm!
+ AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
+ am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
+
+ // Tell the user about what we did.
+ if (mToast != null) {
+ mToast.cancel();
+ }
+ mToast = Toast.makeText(AlarmController.this, R.string.one_shot_scheduled,
+ Toast.LENGTH_LONG);
+ mToast.show();
+ }
+ };
+
+ private OnClickListener mStartRepeatingListener = new OnClickListener() {
+ public void onClick(View v) {
+ // When the alarm goes off, we want to broadcast an Intent to our
+ // BroadcastReceiver. Here we make an Intent with an explicit class
+ // name to have our own receiver (which has been published in
+ // AndroidManifest.xml) instantiated and called, and then create an
+ // IntentSender to have the intent executed as a broadcast.
+ // Note that unlike above, this IntentSender is configured to
+ // allow itself to be sent multiple times.
+ Intent intent = new Intent(AlarmController.this, RepeatingAlarm.class);
+ PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,
+ 0, intent, 0);
+
+ // We want the alarm to go off 30 seconds from now.
+ long firstTime = SystemClock.elapsedRealtime();
+ firstTime += 15*1000;
+
+ // Schedule the alarm!
+ AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
+ am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ firstTime, 15*1000, sender);
+
+ // Tell the user about what we did.
+ if (mToast != null) {
+ mToast.cancel();
+ }
+ mToast = Toast.makeText(AlarmController.this, R.string.repeating_scheduled,
+ Toast.LENGTH_LONG);
+ mToast.show();
+ }
+ };
+
+ private OnClickListener mStopRepeatingListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Create the same intent, and thus a matching IntentSender, for
+ // the one that was scheduled.
+ Intent intent = new Intent(AlarmController.this, RepeatingAlarm.class);
+ PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,
+ 0, intent, 0);
+
+ // And cancel the alarm.
+ AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
+ am.cancel(sender);
+
+ // Tell the user about what we did.
+ if (mToast != null) {
+ mToast.cancel();
+ }
+ mToast = Toast.makeText(AlarmController.this, R.string.repeating_unscheduled,
+ Toast.LENGTH_LONG);
+ mToast.show();
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/AlarmService.java b/samples/ApiDemos/src/com/example/android/apis/app/AlarmService.java
new file mode 100644
index 0000000..151838a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/AlarmService.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2007 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.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+
+/**
+ * This demonstrates how you can schedule an alarm that causes a service to
+ * be started. This is useful when you want to schedule alarms that initiate
+ * long-running operations, such as retrieving recent e-mails.
+ */
+public class AlarmService extends Activity {
+ private PendingIntent mAlarmSender;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create an IntentSender that will launch our service, to be scheduled
+ // with the alarm manager.
+ mAlarmSender = PendingIntent.getService(AlarmService.this,
+ 0, new Intent(AlarmService.this, AlarmService_Service.class), 0);
+
+ setContentView(R.layout.alarm_service);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.start_alarm);
+ button.setOnClickListener(mStartAlarmListener);
+ button = (Button)findViewById(R.id.stop_alarm);
+ button.setOnClickListener(mStopAlarmListener);
+ }
+
+ private OnClickListener mStartAlarmListener = new OnClickListener() {
+ public void onClick(View v) {
+ // We want the alarm to go off 30 seconds from now.
+ long firstTime = SystemClock.elapsedRealtime();
+
+ // Schedule the alarm!
+ AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
+ am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ firstTime, 30*1000, mAlarmSender);
+
+ // Tell the user about what we did.
+ Toast.makeText(AlarmService.this, R.string.repeating_scheduled,
+ Toast.LENGTH_LONG).show();
+ }
+ };
+
+ private OnClickListener mStopAlarmListener = new OnClickListener() {
+ public void onClick(View v) {
+ // And cancel the alarm.
+ AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
+ am.cancel(mAlarmSender);
+
+ // Tell the user about what we did.
+ Toast.makeText(AlarmService.this, R.string.repeating_unscheduled,
+ Toast.LENGTH_LONG).show();
+
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.java b/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.java
new file mode 100644
index 0000000..6762ba9
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2007 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.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.widget.Toast;
+
+/**
+ * This is an example of implementing an application service that will run in
+ * response to an alarm, allowing us to move long duration work out of an
+ * intent receiver.
+ *
+ * @see AlarmService
+ * @see AlarmService_Alarm
+ */
+public class AlarmService_Service extends Service {
+ NotificationManager mNM;
+
+ @Override
+ public void onCreate() {
+ mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+ // show the icon in the status bar
+ showNotification();
+
+ // Start up the thread running the service. Note that we create a
+ // separate thread because the service normally runs in the process's
+ // main thread, which we don't want to block.
+ Thread thr = new Thread(null, mTask, "AlarmService_Service");
+ thr.start();
+ }
+
+ @Override
+ public void onDestroy() {
+ // Cancel the notification -- we use the same ID that we had used to start it
+ mNM.cancel(R.string.alarm_service_started);
+
+ // Tell the user we stopped.
+ Toast.makeText(this, R.string.alarm_service_finished, Toast.LENGTH_SHORT).show();
+ }
+
+ /**
+ * The function that runs in our worker thread
+ */
+ Runnable mTask = new Runnable() {
+ public void run() {
+ // Normally we would do some work here... for our sample, we will
+ // just sleep for 30 seconds.
+ long endTime = System.currentTimeMillis() + 15*1000;
+ while (System.currentTimeMillis() < endTime) {
+ synchronized (mBinder) {
+ try {
+ mBinder.wait(endTime - System.currentTimeMillis());
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ // Done with our work... stop the service!
+ AlarmService_Service.this.stopSelf();
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ /**
+ * Show a notification while this service is running.
+ */
+ private void showNotification() {
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(R.string.alarm_service_started);
+
+ // Set the icon, scrolling text and timestamp
+ Notification notification = new Notification(R.drawable.stat_sample, text,
+ System.currentTimeMillis());
+
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, AlarmService.class), 0);
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(this, getText(R.string.alarm_service_label),
+ text, contentIntent);
+
+ // Send the notification.
+ // We use a layout id because it is a unique number. We use it later to cancel.
+ mNM.notify(R.string.alarm_service_started, notification);
+ }
+
+ /**
+ * This is the object that receives interactions from clients. See RemoteService
+ * for a more complete example.
+ */
+ private final IBinder mBinder = new Binder() {
+ @Override
+ protected boolean onTransact(int code, Parcel data, Parcel reply,
+ int flags) throws RemoteException {
+ return super.onTransact(code, data, reply, flags);
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/AlertDialogSamples.java b/samples/ApiDemos/src/com/example/android/apis/app/AlertDialogSamples.java
new file mode 100644
index 0000000..fabdfc1
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/AlertDialogSamples.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.example.android.apis.R;
+
+/**
+ * Example of how to use an {@link android.app.AlertDialog}.
+ * <h3>AlertDialogSamples</h3>
+
+<p>This demonstrates the different ways the AlertDialog can be used.</p>
+
+<h4>Demo</h4>
+App/Dialog/Alert Dialog
+
+<h4>Source files</h4>
+ * <table class="LinkTable">
+ * <tr>
+ * <td >src/com.example.android.apis/app/AlertDialogSamples.java</td>
+ * <td >The Alert Dialog Samples implementation</td>
+ * </tr>
+ * <tr>
+ * <td >/res/any/layout/alert_dialog.xml</td>
+ * <td >Defines contents of the screen</td>
+ * </tr>
+ * </table>
+ */
+public class AlertDialogSamples extends Activity {
+ private static final int DIALOG_YES_NO_MESSAGE = 1;
+ private static final int DIALOG_YES_NO_LONG_MESSAGE = 2;
+ private static final int DIALOG_LIST = 3;
+ private static final int DIALOG_PROGRESS = 4;
+ private static final int DIALOG_SINGLE_CHOICE = 5;
+ private static final int DIALOG_MULTIPLE_CHOICE = 6;
+ private static final int DIALOG_TEXT_ENTRY = 7;
+
+ private static final int MAX_PROGRESS = 100;
+
+ private ProgressDialog mProgressDialog;
+ private int mProgress;
+ private Handler mProgressHandler;
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DIALOG_YES_NO_MESSAGE:
+ return new AlertDialog.Builder(AlertDialogSamples.this)
+ .setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.alert_dialog_two_buttons_title)
+ .setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked OK so do some stuff */
+ }
+ })
+ .setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked Cancel so do some stuff */
+ }
+ })
+ .create();
+ case DIALOG_YES_NO_LONG_MESSAGE:
+ return new AlertDialog.Builder(AlertDialogSamples.this)
+ .setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.alert_dialog_two_buttons_msg)
+ .setMessage(R.string.alert_dialog_two_buttons2_msg)
+ .setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked OK so do some stuff */
+ }
+ })
+ .setNeutralButton(R.string.alert_dialog_something, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked Something so do some stuff */
+ }
+ })
+ .setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked Cancel so do some stuff */
+ }
+ })
+ .create();
+ case DIALOG_LIST:
+ return new AlertDialog.Builder(AlertDialogSamples.this)
+ .setTitle(R.string.select_dialog)
+ .setItems(R.array.select_dialog_items, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+
+ /* User clicked so do some stuff */
+ String[] items = getResources().getStringArray(R.array.select_dialog_items);
+ new AlertDialog.Builder(AlertDialogSamples.this)
+ .setMessage("You selected: " + which + " , " + items[which])
+ .show();
+ }
+ })
+ .create();
+ case DIALOG_PROGRESS:
+ mProgressDialog = new ProgressDialog(AlertDialogSamples.this);
+ mProgressDialog.setIcon(R.drawable.alert_dialog_icon);
+ mProgressDialog.setTitle(R.string.select_dialog);
+ mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ mProgressDialog.setMax(MAX_PROGRESS);
+ mProgressDialog.setButton(getText(R.string.alert_dialog_hide), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked Yes so do some stuff */
+ }
+ });
+ mProgressDialog.setButton2(getText(R.string.alert_dialog_cancel), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked No so do some stuff */
+ }
+ });
+ return mProgressDialog;
+ case DIALOG_SINGLE_CHOICE:
+ return new AlertDialog.Builder(AlertDialogSamples.this)
+ .setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.alert_dialog_single_choice)
+ .setSingleChoiceItems(R.array.select_dialog_items2, 0, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked on a radio button do some stuff */
+ }
+ })
+ .setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked Yes so do some stuff */
+ }
+ })
+ .setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked No so do some stuff */
+ }
+ })
+ .create();
+ case DIALOG_MULTIPLE_CHOICE:
+ return new AlertDialog.Builder(AlertDialogSamples.this)
+ .setIcon(R.drawable.ic_popup_reminder)
+ .setTitle(R.string.alert_dialog_multi_choice)
+ .setMultiChoiceItems(R.array.select_dialog_items3,
+ new boolean[]{false, true, false, true, false, false, false},
+ new DialogInterface.OnMultiChoiceClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton,
+ boolean isChecked) {
+
+ /* User clicked on a check box do some stuff */
+ }
+ })
+ .setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked Yes so do some stuff */
+ }
+ })
+ .setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked No so do some stuff */
+ }
+ })
+ .create();
+ case DIALOG_TEXT_ENTRY:
+ // This example shows how to add a custom layout to an AlertDialog
+ LayoutInflater factory = LayoutInflater.from(this);
+ final View textEntryView = factory.inflate(R.layout.alert_dialog_text_entry, null);
+ return new AlertDialog.Builder(AlertDialogSamples.this)
+ .setIcon(R.drawable.alert_dialog_icon)
+ .setTitle(R.string.alert_dialog_text_entry)
+ .setView(textEntryView)
+ .setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked OK so do some stuff */
+ }
+ })
+ .setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+
+ /* User clicked cancel so do some stuff */
+ }
+ })
+ .create();
+ }
+ return null;
+ }
+
+ /**
+ * Initialization of the Activity after it is first created. Must at least
+ * call {@link android.app.Activity#setContentView(int)} to
+ * describe what is to be displayed in the screen.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.alert_dialog);
+
+ /* Display a text message with yes/no buttons and handle each message as well as the cancel action */
+ Button twoButtonsTitle = (Button) findViewById(R.id.two_buttons);
+ twoButtonsTitle.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG_YES_NO_MESSAGE);
+ }
+ });
+
+ /* Display a long text message with yes/no buttons and handle each message as well as the cancel action */
+ Button twoButtons2Title = (Button) findViewById(R.id.two_buttons2);
+ twoButtons2Title.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG_YES_NO_LONG_MESSAGE);
+ }
+ });
+
+
+ /* Display a list of items */
+ Button selectButton = (Button) findViewById(R.id.select_button);
+ selectButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG_LIST);
+ }
+ });
+
+ /* Display a custom progress bar */
+ Button progressButton = (Button) findViewById(R.id.progress_button);
+ progressButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG_PROGRESS);
+ mProgress = 0;
+ mProgressDialog.setProgress(0);
+ mProgressHandler.sendEmptyMessage(0);
+ }
+ });
+
+ /* Display a radio button group */
+ Button radioButton = (Button) findViewById(R.id.radio_button);
+ radioButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG_SINGLE_CHOICE);
+ }
+ });
+
+ /* Display a list of checkboxes */
+ Button checkBox = (Button) findViewById(R.id.checkbox_button);
+ checkBox.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG_MULTIPLE_CHOICE);
+ }
+ });
+
+ /* Display a text entry dialog */
+ Button textEntry = (Button) findViewById(R.id.text_entry_button);
+ textEntry.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG_TEXT_ENTRY);
+ }
+ });
+
+ mProgressHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ if (mProgress >= MAX_PROGRESS) {
+ mProgressDialog.dismiss();
+ } else {
+ mProgress++;
+ mProgressDialog.incrementProgressBy(1);
+ mProgressHandler.sendEmptyMessageDelayed(0, 100);
+ }
+ }
+ };
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ContactsFilter.java b/samples/ApiDemos/src/com/example/android/apis/app/ContactsFilter.java
new file mode 100644
index 0000000..bb843e5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ContactsFilter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 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 android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Front-end for launching {@link ContactsFilterInstrumentation} example
+ * instrumentation class.
+ */
+public class ContactsFilter extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.contacts_filter);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.go);
+ button.setOnClickListener(mGoListener);
+ }
+
+ private OnClickListener mGoListener = new OnClickListener() {
+ public void onClick(View v) {
+ startInstrumentation(new ComponentName(ContactsFilter.this,
+ ContactsFilterInstrumentation.class), null, null);
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ContactsFilterInstrumentation.java b/samples/ApiDemos/src/com/example/android/apis/app/ContactsFilterInstrumentation.java
new file mode 100644
index 0000000..04bb671
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ContactsFilterInstrumentation.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.view.KeyEvent;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.Map;
+
+/**
+ * This is an example implementation of the {@link android.app.Instrumentation}
+ * class, allowing you to run tests against application code. The
+ * instrumentation implementation here is loaded into the application's
+ * process, for controlling and monitoring what it does.
+ */
+public class ContactsFilterInstrumentation extends Instrumentation {
+ @Override
+ public void onCreate(Bundle arguments) {
+ super.onCreate(arguments);
+
+ // When this instrumentation is created, we simply want to start
+ // its test code off in a separate thread, which will call back
+ // to us in onStart().
+ start();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // First start the activity we are instrumenting -- the contacts
+ // list.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClassName(getTargetContext(),
+ "com.android.phone.Dialer");
+ Activity activity = startActivitySync(intent);
+
+ // This is the Activity object that was started, to do with as we want.
+ Log.i("ContactsFilterInstrumentation", "Started: " + activity);
+
+ // We are going to enqueue a couple key events to simulate the user
+ // filtering the list. This is the low-level API so we must send both
+ // down and up events.
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_M));
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_M));
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A));
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A));
+
+ // Wait for the activity to finish all of its processing.
+ waitForIdleSync();
+
+ // And we are done!
+ Log.i("ContactsFilterInstrumentation", "Done!");
+ finish(Activity.RESULT_OK, null);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ContactsSelectInstrumentation.java b/samples/ApiDemos/src/com/example/android/apis/app/ContactsSelectInstrumentation.java
new file mode 100644
index 0000000..dcb8b83
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ContactsSelectInstrumentation.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.IBinder;
+import android.view.KeyEvent;
+import android.provider.Contacts;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.Map;
+
+/**
+ * This is an example implementation of the {@link android.app.Instrumentation}
+ * class, allowing you to run tests against application code. The
+ * instrumentation implementation here is loaded into the application's
+ * process, for controlling and monitoring what it does.
+ */
+public class ContactsSelectInstrumentation extends Instrumentation {
+ @Override
+ public void onCreate(Bundle arguments) {
+ super.onCreate(arguments);
+
+ // When this instrumentation is created, we simply want to start
+ // its test code off in a separate thread, which will call back
+ // to us in onStart().
+ start();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // First start the activity we are instrumenting -- the contacts
+ // list.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClassName(getTargetContext(),
+ "com.android.phone.Dialer");
+ Activity activity = startActivitySync(intent);
+
+ // This is the Activity object that was started, to do with as we want.
+ Log.i("ContactsSelectInstrumentation", "Started: " + activity);
+
+ // Monitor for the expected start activity call.
+ ActivityMonitor am = addMonitor(IntentFilter.create(
+ Intent.ACTION_VIEW, Contacts.People.CONTENT_ITEM_TYPE), null, true);
+
+ // We are going to enqueue a couple key events to simulate the user
+ // selecting an item in the list.
+ sendKeySync(new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
+ sendKeySync(new KeyEvent(
+ KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_DOWN));
+ sendKeySync(new KeyEvent(
+ KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
+ sendKeySync(new KeyEvent(
+ KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER));
+
+ // Was the expected activity started?
+ if (checkMonitorHit(am, 1)) {
+ Log.i("ContactsSelectInstrumentation", "Activity started!");
+ } else {
+ Log.i("ContactsSelectInstrumentation", "*** ACTIVITY NOT STARTED!");
+ }
+
+ // And we are done!
+ Log.i("ContactsSelectInstrumentation", "Done!");
+ finish(Activity.RESULT_OK, null);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/CustomDialogActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/CustomDialogActivity.java
new file mode 100644
index 0000000..62f0ae1
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/CustomDialogActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 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.os.Bundle;
+
+/**
+ * <h3>Dialog Activity</h3>
+ *
+ * <p>This demonstrates the how to write an activity that looks like
+ * a pop-up dialog with a custom theme using a different text color.</p>
+ */
+public class CustomDialogActivity extends Activity {
+ /**
+ * 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);
+
+ // See assets/res/any/layout/dialog_activity.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.custom_dialog_activity);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/CustomTitle.java b/samples/ApiDemos/src/com/example/android/apis/app/CustomTitle.java
new file mode 100644
index 0000000..e22a5cc
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/CustomTitle.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Example of how to use a custom title {@link android.view.Window#FEATURE_CUSTOM_TITLE}.
+ * <h3>CustomTitle</h3>
+
+<p>This demonstrates how a custom title can be used.</p>
+
+<h4>Demo</h4>
+App/Title/Custom Title
+
+<h4>Source files</h4>
+ * <table class="LinkTable">
+ * <tr>
+ * <td >src/com.example.android.apis/app/CustomTitle.java</td>
+ * <td >The Custom Title implementation</td>
+ * </tr>
+ * <tr>
+ * <td >/res/any/layout/custom_title.xml</td>
+ * <td >Defines contents of the screen</td>
+ * </tr>
+ * </table>
+ */
+public class CustomTitle extends Activity {
+
+ /**
+ * Initialization of the Activity after it is first created. Must at least
+ * call {@link android.app.Activity#setContentView(int)} to
+ * describe what is to be displayed in the screen.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
+ setContentView(R.layout.custom_title);
+ getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_1);
+
+ final TextView leftText = (TextView) findViewById(R.id.left_text);
+ final TextView rightText = (TextView) findViewById(R.id.right_text);
+ final EditText leftTextEdit = (EditText) findViewById(R.id.left_text_edit);
+ final EditText rightTextEdit = (EditText) findViewById(R.id.right_text_edit);
+ Button leftButton = (Button) findViewById(R.id.left_text_button);
+ Button rightButton = (Button) findViewById(R.id.right_text_button);
+
+ leftButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ leftText.setText(leftTextEdit.getText());
+ }
+ });
+ rightButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ rightText.setText(rightTextEdit.getText());
+ }
+ });
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/DefaultValues.java b/samples/ApiDemos/src/com/example/android/apis/app/DefaultValues.java
new file mode 100644
index 0000000..35bdf13
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/DefaultValues.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.ApiDemosApplication;
+import com.example.android.apis.R;
+
+import android.app.Application;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceManager;
+
+/**
+ * This activity is an example of a simple settings screen that has default
+ * values.
+ * <p>
+ * In order for the default values to be populated into the
+ * {@link SharedPreferences} (from the preferences XML file), the client must
+ * call
+ * {@link PreferenceManager#setDefaultValues(android.content.Context, int, boolean)}.
+ * <p>
+ * This should be called early, typically when the application is first created.
+ * This ensures any of the application's activities, services, etc. will have
+ * the default values present, even if the user has not wandered into the
+ * application's settings. For ApiDemos, this is {@link ApiDemosApplication},
+ * and you can find the call to
+ * {@link PreferenceManager#setDefaultValues(android.content.Context, int, boolean)}
+ * in its {@link ApiDemosApplication#onCreate() onCreate}.
+ */
+public class DefaultValues extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.default_values);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/DialogActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/DialogActivity.java
new file mode 100644
index 0000000..7441b75
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/DialogActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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 android.app.Activity;
+import android.os.Bundle;
+import android.view.Window;
+
+import com.example.android.apis.R;
+
+/**
+ * <h3>Dialog Activity</h3>
+ *
+ * <p>This demonstrates the how to write an activity that looks like
+ * a pop-up dialog.</p>
+ */
+public class DialogActivity extends Activity {
+ /**
+ * 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);
+
+ requestWindowFeature(Window.FEATURE_LEFT_ICON);
+
+ // See assets/res/any/layout/dialog_activity.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.dialog_activity);
+
+ getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
+ android.R.drawable.ic_dialog_alert);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ForwardTarget.java b/samples/ApiDemos/src/com/example/android/apis/app/ForwardTarget.java
new file mode 100644
index 0000000..ee699aa
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ForwardTarget.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 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.os.Bundle;
+
+
+/**
+ * Example of removing yourself from the history stack after forwarding to
+ * another activity.
+ */
+public class ForwardTarget extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.forward_target);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/Forwarding.java b/samples/ApiDemos/src/com/example/android/apis/app/Forwarding.java
new file mode 100644
index 0000000..ef082bf
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/Forwarding.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+
+/**
+ * <p>Example of removing yourself from the history stack after forwarding to
+ * another activity. This can be useful, for example, to implement
+ a confirmation dialog before the user goes on to another activity -- once the
+ user has confirmed this operation, they should not see the dialog again if they
+go back from it.</p>
+
+<p>Note that another way to implement a confirmation dialog would be as
+an activity that returns a result to its caller. Either approach can be
+useful depending on how it makes sense to structure the application.</p>
+
+<h4>Demo</h4>
+App/Activity/Receive Result
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn">src/com.example.android.apis/app/Forwarding.java</td>
+ <td class="DescrColumn">Forwards the user to another activity when its button is pressed</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">/res/any/layout/forwarding.xml</td>
+ <td class="DescrColumn">Defines contents of the Forwarding screen</td>
+ </tr>
+</table>
+ */
+public class Forwarding extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.forwarding);
+
+ // Watch for button clicks.
+ Button goButton = (Button)findViewById(R.id.go);
+ goButton.setOnClickListener(mGoListener);
+ }
+
+ private OnClickListener mGoListener = new OnClickListener()
+ {
+ public void onClick(View v)
+ {
+ // Here we start the next activity, and then call finish()
+ // so that our own will stop running and be removed from the
+ // history stack.
+ Intent intent = new Intent();
+ intent.setClass(Forwarding.this, ForwardTarget.class);
+ startActivity(intent);
+ finish();
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/HelloWorld.java b/samples/ApiDemos/src/com/example/android/apis/app/HelloWorld.java
new file mode 100644
index 0000000..1a7f698
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/HelloWorld.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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.os.Bundle;
+
+
+/**
+ * Simple example of writing an application Activity.
+ * Hello World</a></h3>
+
+<p>This demonstrates the basic code needed to write a Screen activity.</p>
+
+<h4>Demo</h4>
+App/Activity/Hello World
+
+<h4>Source files</h4>
+ * <table class="LinkTable">
+ * <tr>
+ * <td >src/com.example.android.apis/app/HelloWorld.java</td>
+ * <td >The Hello World Screen implementation</td>
+ * </tr>
+ * <tr>
+ * <td >/res/any/layout/hello_world.xml</td>
+ * <td >Defines contents of the screen</td>
+ * </tr>
+ * </table>
+ */
+public class HelloWorld extends Activity
+{
+ /**
+ * 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);
+
+ // See assets/res/any/layout/hello_world.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.hello_world);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/IRemoteService.aidl b/samples/ApiDemos/src/com/example/android/apis/app/IRemoteService.aidl
new file mode 100644
index 0000000..046e3f6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/IRemoteService.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.app.IRemoteServiceCallback;
+
+/**
+ * Example of defining an interface for calling on to a remote service
+ * (running in another process).
+ */
+interface IRemoteService {
+ /**
+ * Often you want to allow a service to call back to its clients.
+ * This shows how to do so, by registering a callback interface with
+ * the service.
+ */
+ void registerCallback(IRemoteServiceCallback cb);
+
+ /**
+ * Remove a previously registered callback interface.
+ */
+ void unregisterCallback(IRemoteServiceCallback cb);
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/IRemoteServiceCallback.aidl b/samples/ApiDemos/src/com/example/android/apis/app/IRemoteServiceCallback.aidl
new file mode 100644
index 0000000..4fed807
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/IRemoteServiceCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2007 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;
+
+/**
+ * Example of a callback interface used by IRemoteService to send
+ * synchronous notifications back to its clients. Note that this is a
+ * one-way interface so the server does not block waiting for the client.
+ */
+oneway interface IRemoteServiceCallback {
+ /**
+ * Called when the service has a new value for you.
+ */
+ void valueChanged(int value);
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ISecondary.aidl b/samples/ApiDemos/src/com/example/android/apis/app/ISecondary.aidl
new file mode 100644
index 0000000..98e2823
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ISecondary.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 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;
+
+/**
+ * Example of a secondary interface associated with a service. (Note that
+ * the interface itself doesn't impact, it is just a matter of how you
+ * retrieve it from the service.)
+ */
+interface ISecondary {
+ /**
+ * Request the PID of this service, to do evil things with it.
+ */
+ int getPid();
+
+ /**
+ * This demonstrates the basic types that you can use as parameters
+ * and return values in AIDL.
+ */
+ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
+ double aDouble, String aString);
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java b/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
new file mode 100644
index 0000000..d44c008
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class IncomingMessage extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.incoming_message);
+
+ Button button = (Button) findViewById(R.id.notify);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ showToast();
+ showNotification();
+ }
+ });
+ }
+
+ /**
+ * The toast pops up a quick message to the user showing what could be
+ * the text of an incoming message. It uses a custom view to do so.
+ */
+ protected void showToast() {
+ // create the view
+ View view = inflateView(R.layout.incoming_message_panel);
+
+ // set the text in the view
+ TextView tv = (TextView)view.findViewById(R.id.message);
+ tv.setText("khtx. meet u for dinner. cul8r");
+
+ // show the toast
+ Toast toast = new Toast(this);
+ toast.setView(view);
+ toast.setDuration(Toast.LENGTH_LONG);
+ toast.show();
+ }
+
+ private View inflateView(int resource) {
+ LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ return vi.inflate(resource, null);
+ }
+
+ /**
+ * The notification is the icon and associated expanded entry in the
+ * status bar.
+ */
+ protected void showNotification() {
+ // look up the notification manager service
+ NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+ // The details of our fake message
+ CharSequence from = "Joe";
+ CharSequence message = "kthx. meet u for dinner. cul8r";
+
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, IncomingMessageView.class), 0);
+
+ // The ticker text, this uses a formatted string so our message could be localized
+ String tickerText = getString(R.string.imcoming_message_ticker_text, message);
+
+ // construct the Notification object.
+ Notification notif = new Notification(R.drawable.stat_sample, tickerText,
+ System.currentTimeMillis());
+
+ // Set the info for the views that show in the notification panel.
+ notif.setLatestEventInfo(this, from, message, contentIntent);
+
+ // after a 100ms delay, vibrate for 250ms, pause for 100 ms and
+ // then vibrate for 500ms.
+ notif.vibrate = new long[] { 100, 250, 100, 500};
+
+ // Note that we use R.layout.incoming_message_panel as the ID for
+ // the notification. It could be any integer you want, but we use
+ // the convention of using a resource id for a string related to
+ // the notification. It will always be a unique number within your
+ // application.
+ nm.notify(R.string.imcoming_message_ticker_text, notif);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageView.java b/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageView.java
new file mode 100644
index 0000000..c3bead0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageView.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.os.Bundle;
+
+import java.util.Map;
+
+/**
+ * This activity is run as the click activity for {@link IncomingMessage}.
+ * When it comes up, it also clears the notification, because the "message"
+ * has been "read."
+ */
+public class IncomingMessageView extends Activity {
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.incoming_message_view);
+
+ // look up the notification manager service
+ NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+
+ // cancel the notification that we started in IncomingMessage
+ nm.cancel(R.string.imcoming_message_ticker_text);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/Intents.java b/samples/ApiDemos/src/com/example/android/apis/app/Intents.java
new file mode 100644
index 0000000..8f02b83
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/Intents.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class Intents extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.intents);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.get_music);
+ button.setOnClickListener(mGetMusicListener);
+ }
+
+ private OnClickListener mGetMusicListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("audio/*");
+ startActivity(Intent.createChooser(intent, "Select music"));
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LauncherShortcuts.java b/samples/ApiDemos/src/com/example/android/apis/app/LauncherShortcuts.java
new file mode 100644
index 0000000..f28deab
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LauncherShortcuts.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008 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;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.widget.TextView;
+
+import com.example.android.apis.R;
+
+/**
+ * This Activity actually handles two stages of a launcher shortcut's life cycle.
+ *
+ * 1. Your application offers to provide shortcuts to the launcher. When
+ * the user installs a shortcut, an activity within your application
+ * generates the actual shortcut and returns it to the launcher, where it
+ * is shown to the user as an icon.
+ *
+ * 2. Any time the user clicks on an installed shortcut, an intent is sent.
+ * Typically this would then be handled as necessary by an activity within
+ * your application.
+ *
+ * We handle stage 1 (creating a shortcut) by simply sending back the information (in the form
+ * of an {@link android.content.Intent} that the launcher will use to create the shortcut.
+ *
+ * You can also implement this in an interactive way, by having your activity actually present
+ * UI for the user to select the specific nature of the shortcut, such as a contact, picture, URL,
+ * media item, or action.
+ *
+ * We handle stage 2 (responding to a shortcut) in this sample by simply displaying the contents
+ * of the incoming {@link android.content.Intent}.
+ *
+ * In a real application, you would probably use the shortcut intent to display specific content
+ * or start a particular operation.
+ */
+public class LauncherShortcuts extends Activity {
+
+ private static final String EXTRA_KEY = "com.example.android.apis.app.LauncherShortcuts";
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Resolve the intent
+
+ final Intent intent = getIntent();
+ final String action = intent.getAction();
+
+ // If the intent is a request to create a shortcut, we'll do that and exit
+
+ if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
+ setupShortcut();
+ finish();
+ return;
+ }
+
+ // If we weren't launched with a CREATE_SHORTCUT intent, simply put up an informative
+ // display.
+
+ // Inflate our UI from its XML layout description.
+
+ setContentView(R.layout.launcher_shortcuts);
+
+ // Provide a lightweight view of the Intent that launched us
+
+ TextView intentInfo = (TextView) findViewById(R.id.txt_shortcut_intent);
+ String info = intent.toString();
+ String extra = intent.getStringExtra(EXTRA_KEY);
+ if (extra != null) {
+ info = info + " " + extra;
+ }
+ intentInfo.setText(info);
+ }
+
+ /**
+ * This function creates a shortcut and returns it to the caller. There are actually two
+ * intents that you will send back.
+ *
+ * The first intent serves as a container for the shortcut and is returned to the launcher by
+ * setResult(). This intent must contain three fields:
+ *
+ * <ul>
+ * <li>{@link android.content.Intent#EXTRA_SHORTCUT_INTENT} The shortcut intent.</li>
+ * <li>{@link android.content.Intent#EXTRA_SHORTCUT_NAME} The text that will be displayed with
+ * the shortcut.</li>
+ * <li>{@link android.content.Intent#EXTRA_SHORTCUT_ICON} The shortcut's icon, if provided as a
+ * bitmap, <i>or</i> {@link android.content.Intent#EXTRA_SHORTCUT_ICON_RESOURCE} if provided as
+ * a drawable resource.</li>
+ * </ul>
+ *
+ * If you use a simple drawable resource, note that you must wrapper it using
+ * {@link android.content.Intent.ShortcutIconResource}, as shown below. This is required so
+ * that the launcher can access resources that are stored in your application's .apk file. If
+ * you return a bitmap, such as a thumbnail, you can simply put the bitmap into the extras
+ * bundle using {@link android.content.Intent#EXTRA_SHORTCUT_ICON}.
+ *
+ * The shortcut intent can be any intent that you wish the launcher to send, when the user
+ * clicks on the shortcut. Typically this will be {@link android.content.Intent#ACTION_VIEW}
+ * with an appropriate Uri for your content, but any Intent will work here as long as it
+ * triggers the desired action within your Activity.
+ */
+ private void setupShortcut() {
+ // First, set up the shortcut intent. For this example, we simply create an intent that
+ // will bring us directly back to this activity. A more typical implementation would use a
+ // data Uri in order to display a more specific result, or a custom action in order to
+ // launch a specific operation.
+
+ Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
+ shortcutIntent.setClassName(this, this.getClass().getName());
+ shortcutIntent.putExtra(EXTRA_KEY, "ApiDemos Provided This Shortcut");
+
+ // Then, set up the container intent (the response to the caller)
+
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getString(R.string.shortcut_name));
+ Parcelable iconResource = Intent.ShortcutIconResource.fromContext(
+ this, R.drawable.app_sample_code);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
+
+ // Now, return the result to the launcher
+
+ setResult(RESULT_OK, intent);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LaunchingPreferences.java b/samples/ApiDemos/src/com/example/android/apis/app/LaunchingPreferences.java
new file mode 100644
index 0000000..aa151fe
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LaunchingPreferences.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.LinearLayout.LayoutParams;
+
+/**
+ * Demonstrates launching a PreferenceActivity and grabbing a value it saved.
+ */
+public class LaunchingPreferences extends Activity implements OnClickListener {
+
+ private static final int REQUEST_CODE_PREFERENCES = 1;
+
+ private TextView mCounterText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ /*
+ * If this were my app's main activity, I would load the default values
+ * so they're set even if the user does not go into the preferences
+ * screen. Another good place to call this method would be from a
+ * subclass of Application, so your default values would be loaded
+ * regardless of entry into your application (for example, a service or
+ * activity).
+ */
+ PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
+
+ // Simple layout
+ LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ setContentView(layout);
+
+ // Create a simple button that will launch the preferences
+ Button launchPreferences = new Button(this);
+ launchPreferences.setText(getString(R.string.launch_preference_activity));
+ launchPreferences.setOnClickListener(this);
+ layout.addView(launchPreferences, new LayoutParams(LayoutParams.FILL_PARENT,
+ LayoutParams.WRAP_CONTENT));
+
+ mCounterText = new TextView(this);
+ layout.addView(mCounterText, new LayoutParams(LayoutParams.FILL_PARENT,
+ LayoutParams.WRAP_CONTENT));
+
+ updateCounterText();
+ }
+
+ public void onClick(View v) {
+
+ // When the button is clicked, launch an activity through this intent
+ Intent launchPreferencesIntent = new Intent().setClass(this, AdvancedPreferences.class);
+
+ // Make it a subactivity so we know when it returns
+ startActivityForResult(launchPreferencesIntent, REQUEST_CODE_PREFERENCES);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ // The preferences returned if the request code is what we had given
+ // earlier in startSubActivity
+ if (requestCode == REQUEST_CODE_PREFERENCES) {
+ // Read a sample value they have set
+ updateCounterText();
+ }
+ }
+
+ private void updateCounterText() {
+ // Since we're in the same package, we can use this context to get
+ // the default shared preferences
+ SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
+ final int counter = sharedPref.getInt(AdvancedPreferences.KEY_MY_PREFERENCE, 0);
+ mCounterText.setText(getString(R.string.counter_value_is) + " " + counter);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalSample.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalSample.java
new file mode 100644
index 0000000..1bb26e9
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalSample.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 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 android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Front-end for launching {@link LocalSampleInstrumentation} example
+ * instrumentation class.
+ */
+public class LocalSample extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.local_sample);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.go);
+ button.setOnClickListener(mGoListener);
+ }
+
+ private OnClickListener mGoListener = new OnClickListener() {
+ public void onClick(View v) {
+ startInstrumentation(new ComponentName(LocalSample.this,
+ LocalSampleInstrumentation.class), null, null);
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalSampleInstrumentation.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalSampleInstrumentation.java
new file mode 100644
index 0000000..e0f6163
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalSampleInstrumentation.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.view.KeyEvent;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.Map;
+
+/**
+ * This is an example implementation of the {@link android.app.Instrumentation}
+ * class demonstrating instrumentation against one of this application's sample
+ * activities.
+ */
+public class LocalSampleInstrumentation extends Instrumentation {
+ public abstract static class ActivityRunnable implements Runnable {
+ public final Activity activity;
+ public ActivityRunnable(Activity _activity) {
+ activity = _activity;
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle arguments) {
+ super.onCreate(arguments);
+
+ // When this instrumentation is created, we simply want to start
+ // its test code off in a separate thread, which will call back
+ // to us in onStart().
+ start();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // First start the activity we are instrumenting -- the save/restore
+ // state sample, which has a nice edit text into which we can write
+ // text.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClass(getTargetContext(), SaveRestoreState.class);
+ SaveRestoreState activity = (SaveRestoreState)startActivitySync(intent);
+
+ // This is the Activity object that was started, to do with as we want.
+ Log.i("LocalSampleInstrumentation",
+ "Initial text: " + activity.getSavedText());
+
+ // Clear the text so we start fresh.
+ runOnMainSync(new ActivityRunnable(activity) {
+ public void run() {
+ ((SaveRestoreState)activity).setSavedText("");
+ }
+ });
+
+ // Act like the user is typing some text.
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT));
+ sendCharacterSync(KeyEvent.KEYCODE_H);
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT));
+ sendCharacterSync(KeyEvent.KEYCODE_E);
+ sendCharacterSync(KeyEvent.KEYCODE_L);
+ sendCharacterSync(KeyEvent.KEYCODE_L);
+ sendCharacterSync(KeyEvent.KEYCODE_O);
+
+ // Wait for the activity to finish all of its processing.
+ waitForIdleSync();
+
+ // Retrieve the text we should have written...
+ Log.i("LocalSampleInstrumentation",
+ "Final text: " + activity.getSavedText());
+
+ // And we are done!
+ Log.i("ContactsFilterInstrumentation", "Done!");
+ finish(Activity.RESULT_OK, null);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
new file mode 100644
index 0000000..8791578
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.widget.Toast;
+
+// 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;
+
+/**
+ * This is an example of implementing an application service that runs locally
+ * in the same process as the application. The {@link LocalServiceController}
+ * and {@link LocalServiceBinding} classes show how to interact with the
+ * service.
+ *
+ * <p>Notice the use of the {@link NotificationManager} when interesting things
+ * happen in the service. This is generally how background services should
+ * interact with the user, rather than doing something more disruptive such as
+ * calling startActivity().
+ */
+public class LocalService extends Service {
+ private NotificationManager mNM;
+
+ /**
+ * Class for clients to access. Because we know this service always
+ * runs in the same process as its clients, we don't need to deal with
+ * IPC.
+ */
+ public class LocalBinder extends Binder {
+ LocalService getService() {
+ return LocalService.this;
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+ // Display a notification about us starting. We put an icon in the status bar.
+ showNotification();
+ }
+
+ @Override
+ public void onDestroy() {
+ // Cancel the persistent notification.
+ mNM.cancel(R.string.local_service_started);
+
+ // Tell the user we stopped.
+ Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ // This is the object that receives interactions from clients. See
+ // RemoteService for a more complete example.
+ private final IBinder mBinder = new LocalBinder();
+
+ /**
+ * Show a notification while this service is running.
+ */
+ private void showNotification() {
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(R.string.local_service_started);
+
+ // Set the icon, scrolling text and timestamp
+ Notification notification = new Notification(R.drawable.stat_sample, text,
+ System.currentTimeMillis());
+
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, LocalServiceController.class), 0);
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(this, getText(R.string.local_service_label),
+ text, contentIntent);
+
+ // Send the notification.
+ // We use a layout id because it is a unique number. We use it later to cancel.
+ mNM.notify(R.string.local_service_started, notification);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceBinding.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceBinding.java
new file mode 100644
index 0000000..ddcfad5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceBinding.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+
+/**
+ * <p>Example of binding and unbinding to the {@link LocalService}.
+ * This demonstrates the implementation of a service which the client will
+ * bind to, receiving an object through which it can communicate with the service.</p>
+ */
+public class LocalServiceBinding extends Activity {
+ private boolean mIsBound;
+ private LocalService mBoundService;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.local_service_binding);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.bind);
+ button.setOnClickListener(mBindListener);
+ button = (Button)findViewById(R.id.unbind);
+ button.setOnClickListener(mUnbindListener);
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ // This is called when the connection with the service has been
+ // established, giving us the service object we can use to
+ // interact with the service. Because we have bound to a explicit
+ // service that we know is running in our own process, we can
+ // cast its IBinder to a concrete class and directly access it.
+ mBoundService = ((LocalService.LocalBinder)service).getService();
+
+ // Tell the user about this for our demo.
+ Toast.makeText(LocalServiceBinding.this, R.string.local_service_connected,
+ Toast.LENGTH_SHORT).show();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been
+ // unexpectedly disconnected -- that is, its process crashed.
+ // Because it is running in our same process, we should never
+ // see this happen.
+ mBoundService = null;
+ Toast.makeText(LocalServiceBinding.this, R.string.local_service_disconnected,
+ Toast.LENGTH_SHORT).show();
+ }
+ };
+
+ private OnClickListener mBindListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Establish a connection with the service. We use an explicit
+ // class name because we want a specific service implementation that
+ // we know will be running in our own process (and thus won't be
+ // supporting component replacement by other applications).
+ bindService(new Intent(LocalServiceBinding.this,
+ LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
+ mIsBound = true;
+ }
+ };
+
+ private OnClickListener mUnbindListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (mIsBound) {
+ // Detach our existing connection.
+ unbindService(mConnection);
+ mIsBound = false;
+ }
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceController.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceController.java
new file mode 100644
index 0000000..6041249
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceController.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007 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.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+
+/**
+ * <p>Example of explicitly starting and stopping the {@link LocalService}.
+ * This demonstrates the implementation of a service that runs in the same
+ * process as the rest of the application, which is explicitly started and stopped
+ * as desired.</p>
+ */
+public class LocalServiceController extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.local_service_controller);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.start);
+ button.setOnClickListener(mStartListener);
+ button = (Button)findViewById(R.id.stop);
+ button.setOnClickListener(mStopListener);
+ }
+
+ private OnClickListener mStartListener = new OnClickListener() {
+ public void onClick(View v)
+ {
+ // Make sure the service is started. It will continue running
+ // until someone calls stopService(). The Intent we use to find
+ // the service explicitly specifies our service component, because
+ // we want it running in our own process and don't want other
+ // applications to replace it.
+ startService(new Intent(LocalServiceController.this,
+ LocalService.class));
+ }
+ };
+
+ private OnClickListener mStopListener = new OnClickListener() {
+ public void onClick(View v)
+ {
+ // Cancel a previous call to startService(). Note that the
+ // service will not actually stop at this point if there are
+ // still bound clients.
+ stopService(new Intent(LocalServiceController.this,
+ LocalService.class));
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/MenuInflateFromXml.java b/samples/ApiDemos/src/com/example/android/apis/app/MenuInflateFromXml.java
new file mode 100644
index 0000000..f51b3b8
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/MenuInflateFromXml.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * Demonstrates inflating menus from XML. There are different menu XML resources
+ * that the user can choose to inflate. First, select an example resource from
+ * the spinner, and then hit the menu button. To choose another, back out of the
+ * activity and start over.
+ */
+public class MenuInflateFromXml extends Activity {
+ /**
+ * Different example menu resources.
+ */
+ private static final int sMenuExampleResources[] = {
+ R.menu.title_only, R.menu.title_icon, R.menu.submenu, R.menu.groups,
+ R.menu.checkable, R.menu.shortcuts, R.menu.order, R.menu.category_order,
+ R.menu.visible, R.menu.disabled
+ };
+
+ /**
+ * Names corresponding to the different example menu resources.
+ */
+ private static final String sMenuExampleNames[] = {
+ "Title only", "Title and Icon", "Submenu", "Groups",
+ "Checkable", "Shortcuts", "Order", "Category and Order",
+ "Visible", "Disabled"
+ };
+
+ /**
+ * Lets the user choose a menu resource.
+ */
+ private Spinner mSpinner;
+
+ /**
+ * Shown as instructions.
+ */
+ private TextView mInstructionsText;
+
+ /**
+ * Safe to hold on to this.
+ */
+ private Menu mMenu;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create a simple layout
+ LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+
+ // Create the spinner to allow the user to choose a menu XML
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, sMenuExampleNames);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mSpinner = new Spinner(this);
+ // When programmatically creating views, make sure to set an ID
+ // so it will automatically save its instance state
+ mSpinner.setId(R.id.spinner);
+ mSpinner.setAdapter(adapter);
+
+ // Add the spinner
+ layout.addView(mSpinner,
+ new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.FILL_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ // Create help text
+ mInstructionsText = new TextView(this);
+ mInstructionsText.setText(getResources().getString(
+ R.string.menu_from_xml_instructions_press_menu));
+
+ // Add the help, make it look decent
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.FILL_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(10, 10, 10, 10);
+ layout.addView(mInstructionsText, lp);
+
+ // Set the layout as our content view
+ setContentView(layout);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Hold on to this
+ mMenu = menu;
+
+ // Inflate the currently selected menu XML resource.
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(sMenuExampleResources[mSpinner.getSelectedItemPosition()], menu);
+
+ // Disable the spinner since we've already created the menu and the user
+ // can no longer pick a different menu XML.
+ mSpinner.setEnabled(false);
+
+ // Change instructions
+ mInstructionsText.setText(getResources().getString(
+ R.string.menu_from_xml_instructions_go_back));
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ // For "Title only": Examples of matching an ID with one assigned in
+ // the XML
+ case R.id.jump:
+ Toast.makeText(this, "Jump up in the air!", Toast.LENGTH_SHORT).show();
+ return true;
+
+ case R.id.dive:
+ Toast.makeText(this, "Dive into the water!", Toast.LENGTH_SHORT).show();
+ return true;
+
+ // For "Groups": Toggle visibility of grouped menu items with
+ // nongrouped menu items
+ case R.id.browser_visibility:
+ // The refresh item is part of the browser group
+ final boolean shouldShowBrowser = !mMenu.findItem(R.id.refresh).isVisible();
+ mMenu.setGroupVisible(R.id.browser, shouldShowBrowser);
+ break;
+
+ case R.id.email_visibility:
+ // The reply item is part of the email group
+ final boolean shouldShowEmail = !mMenu.findItem(R.id.reply).isVisible();
+ mMenu.setGroupVisible(R.id.email, shouldShowEmail);
+ break;
+
+ // Generic catch all for all the other menu resources
+ default:
+ // Don't toast text when a submenu is clicked
+ if (!item.hasSubMenu()) {
+ Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
+ return true;
+ }
+ break;
+ }
+
+ return false;
+ }
+
+
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/MyPreference.java b/samples/ApiDemos/src/com/example/android/apis/app/MyPreference.java
new file mode 100644
index 0000000..967c181
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/MyPreference.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * This is an example of a custom preference type. The preference counts the
+ * number of clicks it has received and stores/retrieves it from the storage.
+ */
+public class MyPreference extends Preference {
+ private int mClickCounter;
+
+ // This is the constructor called by the inflater
+ public MyPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ setWidgetLayoutResource(R.layout.preference_widget_mypreference);
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+
+ // Set our custom views inside the layout
+ final TextView myTextView = (TextView) view.findViewById(R.id.mypreference_widget);
+ if (myTextView != null) {
+ myTextView.setText(String.valueOf(mClickCounter));
+ }
+ }
+
+ @Override
+ protected void onClick() {
+ int newValue = mClickCounter + 1;
+ // Give the client a chance to ignore this change if they deem it
+ // invalid
+ if (!callChangeListener(newValue)) {
+ // They don't want the value to be set
+ return;
+ }
+
+ // Increment counter
+ mClickCounter = newValue;
+
+ // Save to persistent storage (this method will make sure this
+ // preference should be persistent, along with other useful checks)
+ persistInt(mClickCounter);
+
+ // Data has changed, notify so UI can be refreshed!
+ notifyChanged();
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ // This preference type's value type is Integer, so we read the default
+ // value from the attributes as an Integer.
+ return a.getInteger(index, 0);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ if (restoreValue) {
+ // Restore state
+ mClickCounter = getPersistedInt(mClickCounter);
+ } else {
+ // Set state
+ int value = (Integer) defaultValue;
+ mClickCounter = value;
+ persistInt(value);
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ /*
+ * Suppose a client uses this preference type without persisting. We
+ * must save the instance state so it is able to, for example, survive
+ * orientation changes.
+ */
+
+ final Parcelable superState = super.onSaveInstanceState();
+ if (isPersistent()) {
+ // No need to save instance state since it's persistent
+ return superState;
+ }
+
+ // Save the instance state
+ final SavedState myState = new SavedState(superState);
+ myState.clickCounter = mClickCounter;
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (!state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ // Restore the instance state
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ mClickCounter = myState.clickCounter;
+ notifyChanged();
+ }
+
+ /**
+ * SavedState, a subclass of {@link BaseSavedState}, will store the state
+ * of MyPreference, a subclass of Preference.
+ * <p>
+ * It is important to always call through to super methods.
+ */
+ private static class SavedState extends BaseSavedState {
+ int clickCounter;
+
+ public SavedState(Parcel source) {
+ super(source);
+
+ // Restore the click counter
+ clickCounter = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+
+ // Save the click counter
+ dest.writeInt(clickCounter);
+ }
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java b/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java
new file mode 100644
index 0000000..a6c20ea
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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.NotificationManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+
+/**
+ * Activity used by StatusBarNotification to show the notification to the user.
+ */
+public class NotificationDisplay extends Activity implements View.OnClickListener {
+ /**
+ * 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 icicle) {
+ // Be sure to call the super class.
+ super.onCreate(icicle);
+
+ // Have the system blur any windows behind this one.
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
+ WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+
+ RelativeLayout container = new RelativeLayout(this);
+
+ ImageButton button = new ImageButton(this);
+ button.setImageResource(getIntent().getIntExtra("moodimg", 0));
+ button.setOnClickListener(this);
+
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT);
+ lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+
+ container.addView(button, lp);
+
+ setContentView(container);
+ }
+
+ public void onClick(View v) {
+ // The user has confirmed this notification, so remove it.
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .cancel(R.layout.status_bar_notifications);
+
+ // Pressing on the button brings the user back to our mood ring,
+ // as part of the api demos app. Note the use of NEW_TASK here,
+ // since the notification display activity is run as a separate task.
+ Intent intent = new Intent(this, StatusBarNotifications.class);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+
+ // We're done.
+ finish();
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/NotifyWithText.java b/samples/ApiDemos/src/com/example/android/apis/app/NotifyWithText.java
new file mode 100644
index 0000000..950ded9
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/NotifyWithText.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.Button;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+/**
+ * When you push the button on this Activity, it creates a {@link Toast} object and
+ * using the Toast method.
+ * @see Toast
+ * @see Toast#makeText(android.content.Context,int,int)
+ * @see Toast#makeText(android.content.Context,java.lang.CharSequence,int)
+ * @see Toast#LENGTH_SHORT
+ * @see Toast#LENGTH_LONG
+ */
+public class NotifyWithText extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.notify_with_text);
+
+ Button button;
+
+ // short notification
+ button = (Button) findViewById(R.id.short_notify);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ // Note that we create the Toast object and call the show() method
+ // on it all on one line. Most uses look like this, but there
+ // are other methods on Toast that you can call to configure how
+ // it appears.
+ //
+ // Note also that we use the version of makeText that takes a
+ // resource id (R.string.short_notification_text). There is also
+ // a version that takes a CharSequence if you must construct
+ // the text yourself.
+ Toast.makeText(NotifyWithText.this, R.string.short_notification_text,
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ // long notification
+ // The only difference here is that the notification stays up longer.
+ // You might want to use this if there is more text that they're going
+ // to read.
+ button = (Button) findViewById(R.id.long_notify);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ Toast.makeText(NotifyWithText.this, R.string.long_notification_text,
+ Toast.LENGTH_LONG).show();
+ }
+ });
+
+
+
+
+
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/NotifyingController.java b/samples/ApiDemos/src/com/example/android/apis/app/NotifyingController.java
new file mode 100644
index 0000000..a0de699
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/NotifyingController.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 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.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+
+/**
+ * Controller to start and stop a service. The serivce will update a status bar
+ * notification every 5 seconds for a minute.
+ */
+public class NotifyingController extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.notifying_controller);
+
+ Button button = (Button) findViewById(R.id.notifyStart);
+ button.setOnClickListener(mStartListener);
+ button = (Button) findViewById(R.id.notifyStop);
+ button.setOnClickListener(mStopListener);
+ }
+
+ private OnClickListener mStartListener = new OnClickListener() {
+ public void onClick(View v) {
+ startService(new Intent(NotifyingController.this,
+ NotifyingService.class));
+ }
+ };
+
+ private OnClickListener mStopListener = new OnClickListener() {
+ public void onClick(View v) {
+ stopService(new Intent(NotifyingController.this,
+ NotifyingService.class));
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/NotifyingService.java b/samples/ApiDemos/src/com/example/android/apis/app/NotifyingService.java
new file mode 100644
index 0000000..e580978
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/NotifyingService.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007 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.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.ConditionVariable;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.widget.RemoteViews;
+
+/**
+ * This is an example of service that will update its status bar balloon
+ * every 5 seconds for a minute.
+ *
+ */
+public class NotifyingService extends Service {
+
+ // Use a layout id for a unique identifier
+ private static int MOOD_NOTIFICATIONS = R.layout.status_bar_notifications;
+
+ // variable which controls the notification thread
+ private ConditionVariable mCondition;
+
+ @Override
+ public void onCreate() {
+ mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+
+ // Start up the thread running the service. Note that we create a
+ // separate thread because the service normally runs in the process's
+ // main thread, which we don't want to block.
+ Thread notifyingThread = new Thread(null, mTask, "NotifyingService");
+ mCondition = new ConditionVariable(false);
+ notifyingThread.start();
+ }
+
+ @Override
+ public void onDestroy() {
+ // Cancel the persistent notification.
+ mNM.cancel(MOOD_NOTIFICATIONS);
+ // Stop the thread from generating further notifications
+ mCondition.open();
+ }
+
+ private Runnable mTask = new Runnable() {
+ public void run() {
+ for (int i = 0; i < 4; ++i) {
+ showNotification(R.drawable.stat_happy,
+ R.string.status_bar_notifications_happy_message);
+ if (mCondition.block(5 * 1000))
+ break;
+ showNotification(R.drawable.stat_neutral,
+ R.string.status_bar_notifications_ok_message);
+ if (mCondition.block(5 * 1000))
+ break;
+ showNotification(R.drawable.stat_sad,
+ R.string.status_bar_notifications_sad_message);
+ if (mCondition.block(5 * 1000))
+ break;
+ }
+ // Done with our work... stop the service!
+ NotifyingService.this.stopSelf();
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ private void showNotification(int moodId, int textId) {
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(textId);
+
+ // Set the icon, scrolling text and timestamp.
+ // Note that in this example, we pass null for tickerText. We update the icon enough that
+ // it is distracting to show the ticker text every time it changes. We strongly suggest
+ // that you do this as well. (Think of of the "New hardware found" or "Network connection
+ // changed" messages that always pop up)
+ Notification notification = new Notification(moodId, null, System.currentTimeMillis());
+
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, NotifyingController.class), 0);
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(this, getText(R.string.status_bar_notifications_mood_title),
+ text, contentIntent);
+
+ // Send the notification.
+ // We use a layout id because it is a unique number. We use it later to cancel.
+ mNM.notify(MOOD_NOTIFICATIONS, notification);
+ }
+
+ // This is the object that receives interactions from clients. See
+ // RemoteService for a more complete example.
+ private final IBinder mBinder = new Binder() {
+ @Override
+ protected boolean onTransact(int code, Parcel data, Parcel reply,
+ int flags) throws RemoteException {
+ return super.onTransact(code, data, reply, flags);
+ }
+ };
+
+ private NotificationManager mNM;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/OneShotAlarm.java b/samples/ApiDemos/src/com/example/android/apis/app/OneShotAlarm.java
new file mode 100644
index 0000000..ec7e074
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/OneShotAlarm.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+import android.widget.Toast;
+
+// 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;
+
+/**
+ * This is an example of implement an {@link BroadcastReceiver} for an alarm that
+ * should occur once.
+ * <p>
+ * When the alarm goes off, we show a <i>Toast</i>, a quick message.
+ */
+public class OneShotAlarm extends BroadcastReceiver
+{
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ Toast.makeText(context, R.string.one_shot_received, Toast.LENGTH_SHORT).show();
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PersistentState.java b/samples/ApiDemos/src/com/example/android/apis/app/PersistentState.java
new file mode 100644
index 0000000..618a692
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PersistentState.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2007 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.content.SharedPreferences;
+import android.os.Bundle;
+import android.widget.EditText;
+import android.widget.TextView;
+
+/**
+ * Simple example of using persistent preferences to retain a screen's state.
+ * <p>This can be used as an alternative to the normal
+ * <code>onSaveInstanceState()</code> mechanism, if you
+ * wish the state to persist even after an activity is finished.</p>
+ *
+ * <p>Note that using this approach requires more care, since you are sharing
+ * the persistent state potentially across multiple instances of the activity.
+ * In particular, if you allow a new instance of the activity to be launched
+ * directly on top of the existing instance, the state can get out of sync
+ * because the new instance is resumed before the old one is paused.</p>
+ *
+ * <p>For any persistent state that is not simplistic, a content
+ * provider is often a better choice.</p>
+ *
+ * <p>In this example we are currently saving and restoring the state of the
+ * top text editor, but not of the bottom text editor. You can see the difference
+ * by editing the two text fields, then going back from the activity and
+ * starting it again.</p>
+ *
+ * <h4>Demo</h4>
+ * App/Activity/Save & Restore State
+ *
+ * <h4>Source files</h4>
+ * <table class="LinkTable">
+ * <tr>
+ * <td class="LinkColumn">src/com.example.android.apis/app/PersistentState.java</td>
+ * <td class="DescrColumn">The Save/Restore Screen implementation</td>
+ * </tr>
+ * <tr>
+ * <td class="LinkColumn">/res/any/layout/save_restore_state.xml</td>
+ * <td class="DescrColumn">Defines contents of the screen</td>
+ * </tr>
+ * </table>
+ *
+ */
+public class PersistentState extends Activity
+{
+ /**
+ * Initialization of the Activity after it is first created. Here we use
+ * {@link android.app.Activity#setContentView setContentView()} to set up
+ * the Activity's content, and retrieve the EditText widget whose state we
+ * will persistent.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ // Be sure to call the super class.
+ super.onCreate(savedInstanceState);
+
+ // See assets/res/any/layout/save_restore_state.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.save_restore_state);
+
+ // Set message to be appropriate for this screen.
+ ((TextView)findViewById(R.id.msg)).setText(R.string.persistent_msg);
+
+ // Retrieve the EditText widget whose state we will save.
+ mSaved = (EditText)findViewById(R.id.saved);
+ }
+
+ /**
+ * Upon being resumed we can retrieve the current state. This allows us
+ * to update the state if it was changed at any time while paused.
+ */
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ SharedPreferences prefs = getPreferences(0);
+ String restoredText = prefs.getString("text", null);
+ if (restoredText != null) {
+ mSaved.setText(restoredText, TextView.BufferType.EDITABLE);
+
+ int selectionStart = prefs.getInt("selection-start", -1);
+ int selectionEnd = prefs.getInt("selection-end", -1);
+ if (selectionStart != -1 && selectionEnd != -1) {
+ mSaved.setSelection(selectionStart, selectionEnd);
+ }
+ }
+ }
+
+ /**
+ * Any time we are paused we need to save away the current state, so it
+ * will be restored correctly when we are resumed.
+ */
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ SharedPreferences.Editor editor = getPreferences(0).edit();
+ editor.putString("text", mSaved.getText().toString());
+ editor.putInt("selection-start", mSaved.getSelectionStart());
+ editor.putInt("selection-end", mSaved.getSelectionEnd());
+ editor.commit();
+ }
+
+ private EditText mSaved;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PreferenceDependencies.java b/samples/ApiDemos/src/com/example/android/apis/app/PreferenceDependencies.java
new file mode 100644
index 0000000..27c22de
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PreferenceDependencies.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+public class PreferenceDependencies extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.preference_dependencies);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PreferencesFromCode.java b/samples/ApiDemos/src/com/example/android/apis/app/PreferencesFromCode.java
new file mode 100644
index 0000000..be22b49
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PreferencesFromCode.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceScreen;
+
+import com.example.android.apis.R;
+
+public class PreferencesFromCode extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setPreferenceScreen(createPreferenceHierarchy());
+ }
+
+ private PreferenceScreen createPreferenceHierarchy() {
+ // Root
+ PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
+
+ // Inline preferences
+ PreferenceCategory inlinePrefCat = new PreferenceCategory(this);
+ inlinePrefCat.setTitle(R.string.inline_preferences);
+ root.addPreference(inlinePrefCat);
+
+ // Toggle preference
+ CheckBoxPreference togglePref = new CheckBoxPreference(this);
+ togglePref.setKey("toggle_preference");
+ togglePref.setTitle(R.string.title_toggle_preference);
+ togglePref.setSummary(R.string.summary_toggle_preference);
+ inlinePrefCat.addPreference(togglePref);
+
+ // Dialog based preferences
+ PreferenceCategory dialogBasedPrefCat = new PreferenceCategory(this);
+ dialogBasedPrefCat.setTitle(R.string.dialog_based_preferences);
+ root.addPreference(dialogBasedPrefCat);
+
+ // Edit text preference
+ EditTextPreference editTextPref = new EditTextPreference(this);
+ editTextPref.setDialogTitle(R.string.dialog_title_edittext_preference);
+ editTextPref.setKey("edittext_preference");
+ editTextPref.setTitle(R.string.title_edittext_preference);
+ editTextPref.setSummary(R.string.summary_edittext_preference);
+ dialogBasedPrefCat.addPreference(editTextPref);
+
+ // List preference
+ ListPreference listPref = new ListPreference(this);
+ listPref.setEntries(R.array.entries_list_preference);
+ listPref.setEntryValues(R.array.entryvalues_list_preference);
+ listPref.setDialogTitle(R.string.dialog_title_list_preference);
+ listPref.setKey("list_preference");
+ listPref.setTitle(R.string.title_list_preference);
+ listPref.setSummary(R.string.summary_list_preference);
+ dialogBasedPrefCat.addPreference(listPref);
+
+ // Launch preferences
+ PreferenceCategory launchPrefCat = new PreferenceCategory(this);
+ launchPrefCat.setTitle(R.string.launch_preferences);
+ root.addPreference(launchPrefCat);
+
+ /*
+ * The Preferences screenPref serves as a screen break (similar to page
+ * break in word processing). Like for other preference types, we assign
+ * a key here so that it is able to save and restore its instance state.
+ */
+ // Screen preference
+ PreferenceScreen screenPref = getPreferenceManager().createPreferenceScreen(this);
+ screenPref.setKey("screen_preference");
+ screenPref.setTitle(R.string.title_screen_preference);
+ screenPref.setSummary(R.string.summary_screen_preference);
+ launchPrefCat.addPreference(screenPref);
+
+ /*
+ * You can add more preferences to screenPref that will be shown on the
+ * next screen.
+ */
+
+ // Example of next screen toggle preference
+ CheckBoxPreference nextScreenCheckBoxPref = new CheckBoxPreference(this);
+ nextScreenCheckBoxPref.setKey("next_screen_toggle_preference");
+ nextScreenCheckBoxPref.setTitle(R.string.title_next_screen_toggle_preference);
+ nextScreenCheckBoxPref.setSummary(R.string.summary_next_screen_toggle_preference);
+ screenPref.addPreference(nextScreenCheckBoxPref);
+
+ // Intent preference
+ PreferenceScreen intentPref = getPreferenceManager().createPreferenceScreen(this);
+ intentPref.setIntent(new Intent().setAction(Intent.ACTION_VIEW)
+ .setData(Uri.parse("http://www.android.com")));
+ intentPref.setTitle(R.string.title_intent_preference);
+ intentPref.setSummary(R.string.summary_intent_preference);
+ launchPrefCat.addPreference(intentPref);
+
+ // Preference attributes
+ PreferenceCategory prefAttrsCat = new PreferenceCategory(this);
+ prefAttrsCat.setTitle(R.string.preference_attributes);
+ root.addPreference(prefAttrsCat);
+
+ // Visual parent toggle preference
+ CheckBoxPreference parentCheckBoxPref = new CheckBoxPreference(this);
+ parentCheckBoxPref.setTitle(R.string.title_parent_preference);
+ parentCheckBoxPref.setSummary(R.string.summary_parent_preference);
+ prefAttrsCat.addPreference(parentCheckBoxPref);
+
+ // Visual child toggle preference
+ // See res/values/attrs.xml for the <declare-styleable> that defines
+ // TogglePrefAttrs.
+ TypedArray a = obtainStyledAttributes(R.styleable.TogglePrefAttrs);
+ CheckBoxPreference childCheckBoxPref = new CheckBoxPreference(this);
+ childCheckBoxPref.setTitle(R.string.title_child_preference);
+ childCheckBoxPref.setSummary(R.string.summary_child_preference);
+ childCheckBoxPref.setLayoutResource(
+ a.getResourceId(R.styleable.TogglePrefAttrs_android_preferenceLayoutChild,
+ 0));
+ prefAttrsCat.addPreference(childCheckBoxPref);
+ a.recycle();
+
+ return root;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PreferencesFromXml.java b/samples/ApiDemos/src/com/example/android/apis/app/PreferencesFromXml.java
new file mode 100644
index 0000000..23461c6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PreferencesFromXml.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+
+public class PreferencesFromXml extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.preferences);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ReceiveResult.java b/samples/ApiDemos/src/com/example/android/apis/app/ReceiveResult.java
new file mode 100644
index 0000000..4e248b9
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ReceiveResult.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007 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 java.util.Map;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.text.Editable;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.util.Map;
+
+/**
+ * Shows how an activity can send data to its launching activity when done.y.
+ * <p>This can be used, for example, to implement a dialog alowing the user to
+pick an e-mail address or image -- the picking activity sends the selected
+data back to the originating activity when done.</p>
+
+<p>The example here is composed of two activities: ReceiveResult launches
+the picking activity and receives its results; SendResult allows the user
+to pick something and sends the selection back to its caller. Implementing
+this functionality involves the
+{@link android.app.Activity#setResult setResult()} method for sending a
+result and
+{@link android.app.Activity#onActivityResult onActivityResult()} to
+receive it.</p>
+
+<h4>Demo</h4>
+App/Activity/Receive Result
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn">src/com.example.android.apis/app/ReceiveResult.java</td>
+ <td class="DescrColumn">Launches pick activity and receives its result</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">src/com.example.android.apis/app/SendResult.java</td>
+ <td class="DescrColumn">Allows user to pick an option and sends it back to its caller</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">/res/any/layout/receive_result.xml</td>
+ <td class="DescrColumn">Defines contents of the ReceiveResult screen</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">/res/any/layout/send_result.xml</td>
+ <td class="DescrColumn">Defines contents of the SendResult screen</td>
+ </tr>
+</table>
+
+ */
+public class ReceiveResult extends Activity {
+ /**
+ * 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);
+
+ // See assets/res/any/layout/hello_world.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.receive_result);
+
+ // Retrieve the TextView widget that will display results.
+ mResults = (TextView)findViewById(R.id.results);
+
+ // This allows us to later extend the text buffer.
+ mResults.setText(mResults.getText(), TextView.BufferType.EDITABLE);
+
+ // Watch for button clicks.
+ Button getButton = (Button)findViewById(R.id.get);
+ getButton.setOnClickListener(mGetListener);
+ }
+
+ /**
+ * This method is called when the sending activity has finished, with the
+ * result it supplied.
+ *
+ * @param requestCode The original request code as given to
+ * startActivity().
+ * @param resultCode From sending activity as per setResult().
+ * @param data From sending activity as per setResult().
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ // You can use the requestCode to select between multiple child
+ // activities you may have started. Here there is only one thing
+ // we launch.
+ if (requestCode == GET_CODE) {
+
+ // We will be adding to our text.
+ Editable text = (Editable)mResults.getText();
+
+ // This is a standard resultCode that is sent back if the
+ // activity doesn't supply an explicit result. It will also
+ // be returned if the activity failed to launch.
+ if (resultCode == RESULT_CANCELED) {
+ text.append("(cancelled)");
+
+ // Our protocol with the sending activity is that it will send
+ // text in 'data' as its result.
+ } else {
+ text.append("(okay ");
+ text.append(Integer.toString(resultCode));
+ text.append(") ");
+ if (data != null) {
+ text.append(data.getAction());
+ }
+ }
+
+ text.append("\n");
+ }
+ }
+
+ // Definition of the one requestCode we use for receiving resuls.
+ static final private int GET_CODE = 0;
+
+ private OnClickListener mGetListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Start the activity whose result we want to retrieve. The
+ // result will come back with request code GET_CODE.
+ Intent intent = new Intent(ReceiveResult.this, SendResult.class);
+ startActivityForResult(intent, GET_CODE);
+ }
+ };
+
+ private TextView mResults;
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RedirectEnter.java b/samples/ApiDemos/src/com/example/android/apis/app/RedirectEnter.java
new file mode 100644
index 0000000..3a3e6f2
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RedirectEnter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 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.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+
+/**
+ * Entry into our redirection example, describing what will happen.
+ */
+public class RedirectEnter extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.redirect_enter);
+
+ // Watch for button clicks.
+ Button goButton = (Button)findViewById(R.id.go);
+ goButton.setOnClickListener(mGoListener);
+ }
+
+ private OnClickListener mGoListener = new OnClickListener()
+ {
+ public void onClick(View v)
+ {
+ // Here we start up the main entry point of our redirection
+ // example.
+ Intent intent = new Intent(RedirectEnter.this, RedirectMain.class);
+ startActivity(intent);
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RedirectGetter.java b/samples/ApiDemos/src/com/example/android/apis/app/RedirectGetter.java
new file mode 100644
index 0000000..982317c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RedirectGetter.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * Sub-activity that is executed by the redirection example when input is needed
+ * from the user.
+ */
+public class RedirectGetter extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.redirect_getter);
+
+ // Watch for button clicks.
+ Button applyButton = (Button)findViewById(R.id.apply);
+ applyButton.setOnClickListener(mApplyListener);
+
+ // The text being set.
+ mText = (TextView)findViewById(R.id.text);
+ }
+
+ private final boolean loadPrefs()
+ {
+ // Retrieve the current redirect values.
+ // NOTE: because this preference is shared between multiple
+ // activities, you must be careful about when you read or write
+ // it in order to keep from stepping on yourself.
+ SharedPreferences preferences = getSharedPreferences("RedirectData", 0);
+
+ mTextPref = preferences.getString("text", null);
+ if (mTextPref != null) {
+ mText.setText(mTextPref);
+ return true;
+ }
+
+ return false;
+ }
+
+ private OnClickListener mApplyListener = new OnClickListener()
+ {
+ public void onClick(View v)
+ {
+ SharedPreferences preferences = getSharedPreferences("RedirectData", 0);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString("text", mText.getText().toString());
+
+ if (editor.commit()) {
+ setResult(RESULT_OK);
+ }
+
+ finish();
+ }
+ };
+
+ private String mTextPref;
+ TextView mText;
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RedirectMain.java b/samples/ApiDemos/src/com/example/android/apis/app/RedirectMain.java
new file mode 100644
index 0000000..6d01ff0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RedirectMain.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * Entry into our redirection example, describing what will happen.
+ */
+public class RedirectMain extends Activity {
+ static final int INIT_TEXT_REQUEST = 0;
+ static final int NEW_TEXT_REQUEST = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.redirect_main);
+
+ // Watch for button clicks.
+ Button clearButton = (Button)findViewById(R.id.clear);
+ clearButton.setOnClickListener(mClearListener);
+ Button newButton = (Button)findViewById(R.id.newView);
+ newButton.setOnClickListener(mNewListener);
+
+ // Retrieve the current text preference. If there is no text
+ // preference set, we need to get it from the user by invoking the
+ // activity that retrieves it. To do this cleanly, we will
+ // temporarily hide our own activity so it is not displayed until the
+ // result is returned.
+ if (!loadPrefs()) {
+ Intent intent = new Intent(this, RedirectGetter.class);
+ startActivityForResult(intent, INIT_TEXT_REQUEST);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ if (requestCode == INIT_TEXT_REQUEST) {
+
+ // If the request was cancelled, then we are cancelled as well.
+ if (resultCode == RESULT_CANCELED) {
+ finish();
+
+ // Otherwise, there now should be text... reload the prefs,
+ // and show our UI. (Optionally we could verify that the text
+ // is now set and exit if it isn't.)
+ } else {
+ loadPrefs();
+ }
+
+ } else if (requestCode == NEW_TEXT_REQUEST) {
+
+ // In this case we are just changing the text, so if it was
+ // cancelled then we can leave things as-is.
+ if (resultCode != RESULT_CANCELED) {
+ loadPrefs();
+ }
+
+ }
+ }
+
+ private final boolean loadPrefs() {
+ // Retrieve the current redirect values.
+ // NOTE: because this preference is shared between multiple
+ // activities, you must be careful about when you read or write
+ // it in order to keep from stepping on yourself.
+ SharedPreferences preferences = getSharedPreferences("RedirectData", 0);
+
+ mTextPref = preferences.getString("text", null);
+ if (mTextPref != null) {
+ TextView text = (TextView)findViewById(R.id.text);
+ text.setText(mTextPref);
+ return true;
+ }
+
+ return false;
+ }
+
+ private OnClickListener mClearListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Erase the preferences and exit!
+ SharedPreferences preferences = getSharedPreferences("RedirectData", 0);
+ preferences.edit().remove("text").commit();
+ finish();
+ }
+ };
+
+ private OnClickListener mNewListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Retrieve new text preferences.
+ Intent intent = new Intent(RedirectMain.this, RedirectGetter.class);
+ startActivityForResult(intent, NEW_TEXT_REQUEST);
+ }
+ };
+
+ private String mTextPref;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java b/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
new file mode 100644
index 0000000..c0debbc
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteCallbackList;
+import android.widget.Toast;
+
+import java.util.HashMap;
+
+// 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;
+
+/**
+ * This is an example of implementing an application service that runs in a
+ * different process than the application. Because it can be in another
+ * process, we must use IPC to interact with it. The
+ * {@link RemoteServiceController} and {@link RemoteServiceBinding} classes
+ * show how to interact with the service.
+ */
+public class RemoteService extends Service {
+ /**
+ * This is a list of callbacks that have been registered with the
+ * service. Note that this is package scoped (instead of private) so
+ * that it can be accessed more efficiently from inner classes.
+ */
+ final RemoteCallbackList<IRemoteServiceCallback> mCallbacks
+ = new RemoteCallbackList<IRemoteServiceCallback>();
+
+ int mValue = 0;
+ NotificationManager mNM;
+
+ @Override
+ public void onCreate() {
+ mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+ // Display a notification about us starting.
+ showNotification();
+
+ // While this service is running, it will continually increment a
+ // number. Send the first message that is used to perform the
+ // increment.
+ mHandler.sendEmptyMessage(REPORT_MSG);
+ }
+
+ @Override
+ public void onDestroy() {
+ // Cancel the persistent notification.
+ mNM.cancel(R.string.remote_service_started);
+
+ // Tell the user we stopped.
+ Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
+
+ // Unregister all callbacks.
+ mCallbacks.kill();
+
+ // Remove the next pending message to increment the counter, stopping
+ // the increment loop.
+ mHandler.removeMessages(REPORT_MSG);
+ }
+
+// BEGIN_INCLUDE(exposing_a_service)
+ @Override
+ public IBinder onBind(Intent intent) {
+ // Select the interface to return. If your service only implements
+ // a single interface, you can just return it here without checking
+ // the Intent.
+ if (IRemoteService.class.getName().equals(intent.getAction())) {
+ return mBinder;
+ }
+ if (ISecondary.class.getName().equals(intent.getAction())) {
+ return mSecondaryBinder;
+ }
+ return null;
+ }
+
+ /**
+ * The IRemoteInterface is defined through IDL
+ */
+ private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+ public void registerCallback(IRemoteServiceCallback cb) {
+ if (cb != null) mCallbacks.register(cb);
+ }
+ public void unregisterCallback(IRemoteServiceCallback cb) {
+ if (cb != null) mCallbacks.unregister(cb);
+ }
+ };
+
+ /**
+ * A secondary interface to the service.
+ */
+ private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
+ public int getPid() {
+ return Process.myPid();
+ }
+ public void basicTypes(int anInt, long aLong, boolean aBoolean,
+ float aFloat, double aDouble, String aString) {
+ }
+ };
+// END_INCLUDE(exposing_a_service)
+
+ private static final int REPORT_MSG = 1;
+
+ /**
+ * Our Handler used to execute operations on the main thread. This is used
+ * to schedule increments of our value.
+ */
+ private final Handler mHandler = new Handler() {
+ @Override public void handleMessage(Message msg) {
+ switch (msg.what) {
+
+ // It is time to bump the value!
+ case REPORT_MSG: {
+ // Up it goes.
+ int value = ++mValue;
+
+ // Broadcast to all clients the new value.
+ final int N = mCallbacks.beginBroadcast();
+ for (int i=0; i<N; i++) {
+ try {
+ mCallbacks.getBroadcastItem(i).valueChanged(value);
+ } catch (RemoteException e) {
+ // The RemoteCallbackList will take care of removing
+ // the dead object for us.
+ }
+ }
+ mCallbacks.finishBroadcast();
+
+ // Repeat every 1 second.
+ sendMessageDelayed(obtainMessage(REPORT_MSG), 1*1000);
+ } break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ };
+
+ /**
+ * Show a notification while this service is running.
+ */
+ private void showNotification() {
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(R.string.remote_service_started);
+
+ // Set the icon, scrolling text and timestamp
+ Notification notification = new Notification(R.drawable.stat_sample, text,
+ System.currentTimeMillis());
+
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, LocalServiceController.class), 0);
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(this, getText(R.string.remote_service_label),
+ text, contentIntent);
+
+ // Send the notification.
+ // We use a string id because it is a unique number. We use it later to cancel.
+ mNM.notify(R.string.remote_service_started, notification);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java b/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java
new file mode 100644
index 0000000..f9ad4e5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+// BEGIN_INCLUDE(exposing_a_service)
+public class RemoteServiceBinding extends Activity {
+ /** The primary interface we will be calling on the service. */
+ IRemoteService mService = null;
+ /** Another interface we use on the service. */
+ ISecondary mSecondaryService = null;
+
+ Button mKillButton;
+ TextView mCallbackText;
+
+ private boolean mIsBound;
+
+ /**
+ * Standard initialization of this activity. Set up the UI, then wait
+ * for the user to poke it before doing anything.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.remote_service_binding);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.bind);
+ button.setOnClickListener(mBindListener);
+ button = (Button)findViewById(R.id.unbind);
+ button.setOnClickListener(mUnbindListener);
+ mKillButton = (Button)findViewById(R.id.kill);
+ mKillButton.setOnClickListener(mKillListener);
+ mKillButton.setEnabled(false);
+
+ mCallbackText = (TextView)findViewById(R.id.callback);
+ mCallbackText.setText("Not attached.");
+ }
+
+ /**
+ * Class for interacting with the main interface of the service.
+ */
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+ // This is called when the connection with the service has been
+ // established, giving us the service object we can use to
+ // interact with the service. We are communicating with our
+ // service through an IDL interface, so get a client-side
+ // representation of that from the raw service object.
+ mService = IRemoteService.Stub.asInterface(service);
+ mKillButton.setEnabled(true);
+ mCallbackText.setText("Attached.");
+
+ // We want to monitor the service for as long as we are
+ // connected to it.
+ try {
+ mService.registerCallback(mCallback);
+ } catch (RemoteException e) {
+ // In this case the service has crashed before we could even
+ // do anything with it; we can count on soon being
+ // disconnected (and then reconnected if it can be restarted)
+ // so there is no need to do anything here.
+ }
+
+ // As part of the sample, tell the user what happened.
+ Toast.makeText(RemoteServiceBinding.this, R.string.remote_service_connected,
+ Toast.LENGTH_SHORT).show();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been
+ // unexpectedly disconnected -- that is, its process crashed.
+ mService = null;
+ mKillButton.setEnabled(false);
+ mCallbackText.setText("Disconnected.");
+
+ // As part of the sample, tell the user what happened.
+ Toast.makeText(RemoteServiceBinding.this, R.string.remote_service_disconnected,
+ Toast.LENGTH_SHORT).show();
+ }
+ };
+
+ /**
+ * Class for interacting with the secondary interface of the service.
+ */
+ private ServiceConnection mSecondaryConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+ // Connecting to a secondary interface is the same as any
+ // other interface.
+ mSecondaryService = ISecondary.Stub.asInterface(service);
+ mKillButton.setEnabled(true);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ mSecondaryService = null;
+ mKillButton.setEnabled(false);
+ }
+ };
+
+ private OnClickListener mBindListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Establish a couple connections with the service, binding
+ // by interface names. This allows other applications to be
+ // installed that replace the remote service by implementing
+ // the same interface.
+ bindService(new Intent(IRemoteService.class.getName()),
+ mConnection, Context.BIND_AUTO_CREATE);
+ bindService(new Intent(ISecondary.class.getName()),
+ mSecondaryConnection, Context.BIND_AUTO_CREATE);
+ mIsBound = true;
+ mCallbackText.setText("Binding.");
+ }
+ };
+
+ private OnClickListener mUnbindListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (mIsBound) {
+ // If we have received the service, and hence registered with
+ // it, then now is the time to unregister.
+ if (mService != null) {
+ try {
+ mService.unregisterCallback(mCallback);
+ } catch (RemoteException e) {
+ // There is nothing special we need to do if the service
+ // has crashed.
+ }
+ }
+
+ // Detach our existing connection.
+ unbindService(mConnection);
+ unbindService(mSecondaryConnection);
+ mKillButton.setEnabled(false);
+ mIsBound = false;
+ mCallbackText.setText("Unbinding.");
+ }
+ }
+ };
+
+ private OnClickListener mKillListener = new OnClickListener() {
+ public void onClick(View v) {
+ // To kill the process hosting our service, we need to know its
+ // PID. Conveniently our service has a call that will return
+ // to us that information.
+ if (mSecondaryService != null) {
+ try {
+ int pid = mSecondaryService.getPid();
+ // Note that, though this API allows us to request to
+ // kill any process based on its PID, the kernel will
+ // still impose standard restrictions on which PIDs you
+ // are actually able to kill. Typically this means only
+ // the process running your application and any additional
+ // processes created by that app as shown here; packages
+ // sharing a common UID will also be able to kill each
+ // other's processes.
+ Process.killProcess(pid);
+ mCallbackText.setText("Killed service process.");
+ } catch (RemoteException ex) {
+ // Recover gracefully from the process hosting the
+ // server dying.
+ // Just for purposes of the sample, put up a notification.
+ Toast.makeText(RemoteServiceBinding.this,
+ R.string.remote_call_failed,
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ };
+
+ // ----------------------------------------------------------------------
+ // Code showing how to deal with callbacks.
+ // ----------------------------------------------------------------------
+
+ /**
+ * This implementation is used to receive callbacks from the remote
+ * service.
+ */
+ private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
+ /**
+ * This is called by the remote service regularly to tell us about
+ * new values. Note that IPC calls are dispatched through a thread
+ * pool running in each process, so the code executing here will
+ * NOT be running in our main thread like most other things -- so,
+ * to update the UI, we need to use a Handler to hop over there.
+ */
+ public void valueChanged(int value) {
+ mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));
+ }
+ };
+
+ private static final int BUMP_MSG = 1;
+
+ private Handler mHandler = new Handler() {
+ @Override public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case BUMP_MSG:
+ mCallbackText.setText("Received from service: " + msg.arg1);
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+
+ };
+}
+// END_INCLUDE(exposing_a_service)
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceController.java b/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceController.java
new file mode 100644
index 0000000..681d411
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceController.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007 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.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class RemoteServiceController extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.remote_service_controller);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.start);
+ button.setOnClickListener(mStartListener);
+ button = (Button)findViewById(R.id.stop);
+ button.setOnClickListener(mStopListener);
+ }
+
+ private OnClickListener mStartListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Make sure the service is started. It will continue running
+ // until someone calls stopService().
+ // We use an action code here, instead of explictly supplying
+ // the component name, so that other packages can replace
+ // the service.
+ startService(new Intent(
+ "com.example.android.apis.app.REMOTE_SERVICE"));
+ }
+ };
+
+ private OnClickListener mStopListener = new OnClickListener() {
+ public void onClick(View v) {
+ // Cancel a previous call to startService(). Note that the
+ // service will not actually stop at this point if there are
+ // still bound clients.
+ stopService(new Intent(
+ "com.example.android.apis.app.REMOTE_SERVICE"));
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ReorderFour.java b/samples/ApiDemos/src/com/example/android/apis/app/ReorderFour.java
new file mode 100644
index 0000000..cdff538
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ReorderFour.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class ReorderFour extends Activity {
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ setContentView(R.layout.reorder_four);
+
+ Button twoButton = (Button) findViewById(R.id.reorder_second_to_front);
+ twoButton.setOnClickListener(mClickListener);
+ }
+
+ private final OnClickListener mClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(ReorderFour.this, ReorderTwo.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+ startActivity(intent);
+ }
+ };
+}
\ No newline at end of file
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ReorderOnLaunch.java b/samples/ApiDemos/src/com/example/android/apis/app/ReorderOnLaunch.java
new file mode 100644
index 0000000..5856184
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ReorderOnLaunch.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class ReorderOnLaunch extends Activity {
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ setContentView(R.layout.reorder_on_launch);
+
+ Button twoButton = (Button) findViewById(R.id.reorder_launch_two);
+ twoButton.setOnClickListener(mClickListener);
+ }
+
+ private final OnClickListener mClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ startActivity(new Intent(ReorderOnLaunch.this, ReorderTwo.class));
+ }
+ };
+}
\ No newline at end of file
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ReorderThree.java b/samples/ApiDemos/src/com/example/android/apis/app/ReorderThree.java
new file mode 100644
index 0000000..7f725a6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ReorderThree.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class ReorderThree extends Activity {
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ setContentView(R.layout.reorder_three);
+
+ Button twoButton = (Button) findViewById(R.id.reorder_launch_four);
+ twoButton.setOnClickListener(mClickListener);
+ }
+
+ private final OnClickListener mClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ startActivity(new Intent(ReorderThree.this, ReorderFour.class));
+ }
+ };
+}
\ No newline at end of file
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ReorderTwo.java b/samples/ApiDemos/src/com/example/android/apis/app/ReorderTwo.java
new file mode 100644
index 0000000..a1521d0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ReorderTwo.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class ReorderTwo extends Activity {
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ setContentView(R.layout.reorder_two);
+
+ Button twoButton = (Button) findViewById(R.id.reorder_launch_three);
+ twoButton.setOnClickListener(mClickListener);
+ }
+
+ private final OnClickListener mClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ startActivity(new Intent(ReorderTwo.this, ReorderThree.class));
+ }
+ };
+}
\ No newline at end of file
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RepeatingAlarm.java b/samples/ApiDemos/src/com/example/android/apis/app/RepeatingAlarm.java
new file mode 100644
index 0000000..0027983
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RepeatingAlarm.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2007 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.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+import android.widget.Toast;
+
+/**
+ * This is an example of implement an {@link BroadcastReceiver} for an alarm that
+ * should occur once.
+ */
+public class RepeatingAlarm extends BroadcastReceiver
+{
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ Toast.makeText(context, R.string.repeating_received, Toast.LENGTH_SHORT).show();
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SaveRestoreState.java b/samples/ApiDemos/src/com/example/android/apis/app/SaveRestoreState.java
new file mode 100644
index 0000000..bddedf3
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SaveRestoreState.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007 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.os.Bundle;
+import android.widget.EditText;
+import android.widget.TextView;
+
+/**
+ * <p>Demonstrates required behavior of saving and restoring dynamic activity
+ * state, so that an activity will restart with the correct state if it is
+ * stopped by the system.</p>
+ *
+ * <p>In general, any activity that has been paused may be stopped by the system
+ * at any time if it needs more resources for the currently running activity.
+ * To handle this, before being paused the
+ * {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} method is called before
+ * an activity is paused, allowing it to supply its current state. If that
+ * activity then needs to be stopped, upon restarting it will receive its
+ * last saved state in
+ * {@link android.app.Activity#onCreate}.</p>
+ * <p>In this example we are currently saving and restoring the state of the
+ * top text editor, but not of the bottom text editor. You can see the difference
+ * by editing the two text fields, then going to a couple different
+ * applications while the demo is running and then returning back to it. The
+ * system takes care of saving a view's state as long as an id has been
+ * assigned to the view, so we assign an ID to the view being saved but not
+ * one to the view that isn't being saved.</p>
+ * <h4>Demo</h4>
+ * App/Activity/Save & Restore State
+ * <h4>Source files</h4>
+ * <table class="LinkTable">
+ <tr>
+ <td class="LinkColumn">src/com.example.android.apis/app/SaveRestoreState.java</td>
+ <td class="DescrColumn">The Save/Restore Screen implementation</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn">/res/any/layout/save_restore_state.xml</td>
+ <td class="DescrColumn">Defines contents of the screen</td>
+ </tr>
+</table>
+ */
+public class SaveRestoreState extends Activity
+{
+ /**
+ * Initialization of the Activity after it is first created. Here we use
+ * {@link android.app.Activity#setContentView setContentView()} to set up
+ * the Activity's content, and retrieve the EditText widget whose state we
+ * will save/restore.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ // Be sure to call the super class.
+ super.onCreate(savedInstanceState);
+
+ // See assets/res/any/layout/save_restore_state.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.save_restore_state);
+
+ // Set message to be appropriate for this screen.
+ ((TextView)findViewById(R.id.msg)).setText(R.string.save_restore_msg);
+ }
+
+ /**
+ * Retrieve the text that is currently in the "saved" editor.
+ */
+ CharSequence getSavedText() {
+ return ((EditText)findViewById(R.id.saved)).getText();
+ }
+
+ /**
+ * Change the text that is currently in the "saved" editor.
+ */
+ void setSavedText(CharSequence text) {
+ ((EditText)findViewById(R.id.saved)).setText(text);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java b/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
new file mode 100644
index 0000000..a8d350c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2008 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.SearchManager;
+import android.os.Bundle;
+import android.provider.SearchRecentSuggestions;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+public class SearchInvoke extends Activity
+{
+ // UI elements
+ Button mStartSearch;
+ Spinner mMenuMode;
+ EditText mQueryPrefill;
+ EditText mQueryAppData;
+
+ // Menu mode spinner choices
+ // This list must match the list found in samples/ApiDemos/res/values/arrays.xml
+ final static int MENUMODE_SEARCH_KEY = 0;
+ final static int MENUMODE_MENU_ITEM = 1;
+ final static int MENUMODE_TYPE_TO_SEARCH = 2;
+ final static int MENUMODE_DISABLED = 3;
+
+ /**
+ * Called with the activity is first created.
+ *
+ * We aren't doing anything special in this implementation, other than
+ * the usual activity setup code.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Inflate our UI from its XML layout description.
+ setContentView(R.layout.search_invoke);
+
+ // Get display items for later interaction
+ mStartSearch = (Button) findViewById(R.id.btn_start_search);
+ mMenuMode = (Spinner) findViewById(R.id.spinner_menu_mode);
+ mQueryPrefill = (EditText) findViewById(R.id.txt_query_prefill);
+ mQueryAppData = (EditText) findViewById(R.id.txt_query_appdata);
+
+ // Populate items
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
+ this, R.array.search_menuModes, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mMenuMode.setAdapter(adapter);
+
+ // Create listener for the menu mode dropdown. We use this to demonstrate control
+ // of the default keys handler in every Activity. More typically, you will simply set
+ // the default key mode in your activity's onCreate() handler.
+ mMenuMode.setOnItemSelectedListener(
+ new OnItemSelectedListener() {
+ public void onItemSelected(
+ AdapterView<?> parent, View view, int position, long id) {
+ if (position == MENUMODE_TYPE_TO_SEARCH) {
+ setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+ } else {
+ setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
+ }
+ }
+
+ public void onNothingSelected(AdapterView<?> parent) {
+ setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
+ }
+ });
+
+ // Attach actions to buttons
+ mStartSearch.setOnClickListener(
+ new OnClickListener() {
+ public void onClick(View v) {
+ onSearchRequested();
+ }
+ });
+ }
+
+ /**
+ * Called when your activity's options menu needs to be updated.
+ */
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ MenuItem item;
+
+ // first, get rid of our menus (if any)
+ menu.removeItem(0);
+ menu.removeItem(1);
+
+ // next, add back item(s) based on current menu mode
+ switch (mMenuMode.getSelectedItemPosition())
+ {
+ case MENUMODE_SEARCH_KEY:
+ item = menu.add( 0, 0, 0, "(Search Key)");
+ break;
+
+ case MENUMODE_MENU_ITEM:
+ item = menu.add( 0, 0, 0, "Search");
+ item.setAlphabeticShortcut(SearchManager.MENU_KEY);
+ break;
+
+ case MENUMODE_TYPE_TO_SEARCH:
+ item = menu.add( 0, 0, 0, "(Type-To-Search)");
+ break;
+
+ case MENUMODE_DISABLED:
+ item = menu.add( 0, 0, 0, "(Disabled)");
+ break;
+ }
+
+ item = menu.add(0, 1, 0, "Clear History");
+ return true;
+ }
+
+ /** Handle the menu item selections */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case 0:
+ switch (mMenuMode.getSelectedItemPosition()) {
+ case MENUMODE_SEARCH_KEY:
+ new AlertDialog.Builder(this)
+ .setMessage("To invoke search, dismiss this dialog and press the search key" +
+ " (F5 on the simulator).")
+ .setPositiveButton("OK", null)
+ .show();
+ break;
+
+ case MENUMODE_MENU_ITEM:
+ onSearchRequested();
+ break;
+
+ case MENUMODE_TYPE_TO_SEARCH:
+ new AlertDialog.Builder(this)
+ .setMessage("To invoke search, dismiss this dialog and start typing.")
+ .setPositiveButton("OK", null)
+ .show();
+ break;
+
+ case MENUMODE_DISABLED:
+ new AlertDialog.Builder(this)
+ .setMessage("You have disabled search.")
+ .setPositiveButton("OK", null)
+ .show();
+ break;
+ }
+ break;
+ case 1:
+ clearSearchHistory();
+ break;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * This hook is called when the user signals the desire to start a search.
+ *
+ * By overriding this hook we can insert local or context-specific data.
+ *
+ * @return Returns true if search launched, false if activity blocks it
+ */
+ @Override
+ public boolean onSearchRequested() {
+ // If your application absolutely must disable search, do it here.
+ if (mMenuMode.getSelectedItemPosition() == MENUMODE_DISABLED) {
+ return false;
+ }
+
+ // It's possible to prefill the query string before launching the search
+ // UI. For this demo, we simply copy it from the user input field.
+ // For most applications, you can simply pass null to startSearch() to
+ // open the UI with an empty query string.
+ final String queryPrefill = mQueryPrefill.getText().toString();
+
+ // Next, set up a bundle to send context-specific search data (if any)
+ // The bundle can contain any number of elements, using any number of keys;
+ // For this Api Demo we copy a string from the user input field, and store
+ // it in the bundle as a string with the key "demo_key".
+ // For most applications, you can simply pass null to startSearch().
+ Bundle appDataBundle = null;
+ final String queryAppDataString = mQueryAppData.getText().toString();
+ if (queryAppDataString != null) {
+ appDataBundle = new Bundle();
+ appDataBundle.putString("demo_key", queryAppDataString);
+ }
+
+ // Now call the Activity member function that invokes the Search Manager UI.
+ startSearch(queryPrefill, false, appDataBundle, false);
+
+ // Returning true indicates that we did launch the search, instead of blocking it.
+ return true;
+ }
+
+ /**
+ * Any application that implements search suggestions based on previous actions (such as
+ * recent queries, page/items viewed, etc.) should provide a way for the user to clear the
+ * history. This gives the user a measure of privacy, if they do not wish for their recent
+ * searches to be replayed by other users of the device (via suggestions).
+ *
+ * This example shows how to clear the search history for apps that use
+ * android.provider.SearchRecentSuggestions. If you have developed a custom suggestions
+ * provider, you'll need to provide a similar API for clearing history.
+ *
+ * In this sample app we call this method from a "Clear History" menu item. You could also
+ * implement the UI in your preferences, or any other logical place in your UI.
+ */
+ private void clearSearchHistory() {
+ SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
+ SearchSuggestionSampleProvider.AUTHORITY, SearchSuggestionSampleProvider.MODE);
+ suggestions.clearHistory();
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SearchQueryResults.java b/samples/ApiDemos/src/com/example/android/apis/app/SearchQueryResults.java
new file mode 100644
index 0000000..668ad57
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SearchQueryResults.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2008 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.SearchRecentSuggestions;
+import android.widget.TextView;
+
+public class SearchQueryResults extends Activity
+{
+ // UI elements
+ TextView mQueryText;
+ TextView mAppDataText;
+ TextView mDeliveredByText;
+
+ /** Called with the activity is first created.
+ *
+ * After the typical activity setup code, we check to see if we were launched
+ * with the ACTION_SEARCH intent, and if so, we handle it.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Inflate our UI from its XML layout description.
+ setContentView(R.layout.search_query_results);
+
+ // Get active display items for later updates
+ mQueryText = (TextView) findViewById(R.id.txt_query);
+ mAppDataText = (TextView) findViewById(R.id.txt_appdata);
+ mDeliveredByText = (TextView) findViewById(R.id.txt_deliveredby);
+
+ // get and process search query here
+ final Intent queryIntent = getIntent();
+ final String queryAction = queryIntent.getAction();
+ if (Intent.ACTION_SEARCH.equals(queryAction)) {
+ doSearchQuery(queryIntent, "onCreate()");
+ }
+ else {
+ mDeliveredByText.setText("onCreate(), but no ACTION_SEARCH intent");
+ }
+ }
+
+ /**
+ * Called when new intent is delivered.
+ *
+ * This is where we check the incoming intent for a query string.
+ *
+ * @param newIntent The intent used to restart this activity
+ */
+ @Override
+ public void onNewIntent(final Intent newIntent) {
+ super.onNewIntent(newIntent);
+
+ // get and process search query here
+ final Intent queryIntent = getIntent();
+ final String queryAction = queryIntent.getAction();
+ if (Intent.ACTION_SEARCH.equals(queryAction)) {
+ doSearchQuery(queryIntent, "onNewIntent()");
+ }
+ else {
+ mDeliveredByText.setText("onNewIntent(), but no ACTION_SEARCH intent");
+ }
+ }
+
+ /**
+ * Generic search handler.
+ *
+ * In a "real" application, you would use the query string to select results from
+ * your data source, and present a list of those results to the user.
+ */
+ private void doSearchQuery(final Intent queryIntent, final String entryPoint) {
+
+ // The search query is provided as an "extra" string in the query intent
+ final String queryString = queryIntent.getStringExtra(SearchManager.QUERY);
+ mQueryText.setText(queryString);
+
+ // Record the query string in the recent queries suggestions provider.
+ SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
+ SearchSuggestionSampleProvider.AUTHORITY, SearchSuggestionSampleProvider.MODE);
+ suggestions.saveRecentQuery(queryString, null);
+
+ // If your application provides context data for its searches,
+ // you will receive it as an "extra" bundle in the query intent.
+ // The bundle can contain any number of elements, using any number of keys;
+ // For this Api Demo we're just using a single string, stored using "demo key".
+ final Bundle appData = queryIntent.getBundleExtra(SearchManager.APP_DATA);
+ if (appData == null) {
+ mAppDataText.setText("<no app data bundle>");
+ }
+ if (appData != null) {
+ String testStr = appData.getString("demo_key");
+ mAppDataText.setText((testStr == null) ? "<no app data>" : testStr);
+ }
+
+ // Report the method by which we were called.
+ mDeliveredByText.setText(entryPoint);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SearchSuggestionSampleProvider.java b/samples/ApiDemos/src/com/example/android/apis/app/SearchSuggestionSampleProvider.java
new file mode 100644
index 0000000..4baccd0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SearchSuggestionSampleProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 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;
+
+import android.content.SearchRecentSuggestionsProvider;
+
+/**
+ * To create a search suggestions provider using the built-in recent queries mode,
+ * simply extend SearchRecentSuggestionsProvider as shown here, and configure with
+ * a unique authority and the mode you with to use. For more information, see
+ * {@link android.content.SearchRecentSuggestionsProvider}.
+ */
+public class SearchSuggestionSampleProvider extends SearchRecentSuggestionsProvider {
+
+ /**
+ * This is the provider authority identifier. The same string must appear in your
+ * Manifest file, and any time you instantiate a
+ * {@link android.provider.SearchRecentSuggestions} helper class.
+ */
+ final static String AUTHORITY = "com.example.android.apis.SuggestionProvider";
+ /**
+ * These flags determine the operating mode of the suggestions provider. This value should
+ * not change from run to run, because when it does change, your suggestions database may
+ * be wiped.
+ */
+ final static int MODE = DATABASE_MODE_QUERIES;
+
+ /**
+ * The main job of the constructor is to call {@link #setupSuggestions(String, int)} with the
+ * appropriate configuration values.
+ */
+ public SearchSuggestionSampleProvider() {
+ super();
+ setupSuggestions(AUTHORITY, MODE);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SendResult.java b/samples/ApiDemos/src/com/example/android/apis/app/SendResult.java
new file mode 100644
index 0000000..1171eea
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SendResult.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 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.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+
+/**
+ * Example of receiving a result from another activity.
+ */
+public class SendResult extends Activity
+{
+ /**
+ * 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);
+
+ // See assets/res/any/layout/hello_world.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.send_result);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.corky);
+ button.setOnClickListener(mCorkyListener);
+ button = (Button)findViewById(R.id.violet);
+ button.setOnClickListener(mVioletListener);
+ }
+
+ private OnClickListener mCorkyListener = new OnClickListener()
+ {
+ public void onClick(View v)
+ {
+ // To send a result, simply call setResult() before your
+ // activity is finished.
+ setResult(RESULT_OK, (new Intent()).setAction("Corky!"));
+ finish();
+ }
+ };
+
+ private OnClickListener mVioletListener = new OnClickListener()
+ {
+ public void onClick(View v)
+ {
+ // To send a result, simply call setResult() before your
+ // activity is finished.
+ setResult(RESULT_OK, (new Intent()).setAction("Violet!"));
+ finish();
+ }
+ };
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java b/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java
new file mode 100644
index 0000000..5e16158
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007 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;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.example.android.apis.R;
+
+/**
+ * This is an example of implementing an application service that runs locally
+ * in the same process as the application. The {@link ServiceStartArgumentsController}
+ * class shows how to interact with the service.
+ *
+ * <p>Notice the use of the {@link NotificationManager} when interesting things
+ * happen in the service. This is generally how background services should
+ * interact with the user, rather than doing something more disruptive such as
+ * calling startActivity().
+ */
+public class ServiceStartArguments extends Service
+{
+ private NotificationManager mNM;
+ private Intent mInvokeIntent;
+ private volatile Looper mServiceLooper;
+ private volatile ServiceHandler mServiceHandler;
+
+ private final class ServiceHandler extends Handler {
+ public ServiceHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg)
+ {
+ Bundle arguments = (Bundle)msg.obj;
+ String txt = getResources()
+ .getString(R.string.service_arguments_started);
+ txt = txt + arguments.getString("name");
+
+ Log.i("ServiceStartArguments", "Message: " + msg + ", " + txt);
+
+ showNotification();
+
+ // Normally we would do some work here... for our sample, we will
+ // just sleep for 10 seconds.
+ long endTime = System.currentTimeMillis() + 5*1000;
+ while (System.currentTimeMillis() < endTime) {
+ synchronized (this) {
+ try {
+ wait(endTime - System.currentTimeMillis());
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ Log.i("ServiceStartArguments", "Done with #" + msg.arg1);
+ stopSelf(msg.arg1);
+ }
+
+ };
+
+ @Override
+ public void onCreate() {
+ mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+ // This is who should be launched if the user selects our persistent
+ // notification.
+ mInvokeIntent = new Intent(this, ServiceStartArgumentsController.class);
+
+ // Start up the thread running the service. Note that we create a
+ // separate thread because the service normally runs in the process's
+ // main thread, which we don't want to block.
+ HandlerThread thread = new HandlerThread("ServiceStartArguments");
+ thread.start();
+
+ mServiceLooper = thread.getLooper();
+ mServiceHandler = new ServiceHandler(mServiceLooper);
+ }
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ Log.i("ServiceStartArguments",
+ "Starting #" + startId + ": " + intent.getExtras());
+ Message msg = mServiceHandler.obtainMessage();
+ msg.arg1 = startId;
+ msg.obj = intent.getExtras();
+ mServiceHandler.sendMessage(msg);
+ Log.i("ServiceStartArguments", "Sending: " + msg);
+ }
+
+ @Override
+ public void onDestroy() {
+ mServiceLooper.quit();
+
+ // Cancel the persistent notification.
+ mNM.cancel(R.string.service_arguments_started);
+
+ // Tell the user we stopped.
+ Toast.makeText(ServiceStartArguments.this, R.string.service_arguments_stopped,
+ Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ /**
+ * Show a notification while this service is running.
+ */
+ private void showNotification() {
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(R.string.service_arguments_started);
+
+ // Set the icon, scrolling text and timestamp
+ Notification notification = new Notification(R.drawable.stat_sample, text,
+ System.currentTimeMillis());
+
+ // The PendingIntent to launch our activity if the user selects this notification
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, AlarmService.class), 0);
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(this, getText(R.string.service_start_arguments_label),
+ text, contentIntent);
+
+ // Send the notification.
+ // We use a string id because it is a unique number. We use it later to cancel.
+ mNM.notify(R.string.service_arguments_started, notification);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArgumentsController.java b/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArgumentsController.java
new file mode 100644
index 0000000..2c53ff4
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArgumentsController.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 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 android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.example.android.apis.R;
+
+import java.util.HashMap;
+
+/**
+ * Example of explicitly starting the {@link ServiceStartArguments}.
+ */
+public class ServiceStartArgumentsController extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.service_start_arguments_controller);
+
+ // Watch for button clicks.
+ Button button = (Button)findViewById(R.id.start1);
+ button.setOnClickListener(mStart1Listener);
+ button = (Button)findViewById(R.id.start2);
+ button.setOnClickListener(mStart2Listener);
+ button = (Button)findViewById(R.id.start3);
+ button.setOnClickListener(mStart3Listener);
+ }
+
+ private OnClickListener mStart1Listener = new OnClickListener() {
+ public void onClick(View v) {
+ startService(new Intent(ServiceStartArgumentsController.this,
+ ServiceStartArguments.class).putExtra("name", "One"));
+ }
+ };
+
+ private OnClickListener mStart2Listener = new OnClickListener() {
+ public void onClick(View v) {
+ startService(new Intent(ServiceStartArgumentsController.this,
+ ServiceStartArguments.class).putExtra("name", "Two"));
+ }
+ };
+
+ private OnClickListener mStart3Listener = new OnClickListener() {
+ public void onClick(View v) {
+ startService(new Intent(ServiceStartArgumentsController.this,
+ ServiceStartArguments.class).putExtra("name", "Three"));
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java b/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
new file mode 100644
index 0000000..97f6199
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2007 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;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.RemoteViews;
+
+/**
+ * Demonstrates adding notifications to the status bar
+ */
+public class StatusBarNotifications extends Activity {
+
+ private NotificationManager mNotificationManager;
+
+ // Use our layout id for a unique identifier
+ private static int MOOD_NOTIFICATIONS = R.layout.status_bar_notifications;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.status_bar_notifications);
+
+ Button button;
+
+ // Get the notification manager serivce.
+ mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+
+ button = (Button) findViewById(R.id.happy);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMood(R.drawable.stat_happy, R.string.status_bar_notifications_happy_message,
+ false);
+ }
+ });
+
+ button = (Button) findViewById(R.id.neutral);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMood(R.drawable.stat_neutral, R.string.status_bar_notifications_ok_message,
+ false);
+ }
+ });
+
+ button = (Button) findViewById(R.id.sad);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMood(R.drawable.stat_sad, R.string.status_bar_notifications_sad_message, false);
+ }
+ });
+
+ button = (Button) findViewById(R.id.happyMarquee);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMood(R.drawable.stat_happy, R.string.status_bar_notifications_happy_message,
+ true);
+ }
+ });
+
+ button = (Button) findViewById(R.id.neutralMarquee);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMood(R.drawable.stat_neutral, R.string.status_bar_notifications_ok_message, true);
+ }
+ });
+
+ button = (Button) findViewById(R.id.sadMarquee);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMood(R.drawable.stat_sad, R.string.status_bar_notifications_sad_message, true);
+ }
+ });
+
+ button = (Button) findViewById(R.id.happyViews);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMoodView(R.drawable.stat_happy, R.string.status_bar_notifications_happy_message);
+ }
+ });
+
+ button = (Button) findViewById(R.id.neutralViews);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMoodView(R.drawable.stat_neutral, R.string.status_bar_notifications_ok_message);
+ }
+ });
+
+ button = (Button) findViewById(R.id.sadViews);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setMoodView(R.drawable.stat_sad, R.string.status_bar_notifications_sad_message);
+ }
+ });
+
+ button = (Button) findViewById(R.id.defaultSound);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setDefault(Notification.DEFAULT_SOUND);
+ }
+ });
+
+ button = (Button) findViewById(R.id.defaultVibrate);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setDefault(Notification.DEFAULT_VIBRATE);
+ }
+ });
+
+ button = (Button) findViewById(R.id.defaultAll);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ setDefault(Notification.DEFAULT_ALL);
+ }
+ });
+
+ button = (Button) findViewById(R.id.clear);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ mNotificationManager.cancel(R.layout.status_bar_notifications);
+ }
+ });
+ }
+
+ private PendingIntent makeMoodIntent(int moodId) {
+ // The PendingIntent to launch our activity if the user selects this
+ // notification. Note the use of FLAG_UPDATE_CURRENT so that if there
+ // is already an active matching pending intent, we will update its
+ // extras to be the ones passed in here.
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, NotificationDisplay.class)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .putExtra("moodimg", moodId),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ return contentIntent;
+ }
+
+ private void setMood(int moodId, int textId, boolean showTicker) {
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(textId);
+
+ // choose the ticker text
+ String tickerText = showTicker ? getString(textId) : null;
+
+ // Set the icon, scrolling text and timestamp
+ Notification notification = new Notification(moodId, tickerText,
+ System.currentTimeMillis());
+
+ // Set the info for the views that show in the notification panel.
+ notification.setLatestEventInfo(this, getText(R.string.status_bar_notifications_mood_title),
+ text, makeMoodIntent(moodId));
+
+ // Send the notification.
+ // We use a layout id because it is a unique number. We use it later to cancel.
+ mNotificationManager.notify(R.layout.status_bar_notifications, notification);
+ }
+
+ private void setMoodView(int moodId, int textId) {
+ // Instead of the normal constructor, we're going to use the one with no args and fill
+ // in all of the data ourselves. The normal one uses the default layout for notifications.
+ // You probably want that in most cases, but if you want to do something custom, you
+ // can set the contentView field to your own RemoteViews object.
+ Notification notif = new Notification();
+
+ // This is who should be launched if the user selects our notification.
+ notif.contentIntent = makeMoodIntent(moodId);
+
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(textId);
+ notif.tickerText = text;
+
+ // the icon for the status bar
+ notif.icon = moodId;
+
+ // our custom view
+ RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.status_bar_balloon);
+ contentView.setTextViewText(R.id.text, text);
+ contentView.setImageViewResource(R.id.icon, moodId);
+ notif.contentView = contentView;
+
+ // we use a string id because is a unique number. we use it later to cancel the
+ // notification
+ mNotificationManager.notify(R.layout.status_bar_notifications, notif);
+ }
+
+ private void setDefault(int defaults) {
+
+ // This method sets the defaults on the notification before posting it.
+
+ // This is who should be launched if the user selects our notification.
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, StatusBarNotifications.class), 0);
+
+ // In this sample, we'll use the same text for the ticker and the expanded notification
+ CharSequence text = getText(R.string.status_bar_notifications_happy_message);
+
+ final Notification notification = new Notification(
+ R.drawable.stat_happy, // the icon for the status bar
+ text, // the text to display in the ticker
+ System.currentTimeMillis()); // the timestamp for the notification
+
+ notification.setLatestEventInfo(
+ this, // the context to use
+ getText(R.string.status_bar_notifications_mood_title),
+ // the title for the notification
+ text, // the details to display in the notification
+ contentIntent); // the contentIntent (see above)
+
+ notification.defaults = defaults;
+
+ mNotificationManager.notify(
+ R.layout.status_bar_notifications, // we use a string id because it is a unique
+ // number. we use it later to cancel the
+ notification); // notification
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/TranslucentActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/TranslucentActivity.java
new file mode 100644
index 0000000..522fe13
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/TranslucentActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 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.os.Bundle;
+
+/**
+ * <h3>Translucent Activity</h3>
+ *
+ * <p>This demonstrates the how to write an activity that is translucent,
+ * allowing windows underneath to show through.</p>
+ */
+public class TranslucentActivity extends Activity {
+ /**
+ * 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);
+
+ // See assets/res/any/layout/translucent_background.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.translucent_background);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/TranslucentBlurActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/TranslucentBlurActivity.java
new file mode 100644
index 0000000..dd88227
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/TranslucentBlurActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 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.os.Bundle;
+import android.view.WindowManager;
+
+
+/**
+ * <h3>Fancy Blur Activity</h3>
+ *
+ * <p>This demonstrates the how to write an activity that is translucent,
+ * allowing windows underneath to show through, with a fancy blur
+ * compositing effect.</p>
+ */
+public class TranslucentBlurActivity extends Activity {
+ /**
+ * 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 icicle) {
+ // Be sure to call the super class.
+ super.onCreate(icicle);
+
+ // Have the system blur any windows behind this one.
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
+ WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+
+ // See assets/res/any/layout/translucent_background.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.translucent_background);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/VoiceRecognition.java b/samples/ApiDemos/src/com/example/android/apis/app/VoiceRecognition.java
new file mode 100644
index 0000000..a784e15
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/VoiceRecognition.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008 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;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+
+import com.example.android.apis.R;
+
+import java.util.ArrayList;
+
+/**
+ * Sample code that invokes the speech recognition intent API.
+ */
+public class VoiceRecognition extends Activity implements OnClickListener {
+
+ private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
+
+ private ListView mList;
+
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Inflate our UI from its XML layout description.
+ setContentView(R.layout.voice_recognition);
+
+ // Get display items for later interaction
+ Button speakButton = (Button) findViewById(R.id.btn_speak);
+
+ mList = (ListView) findViewById(R.id.list);
+
+ // Attach actions to buttons
+ speakButton.setOnClickListener(this);
+ }
+
+ /**
+ * Handle the click on the start recognition button.
+ */
+ public void onClick(View v) {
+ if (v.getId() == R.id.btn_speak) {
+ startVoiceRecognitionActivity();
+ }
+ }
+
+ /**
+ * Fire an intent to start the speech recognition activity.
+ */
+ private void startVoiceRecognitionActivity() {
+ //TODO Get these values from constants
+ Intent intent = new Intent("android.speech.action.RECOGNIZE_SPEECH");
+ intent.putExtra("language_model", "free_form");
+ intent.putExtra("prompt", "Speech recognition demo");
+ startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
+ }
+
+ /**
+ * Handle the results from the recognition activity.
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) {
+ //TODO get the value from a constant
+ ArrayList<String>matches = data.getStringArrayListExtra("results");
+ mList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
+ matches));
+ }
+
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/_index.html b/samples/ApiDemos/src/com/example/android/apis/app/_index.html
new file mode 100644
index 0000000..8a768bb
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/_index.html
@@ -0,0 +1,145 @@
+
+<h3>Activity</h3>
+<dl>
+ <dt><a href="HelloWorld.html">Hello World</a></dt>
+ <dd>Demonstrates a basic screen activity.
+ <dl>
+ <dt>Code:
+ <dd> <a href="HelloWorld.html">HelloWorld.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/hello_world.html">
+ hello_world.xml</a>
+ </dl>
+ </dd>
+ <dt><a href="SaveRestoreState.html">Save & Restore State</a></dt>
+ <dd>Demonstrates how an activity should save state when it is paused.</dd>
+
+ <dt><a href="PersistentState.html">Persistent State</a></dt>
+ <dd>Demonstrates how you can save and restore preferences, which are stored
+ even after the user closes the application. </dd>
+
+ <dt><a href="ReceiveResult.html">Receive Result</a></dt>
+ <dd>Demonstrates how an activity screen can return a result to the
+ activity that opened it. </dd>
+
+ <dt><a href="Forwarding.html">Forwarding</a></dt>
+ <dd>Demonstrates opening a new activity and removing the current activity
+ from the history stack, so that when the user later presses BACK they will
+ not see the intermediate activity.</dd>
+
+ <dt><a href="RedirectEnter.html">Redirection</a></dt>
+ <dd>Demonstrates how to save data to preferences and use it to determine
+ which activity to open next.</dd>
+
+ <dt><a href="TranslucentActivity.html">Translucent</a></dt>
+ <dd>Demonstrates how to make an activity with a transparent background. </dd>
+
+ <dt><a href="TranslucentFancyActivity.html">TranslucentFancy</a></dt>
+ <dd>Demonstrates how to make an activity with a transparent background with
+ a special effect (blur). </dd>
+</dl>
+
+<h3>Service</h3>
+<dl>
+ <dt><a href="LocalServiceController.html">Local Service Controller</a></dt>
+ <dd>Starts and stops the service class
+ <a href="LocalService.html">LocalService</a> that runs in the same
+ process as the activity, to demonstrate a service's
+ lifecycle when using {@link android.content.Context#startService
+ Context.startService} and {@link android.content.Context#stopService
+ Context.stopService}.</dd>
+
+ <dt><a href="LocalServiceBinding.html">Local Service Binding</a></dt>
+ <dd>Demonstrates binding to a service class
+ <a href="LocalService.html">LocalService</a> that runs in the same
+ process as the activity, to demonstrate using the
+ {@link android.content.Context#bindService Context.bindService} and
+ {@link android.content.Context#unbindService Context.unindService}
+ methods with a service. This also shows how you can simplify working
+ with a service when you know it will only run in your own process.</dd>
+
+ <dt><a href="RemoteServiceController.html">Remote Service Controller</a></dt>
+ <dd>Demonstrates starting a service in a separate process, by assigning
+ <code>android:process=":remote"</code> to the service in the
+ AndroidManifest.xml file. </dd>
+
+ <dt><a href="RemoteServiceBinding.html">Remote Service Binding</a></dt>
+ <dd>Demonstrates binding to a remote service, similar to the Local Service
+ Binding sample, but illustrating the additional work (defining aidl
+ interfaces) needed to interact with a service in another process. Also
+ shows how a service can publish multiple interfaces and implement
+ callbacks to its clients.</dd>
+
+ <dt><a href="ServiceStartArgumentsController.html">Service Start Arguments Controller</a></dt>
+ <dd>Demonstrates how you can use a Service as a job queue, where you
+ submit jobs to it with {@link android.content.Context#startService
+ Context.startService} instead of binding to the service. Such a service
+ automatically stops itself once all jobs have been processed. This can be
+ a very convenient way to interact with a service when you do not need
+ a result back from it.
+ <dl>
+ <dt>Code:
+ <dd> <a href="ServiceStartArgumentsController.html">ServiceStartArgumentsController.java</a>
+ <dd> <a href="ServiceStartArguments.html">ServiceStartArguments.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/service_start_arguments_controller.html">
+ service_start_arguments_controller.xml</a>
+ </dl>
+ </dd>
+</dl>
+
+<h3>Alarm</h3>
+<dl>
+ <dt><a href="AlarmController.html">Alarm Controller</a></dt>
+ <dd>Demonstrates two ways you can schedule alarms: a one-shot alarm that
+ will happen once at a given time, and a repeating alarm that will happen
+ first at a given time and then continually trigger at regular intervals
+ after that.
+ <dl>
+ <dt>Code:
+ <dd> <a href="AlarmController.html">AlarmController.java</a>
+ <dd> <a href="OneShotAlarm.html">OneShotAlarm.java</a>
+ <dd> <a href="RepeatingAlarm.html">RepeatingAlarm.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/alarm_controller.html">
+ alarm_controller.xml</a>
+ </dl>
+ </dd>
+
+ <dt><a href="AlarmService.html">Alarm Service</a></dt>
+ <dd>Demonstrates how you can schedule an alarm that causes a service to
+ be started. This is useful when you want to schedule alarms that initiate
+ long-running operations, such as retrieving recent e-mails.
+ <dl>
+ <dt>Code:
+ <dd> <a href="AlarmService.html">AlarmService.java</a>
+ <dd> <a href="AlarmService_Service.html">AlarmService_Service.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/alarm_service.html">
+ alarm_service.xml</a>
+ </dl>
+ </dd>
+</dl>
+
+<h3>Notification</h3>
+<dl>
+ <dt><a href="NotifyWithText.html">NotifyWithText</a></dt>
+ <dd>Demonstrates popup notifications of varying length.</dd>
+
+ <dt><a href="IncomingMessage.html">IncomingMessage</a></dt>
+ <dd> Demonstrates sending persistent and transient notifications, with a View object in the notification. It also demonstrated inflating a View object from an XML layout resource. </dd>
+</dl>
+
+<h3>Search</h3>
+<dl>
+ <dt><a href="SearchInvoke.html">SearchInvoke</a></dt>
+ <dd>Demonstrates various ways in which activities can launch the Search UI.</dd>
+
+ <dt><a href="SearchQueryResults.html">SearchQueryResults</a></dt>
+ <dd>Demonstrates an activity that receives Search intents and handles them.</dd>
+
+ <dt><a href="SearchSuggestionSampleProvider.html">SearchSuggestionSampleProvider</a></dt>
+ <dd>Demonstrates how to configure and use the built-in "recent queries" suggestion provider.</dd>
+</dl>
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/_package.html b/samples/ApiDemos/src/com/example/android/apis/app/_package.html
new file mode 100644
index 0000000..7f99501
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/_package.html
@@ -0,0 +1,48 @@
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="assets/style.css" />
+<script type="text/javascript" src="http://www.corp.google.com/style/prettify.js"></script>
+<script src="http://www.corp.google.com/eng/techpubs/include/navbar.js" type="text/javascript"></script>
+
+
+
+</head>
+
+<body>
+
+<p>
+Examples of how to use the android.app APIs.
+
+<ol>
+ <li> Activities
+ - These examples show various ways you can use activities to implement an
+application's user interface.
+ <ol>
+ <li> {@link com.android.samples.app.HelloWorld Hello World}
+ <li> {@link com.android.samples.app.SaveRestoreState Save & Restore State}
+ <li>{@link com.android.samples.app.PersistentState Persistent State}
+ <li>{@link com.android.samples.app.ReceiveResult Receive Result}
+ <li>{@link com.android.samples.app.Forwarding Forwarding}
+ </ol>
+ <li> Services
+ - These examples show how you can implement application services, which
+give you a way to run code in the background outside of the normal UI flow.
+ <ol>
+ <li>{@link com.android.samples.app.LocalServiceController Local Service
+ Controller}
+ <li>{@link com.android.samples.app.LocalServiceBinding Local Service Binding}
+ <li>{@link com.android.samples.app.RemoteServiceController Remote Service
+ Controller}
+ <li>{@link com.android.samples.app.RemoteServiceBinding Remote Service
+ Binding}
+ </ol>
+ <li> Alarms
+ - These examples show how you can use alarms to schedule background
+events.
+ <ol>
+ <li>{@link com.android.samples.app.AlarmController Alarm Controller}
+ <li>{@link com.android.samples.app.AlarmService Alarm Service}
+ </ol>
+</ol>
+</body>
+</html>
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/ReadAsset.java b/samples/ApiDemos/src/com/example/android/apis/content/ReadAsset.java
new file mode 100644
index 0000000..47503c4
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/content/ReadAsset.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007 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.content;
+
+// 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.os.Bundle;
+import android.widget.TextView;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * Demonstration of styled text resources.
+ */
+public class ReadAsset extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // See assets/res/any/layout/styled_text.xml for this
+ // view layout definition.
+ setContentView(R.layout.read_asset);
+
+ // Programmatically load text from an asset and place it into the
+ // text view. Note that the text we are loading is ASCII, so we
+ // need to convert it to UTF-16.
+ try {
+ InputStream is = getAssets().open("read_asset.txt");
+
+ // We guarantee that the available method returns the total
+ // size of the asset... of course, this does mean that a single
+ // asset can't be more than 2 gigs.
+ int size = is.available();
+
+ // Read the entire asset into a local byte buffer.
+ byte[] buffer = new byte[size];
+ is.read(buffer);
+ is.close();
+
+ // Convert the buffer into a string.
+ String text = new String(buffer);
+
+ // Finally stick the string into the text view.
+ TextView tv = (TextView)findViewById(R.id.text);
+ tv.setText(text);
+ } catch (IOException e) {
+ // Should never happen!
+ throw new RuntimeException(e);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/ResourcesSample.java b/samples/ApiDemos/src/com/example/android/apis/content/ResourcesSample.java
new file mode 100755
index 0000000..f38be0f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/content/ResourcesSample.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007 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.content;
+
+// 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.content.Context;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.widget.TextView;
+
+
+/**
+ * Demonstration of loading resources.
+ *
+ * <p>
+ * Each context has a resources object that you can access. Additionally,
+ * the Context class (an Activity is a Context) has a getString convenience
+ * method getString() that looks up a string resource.
+ *
+ * @see StyledText for more depth about using styled text, both with getString()
+ * and in the layout xml files.
+ */
+public class ResourcesSample extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // See res/any/layout/resources.xml for this view layout definition.
+ setContentView(R.layout.resources);
+
+ TextView tv;
+ CharSequence cs;
+ String str;
+
+ // ====== Using the Context.getString() convenience method ===========
+
+ // Using the getString() conevenience method, retrieve a string
+ // resource that hapepns to have style information. Note the use of
+ // CharSequence instead of String so we don't lose the style info.
+ cs = getText(R.string.styled_text);
+ tv = (TextView)findViewById(R.id.styled_text);
+ tv.setText(cs);
+
+ // Use the same resource, but convert it to a string, which causes it
+ // to lose the style information.
+ str = getString(R.string.styled_text);
+ tv = (TextView)findViewById(R.id.plain_text);
+ tv.setText(str);
+
+ // ====== Using the Resources object =================================
+
+ // You might need to do this if your code is not in an activity.
+ // For example View has a protected mContext field you can use.
+ // In this case it's just 'this' since Activity is a context.
+ Context context = this;
+
+ // Get the Resources object from our context
+ Resources res = context.getResources();
+
+ // Get the string resource, like above.
+ cs = res.getText(R.string.styled_text);
+ tv = (TextView)findViewById(R.id.res1);
+ tv.setText(cs);
+
+ // Note that the Resources class has methods like getColor(),
+ // getDimen(), getDrawable() because themes are stored in resources.
+ // You can use them, but you might want to take a look at the view
+ // examples to see how to make custom widgets.
+
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/StyledText.java b/samples/ApiDemos/src/com/example/android/apis/content/StyledText.java
new file mode 100644
index 0000000..b158929
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/content/StyledText.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 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.content;
+
+// 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.os.Bundle;
+import android.widget.TextView;
+
+
+/**
+ * Demonstration of styled text resources.
+ */
+public class StyledText extends Activity
+{
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // See assets/res/any/layout/styled_text.xml for this
+ // view layout definition.
+ setContentView(R.layout.styled_text);
+
+ // Programmatically retrieve a string resource with style
+ // information and apply it to the second text view. Note the
+ // use of CharSequence instead of String so we don't lose
+ // the style info.
+ CharSequence str = getText(R.string.styled_text);
+ TextView tv = (TextView)findViewById(R.id.text);
+ tv.setText(str);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/content/_index.html b/samples/ApiDemos/src/com/example/android/apis/content/_index.html
new file mode 100644
index 0000000..1aa52b3
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/content/_index.html
@@ -0,0 +1,8 @@
+<h3>Resources</h3>
+<dl>
+ <dt><a href="StyledText.html">Styled Text</a></dt>
+ <dd>Demonstrates loading styled text (bold, italic) defined in a resource file. </dd>
+
+ <dt><a href="ResourcesSample.html">Resources</a></dt>
+ <dd>Demonstrates loading styled strings from a resource file, and extracting the raw text. </dd>
+</dl>
diff --git a/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleBroadcastReceiver.java b/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleBroadcastReceiver.java
new file mode 100644
index 0000000..eec10b2
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleBroadcastReceiver.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 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.gadget;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.gadget.GadgetManager;
+import android.gadget.GadgetProvider;
+import android.os.SystemClock;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import java.util.ArrayList;
+
+// 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;
+
+/**
+ * A BroadcastReceiver that listens for updates for the ExampleGadgetProvider. This
+ * BroadcastReceiver starts off disabled, and we only enable it when there is a gadget
+ * instance created, in order to only receive notifications when we need them.
+ */
+public class ExampleBroadcastReceiver extends BroadcastReceiver {
+
+ public void onReceive(Context context, Intent intent) {
+ Log.d("ExmampleBroadcastReceiver", "intent=" + intent);
+
+ // For our example, we'll also update all of the gadgets when the timezone
+ // changes, or the user or network sets the time.
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)
+ || action.equals(Intent.ACTION_TIME_CHANGED)) {
+ GadgetManager gm = GadgetManager.getInstance(context);
+ ArrayList<Integer> gadgetIds = new ArrayList();
+ ArrayList<String> texts = new ArrayList();
+
+ ExampleGadgetConfigure.loadAllTitlePrefs(context, gadgetIds, texts);
+
+ final int N = gadgetIds.size();
+ for (int i=0; i<N; i++) {
+ ExampleGadgetProvider.updateGadget(context, gm, gadgetIds.get(i), texts.get(i));
+ }
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleGadgetConfigure.java b/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleGadgetConfigure.java
new file mode 100644
index 0000000..03e7bb4
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleGadgetConfigure.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2008 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.gadget;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.gadget.GadgetManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+
+import java.util.ArrayList;
+
+// 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;
+
+/**
+ * The configuration screen for the ExampleGadgetProvider gadget sample.
+ */
+public class ExampleGadgetConfigure extends Activity {
+ static final String TAG = "ExampleGadgetConfigure";
+
+ private static final String PREFS_NAME
+ = "com.example.android.apis.gadget.ExampleGadgetProvider";
+ private static final String PREF_PREFIX_KEY = "prefix_";
+
+ int mGadgetId = GadgetManager.INVALID_GADGET_ID;
+ EditText mGadgetPrefix;
+
+ public ExampleGadgetConfigure() {
+ super();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Set the result to CANCELED. This will cause the gadget host to cancel
+ // out of the gadget placement if they press the back button.
+ setResult(RESULT_CANCELED);
+
+ // Set the view layout resource to use.
+ setContentView(R.layout.gadget_configure);
+
+ // Find the EditText
+ mGadgetPrefix = (EditText)findViewById(R.id.gadget_prefix);
+
+ // Bind the action for the save button.
+ findViewById(R.id.save_button).setOnClickListener(mOnClickListener);
+
+ // Find the gadget id from the intent.
+ Intent intent = getIntent();
+ Bundle extras = intent.getExtras();
+ if (extras != null) {
+ mGadgetId = extras.getInt(
+ GadgetManager.EXTRA_GADGET_ID, GadgetManager.INVALID_GADGET_ID);
+ }
+
+ // If they gave us an intent without the gadget id, just bail.
+ if (mGadgetId == GadgetManager.INVALID_GADGET_ID) {
+ finish();
+ }
+
+ mGadgetPrefix.setText(loadTitlePref(ExampleGadgetConfigure.this, mGadgetId));
+ }
+
+ View.OnClickListener mOnClickListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ // When the button is clicked, save the string in our prefs and return that they
+ // clicked OK.
+ saveTitlePref(ExampleGadgetConfigure.this, mGadgetId,
+ mGadgetPrefix.getText().toString());
+
+ setResult(RESULT_OK);
+ finish();
+ }
+ };
+
+ // Write the prefix to the SharedPreferences object for this gadget
+ static void saveTitlePref(Context context, int gadgetId, String text) {
+ SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
+ prefs.putString(PREF_PREFIX_KEY + gadgetId, text);
+ prefs.commit();
+ }
+
+ // Read the prefix from the SharedPreferences object for this gadget.
+ // If there is no preference saved, get the default from a resource
+ static String loadTitlePref(Context context, int gadgetId) {
+ SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
+ String prefix = prefs.getString(PREF_PREFIX_KEY, null);
+ if (prefix != null) {
+ return prefix;
+ } else {
+ return context.getString(R.string.gadget_prefix_default);
+ }
+ }
+
+ static void deleteTitlePref(Context context, int gadgetId) {
+ }
+
+ static void loadAllTitlePrefs(Context context, ArrayList<Integer> gadgetIds,
+ ArrayList<String> texts) {
+ }
+}
+
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleGadgetProvider.java b/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleGadgetProvider.java
new file mode 100644
index 0000000..eb1dab3
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/gadget/ExampleGadgetProvider.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 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.gadget;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.gadget.GadgetManager;
+import android.gadget.GadgetProvider;
+import android.os.SystemClock;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import java.util.ArrayList;
+
+// 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;
+
+/**
+ * A gadget provider. We have a string that we pull from a preference in order to show
+ * the configuration settings and the current time when the gadget was updated. We also
+ * register a BroadcastReceiver for time-changed and timezone-changed broadcasts, and
+ * update then too.
+ *
+ * <p>See also the following files:
+ * <ul>
+ * <li>ExampleGadgetConfigure.java</li>
+ * <li>ExampleBroadcastReceiver.java</li>
+ * <li>res/layout/gadget_configure.xml</li>
+ * <li>res/layout/gadget_provider.xml</li>
+ * <li>res/xml/gadget_provider.xml</li>
+ * </ul>
+ */
+public class ExampleGadgetProvider extends GadgetProvider {
+ // log tag
+ private static final String TAG = "ExampleGadgetProvider";
+
+ public void onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds) {
+ Log.d(TAG, "onUpdate");
+ // For each gadget that needs an update, get the text that we should display:
+ // - Create a RemoteViews object for it
+ // - Set the text in the RemoteViews object
+ // - Tell the GadgetManager to show that views object for the gadget.
+ final int N = gadgetIds.length;
+ for (int i=0; i<N; i++) {
+ int gadgetId = gadgetIds[i];
+ String titlePrefix = ExampleGadgetConfigure.loadTitlePref(context, gadgetId);
+ updateGadget(context, gadgetManager, gadgetId, titlePrefix);
+ }
+ }
+
+ public void onDeleted(Context context, int[] gadgetIds) {
+ Log.d(TAG, "onDeleted");
+ // When the user deletes the gadget, delete the preference associated with it.
+ final int N = gadgetIds.length;
+ for (int i=0; i<N; i++) {
+ ExampleGadgetConfigure.deleteTitlePref(context, gadgetIds[i]);
+ }
+ }
+
+ public void onEnabled(Context context) {
+ Log.d(TAG, "onEnabled");
+ // When the first gadget is created, register for the TIMEZONE_CHANGED and TIME_CHANGED
+ // broadcasts. We don't want to be listening for these if nobody has our gadget active.
+ // This setting is sticky across reboots, but that doesn't matter, because this will
+ // be called after boot if there is a gadget instance for this provider.
+ PackageManager pm = context.getPackageManager();
+ pm.setComponentEnabledSetting(
+ new ComponentName("com.example.android.apis", ".gadget.ExampleBroadcastReceiver"),
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+
+ public void onDisabled(Context context) {
+ // When the first gadget is created, stop listening for the TIMEZONE_CHANGED and
+ // TIME_CHANGED broadcasts.
+ Log.d(TAG, "onDisabled");
+ Class clazz = ExampleBroadcastReceiver.class;
+ PackageManager pm = context.getPackageManager();
+ pm.setComponentEnabledSetting(
+ new ComponentName("com.example.android.apis", ".gadget.ExampleBroadcastReceiver"),
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+
+ static void updateGadget(Context context, GadgetManager gadgetManager,
+ int gadgetId, String titlePrefix) {
+ Log.d(TAG, "updateGadget gadgetId=" + gadgetId + " titlePrefix=" + titlePrefix);
+ // Getting the string this way allows the string to be localized. The format
+ // string is filled in using java.util.Formatter-style format strings.
+ CharSequence text = context.getString(R.string.gadget_text_format,
+ ExampleGadgetConfigure.loadTitlePref(context, gadgetId),
+ "0x" + Long.toHexString(SystemClock.elapsedRealtime()));
+
+ // Construct the RemoteViews object. It takes the package name (in our case, it's our
+ // package, but it needs this because on the other side it's the gadget host inflating
+ // the layout from our package).
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.gadget_provider);
+ views.setTextViewText(R.id.gadget_text, text);
+
+ // Tell the gadget manager
+ gadgetManager.updateGadget(gadgetId, views);
+ }
+}
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/AlphaBitmap.java b/samples/ApiDemos/src/com/example/android/apis/graphics/AlphaBitmap.java
new file mode 100644
index 0000000..8fff231
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/AlphaBitmap.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+
+public class AlphaBitmap extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Bitmap mBitmap;
+ private Bitmap mBitmap2;
+ private Bitmap mBitmap3;
+ private Shader mShader;
+
+ private static void drawIntoBitmap(Bitmap bm) {
+ float x = bm.getWidth();
+ float y = bm.getHeight();
+ Canvas c = new Canvas(bm);
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+
+ p.setAlpha(0x80);
+ c.drawCircle(x/2, y/2, x/2, p);
+
+ p.setAlpha(0x30);
+ p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+ p.setTextSize(60);
+ p.setTextAlign(Paint.Align.CENTER);
+ Paint.FontMetrics fm = p.getFontMetrics();
+ c.drawText("Alpha", x/2, (y-fm.ascent)/2, p);
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ InputStream is = context.getResources().openRawResource(R.drawable.app_sample_code);
+ mBitmap = BitmapFactory.decodeStream(is);
+ mBitmap2 = mBitmap.extractAlpha();
+ mBitmap3 = Bitmap.createBitmap(200, 200, Bitmap.Config.ALPHA_8);
+ drawIntoBitmap(mBitmap3);
+
+ mShader = new LinearGradient(0, 0, 100, 70, new int[] {
+ Color.RED, Color.GREEN, Color.BLUE },
+ null, Shader.TileMode.MIRROR);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ Paint p = new Paint();
+ float y = 10;
+
+ p.setColor(Color.RED);
+ canvas.drawBitmap(mBitmap, 10, y, p);
+ y += mBitmap.getHeight() + 10;
+ canvas.drawBitmap(mBitmap2, 10, y, p);
+ y += mBitmap2.getHeight() + 10;
+ p.setShader(mShader);
+ canvas.drawBitmap(mBitmap3, 10, y, p);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/AnimateDrawable.java b/samples/ApiDemos/src/com/example/android/apis/graphics/AnimateDrawable.java
new file mode 100644
index 0000000..279b588
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/AnimateDrawable.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Transformation;
+
+public class AnimateDrawable extends ProxyDrawable {
+
+ private Animation mAnimation;
+ private Transformation mTransformation = new Transformation();
+
+ public AnimateDrawable(Drawable target) {
+ super(target);
+ }
+
+ public AnimateDrawable(Drawable target, Animation animation) {
+ super(target);
+ mAnimation = animation;
+ }
+
+ public Animation getAnimation() {
+ return mAnimation;
+ }
+
+ public void setAnimation(Animation anim) {
+ mAnimation = anim;
+ }
+
+ public boolean hasStarted() {
+ return mAnimation != null && mAnimation.hasStarted();
+ }
+
+ public boolean hasEnded() {
+ return mAnimation == null || mAnimation.hasEnded();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ Drawable dr = getProxy();
+ if (dr != null) {
+ int sc = canvas.save();
+ Animation anim = mAnimation;
+ if (anim != null) {
+ anim.getTransformation(
+ AnimationUtils.currentAnimationTimeMillis(),
+ mTransformation);
+ canvas.concat(mTransformation.getMatrix());
+ }
+ dr.draw(canvas);
+ canvas.restoreToCount(sc);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/AnimateDrawables.java b/samples/ApiDemos/src/com/example/android/apis/graphics/AnimateDrawables.java
new file mode 100644
index 0000000..7c9473d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/AnimateDrawables.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.*;
+import android.view.animation.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+
+public class AnimateDrawables extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private AnimateDrawable mDrawable;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ Drawable dr = context.getResources().getDrawable(R.drawable.beach);
+ dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
+
+ Animation an = new TranslateAnimation(0, 100, 0, 200);
+ an.setDuration(2000);
+ an.setRepeatCount(-1);
+ an.initialize(10, 10, 10, 10);
+
+ mDrawable = new AnimateDrawable(dr, an);
+ an.startNow();
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ mDrawable.draw(canvas);
+ invalidate();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Arcs.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Arcs.java
new file mode 100644
index 0000000..ff8b38b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Arcs.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+// 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.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+
+public class Arcs extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint[] mPaints;
+ private Paint mFramePaint;
+ private boolean[] mUseCenters;
+ private RectF[] mOvals;
+ private RectF mBigOval;
+ private float mStart;
+ private float mSweep;
+ private int mBigIndex;
+
+ private static final float SWEEP_INC = 2;
+ private static final float START_INC = 15;
+
+ public SampleView(Context context) {
+ super(context);
+
+ mPaints = new Paint[4];
+ mUseCenters = new boolean[4];
+ mOvals = new RectF[4];
+
+ mPaints[0] = new Paint();
+ mPaints[0].setAntiAlias(true);
+ mPaints[0].setStyle(Paint.Style.FILL);
+ mPaints[0].setColor(0x88FF0000);
+ mUseCenters[0] = false;
+
+ mPaints[1] = new Paint(mPaints[0]);
+ mPaints[1].setColor(0x8800FF00);
+ mUseCenters[1] = true;
+
+ mPaints[2] = new Paint(mPaints[0]);
+ mPaints[2].setStyle(Paint.Style.STROKE);
+ mPaints[2].setStrokeWidth(4);
+ mPaints[2].setColor(0x880000FF);
+ mUseCenters[2] = false;
+
+ mPaints[3] = new Paint(mPaints[2]);
+ mPaints[3].setColor(0x88888888);
+ mUseCenters[3] = true;
+
+ mBigOval = new RectF(40, 10, 280, 250);
+
+ mOvals[0] = new RectF( 10, 270, 70, 330);
+ mOvals[1] = new RectF( 90, 270, 150, 330);
+ mOvals[2] = new RectF(170, 270, 230, 330);
+ mOvals[3] = new RectF(250, 270, 310, 330);
+
+ mFramePaint = new Paint();
+ mFramePaint.setAntiAlias(true);
+ mFramePaint.setStyle(Paint.Style.STROKE);
+ mFramePaint.setStrokeWidth(0);
+ }
+
+ private void drawArcs(Canvas canvas, RectF oval, boolean useCenter,
+ Paint paint) {
+ canvas.drawRect(oval, mFramePaint);
+ canvas.drawArc(oval, mStart, mSweep, useCenter, paint);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ drawArcs(canvas, mBigOval, mUseCenters[mBigIndex],
+ mPaints[mBigIndex]);
+
+ for (int i = 0; i < 4; i++) {
+ drawArcs(canvas, mOvals[i], mUseCenters[i], mPaints[i]);
+ }
+
+ mSweep += SWEEP_INC;
+ if (mSweep > 360) {
+ mSweep -= 360;
+ mStart += START_INC;
+ if (mStart >= 360) {
+ mStart -= 360;
+ }
+ mBigIndex = (mBigIndex + 1) % mOvals.length;
+ }
+ invalidate();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
new file mode 100644
index 0000000..88f0c1d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+
+public class BitmapDecode extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Bitmap mBitmap;
+ private Bitmap mBitmap2;
+ private Bitmap mBitmap3;
+ private Bitmap mBitmap4;
+ private Drawable mDrawable;
+
+ private Movie mMovie;
+ private long mMovieStart;
+
+ private static byte[] streamToBytes(InputStream is) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
+ byte[] buffer = new byte[1024];
+ int len;
+ try {
+ while ((len = is.read(buffer)) >= 0) {
+ os.write(buffer, 0, len);
+ }
+ } catch (java.io.IOException e) {
+ }
+ return os.toByteArray();
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ java.io.InputStream is;
+ is = context.getResources().openRawResource(R.drawable.beach);
+
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ Bitmap bm;
+
+ opts.inJustDecodeBounds = true;
+ bm = BitmapFactory.decodeStream(is, null, opts);
+
+ // now opts.outWidth and opts.outHeight are the dimension of the
+ // bitmap, even though bm is null
+
+ opts.inJustDecodeBounds = false; // this will request the bm
+ opts.inSampleSize = 4; // scaled down by 4
+ bm = BitmapFactory.decodeStream(is, null, opts);
+
+ mBitmap = bm;
+
+ // decode an image with transparency
+ is = context.getResources().openRawResource(R.drawable.frog);
+ mBitmap2 = BitmapFactory.decodeStream(is);
+
+ // create a deep copy of it using getPixels() into different configs
+ int w = mBitmap2.getWidth();
+ int h = mBitmap2.getHeight();
+ int[] pixels = new int[w*h];
+ mBitmap2.getPixels(pixels, 0, w, 0, 0, w, h);
+ mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
+ Bitmap.Config.ARGB_8888);
+ mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h,
+ Bitmap.Config.ARGB_4444);
+
+ mDrawable = context.getResources().getDrawable(R.drawable.button);
+ mDrawable.setBounds(150, 20, 300, 100);
+
+ is = context.getResources().openRawResource(R.drawable.animated_gif);
+ if (true) {
+ mMovie = Movie.decodeStream(is);
+ } else {
+ byte[] array = streamToBytes(is);
+ mMovie = Movie.decodeByteArray(array, 0, array.length);
+ }
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(0xFFCCCCCC);
+
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+
+ canvas.drawBitmap(mBitmap, 10, 10, null);
+ canvas.drawBitmap(mBitmap2, 10, 170, null);
+ canvas.drawBitmap(mBitmap3, 110, 170, null);
+ canvas.drawBitmap(mBitmap4, 210, 170, null);
+
+ mDrawable.draw(canvas);
+
+ long now = android.os.SystemClock.uptimeMillis();
+ if (mMovieStart == 0) { // first time
+ mMovieStart = now;
+ }
+ if (mMovie != null) {
+ int dur = mMovie.duration();
+ if (dur == 0) {
+ dur = 1000;
+ }
+ int relTime = (int)((now - mMovieStart) % dur);
+ mMovie.setTime(relTime);
+ mMovie.draw(canvas, getWidth() - mMovie.width(),
+ getHeight() - mMovie.height());
+ invalidate();
+ }
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapMesh.java b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapMesh.java
new file mode 100644
index 0000000..4d48a1e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapMesh.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.*;
+import android.util.FloatMath;
+
+public class BitmapMesh extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private static final int WIDTH = 20;
+ private static final int HEIGHT = 20;
+ private static final int COUNT = (WIDTH + 1) * (HEIGHT + 1);
+
+ private final Bitmap mBitmap;
+ private final float[] mVerts = new float[COUNT*2];
+ private final float[] mOrig = new float[COUNT*2];
+
+ private final Matrix mMatrix = new Matrix();
+ private final Matrix mInverse = new Matrix();
+
+ private static void setXY(float[] array, int index, float x, float y) {
+ array[index*2 + 0] = x;
+ array[index*2 + 1] = y;
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mBitmap = BitmapFactory.decodeResource(getResources(),
+ R.drawable.beach);
+
+ float w = mBitmap.getWidth();
+ float h = mBitmap.getHeight();
+ // construct our mesh
+ int index = 0;
+ for (int y = 0; y <= HEIGHT; y++) {
+ float fy = h * y / HEIGHT;
+ for (int x = 0; x <= WIDTH; x++) {
+ float fx = w * x / WIDTH;
+ setXY(mVerts, index, fx, fy);
+ setXY(mOrig, index, fx, fy);
+ index += 1;
+ }
+ }
+
+ mMatrix.setTranslate(10, 10);
+ mMatrix.invert(mInverse);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(0xFFCCCCCC);
+
+ canvas.concat(mMatrix);
+ canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0,
+ null, 0, null);
+ }
+
+ private void warp(float cx, float cy) {
+ final float K = 10000;
+ float[] src = mOrig;
+ float[] dst = mVerts;
+ for (int i = 0; i < COUNT*2; i += 2) {
+ float x = src[i+0];
+ float y = src[i+1];
+ float dx = cx - x;
+ float dy = cy - y;
+ float dd = dx*dx + dy*dy;
+ float d = FloatMath.sqrt(dd);
+ float pull = K / (dd + 0.000001f);
+
+ pull /= (d + 0.000001f);
+ // android.util.Log.d("skia", "index " + i + " dist=" + d + " pull=" + pull);
+
+ if (pull >= 1) {
+ dst[i+0] = cx;
+ dst[i+1] = cy;
+ } else {
+ dst[i+0] = x + dx * pull;
+ dst[i+1] = y + dy * pull;
+ }
+ }
+ }
+
+ private int mLastWarpX = -9999; // don't match a touch coordinate
+ private int mLastWarpY;
+
+ @Override public boolean onTouchEvent(MotionEvent event) {
+ float[] pt = { event.getX(), event.getY() };
+ mInverse.mapPoints(pt);
+
+ int x = (int)pt[0];
+ int y = (int)pt[1];
+ if (mLastWarpX != x || mLastWarpY != y) {
+ mLastWarpX = x;
+ mLastWarpY = y;
+ warp(pt[0], pt[1]);
+ invalidate();
+ }
+ return true;
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapPixels.java b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapPixels.java
new file mode 100644
index 0000000..88717bc
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapPixels.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
+public class BitmapPixels extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Bitmap mBitmap1;
+ private Bitmap mBitmap2;
+ private Bitmap mBitmap3;
+ private Bitmap mBitmap4;
+
+ // access the red component from a premultiplied color
+ private static int getR32(int c) { return (c >> 0) & 0xFF; }
+ // access the red component from a premultiplied color
+ private static int getG32(int c) { return (c >> 8) & 0xFF; }
+ // access the red component from a premultiplied color
+ private static int getB32(int c) { return (c >> 16) & 0xFF; }
+ // access the red component from a premultiplied color
+ private static int getA32(int c) { return (c >> 24) & 0xFF; }
+
+ /**
+ * This takes components that are already in premultiplied form, and
+ * packs them into an int in the correct device order.
+ */
+ private static int pack8888(int r, int g, int b, int a) {
+ return (r << 0) | ( g << 8) | (b << 16) | (a << 24);
+ }
+
+ private static short pack565(int r, int g, int b) {
+ return (short)((r << 11) | ( g << 5) | (b << 0));
+ }
+
+ private static short pack4444(int r, int g, int b, int a) {
+ return (short)((a << 0) | ( b << 4) | (g << 8) | (r << 12));
+ }
+
+ private static int mul255(int c, int a) {
+ int prod = c * a + 128;
+ return (prod + (prod >> 8)) >> 8;
+ }
+
+ /**
+ * Turn a color int into a premultiplied device color
+ */
+ private static int premultiplyColor(int c) {
+ int r = Color.red(c);
+ int g = Color.green(c);
+ int b = Color.blue(c);
+ int a = Color.alpha(c);
+ // now apply the alpha to r, g, b
+ r = mul255(r, a);
+ g = mul255(g, a);
+ b = mul255(b, a);
+ // now pack it in the correct order
+ return pack8888(r, g, b, a);
+ }
+
+ private static void makeRamp(int from, int to, int n,
+ int[] ramp8888, short[] ramp565,
+ short[] ramp4444) {
+ int r = getR32(from) << 23;
+ int g = getG32(from) << 23;
+ int b = getB32(from) << 23;
+ int a = getA32(from) << 23;
+ // now compute our step amounts per componenet (biased by 23 bits)
+ int dr = ((getR32(to) << 23) - r) / (n - 1);
+ int dg = ((getG32(to) << 23) - g) / (n - 1);
+ int db = ((getB32(to) << 23) - b) / (n - 1);
+ int da = ((getA32(to) << 23) - a) / (n - 1);
+
+ for (int i = 0; i < n; i++) {
+ ramp8888[i] = pack8888(r >> 23, g >> 23, b >> 23, a >> 23);
+ ramp565[i] = pack565(r >> (23+3), g >> (23+2), b >> (23+3));
+ ramp4444[i] = pack4444(r >> (23+4), g >> (23+4), b >> (23+4),
+ a >> (23+4));
+ r += dr;
+ g += dg;
+ b += db;
+ a += da;
+ }
+ }
+
+ private static IntBuffer makeBuffer(int[] src, int n) {
+ IntBuffer dst = IntBuffer.allocate(n*n);
+ for (int i = 0; i < n; i++) {
+ dst.put(src);
+ }
+ dst.rewind();
+ return dst;
+ }
+
+ private static ShortBuffer makeBuffer(short[] src, int n) {
+ ShortBuffer dst = ShortBuffer.allocate(n*n);
+ for (int i = 0; i < n; i++) {
+ dst.put(src);
+ }
+ dst.rewind();
+ return dst;
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ final int N = 100;
+ int[] data8888 = new int[N];
+ short[] data565 = new short[N];
+ short[] data4444 = new short[N];
+
+ makeRamp(premultiplyColor(Color.RED), premultiplyColor(Color.GREEN),
+ N, data8888, data565, data4444);
+
+ mBitmap1 = Bitmap.createBitmap(N, N, Bitmap.Config.ARGB_8888);
+ mBitmap2 = Bitmap.createBitmap(N, N, Bitmap.Config.RGB_565);
+ mBitmap3 = Bitmap.createBitmap(N, N, Bitmap.Config.ARGB_4444);
+
+ mBitmap1.copyPixelsFromBuffer(makeBuffer(data8888, N));
+ mBitmap2.copyPixelsFromBuffer(makeBuffer(data565, N));
+ mBitmap3.copyPixelsFromBuffer(makeBuffer(data4444, N));
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(0xFFCCCCCC);
+
+ int y = 10;
+ canvas.drawBitmap(mBitmap1, 10, y, null);
+ y += mBitmap1.getHeight() + 10;
+ canvas.drawBitmap(mBitmap2, 10, y, null);
+ y += mBitmap2.getHeight() + 10;
+ canvas.drawBitmap(mBitmap3, 10, y, null);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
new file mode 100644
index 0000000..ceff150
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.Window;
+import java.io.IOException;
+
+// ----------------------------------------------------------------------
+
+public class CameraPreview extends Activity {
+ private Preview mPreview;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Hide the window title.
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ // Create our Preview view and set it as the content of our activity.
+ mPreview = new Preview(this);
+ setContentView(mPreview);
+ }
+
+}
+
+// ----------------------------------------------------------------------
+
+class Preview extends SurfaceView implements SurfaceHolder.Callback {
+ SurfaceHolder mHolder;
+ Camera mCamera;
+
+ Preview(Context context) {
+ super(context);
+
+ // Install a SurfaceHolder.Callback so we get notified when the
+ // underlying surface is created and destroyed.
+ mHolder = getHolder();
+ mHolder.addCallback(this);
+ mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ // The Surface has been created, acquire the camera and tell it where
+ // to draw.
+ mCamera = Camera.open();
+ try {
+ mCamera.setPreviewDisplay(holder);
+ } catch (IOException exception) {
+ mCamera.release();
+ mCamera = null;
+ // TODO: add more exception handling logic here
+ }
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // Surface will be destroyed when we return, so stop the preview.
+ // Because the CameraDevice object is not a shared resource, it's very
+ // important to release it when the activity is paused.
+ mCamera.stopPreview();
+ mCamera = null;
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ // Now that the size is known, set up the camera parameters and begin
+ // the preview.
+ Camera.Parameters parameters = mCamera.getParameters();
+ parameters.setPreviewSize(w, h);
+ mCamera.setParameters(parameters);
+ mCamera.startPreview();
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Clipping.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Clipping.java
new file mode 100644
index 0000000..cf83597
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Clipping.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+
+public class Clipping extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint;
+ private Path mPath;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setStrokeWidth(6);
+ mPaint.setTextSize(16);
+ mPaint.setTextAlign(Paint.Align.RIGHT);
+
+ mPath = new Path();
+ }
+
+ private void drawScene(Canvas canvas) {
+ canvas.clipRect(0, 0, 100, 100);
+
+ canvas.drawColor(Color.WHITE);
+
+ mPaint.setColor(Color.RED);
+ canvas.drawLine(0, 0, 100, 100, mPaint);
+
+ mPaint.setColor(Color.GREEN);
+ canvas.drawCircle(30, 70, 30, mPaint);
+
+ mPaint.setColor(Color.BLUE);
+ canvas.drawText("Clipping", 100, 30, mPaint);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.GRAY);
+
+ canvas.save();
+ canvas.translate(10, 10);
+ drawScene(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(160, 10);
+ canvas.clipRect(10, 10, 90, 90);
+ canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
+ drawScene(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(10, 160);
+ mPath.reset();
+ canvas.clipPath(mPath); // makes the clip empty
+ mPath.addCircle(50, 50, 50, Path.Direction.CCW);
+ canvas.clipPath(mPath, Region.Op.REPLACE);
+ drawScene(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(160, 160);
+ canvas.clipRect(0, 0, 60, 60);
+ canvas.clipRect(40, 40, 100, 100, Region.Op.UNION);
+ drawScene(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(10, 310);
+ canvas.clipRect(0, 0, 60, 60);
+ canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);
+ drawScene(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(160, 310);
+ canvas.clipRect(0, 0, 60, 60);
+ canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);
+ drawScene(canvas);
+ canvas.restore();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/ColorMatrixSample.java b/samples/ApiDemos/src/com/example/android/apis/graphics/ColorMatrixSample.java
new file mode 100644
index 0000000..19a0f7f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/ColorMatrixSample.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+
+public class ColorMatrixSample extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private ColorMatrix mCM = new ColorMatrix();
+ private Bitmap mBitmap;
+ private float mSaturation;
+ private float mAngle;
+
+ public SampleView(Context context) {
+ super(context);
+
+ mBitmap = BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.balloons);
+ }
+
+ private static void setTranslate(ColorMatrix cm, float dr, float dg,
+ float db, float da) {
+ cm.set(new float[] {
+ 2, 0, 0, 0, dr,
+ 0, 2, 0, 0, dg,
+ 0, 0, 2, 0, db,
+ 0, 0, 0, 1, da });
+ }
+
+ private static void setContrast(ColorMatrix cm, float contrast) {
+ float scale = contrast + 1.f;
+ float translate = (-.5f * scale + .5f) * 255.f;
+ cm.set(new float[] {
+ scale, 0, 0, 0, translate,
+ 0, scale, 0, 0, translate,
+ 0, 0, scale, 0, translate,
+ 0, 0, 0, 1, 0 });
+ }
+
+ private static void setContrastTranslateOnly(ColorMatrix cm, float contrast) {
+ float scale = contrast + 1.f;
+ float translate = (-.5f * scale + .5f) * 255.f;
+ cm.set(new float[] {
+ 1, 0, 0, 0, translate,
+ 0, 1, 0, 0, translate,
+ 0, 0, 1, 0, translate,
+ 0, 0, 0, 1, 0 });
+ }
+
+ private static void setContrastScaleOnly(ColorMatrix cm, float contrast) {
+ float scale = contrast + 1.f;
+ float translate = (-.5f * scale + .5f) * 255.f;
+ cm.set(new float[] {
+ scale, 0, 0, 0, 0,
+ 0, scale, 0, 0, 0,
+ 0, 0, scale, 0, 0,
+ 0, 0, 0, 1, 0 });
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+ float x = 20;
+ float y = 20;
+
+ canvas.drawColor(Color.WHITE);
+
+ paint.setColorFilter(null);
+ canvas.drawBitmap(mBitmap, x, y, paint);
+
+ ColorMatrix cm = new ColorMatrix();
+
+ mAngle += 2;
+ if (mAngle > 180) {
+ mAngle = 0;
+ }
+
+ //convert our animated angle [-180...180] to a contrast value of [-1..1]
+ float contrast = mAngle / 180.f;
+
+ setContrast(cm, contrast);
+ paint.setColorFilter(new ColorMatrixColorFilter(cm));
+ canvas.drawBitmap(mBitmap, x + mBitmap.getWidth() + 10, y, paint);
+
+ setContrastScaleOnly(cm, contrast);
+ paint.setColorFilter(new ColorMatrixColorFilter(cm));
+ canvas.drawBitmap(mBitmap, x, y + mBitmap.getHeight() + 10, paint);
+
+ setContrastTranslateOnly(cm, contrast);
+ paint.setColorFilter(new ColorMatrixColorFilter(cm));
+ canvas.drawBitmap(mBitmap, x, y + 2*(mBitmap.getHeight() + 10),
+ paint);
+
+ invalidate();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/ColorPickerDialog.java b/samples/ApiDemos/src/com/example/android/apis/graphics/ColorPickerDialog.java
new file mode 100644
index 0000000..cc4a0d4
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/ColorPickerDialog.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.R;
+import android.os.Bundle;
+import android.app.Dialog;
+import android.content.Context;
+import android.graphics.*;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class ColorPickerDialog extends Dialog {
+
+ public interface OnColorChangedListener {
+ void colorChanged(int color);
+ }
+
+ private OnColorChangedListener mListener;
+ private int mInitialColor;
+
+ private static class ColorPickerView extends View {
+ private Paint mPaint;
+ private Paint mCenterPaint;
+ private final int[] mColors;
+ private OnColorChangedListener mListener;
+
+ ColorPickerView(Context c, OnColorChangedListener l, int color) {
+ super(c);
+ mListener = l;
+ mColors = new int[] {
+ 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, 0xFF00FF00,
+ 0xFFFFFF00, 0xFFFF0000
+ };
+ Shader s = new SweepGradient(0, 0, mColors, null);
+
+ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mPaint.setShader(s);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeWidth(32);
+
+ mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mCenterPaint.setColor(color);
+ mCenterPaint.setStrokeWidth(5);
+ }
+
+ private boolean mTrackingCenter;
+ private boolean mHighlightCenter;
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ float r = CENTER_X - mPaint.getStrokeWidth()*0.5f;
+
+ canvas.translate(CENTER_X, CENTER_X);
+
+ canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
+ canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint);
+
+ if (mTrackingCenter) {
+ int c = mCenterPaint.getColor();
+ mCenterPaint.setStyle(Paint.Style.STROKE);
+
+ if (mHighlightCenter) {
+ mCenterPaint.setAlpha(0xFF);
+ } else {
+ mCenterPaint.setAlpha(0x80);
+ }
+ canvas.drawCircle(0, 0,
+ CENTER_RADIUS + mCenterPaint.getStrokeWidth(),
+ mCenterPaint);
+
+ mCenterPaint.setStyle(Paint.Style.FILL);
+ mCenterPaint.setColor(c);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(CENTER_X*2, CENTER_Y*2);
+ }
+
+ private static final int CENTER_X = 100;
+ private static final int CENTER_Y = 100;
+ private static final int CENTER_RADIUS = 32;
+
+ private int floatToByte(float x) {
+ int n = java.lang.Math.round(x);
+ return n;
+ }
+ private int pinToByte(int n) {
+ if (n < 0) {
+ n = 0;
+ } else if (n > 255) {
+ n = 255;
+ }
+ return n;
+ }
+
+ private int ave(int s, int d, float p) {
+ return s + java.lang.Math.round(p * (d - s));
+ }
+
+ private int interpColor(int colors[], float unit) {
+ if (unit <= 0) {
+ return colors[0];
+ }
+ if (unit >= 1) {
+ return colors[colors.length - 1];
+ }
+
+ float p = unit * (colors.length - 1);
+ int i = (int)p;
+ p -= i;
+
+ // now p is just the fractional part [0...1) and i is the index
+ int c0 = colors[i];
+ int c1 = colors[i+1];
+ int a = ave(Color.alpha(c0), Color.alpha(c1), p);
+ int r = ave(Color.red(c0), Color.red(c1), p);
+ int g = ave(Color.green(c0), Color.green(c1), p);
+ int b = ave(Color.blue(c0), Color.blue(c1), p);
+
+ return Color.argb(a, r, g, b);
+ }
+
+ private int rotateColor(int color, float rad) {
+ float deg = rad * 180 / 3.1415927f;
+ int r = Color.red(color);
+ int g = Color.green(color);
+ int b = Color.blue(color);
+
+ ColorMatrix cm = new ColorMatrix();
+ ColorMatrix tmp = new ColorMatrix();
+
+ cm.setRGB2YUV();
+ tmp.setRotate(0, deg);
+ cm.postConcat(tmp);
+ tmp.setYUV2RGB();
+ cm.postConcat(tmp);
+
+ final float[] a = cm.getArray();
+
+ int ir = floatToByte(a[0] * r + a[1] * g + a[2] * b);
+ int ig = floatToByte(a[5] * r + a[6] * g + a[7] * b);
+ int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b);
+
+ return Color.argb(Color.alpha(color), pinToByte(ir),
+ pinToByte(ig), pinToByte(ib));
+ }
+
+ private static final float PI = 3.1415926f;
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ float x = event.getX() - CENTER_X;
+ float y = event.getY() - CENTER_Y;
+ boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS;
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mTrackingCenter = inCenter;
+ if (inCenter) {
+ mHighlightCenter = true;
+ invalidate();
+ break;
+ }
+ case MotionEvent.ACTION_MOVE:
+ if (mTrackingCenter) {
+ if (mHighlightCenter != inCenter) {
+ mHighlightCenter = inCenter;
+ invalidate();
+ }
+ } else {
+ float angle = (float)java.lang.Math.atan2(y, x);
+ // need to turn angle [-PI ... PI] into unit [0....1]
+ float unit = angle/(2*PI);
+ if (unit < 0) {
+ unit += 1;
+ }
+ mCenterPaint.setColor(interpColor(mColors, unit));
+ invalidate();
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mTrackingCenter) {
+ if (inCenter) {
+ mListener.colorChanged(mCenterPaint.getColor());
+ }
+ mTrackingCenter = false; // so we draw w/o halo
+ invalidate();
+ }
+ break;
+ }
+ return true;
+ }
+ }
+
+ public ColorPickerDialog(Context context,
+ OnColorChangedListener listener,
+ int initialColor) {
+ super(context);
+
+ mListener = listener;
+ mInitialColor = initialColor;
+ }
+
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ OnColorChangedListener l = new OnColorChangedListener() {
+ public void colorChanged(int color) {
+ mListener.colorChanged(color);
+ dismiss();
+ }
+ };
+
+ setContentView(new ColorPickerView(getContext(), l, mInitialColor));
+ setTitle("Pick a Color");
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Compass.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Compass.java
new file mode 100644
index 0000000..d2a9907
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Compass.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.hardware.SensorListener;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Config;
+import android.util.Log;
+import android.view.View;
+
+public class Compass extends GraphicsActivity {
+
+ private static final String TAG = "Compass";
+
+ private SensorManager mSensorManager;
+ private SampleView mView;
+ private float[] mValues;
+
+ private final SensorListener mListener = new SensorListener() {
+
+ public void onSensorChanged(int sensor, float[] values) {
+ if (Config.LOGD) Log.d(TAG, "sensorChanged (" + values[0] + ", " + values[1] + ", " + values[2] + ")");
+ mValues = values;
+ if (mView != null) {
+ mView.invalidate();
+ }
+ }
+
+ public void onAccuracyChanged(int sensor, int accuracy) {
+ // TODO Auto-generated method stub
+
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ mView = new SampleView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ if (Config.LOGD) Log.d(TAG, "onResume");
+ super.onResume();
+ mSensorManager.registerListener(mListener,
+ SensorManager.SENSOR_ORIENTATION,
+ SensorManager.SENSOR_DELAY_GAME);
+ }
+
+ @Override
+ protected void onStop()
+ {
+ if (Config.LOGD) Log.d(TAG, "onStop");
+ mSensorManager.unregisterListener(mListener);
+ super.onStop();
+ }
+
+ private class SampleView extends View {
+ private Paint mPaint = new Paint();
+ private Path mPath = new Path();
+ private boolean mAnimate;
+ private long mNextTime;
+
+ public SampleView(Context context) {
+ super(context);
+
+ // Construct a wedge-shaped path
+ mPath.moveTo(0, -50);
+ mPath.lineTo(-20, 60);
+ mPath.lineTo(0, 50);
+ mPath.lineTo(20, 60);
+ mPath.close();
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+
+ canvas.drawColor(Color.WHITE);
+
+ paint.setAntiAlias(true);
+ paint.setColor(Color.BLACK);
+ paint.setStyle(Paint.Style.FILL);
+
+ int w = canvas.getWidth();
+ int h = canvas.getHeight();
+ int cx = w / 2;
+ int cy = h / 2;
+
+ canvas.translate(cx, cy);
+ if (mValues != null) {
+ canvas.rotate(-mValues[0]);
+ }
+ canvas.drawPath(mPath, mPaint);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ mAnimate = true;
+ super.onAttachedToWindow();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mAnimate = false;
+ super.onDetachedFromWindow();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CreateBitmap.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CreateBitmap.java
new file mode 100644
index 0000000..e3e5d9a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CreateBitmap.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+import java.io.ByteArrayOutputStream;
+
+public class CreateBitmap extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static final int WIDTH = 50;
+ private static final int HEIGHT = 50;
+ private static final int STRIDE = 64; // must be >= WIDTH
+
+ private static int[] createColors() {
+ int[] colors = new int[STRIDE * HEIGHT];
+ for (int y = 0; y < HEIGHT; y++) {
+ for (int x = 0; x < WIDTH; x++) {
+ int r = x * 255 / (WIDTH - 1);
+ int g = y * 255 / (HEIGHT - 1);
+ int b = 255 - Math.min(r, g);
+ int a = Math.max(r, g);
+ colors[y * STRIDE + x] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ }
+ return colors;
+ }
+
+ private static class SampleView extends View {
+ private Bitmap[] mBitmaps;
+ private Bitmap[] mJPEG;
+ private Bitmap[] mPNG;
+ private int[] mColors;
+ private Paint mPaint;
+
+ private static Bitmap codec(Bitmap src, Bitmap.CompressFormat format,
+ int quality) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ src.compress(format, quality, os);
+
+ byte[] array = os.toByteArray();
+ return BitmapFactory.decodeByteArray(array, 0, array.length);
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mColors = createColors();
+ int[] colors = mColors;
+
+ mBitmaps = new Bitmap[6];
+ // these three are initialized with colors[]
+ mBitmaps[0] = Bitmap.createBitmap(colors, 0, STRIDE, WIDTH, HEIGHT,
+ Bitmap.Config.ARGB_8888);
+ mBitmaps[1] = Bitmap.createBitmap(colors, 0, STRIDE, WIDTH, HEIGHT,
+ Bitmap.Config.RGB_565);
+ mBitmaps[2] = Bitmap.createBitmap(colors, 0, STRIDE, WIDTH, HEIGHT,
+ Bitmap.Config.ARGB_4444);
+
+ // these three will have their colors set later
+ mBitmaps[3] = Bitmap.createBitmap(WIDTH, HEIGHT,
+ Bitmap.Config.ARGB_8888);
+ mBitmaps[4] = Bitmap.createBitmap(WIDTH, HEIGHT,
+ Bitmap.Config.RGB_565);
+ mBitmaps[5] = Bitmap.createBitmap(WIDTH, HEIGHT,
+ Bitmap.Config.ARGB_4444);
+ for (int i = 3; i <= 5; i++) {
+ mBitmaps[i].setPixels(colors, 0, STRIDE, 0, 0, WIDTH, HEIGHT);
+ }
+
+ mPaint = new Paint();
+ mPaint.setDither(true);
+
+ // now encode/decode using JPEG and PNG
+ mJPEG = new Bitmap[mBitmaps.length];
+ mPNG = new Bitmap[mBitmaps.length];
+ for (int i = 0; i < mBitmaps.length; i++) {
+ mJPEG[i] = codec(mBitmaps[i], Bitmap.CompressFormat.JPEG, 80);
+ mPNG[i] = codec(mBitmaps[i], Bitmap.CompressFormat.PNG, 0);
+ }
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ for (int i = 0; i < mBitmaps.length; i++) {
+ canvas.drawBitmap(mBitmaps[i], 0, 0, null);
+ canvas.drawBitmap(mJPEG[i], 80, 0, null);
+ canvas.drawBitmap(mPNG[i], 160, 0, null);
+ canvas.translate(0, mBitmaps[i].getHeight());
+ }
+
+ // draw the color array directly, w/o craeting a bitmap object
+ canvas.drawBitmap(mColors, 0, STRIDE, 0, 0, WIDTH, HEIGHT,
+ true, null);
+ canvas.translate(0, HEIGHT);
+ canvas.drawBitmap(mColors, 0, STRIDE, 0, 0, WIDTH, HEIGHT,
+ false, mPaint);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Cube.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Cube.java
new file mode 100644
index 0000000..bb154eb
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Cube.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A vertex shaded cube.
+ */
+class Cube
+{
+ public Cube()
+ {
+ int one = 0x10000;
+ int vertices[] = {
+ -one, -one, -one,
+ one, -one, -one,
+ one, one, -one,
+ -one, one, -one,
+ -one, -one, one,
+ one, -one, one,
+ one, one, one,
+ -one, one, one,
+ };
+
+ int colors[] = {
+ 0, 0, 0, one,
+ one, 0, 0, one,
+ one, one, 0, one,
+ 0, one, 0, one,
+ 0, 0, one, one,
+ one, 0, one, one,
+ one, one, one, one,
+ 0, one, one, one,
+ };
+
+ byte indices[] = {
+ 0, 4, 5, 0, 5, 1,
+ 1, 5, 6, 1, 6, 2,
+ 2, 6, 7, 2, 7, 3,
+ 3, 7, 4, 3, 4, 0,
+ 4, 7, 6, 4, 6, 5,
+ 3, 0, 1, 3, 1, 2
+ };
+
+ // Buffers to be passed to gl*Pointer() functions
+ // must be direct, i.e., they must be placed on the
+ // native heap where the garbage collector cannot
+ // move them.
+ //
+ // Buffers with multi-byte datatypes (e.g., short, int, float)
+ // must have their byte order set to native order
+
+ ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
+ vbb.order(ByteOrder.nativeOrder());
+ mVertexBuffer = vbb.asIntBuffer();
+ mVertexBuffer.put(vertices);
+ mVertexBuffer.position(0);
+
+ ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
+ cbb.order(ByteOrder.nativeOrder());
+ mColorBuffer = cbb.asIntBuffer();
+ mColorBuffer.put(colors);
+ mColorBuffer.position(0);
+
+ mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
+ mIndexBuffer.put(indices);
+ mIndexBuffer.position(0);
+ }
+
+ public void draw(GL10 gl)
+ {
+ gl.glFrontFace(gl.GL_CW);
+ gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);
+ gl.glColorPointer(4, gl.GL_FIXED, 0, mColorBuffer);
+ gl.glDrawElements(gl.GL_TRIANGLES, 36, gl.GL_UNSIGNED_BYTE, mIndexBuffer);
+ }
+
+ private IntBuffer mVertexBuffer;
+ private IntBuffer mColorBuffer;
+ private ByteBuffer mIndexBuffer;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
new file mode 100644
index 0000000..527e2bc
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLSurfaceView;
+
+/**
+ * Render a pair of tumbling cubes.
+ */
+
+class CubeRenderer implements GLSurfaceView.Renderer {
+ public CubeRenderer(boolean useTranslucentBackground) {
+ mTranslucentBackground = useTranslucentBackground;
+ mCube = new Cube();
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -3.0f);
+ gl.glRotatef(mAngle, 0, 1, 0);
+ gl.glRotatef(mAngle*0.25f, 1, 0, 0);
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+ mCube.draw(gl);
+
+ gl.glRotatef(mAngle*2.0f, 0, 1, 1);
+ gl.glTranslatef(0.5f, 0.5f, 0.5f);
+
+ mCube.draw(gl);
+
+ mAngle += 1.2f;
+ }
+
+ public int[] getConfigSpec() {
+ if (mTranslucentBackground) {
+ // We want a depth buffer and an alpha buffer
+ int[] configSpec = {
+ EGL10.EGL_RED_SIZE, 8,
+ EGL10.EGL_GREEN_SIZE, 8,
+ EGL10.EGL_BLUE_SIZE, 8,
+ EGL10.EGL_ALPHA_SIZE, 8,
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ } else {
+ // We want a depth buffer, don't care about the
+ // details of the color buffer.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ gl.glViewport(0, 0, width, height);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) width / height;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+ GL10.GL_FASTEST);
+
+ if (mTranslucentBackground) {
+ gl.glClearColor(0,0,0,0);
+ } else {
+ gl.glClearColor(1,1,1,1);
+ }
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ }
+ private boolean mTranslucentBackground;
+ private Cube mCube;
+ private float mAngle;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/DrawPoints.java b/samples/ApiDemos/src/com/example/android/apis/graphics/DrawPoints.java
new file mode 100644
index 0000000..cbe6373
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/DrawPoints.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+
+public class DrawPoints extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint = new Paint();
+ private float[] mPts;
+
+ private static final float SIZE = 300;
+ private static final int SEGS = 32;
+ private static final int X = 0;
+ private static final int Y = 1;
+
+ private void buildPoints() {
+ final int ptCount = (SEGS + 1) * 2;
+ mPts = new float[ptCount * 2];
+
+ float value = 0;
+ final float delta = SIZE / SEGS;
+ for (int i = 0; i <= SEGS; i++) {
+ mPts[i*4 + X] = SIZE - value;
+ mPts[i*4 + Y] = 0;
+ mPts[i*4 + X + 2] = 0;
+ mPts[i*4 + Y + 2] = value;
+ value += delta;
+ }
+ }
+
+ public SampleView(Context context) {
+ super(context);
+
+ buildPoints();
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+
+ canvas.translate(10, 10);
+
+ canvas.drawColor(Color.WHITE);
+
+ paint.setColor(Color.RED);
+ paint.setStrokeWidth(0);
+ canvas.drawLines(mPts, paint);
+
+ paint.setColor(Color.BLUE);
+ paint.setStrokeWidth(3);
+ canvas.drawPoints(mPts, paint);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.java b/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.java
new file mode 100644
index 0000000..867da4c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class FingerPaint extends GraphicsActivity
+ implements ColorPickerDialog.OnColorChangedListener {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new MyView(this));
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setDither(true);
+ mPaint.setColor(0xFFFF0000);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeJoin(Paint.Join.ROUND);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setStrokeWidth(12);
+
+ mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
+ 0.4f, 6, 3.5f);
+
+ mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
+ }
+
+ private Paint mPaint;
+ private MaskFilter mEmboss;
+ private MaskFilter mBlur;
+
+ public void colorChanged(int color) {
+ mPaint.setColor(color);
+ }
+
+ public class MyView extends View {
+
+ private static final float MINP = 0.25f;
+ private static final float MAXP = 0.75f;
+
+ private Bitmap mBitmap;
+ private Canvas mCanvas;
+ private Path mPath;
+ private Paint mBitmapPaint;
+
+ public MyView(Context c) {
+ super(c);
+
+ mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
+ mCanvas = new Canvas(mBitmap);
+ mPath = new Path();
+ mBitmapPaint = new Paint(Paint.DITHER_FLAG);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.drawColor(0xFFAAAAAA);
+
+ canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+
+ canvas.drawPath(mPath, mPaint);
+ }
+
+ private float mX, mY;
+ private static final float TOUCH_TOLERANCE = 4;
+
+ private void touch_start(float x, float y) {
+ mPath.reset();
+ mPath.moveTo(x, y);
+ mX = x;
+ mY = y;
+ }
+ private void touch_move(float x, float y) {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
+ mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
+ mX = x;
+ mY = y;
+ }
+ }
+ private void touch_up() {
+ mPath.lineTo(mX, mY);
+ // commit the path to our offscreen
+ mCanvas.drawPath(mPath, mPaint);
+ // kill this so we don't double draw
+ mPath.reset();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ float x = event.getX();
+ float y = event.getY();
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ touch_start(x, y);
+ invalidate();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ touch_move(x, y);
+ invalidate();
+ break;
+ case MotionEvent.ACTION_UP:
+ touch_up();
+ invalidate();
+ break;
+ }
+ return true;
+ }
+ }
+
+ private static final int COLOR_MENU_ID = Menu.FIRST;
+ private static final int EMBOSS_MENU_ID = Menu.FIRST + 1;
+ private static final int BLUR_MENU_ID = Menu.FIRST + 2;
+ private static final int ERASE_MENU_ID = Menu.FIRST + 3;
+ private static final int SRCATOP_MENU_ID = Menu.FIRST + 4;
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('3', 'c');
+ menu.add(0, EMBOSS_MENU_ID, 0, "Emboss").setShortcut('4', 's');
+ menu.add(0, BLUR_MENU_ID, 0, "Blur").setShortcut('5', 'z');
+ menu.add(0, ERASE_MENU_ID, 0, "Erase").setShortcut('5', 'z');
+ menu.add(0, SRCATOP_MENU_ID, 0, "SrcATop").setShortcut('5', 'z');
+
+ /**** Is this the mechanism to extend with filter effects?
+ Intent intent = new Intent(null, getIntent().getData());
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ menu.addIntentOptions(
+ Menu.ALTERNATIVE, 0,
+ new ComponentName(this, NotesList.class),
+ null, intent, 0, null);
+ *****/
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ mPaint.setXfermode(null);
+ mPaint.setAlpha(0xFF);
+
+ switch (item.getItemId()) {
+ case COLOR_MENU_ID:
+ new ColorPickerDialog(this, this, mPaint.getColor()).show();
+ return true;
+ case EMBOSS_MENU_ID:
+ if (mPaint.getMaskFilter() != mEmboss) {
+ mPaint.setMaskFilter(mEmboss);
+ } else {
+ mPaint.setMaskFilter(null);
+ }
+ return true;
+ case BLUR_MENU_ID:
+ if (mPaint.getMaskFilter() != mBlur) {
+ mPaint.setMaskFilter(mBlur);
+ } else {
+ mPaint.setMaskFilter(null);
+ }
+ return true;
+ case ERASE_MENU_ID:
+ mPaint.setXfermode(new PorterDuffXfermode(
+ PorterDuff.Mode.CLEAR));
+ return true;
+ case SRCATOP_MENU_ID:
+ mPaint.setXfermode(new PorterDuffXfermode(
+ PorterDuff.Mode.SRC_ATOP));
+ mPaint.setAlpha(0x80);
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
new file mode 100644
index 0000000..f852186
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+/**
+ * Wrapper activity demonstrating the use of {@link GLSurfaceView}, a view
+ * that uses OpenGL drawing into a dedicated surface.
+ */
+public class GLSurfaceViewActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mGLSurfaceView = new GLSurfaceView(this);
+ mGLSurfaceView.setRenderer(new CubeRenderer(false));
+ setContentView(mGLSurfaceView);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/GradientDrawable1.java b/samples/ApiDemos/src/com/example/android/apis/graphics/GradientDrawable1.java
new file mode 100644
index 0000000..eb6d47d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/GradientDrawable1.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+// 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.os.Bundle;
+
+public class GradientDrawable1 extends GraphicsActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.shape_drawable_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/GraphicsActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/GraphicsActivity.java
new file mode 100644
index 0000000..023c0d7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/GraphicsActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+
+class GraphicsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void setContentView(View view) {
+ if (false) { // set to true to test Picture
+ ViewGroup vg = new PictureLayout(this);
+ vg.addView(view);
+ view = vg;
+ }
+
+ super.setContentView(view);
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Layers.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Layers.java
new file mode 100644
index 0000000..d9f5db0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Layers.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.*;
+
+public class Layers extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private static final int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG |
+ Canvas.CLIP_SAVE_FLAG |
+ Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
+ Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
+ Canvas.CLIP_TO_LAYER_SAVE_FLAG;
+
+ private Paint mPaint;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ canvas.translate(10, 10);
+
+ canvas.saveLayerAlpha(0, 0, 200, 200, 0x88, LAYER_FLAGS);
+
+ mPaint.setColor(Color.RED);
+ canvas.drawCircle(75, 75, 75, mPaint);
+ mPaint.setColor(Color.BLUE);
+ canvas.drawCircle(125, 125, 75, mPaint);
+
+ canvas.restore();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/MeasureText.java b/samples/ApiDemos/src/com/example/android/apis/graphics/MeasureText.java
new file mode 100644
index 0000000..e159efe
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/MeasureText.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+public class MeasureText extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static final int WIDTH = 50;
+ private static final int HEIGHT = 50;
+ private static final int STRIDE = 64; // must be >= WIDTH
+
+ private static int[] createColors() {
+ int[] colors = new int[STRIDE * HEIGHT];
+ for (int y = 0; y < HEIGHT; y++) {
+ for (int x = 0; x < WIDTH; x++) {
+ int r = x * 255 / (WIDTH - 1);
+ int g = y * 255 / (HEIGHT - 1);
+ int b = 255 - Math.min(r, g);
+ int a = Math.max(r, g);
+ colors[y * STRIDE + x] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ }
+ return colors;
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint;
+ private float mOriginX = 10;
+ private float mOriginY = 80;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setStrokeWidth(5);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setTextSize(64);
+ mPaint.setTypeface(Typeface.create(Typeface.SERIF,
+ Typeface.ITALIC));
+ }
+
+ private void showText(Canvas canvas, String text, Paint.Align align) {
+ // mPaint.setTextAlign(align);
+
+ Rect bounds = new Rect();
+ float[] widths = new float[text.length()];
+
+ int count = mPaint.getTextWidths(text, 0, text.length(), widths);
+ float w = mPaint.measureText(text, 0, text.length());
+ mPaint.getTextBounds(text, 0, text.length(), bounds);
+
+ mPaint.setColor(0xFF88FF88);
+ canvas.drawRect(bounds, mPaint);
+ mPaint.setColor(Color.BLACK);
+ canvas.drawText(text, 0, 0, mPaint);
+
+ float[] pts = new float[2 + count*2];
+ float x = 0;
+ float y = 0;
+ pts[0] = x;
+ pts[1] = y;
+ for (int i = 0; i < count; i++) {
+ x += widths[i];
+ pts[2 + i*2] = x;
+ pts[2 + i*2 + 1] = y;
+ }
+ mPaint.setColor(Color.RED);
+ mPaint.setStrokeWidth(0);
+ canvas.drawLine(0, 0, w, 0, mPaint);
+ mPaint.setStrokeWidth(5);
+ canvas.drawPoints(pts, 0, (count + 1) << 1, mPaint);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ canvas.translate(mOriginX, mOriginY);
+
+ showText(canvas, "Measure", Paint.Align.LEFT);
+ canvas.translate(0, 80);
+ showText(canvas, "wiggy!", Paint.Align.CENTER);
+ canvas.translate(0, 80);
+ showText(canvas, "Text", Paint.Align.RIGHT);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/PathEffects.java b/samples/ApiDemos/src/com/example/android/apis/graphics/PathEffects.java
new file mode 100644
index 0000000..80ddf38
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/PathEffects.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+
+public class PathEffects extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint;
+ private Path mPath;
+ private PathEffect[] mEffects;
+ private int[] mColors;
+ private float mPhase;
+
+ private static PathEffect makeDash(float phase) {
+ return new DashPathEffect(new float[] { 15, 5, 8, 5 }, phase);
+ }
+
+ private static void makeEffects(PathEffect[] e, float phase) {
+ e[0] = null; // no effect
+ e[1] = new CornerPathEffect(10);
+ e[2] = new DashPathEffect(new float[] {10, 5, 5, 5}, phase);
+ e[3] = new PathDashPathEffect(makePathDash(), 12, phase,
+ PathDashPathEffect.Style.ROTATE);
+ e[4] = new ComposePathEffect(e[2], e[1]);
+ e[5] = new ComposePathEffect(e[3], e[1]);
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeWidth(6);
+
+ mPath = makeFollowPath();
+
+ mEffects = new PathEffect[6];
+
+ mColors = new int[] { Color.BLACK, Color.RED, Color.BLUE,
+ Color.GREEN, Color.MAGENTA, Color.BLACK
+ };
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ RectF bounds = new RectF();
+ mPath.computeBounds(bounds, false);
+ canvas.translate(10 - bounds.left, 10 - bounds.top);
+
+ makeEffects(mEffects, mPhase);
+ mPhase += 1;
+ invalidate();
+
+ for (int i = 0; i < mEffects.length; i++) {
+ mPaint.setPathEffect(mEffects[i]);
+ mPaint.setColor(mColors[i]);
+ canvas.drawPath(mPath, mPaint);
+ canvas.translate(0, 28);
+ }
+ }
+
+ @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ mPath = makeFollowPath();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ private static Path makeFollowPath() {
+ Path p = new Path();
+ p.moveTo(0, 0);
+ for (int i = 1; i <= 15; i++) {
+ p.lineTo(i*20, (float)Math.random() * 35);
+ }
+ return p;
+ }
+
+ private static Path makePathDash() {
+ Path p = new Path();
+ p.moveTo(4, 0);
+ p.lineTo(0, -4);
+ p.lineTo(8, -4);
+ p.lineTo(12, 0);
+ p.lineTo(8, 4);
+ p.lineTo(0, 4);
+ return p;
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/PathFillTypes.java b/samples/ApiDemos/src/com/example/android/apis/graphics/PathFillTypes.java
new file mode 100644
index 0000000..78dba26
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/PathFillTypes.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+// 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.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+
+public class PathFillTypes extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private Path mPath;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ mPath = new Path();
+ mPath.addCircle(40, 40, 45, Path.Direction.CCW);
+ mPath.addCircle(80, 80, 45, Path.Direction.CCW);
+ }
+
+ private void showPath(Canvas canvas, int x, int y, Path.FillType ft,
+ Paint paint) {
+ canvas.save();
+ canvas.translate(x, y);
+ canvas.clipRect(0, 0, 120, 120);
+ canvas.drawColor(Color.WHITE);
+ mPath.setFillType(ft);
+ canvas.drawPath(mPath, paint);
+ canvas.restore();
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+
+ canvas.drawColor(0xFFCCCCCC);
+
+ canvas.translate(20, 20);
+
+ paint.setAntiAlias(true);
+
+ showPath(canvas, 0, 0, Path.FillType.WINDING, paint);
+ showPath(canvas, 160, 0, Path.FillType.EVEN_ODD, paint);
+ showPath(canvas, 0, 160, Path.FillType.INVERSE_WINDING, paint);
+ showPath(canvas, 160, 160, Path.FillType.INVERSE_EVEN_ODD, paint);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Patterns.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Patterns.java
new file mode 100644
index 0000000..d2a51ff
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Patterns.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.*;
+
+public class Patterns extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static Bitmap makeBitmap1() {
+ Bitmap bm = Bitmap.createBitmap(40, 40, Bitmap.Config.RGB_565);
+ Canvas c = new Canvas(bm);
+ c.drawColor(Color.RED);
+ Paint p = new Paint();
+ p.setColor(Color.BLUE);
+ c.drawRect(5, 5, 35, 35, p);
+ return bm;
+ }
+
+ private static Bitmap makeBitmap2() {
+ Bitmap bm = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bm);
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
+ p.setColor(Color.GREEN);
+ p.setAlpha(0xCC);
+ c.drawCircle(32, 32, 27, p);
+ return bm;
+ }
+
+ private static class SampleView extends View {
+ private final Shader mShader1;
+ private final Shader mShader2;
+ private final Paint mPaint;
+ private final DrawFilter mFastDF;
+
+ private float mTouchStartX;
+ private float mTouchStartY;
+ private float mTouchCurrX;
+ private float mTouchCurrY;
+ private DrawFilter mDF;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ mFastDF = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG |
+ Paint.DITHER_FLAG,
+ 0);
+
+ mShader1 = new BitmapShader(makeBitmap1(), Shader.TileMode.REPEAT,
+ Shader.TileMode.REPEAT);
+ mShader2 = new BitmapShader(makeBitmap2(), Shader.TileMode.REPEAT,
+ Shader.TileMode.REPEAT);
+
+ Matrix m = new Matrix();
+ m.setRotate(30);
+ mShader2.setLocalMatrix(m);
+
+ mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.setDrawFilter(mDF);
+
+ mPaint.setShader(mShader1);
+ canvas.drawPaint(mPaint);
+
+ canvas.translate(mTouchCurrX - mTouchStartX,
+ mTouchCurrY - mTouchStartY);
+
+ mPaint.setShader(mShader2);
+ canvas.drawPaint(mPaint);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ float x = event.getX();
+ float y = event.getY();
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mTouchStartX = mTouchCurrX = x;
+ mTouchStartY = mTouchCurrY = y;
+ mDF = mFastDF;
+ invalidate();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ mTouchCurrX = x;
+ mTouchCurrY = y;
+ invalidate();
+ break;
+ case MotionEvent.ACTION_UP:
+ mDF = null;
+ invalidate();
+ break;
+ }
+ return true;
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/PictureLayout.java b/samples/ApiDemos/src/com/example/android/apis/graphics/PictureLayout.java
new file mode 100644
index 0000000..9bdb49a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/PictureLayout.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Picture;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+
+public class PictureLayout extends ViewGroup {
+ private final Picture mPicture = new Picture();
+
+ public PictureLayout(Context context) {
+ super(context);
+ }
+
+ public PictureLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void addView(View child) {
+ if (getChildCount() > 1) {
+ throw new IllegalStateException("PictureLayout can host only one direct child");
+ }
+
+ super.addView(child);
+ }
+
+ @Override
+ public void addView(View child, int index) {
+ if (getChildCount() > 1) {
+ throw new IllegalStateException("PictureLayout can host only one direct child");
+ }
+
+ super.addView(child, index);
+ }
+
+ @Override
+ public void addView(View child, LayoutParams params) {
+ if (getChildCount() > 1) {
+ throw new IllegalStateException("PictureLayout can host only one direct child");
+ }
+
+ super.addView(child, params);
+ }
+
+ @Override
+ public void addView(View child, int index, LayoutParams params) {
+ if (getChildCount() > 1) {
+ throw new IllegalStateException("PictureLayout can host only one direct child");
+ }
+
+ super.addView(child, index, params);
+ }
+
+ @Override
+ protected LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int count = getChildCount();
+
+ int maxHeight = 0;
+ int maxWidth = 0;
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ measureChild(child, widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ maxWidth += getPaddingLeft() + getPaddingRight();
+ maxHeight += getPaddingTop() + getPaddingBottom();
+
+ Drawable drawable = getBackground();
+ if (drawable != null) {
+ maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
+ maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
+ }
+
+ setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
+ resolveSize(maxHeight, heightMeasureSpec));
+ }
+
+ private void drawPict(Canvas canvas, int x, int y, int w, int h,
+ float sx, float sy) {
+ canvas.save();
+ canvas.translate(x, y);
+ canvas.clipRect(0, 0, w, h);
+ canvas.scale(0.5f, 0.5f);
+ canvas.scale(sx, sy, w, h);
+ canvas.drawPicture(mPicture);
+ canvas.restore();
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
+ mPicture.endRecording();
+
+ int x = getWidth()/2;
+ int y = getHeight()/2;
+
+ if (false) {
+ canvas.drawPicture(mPicture);
+ } else {
+ drawPict(canvas, 0, 0, x, y, 1, 1);
+ drawPict(canvas, x, 0, x, y, -1, 1);
+ drawPict(canvas, 0, y, x, y, 1, -1);
+ drawPict(canvas, x, y, x, y, -1, -1);
+ }
+ }
+
+ @Override
+ public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
+ location[0] = getLeft();
+ location[1] = getTop();
+ dirty.set(0, 0, getWidth(), getHeight());
+ return getParent();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int count = super.getChildCount();
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ final int childLeft = getPaddingLeft();
+ final int childTop = getPaddingTop();
+ child.layout(childLeft, childTop,
+ childLeft + child.getMeasuredWidth(),
+ childTop + child.getMeasuredHeight());
+
+ }
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Pictures.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Pictures.java
new file mode 100644
index 0000000..1bd0a8c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Pictures.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.PictureDrawable;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+
+import java.io.*;
+
+public class Pictures extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Picture mPicture;
+ private Drawable mDrawable;
+
+ static void drawSomething(Canvas canvas) {
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ p.setColor(0x88FF0000);
+ canvas.drawCircle(50, 50, 40, p);
+
+ p.setColor(Color.GREEN);
+ p.setTextSize(30);
+ canvas.drawText("Pictures", 60, 60, p);
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ mPicture = new Picture();
+ drawSomething(mPicture.beginRecording(200, 100));
+ mPicture.endRecording();
+
+ mDrawable = new PictureDrawable(mPicture);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ canvas.drawPicture(mPicture);
+
+ canvas.drawPicture(mPicture, new RectF(0, 100, getWidth(), 200));
+
+ mDrawable.setBounds(0, 200, getWidth(), 300);
+ mDrawable.draw(canvas);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ mPicture.writeToStream(os);
+ InputStream is = new ByteArrayInputStream(os.toByteArray());
+ canvas.translate(0, 300);
+ canvas.drawPicture(Picture.createFromStream(is));
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/PolyToPoly.java b/samples/ApiDemos/src/com/example/android/apis/graphics/PolyToPoly.java
new file mode 100644
index 0000000..15d92de
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/PolyToPoly.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+// 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.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+
+public class PolyToPoly extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private Matrix mMatrix = new Matrix();
+ private Paint.FontMetrics mFontMetrics;
+
+ private void doDraw(Canvas canvas, float src[], float dst[]) {
+ canvas.save();
+ mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);
+ canvas.concat(mMatrix);
+
+ mPaint.setColor(Color.GRAY);
+ mPaint.setStyle(Paint.Style.STROKE);
+ canvas.drawRect(0, 0, 64, 64, mPaint);
+ canvas.drawLine(0, 0, 64, 64, mPaint);
+ canvas.drawLine(0, 64, 64, 0, mPaint);
+
+ mPaint.setColor(Color.RED);
+ mPaint.setStyle(Paint.Style.FILL);
+ // how to draw the text center on our square
+ // centering in X is easy... use alignment (and X at midpoint)
+ float x = 64/2;
+ // centering in Y, we need to measure ascent/descent first
+ float y = 64/2 - (mFontMetrics.ascent + mFontMetrics.descent)/2;
+ canvas.drawText(src.length/2 + "", x, y, mPaint);
+
+ canvas.restore();
+ }
+
+ public SampleView(Context context) {
+ super(context);
+
+ // for when the style is STROKE
+ mPaint.setStrokeWidth(4);
+ // for when we draw text
+ mPaint.setTextSize(40);
+ mPaint.setTextAlign(Paint.Align.CENTER);
+ mFontMetrics = mPaint.getFontMetrics();
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+
+ canvas.drawColor(Color.WHITE);
+
+ canvas.save();
+ canvas.translate(10, 10);
+ // translate (1 point)
+ doDraw(canvas, new float[] { 0, 0 }, new float[] { 5, 5 });
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(160, 10);
+ // rotate/uniform-scale (2 points)
+ doDraw(canvas, new float[] { 32, 32, 64, 32 },
+ new float[] { 32, 32, 64, 48 });
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(10, 110);
+ // rotate/skew (3 points)
+ doDraw(canvas, new float[] { 0, 0, 64, 0, 0, 64 },
+ new float[] { 0, 0, 96, 0, 24, 64 });
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(160, 110);
+ // perspective (4 points)
+ doDraw(canvas, new float[] { 0, 0, 64, 0, 64, 64, 0, 64 },
+ new float[] { 0, 0, 96, 0, 64, 96, 0, 64 });
+ canvas.restore();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/ProxyDrawable.java b/samples/ApiDemos/src/com/example/android/apis/graphics/ProxyDrawable.java
new file mode 100644
index 0000000..d264134
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/ProxyDrawable.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+
+public class ProxyDrawable extends Drawable {
+
+ private Drawable mProxy;
+ private boolean mMutated;
+
+ public ProxyDrawable(Drawable target) {
+ mProxy = target;
+ }
+
+ public Drawable getProxy() {
+ return mProxy;
+ }
+
+ public void setProxy(Drawable proxy) {
+ if (proxy != this) {
+ mProxy = proxy;
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mProxy != null) {
+ mProxy.draw(canvas);
+ }
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mProxy != null ? mProxy.getIntrinsicWidth() : -1;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mProxy != null ? mProxy.getIntrinsicHeight() : -1;
+ }
+
+ @Override
+ public int getOpacity() {
+ return mProxy != null ? mProxy.getOpacity() : PixelFormat.TRANSPARENT;
+ }
+
+ @Override
+ public void setFilterBitmap(boolean filter) {
+ if (mProxy != null) {
+ mProxy.setFilterBitmap(filter);
+ }
+ }
+
+ @Override
+ public void setDither(boolean dither) {
+ if (mProxy != null) {
+ mProxy.setDither(dither);
+ }
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ if (mProxy != null) {
+ mProxy.setColorFilter(colorFilter);
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ if (mProxy != null) {
+ mProxy.setAlpha(alpha);
+ }
+ }
+
+ @Override
+ public Drawable mutate() {
+ if (mProxy != null && !mMutated && super.mutate() == this) {
+ mProxy.mutate();
+ mMutated = true;
+ }
+ return this;
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Regions.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Regions.java
new file mode 100644
index 0000000..833274b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Regions.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+
+public class Regions extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private final Paint mPaint = new Paint();
+ private final Rect mRect1 = new Rect();
+ private final Rect mRect2 = new Rect();
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mPaint.setAntiAlias(true);
+ mPaint.setTextSize(16);
+ mPaint.setTextAlign(Paint.Align.CENTER);
+
+ mRect1.set(10, 10, 100, 80);
+ mRect2.set(50, 50, 130, 110);
+ }
+
+ private void drawOriginalRects(Canvas canvas, int alpha) {
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(Color.RED);
+ mPaint.setAlpha(alpha);
+ drawCentered(canvas, mRect1, mPaint);
+ mPaint.setColor(Color.BLUE);
+ mPaint.setAlpha(alpha);
+ drawCentered(canvas, mRect2, mPaint);
+
+ // restore style
+ mPaint.setStyle(Paint.Style.FILL);
+ }
+
+ private void drawRgn(Canvas canvas, int color, String str, Region.Op op) {
+ if (str != null) {
+ mPaint.setColor(Color.BLACK);
+ canvas.drawText(str, 80, 24, mPaint);
+ }
+
+ Region rgn = new Region();
+ rgn.set(mRect1);
+ rgn.op(mRect2, op);
+
+ mPaint.setColor(color);
+ RegionIterator iter = new RegionIterator(rgn);
+ Rect r = new Rect();
+
+ canvas.translate(0, 30);
+ mPaint.setColor(color);
+ while (iter.next(r)) {
+ canvas.drawRect(r, mPaint);
+ }
+ drawOriginalRects(canvas, 0x80);
+ }
+
+ private static void drawCentered(Canvas c, Rect r, Paint p) {
+ float inset = p.getStrokeWidth() * 0.5f;
+ if (inset == 0) { // catch hairlines
+ inset = 0.5f;
+ }
+ c.drawRect(r.left + inset, r.top + inset,
+ r.right - inset, r.bottom - inset, p);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.GRAY);
+
+ canvas.save();
+ canvas.translate(80, 5);
+ drawOriginalRects(canvas, 0xFF);
+ canvas.restore();
+
+ mPaint.setStyle(Paint.Style.FILL);
+
+ canvas.save();
+ canvas.translate(0, 140);
+ drawRgn(canvas, Color.RED, "Union", Region.Op.UNION);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(0, 280);
+ drawRgn(canvas, Color.BLUE, "Xor", Region.Op.XOR);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(160, 140);
+ drawRgn(canvas, Color.GREEN, "Difference", Region.Op.DIFFERENCE);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(160, 280);
+ drawRgn(canvas, Color.WHITE, "Intersect", Region.Op.INTERSECT);
+ canvas.restore();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/RoundRects.java b/samples/ApiDemos/src/com/example/android/apis/graphics/RoundRects.java
new file mode 100644
index 0000000..b0ff035
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/RoundRects.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+public class RoundRects extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Path mPath;
+ private Paint mPaint;
+ private Rect mRect;
+ private GradientDrawable mDrawable;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mPath = new Path();
+ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mRect = new Rect(0, 0, 120, 120);
+
+ mDrawable = new GradientDrawable(GradientDrawable.Orientation.TL_BR,
+ new int[] { 0xFFFF0000, 0xFF00FF00,
+ 0xFF0000FF });
+ mDrawable.setShape(GradientDrawable.RECTANGLE);
+ mDrawable.setGradientRadius((float)(Math.sqrt(2) * 60));
+ }
+
+ static void setCornerRadii(GradientDrawable drawable, float r0,
+ float r1, float r2, float r3) {
+ drawable.setCornerRadii(new float[] { r0, r0, r1, r1,
+ r2, r2, r3, r3 });
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+
+ mDrawable.setBounds(mRect);
+
+ float r = 16;
+
+ canvas.save();
+ canvas.translate(10, 10);
+ mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
+ setCornerRadii(mDrawable, r, r, 0, 0);
+ mDrawable.draw(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(10 + mRect.width() + 10, 10);
+ mDrawable.setGradientType(GradientDrawable.RADIAL_GRADIENT);
+ setCornerRadii(mDrawable, 0, 0, r, r);
+ mDrawable.draw(canvas);
+ canvas.restore();
+
+ canvas.translate(0, mRect.height() + 10);
+
+ canvas.save();
+ canvas.translate(10, 10);
+ mDrawable.setGradientType(GradientDrawable.SWEEP_GRADIENT);
+ setCornerRadii(mDrawable, 0, r, r, 0);
+ mDrawable.draw(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(10 + mRect.width() + 10, 10);
+ mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
+ setCornerRadii(mDrawable, r, 0, 0, r);
+ mDrawable.draw(canvas);
+ canvas.restore();
+
+ canvas.translate(0, mRect.height() + 10);
+
+ canvas.save();
+ canvas.translate(10, 10);
+ mDrawable.setGradientType(GradientDrawable.RADIAL_GRADIENT);
+ setCornerRadii(mDrawable, r, 0, r, 0);
+ mDrawable.draw(canvas);
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(10 + mRect.width() + 10, 10);
+ mDrawable.setGradientType(GradientDrawable.SWEEP_GRADIENT);
+ setCornerRadii(mDrawable, 0, r, 0, r);
+ mDrawable.draw(canvas);
+ canvas.restore();
+
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/ScaleToFit.java b/samples/ApiDemos/src/com/example/android/apis/graphics/ScaleToFit.java
new file mode 100644
index 0000000..f55e55b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/ScaleToFit.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+
+public class ScaleToFit extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Paint mHairPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Paint mLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Matrix mMatrix = new Matrix();
+ private final RectF mSrcR = new RectF();
+
+ private static final Matrix.ScaleToFit[] sFits =
+ new Matrix.ScaleToFit[] {
+ Matrix.ScaleToFit.FILL,
+ Matrix.ScaleToFit.START,
+ Matrix.ScaleToFit.CENTER,
+ Matrix.ScaleToFit.END
+ };
+
+ private static final String[] sFitLabels = new String[] {
+ "FILL", "START", "CENTER", "END"
+ };
+
+ private static final int[] sSrcData = new int[] {
+ 80, 40, Color.RED,
+ 40, 80, Color.GREEN,
+ 30, 30, Color.BLUE,
+ 80, 80, Color.BLACK
+ };
+ private static final int N = 4;
+
+ private static final int WIDTH = 52;
+ private static final int HEIGHT = 52;
+ private final RectF mDstR = new RectF(0, 0, WIDTH, HEIGHT);
+
+ public SampleView(Context context) {
+ super(context);
+
+ mHairPaint.setStyle(Paint.Style.STROKE);
+ mLabelPaint.setTextSize(16);
+ }
+
+ private void setSrcR(int index) {
+ int w = sSrcData[index*3 + 0];
+ int h = sSrcData[index*3 + 1];
+ mSrcR.set(0, 0, w, h);
+ }
+
+ private void drawSrcR(Canvas canvas, int index) {
+ mPaint.setColor(sSrcData[index*3 + 2]);
+ canvas.drawOval(mSrcR, mPaint);
+ }
+
+ private void drawFit(Canvas canvas, int index, Matrix.ScaleToFit stf) {
+ canvas.save();
+
+ setSrcR(index);
+ mMatrix.setRectToRect(mSrcR, mDstR, stf);
+ canvas.concat(mMatrix);
+ drawSrcR(canvas, index);
+
+ canvas.restore();
+
+ canvas.drawRect(mDstR, mHairPaint);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+
+ canvas.drawColor(Color.WHITE);
+
+ canvas.translate(10, 10);
+
+ canvas.save();
+ for (int i = 0; i < N; i++) {
+ setSrcR(i);
+ drawSrcR(canvas, i);
+ canvas.translate(mSrcR.width() + 15, 0);
+ }
+ canvas.restore();
+
+ canvas.translate(0, 100);
+ for (int j = 0; j < sFits.length; j++) {
+ canvas.save();
+ for (int i = 0; i < N; i++) {
+ drawFit(canvas, i, sFits[j]);
+ canvas.translate(mDstR.width() + 8, 0);
+ }
+ canvas.drawText(sFitLabels[j], 0, HEIGHT*2/3, mLabelPaint);
+ canvas.restore();
+ canvas.translate(0, 80);
+ }
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/SensorTest.java b/samples/ApiDemos/src/com/example/android/apis/graphics/SensorTest.java
new file mode 100644
index 0000000..ed5b5ae
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/SensorTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.hardware.SensorListener;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Config;
+import android.util.Log;
+import android.view.View;
+
+public class SensorTest extends GraphicsActivity {
+
+ private SensorManager mSensorManager;
+ private SampleView mView;
+ private float[] mValues;
+
+ private static class RunAve {
+ private final float[] mWeights;
+ private final float mWeightScale;
+ private final float[] mSamples;
+ private final int mDepth;
+ private int mCurr;
+
+ public RunAve(float[] weights) {
+ mWeights = weights;
+
+ float sum = 0;
+ for (int i = 0; i < weights.length; i++) {
+ sum += weights[i];
+ }
+ mWeightScale = 1 / sum;
+
+ mDepth = weights.length;
+ mSamples = new float[mDepth];
+ mCurr = 0;
+ }
+
+ public void addSample(float value) {
+ mSamples[mCurr] = value;
+ mCurr = (mCurr + 1) % mDepth;
+ }
+
+ public float computeAve() {
+ final int depth = mDepth;
+ int index = mCurr;
+ float sum = 0;
+ for (int i = 0; i < depth; i++) {
+ sum += mWeights[i] * mSamples[index];
+ index -= 1;
+ if (index < 0) {
+ index = depth - 1;
+ }
+ }
+ return sum * mWeightScale;
+ }
+ };
+
+ private final SensorListener mListener = new SensorListener() {
+
+ private final float[] mScale = new float[] { 2, 2.5f, 0.5f }; // accel
+
+ private float[] mPrev = new float[3];
+
+ public void onSensorChanged(int sensor, float[] values) {
+ boolean show = false;
+ float[] diff = new float[3];
+
+ for (int i = 0; i < 3; i++) {
+ diff[i] = Math.round(mScale[i] * (values[i] - mPrev[i]) * 0.45f);
+ if (Math.abs(diff[i]) > 0) {
+ show = true;
+ }
+ mPrev[i] = values[i];
+ }
+
+ if (show) {
+ // only shows if we think the delta is big enough, in an attempt
+ // to detect "serious" moves left/right or up/down
+ android.util.Log.e("test", "sensorChanged " + sensor + " (" + values[0] + ", " + values[1] + ", " + values[2] + ")"
+ + " diff(" + diff[0] + " " + diff[1] + " " + diff[2] + ")");
+ }
+
+ long now = android.os.SystemClock.uptimeMillis();
+ if (now - mLastGestureTime > 1000) {
+ mLastGestureTime = 0;
+
+ float x = diff[0];
+ float y = diff[1];
+ boolean gestX = Math.abs(x) > 3;
+ boolean gestY = Math.abs(y) > 3;
+
+ if ((gestX || gestY) && !(gestX && gestY)) {
+ if (gestX) {
+ if (x < 0) {
+ android.util.Log.e("test", "<<<<<<<< LEFT <<<<<<<<<<<<");
+ } else {
+ android.util.Log.e("test", ">>>>>>>>> RITE >>>>>>>>>>>");
+ }
+ } else {
+ if (y < -2) {
+ android.util.Log.e("test", "<<<<<<<< UP <<<<<<<<<<<<");
+ } else {
+ android.util.Log.e("test", ">>>>>>>>> DOWN >>>>>>>>>>>");
+ }
+ }
+ mLastGestureTime = now;
+ }
+ }
+ }
+
+ private long mLastGestureTime;
+
+ public void onAccuracyChanged(int sensor, int accuracy) {
+ // TODO Auto-generated method stub
+
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ mView = new SampleView(this);
+ setContentView(mView);
+// android.util.Log.d("skia", "create " + mSensorManager);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ int mask = 0;
+// mask |= SensorManager.SENSOR_ORIENTATION;
+ mask |= SensorManager.SENSOR_ACCELEROMETER;
+
+ mSensorManager.registerListener(mListener, mask, SensorManager.SENSOR_DELAY_FASTEST);
+// android.util.Log.d("skia", "resume " + mSensorManager);
+ }
+
+ @Override
+ protected void onStop() {
+ mSensorManager.unregisterListener(mListener);
+ super.onStop();
+// android.util.Log.d("skia", "stop " + mSensorManager);
+ }
+
+ private class SampleView extends View {
+ private Paint mPaint = new Paint();
+ private Path mPath = new Path();
+ private boolean mAnimate;
+ private long mNextTime;
+
+ public SampleView(Context context) {
+ super(context);
+
+ // Construct a wedge-shaped path
+ mPath.moveTo(0, -50);
+ mPath.lineTo(-20, 60);
+ mPath.lineTo(0, 50);
+ mPath.lineTo(20, 60);
+ mPath.close();
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+
+ canvas.drawColor(Color.WHITE);
+
+ paint.setAntiAlias(true);
+ paint.setColor(Color.BLACK);
+ paint.setStyle(Paint.Style.FILL);
+
+ int w = canvas.getWidth();
+ int h = canvas.getHeight();
+ int cx = w / 2;
+ int cy = h / 2;
+
+ canvas.translate(cx, cy);
+ if (mValues != null) {
+ canvas.rotate(-mValues[0]);
+ }
+ canvas.drawPath(mPath, mPaint);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ mAnimate = true;
+ super.onAttachedToWindow();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mAnimate = false;
+ super.onDetachedFromWindow();
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/ShapeDrawable1.java b/samples/ApiDemos/src/com/example/android/apis/graphics/ShapeDrawable1.java
new file mode 100644
index 0000000..6d450bb
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/ShapeDrawable1.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+public class ShapeDrawable1 extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private ShapeDrawable[] mDrawables;
+
+ private static Shader makeSweep() {
+ return new SweepGradient(150, 25,
+ new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFF0000 },
+ null);
+ }
+
+ private static Shader makeLinear() {
+ return new LinearGradient(0, 0, 50, 50,
+ new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF },
+ null, Shader.TileMode.MIRROR);
+ }
+
+ private static Shader makeTiling() {
+ int[] pixels = new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0};
+ Bitmap bm = Bitmap.createBitmap(pixels, 2, 2,
+ Bitmap.Config.ARGB_8888);
+
+ return new BitmapShader(bm, Shader.TileMode.REPEAT,
+ Shader.TileMode.REPEAT);
+ }
+
+ private static class MyShapeDrawable extends ShapeDrawable {
+ private Paint mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ public MyShapeDrawable(Shape s) {
+ super(s);
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ }
+
+ public Paint getStrokePaint() {
+ return mStrokePaint;
+ }
+
+ @Override protected void onDraw(Shape s, Canvas c, Paint p) {
+ s.draw(c, p);
+ s.draw(c, mStrokePaint);
+ }
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ float[] outerR = new float[] { 12, 12, 12, 12, 0, 0, 0, 0 };
+ RectF inset = new RectF(6, 6, 6, 6);
+ float[] innerR = new float[] { 12, 12, 0, 0, 12, 12, 0, 0 };
+
+ Path path = new Path();
+ path.moveTo(50, 0);
+ path.lineTo(0, 50);
+ path.lineTo(50, 100);
+ path.lineTo(100, 50);
+ path.close();
+
+ mDrawables = new ShapeDrawable[7];
+ mDrawables[0] = new ShapeDrawable(new RectShape());
+ mDrawables[1] = new ShapeDrawable(new OvalShape());
+ mDrawables[2] = new ShapeDrawable(new RoundRectShape(outerR, null,
+ null));
+ mDrawables[3] = new ShapeDrawable(new RoundRectShape(outerR, inset,
+ null));
+ mDrawables[4] = new ShapeDrawable(new RoundRectShape(outerR, inset,
+ innerR));
+ mDrawables[5] = new ShapeDrawable(new PathShape(path, 100, 100));
+ mDrawables[6] = new MyShapeDrawable(new ArcShape(45, -270));
+
+ mDrawables[0].getPaint().setColor(0xFFFF0000);
+ mDrawables[1].getPaint().setColor(0xFF00FF00);
+ mDrawables[2].getPaint().setColor(0xFF0000FF);
+ mDrawables[3].getPaint().setShader(makeSweep());
+ mDrawables[4].getPaint().setShader(makeLinear());
+ mDrawables[5].getPaint().setShader(makeTiling());
+ mDrawables[6].getPaint().setColor(0x88FF8844);
+
+ PathEffect pe = new DiscretePathEffect(10, 4);
+ PathEffect pe2 = new CornerPathEffect(4);
+ mDrawables[3].getPaint().setPathEffect(
+ new ComposePathEffect(pe2, pe));
+
+ MyShapeDrawable msd = (MyShapeDrawable)mDrawables[6];
+ msd.getStrokePaint().setStrokeWidth(4);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+
+ int x = 10;
+ int y = 10;
+ int width = 300;
+ int height = 50;
+
+ for (Drawable dr : mDrawables) {
+ dr.setBounds(x, y, x + width, y + height);
+ dr.draw(canvas);
+ y += height + 5;
+ }
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java b/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
new file mode 100644
index 0000000..45e5d60
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+//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;
+
+/**
+ * Demonstration of overlays placed on top of a SurfaceView.
+ */
+public class SurfaceViewOverlay extends Activity {
+ View mVictimContainer;
+ View mVictim1;
+ View mVictim2;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.surface_view_overlay);
+
+ GLSurfaceView glSurfaceView =
+ (GLSurfaceView) findViewById(R.id.glsurfaceview);
+ glSurfaceView.setRenderer(new CubeRenderer(false));
+
+ // Find the views whose visibility will change
+ mVictimContainer = findViewById(R.id.hidecontainer);
+ mVictim1 = findViewById(R.id.hideme1);
+ mVictim1.setOnClickListener(new HideMeListener(mVictim1));
+ mVictim2 = findViewById(R.id.hideme2);
+ mVictim2.setOnClickListener(new HideMeListener(mVictim2));
+
+ // Find our buttons
+ Button visibleButton = (Button) findViewById(R.id.vis);
+ Button invisibleButton = (Button) findViewById(R.id.invis);
+ Button goneButton = (Button) findViewById(R.id.gone);
+
+ // Wire each button to a click listener
+ visibleButton.setOnClickListener(mVisibleListener);
+ invisibleButton.setOnClickListener(mInvisibleListener);
+ goneButton.setOnClickListener(mGoneListener);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ }
+
+ class HideMeListener implements OnClickListener {
+ final View mTarget;
+
+ HideMeListener(View target) {
+ mTarget = target;
+ }
+
+ public void onClick(View v) {
+ mTarget.setVisibility(View.INVISIBLE);
+ }
+
+ }
+
+ OnClickListener mVisibleListener = new OnClickListener() {
+ public void onClick(View v) {
+ mVictim1.setVisibility(View.VISIBLE);
+ mVictim2.setVisibility(View.VISIBLE);
+ mVictimContainer.setVisibility(View.VISIBLE);
+ }
+ };
+
+ OnClickListener mInvisibleListener = new OnClickListener() {
+ public void onClick(View v) {
+ mVictim1.setVisibility(View.INVISIBLE);
+ mVictim2.setVisibility(View.INVISIBLE);
+ mVictimContainer.setVisibility(View.INVISIBLE);
+ }
+ };
+
+ OnClickListener mGoneListener = new OnClickListener() {
+ public void onClick(View v) {
+ mVictim1.setVisibility(View.GONE);
+ mVictim2.setVisibility(View.GONE);
+ mVictimContainer.setVisibility(View.GONE);
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Sweep.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Sweep.java
new file mode 100644
index 0000000..dc127fd
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Sweep.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+// 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.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+
+public class Sweep extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private float mRotate;
+ private Matrix mMatrix = new Matrix();
+ private Shader mShader;
+ private boolean mDoTiming;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ float x = 160;
+ float y = 100;
+ mShader = new SweepGradient(x, y, new int[] { Color.GREEN,
+ Color.RED,
+ Color.BLUE,
+ Color.GREEN }, null);
+ mPaint.setShader(mShader);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ Paint paint = mPaint;
+ float x = 160;
+ float y = 100;
+
+ canvas.drawColor(Color.WHITE);
+
+ mMatrix.setRotate(mRotate, x, y);
+ mShader.setLocalMatrix(mMatrix);
+ mRotate += 3;
+ if (mRotate >= 360) {
+ mRotate = 0;
+ }
+ invalidate();
+
+ if (mDoTiming) {
+ long now = System.currentTimeMillis();
+ for (int i = 0; i < 20; i++) {
+ canvas.drawCircle(x, y, 80, paint);
+ }
+ now = System.currentTimeMillis() - now;
+ android.util.Log.d("skia", "sweep ms = " + (now/20.));
+ }
+ else {
+ canvas.drawCircle(x, y, 80, paint);
+ }
+ }
+
+ @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_D:
+ mPaint.setDither(!mPaint.isDither());
+ invalidate();
+ return true;
+ case KeyEvent.KEYCODE_T:
+ mDoTiming = !mDoTiming;
+ invalidate();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TextAlign.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TextAlign.java
new file mode 100644
index 0000000..0576a7c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TextAlign.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+public class TextAlign extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint;
+ private float mX;
+ private float[] mPos;
+
+ private Path mPath;
+ private Paint mPathPaint;
+
+ private static final int DY = 30;
+ private static final String TEXT_L = "Left";
+ private static final String TEXT_C = "Center";
+ private static final String TEXT_R = "Right";
+ private static final String POSTEXT = "Positioned";
+ private static final String TEXTONPATH = "Along a path";
+
+ private static void makePath(Path p) {
+ p.moveTo(10, 0);
+ p.cubicTo(100, -50, 200, 50, 300, 0);
+ }
+
+ private float[] buildTextPositions(String text, float y, Paint paint) {
+ float[] widths = new float[text.length()];
+ // initially get the widths for each char
+ int n = paint.getTextWidths(text, widths);
+ // now popuplate the array, interleaving spaces for the Y values
+ float[] pos = new float[n * 2];
+ float accumulatedX = 0;
+ for (int i = 0; i < n; i++) {
+ pos[i*2 + 0] = accumulatedX;
+ pos[i*2 + 1] = y;
+ accumulatedX += widths[i];
+ }
+ return pos;
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setTextSize(30);
+ mPaint.setTypeface(Typeface.SERIF);
+
+ mPos = buildTextPositions(POSTEXT, 0, mPaint);
+
+ mPath = new Path();
+ makePath(mPath);
+
+ mPathPaint = new Paint();
+ mPathPaint.setAntiAlias(true);
+ mPathPaint.setColor(0x800000FF);
+ mPathPaint.setStyle(Paint.Style.STROKE);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ Paint p = mPaint;
+ float x = mX;
+ float y = 0;
+ float[] pos = mPos;
+
+ // draw the normal strings
+
+ p.setColor(0x80FF0000);
+ canvas.drawLine(x, y, x, y+DY*3, p);
+ p.setColor(Color.BLACK);
+
+ canvas.translate(0, DY);
+ p.setTextAlign(Paint.Align.LEFT);
+ canvas.drawText(TEXT_L, x, y, p);
+
+ canvas.translate(0, DY);
+ p.setTextAlign(Paint.Align.CENTER);
+ canvas.drawText(TEXT_C, x, y, p);
+
+ canvas.translate(0, DY);
+ p.setTextAlign(Paint.Align.RIGHT);
+ canvas.drawText(TEXT_R, x, y, p);
+
+ canvas.translate(100, DY*2);
+
+ // now draw the positioned strings
+
+ p.setColor(0xBB00FF00);
+ for (int i = 0; i < pos.length/2; i++) {
+ canvas.drawLine(pos[i*2+0], pos[i*2+1]-DY,
+ pos[i*2+0], pos[i*2+1]+DY*2, p);
+ }
+ p.setColor(Color.BLACK);
+
+ p.setTextAlign(Paint.Align.LEFT);
+ canvas.drawPosText(POSTEXT, pos, p);
+
+ canvas.translate(0, DY);
+ p.setTextAlign(Paint.Align.CENTER);
+ canvas.drawPosText(POSTEXT, pos, p);
+
+ canvas.translate(0, DY);
+ p.setTextAlign(Paint.Align.RIGHT);
+ canvas.drawPosText(POSTEXT, pos, p);
+
+ // now draw the text on path
+
+ canvas.translate(-100, DY*2);
+
+ canvas.drawPath(mPath, mPathPaint);
+ p.setTextAlign(Paint.Align.LEFT);
+ canvas.drawTextOnPath(TEXTONPATH, mPath, 0, 0, p);
+
+ canvas.translate(0, DY*1.5f);
+ canvas.drawPath(mPath, mPathPaint);
+ p.setTextAlign(Paint.Align.CENTER);
+ canvas.drawTextOnPath(TEXTONPATH, mPath, 0, 0, p);
+
+ canvas.translate(0, DY*1.5f);
+ canvas.drawPath(mPath, mPathPaint);
+ p.setTextAlign(Paint.Align.RIGHT);
+ canvas.drawTextOnPath(TEXTONPATH, mPath, 0, 0, p);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int ow, int oh) {
+ super.onSizeChanged(w, h, ow, oh);
+ mX = w * 0.5f; // remember the center of the screen
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.java
new file mode 100644
index 0000000..0942852
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+
+//Need the following import to get access to the app resources, since this
+//class is in a sub-package.
+
+
+/**
+ * Demonstrates the handling of touch screen and trackball events to
+ * implement a simple painting app.
+ */
+public class TouchPaint extends GraphicsActivity {
+ /** Used as a pulse to gradually fade the contents of the window. */
+ private static final int FADE_MSG = 1;
+
+ /** Menu ID for the command to clear the window. */
+ private static final int CLEAR_ID = Menu.FIRST;
+ /** Menu ID for the command to toggle fading. */
+ private static final int FADE_ID = Menu.FIRST+1;
+
+ /** How often to fade the contents of the window (in ms). */
+ private static final int FADE_DELAY = 100;
+
+ /** The view responsible for drawing the window. */
+ MyView mView;
+ /** Is fading mode enabled? */
+ boolean mFading;
+
+ @Override protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create and attach the view that is responsible for painting.
+ mView = new MyView(this);
+ setContentView(mView);
+ mView.requestFocus();
+
+ // Restore the fading option if we are being thawed from a
+ // previously saved state. Note that we are not currently remembering
+ // the contents of the bitmap.
+ mFading = savedInstanceState != null ? savedInstanceState.getBoolean("fading", true) : true;
+ }
+
+ @Override public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(0, CLEAR_ID, 0, "Clear");
+ menu.add(0, FADE_ID, 0, "Fade").setCheckable(true);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override public boolean onPrepareOptionsMenu(Menu menu) {
+ menu.findItem(FADE_ID).setChecked(mFading);
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case CLEAR_ID:
+ mView.clear();
+ return true;
+ case FADE_ID:
+ mFading = !mFading;
+ if (mFading) {
+ startFading();
+ } else {
+ stopFading();
+ }
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override protected void onResume() {
+ super.onResume();
+ // If fading mode is enabled, then as long as we are resumed we want
+ // to run pulse to fade the contents.
+ if (mFading) {
+ startFading();
+ }
+ }
+
+ @Override protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ // Save away the fading state to restore if needed later. Note that
+ // we do not currently save the contents of the display.
+ outState.putBoolean("fading", mFading);
+ }
+
+ @Override protected void onPause() {
+ super.onPause();
+ // Make sure to never run the fading pulse while we are paused or
+ // stopped.
+ stopFading();
+ }
+
+ /**
+ * Start up the pulse to fade the screen, clearing any existing pulse to
+ * ensure that we don't have multiple pulses running at a time.
+ */
+ void startFading() {
+ mHandler.removeMessages(FADE_MSG);
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(FADE_MSG), FADE_DELAY);
+ }
+
+ /**
+ * Stop the pulse to fade the screen.
+ */
+ void stopFading() {
+ mHandler.removeMessages(FADE_MSG);
+ }
+
+ private Handler mHandler = new Handler() {
+ @Override public void handleMessage(Message msg) {
+ switch (msg.what) {
+ // Upon receiving the fade pulse, we have the view perform a
+ // fade and then enqueue a new message to pulse at the desired
+ // next time.
+ case FADE_MSG: {
+ mView.fade();
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(FADE_MSG), FADE_DELAY);
+ break;
+ }
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ };
+
+ public class MyView extends View {
+ private static final int FADE_ALPHA = 0x06;
+ private static final int MAX_FADE_STEPS = 256/FADE_ALPHA + 4;
+ private Bitmap mBitmap;
+ private Canvas mCanvas;
+ private final Rect mRect = new Rect();
+ private final Paint mPaint;
+ private final Paint mFadePaint;
+ private boolean mCurDown;
+ private int mCurX;
+ private int mCurY;
+ private float mCurPressure;
+ private float mCurSize;
+ private int mCurWidth;
+ private int mFadeSteps = MAX_FADE_STEPS;
+
+ public MyView(Context c) {
+ super(c);
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setARGB(255, 255, 255, 255);
+ mFadePaint = new Paint();
+ mFadePaint.setDither(true);
+ mFadePaint.setARGB(FADE_ALPHA, 0, 0, 0);
+ }
+
+ public void clear() {
+ if (mCanvas != null) {
+ mPaint.setARGB(0xff, 0, 0, 0);
+ mCanvas.drawPaint(mPaint);
+ invalidate();
+ mFadeSteps = MAX_FADE_STEPS;
+ }
+ }
+
+ public void fade() {
+ if (mCanvas != null && mFadeSteps < MAX_FADE_STEPS) {
+ mCanvas.drawPaint(mFadePaint);
+ invalidate();
+ mFadeSteps++;
+ }
+ }
+
+ @Override protected void onSizeChanged(int w, int h, int oldw,
+ int oldh) {
+ int curW = mBitmap != null ? mBitmap.getWidth() : 0;
+ int curH = mBitmap != null ? mBitmap.getHeight() : 0;
+ if (curW >= w && curH >= h) {
+ return;
+ }
+
+ if (curW < w) curW = w;
+ if (curH < h) curH = h;
+
+ Bitmap newBitmap = Bitmap.createBitmap(curW, curH,
+ Bitmap.Config.RGB_565);
+ Canvas newCanvas = new Canvas();
+ newCanvas.setBitmap(newBitmap);
+ if (mBitmap != null) {
+ newCanvas.drawBitmap(mBitmap, 0, 0, null);
+ }
+ mBitmap = newBitmap;
+ mCanvas = newCanvas;
+ mFadeSteps = MAX_FADE_STEPS;
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ if (mBitmap != null) {
+ canvas.drawBitmap(mBitmap, 0, 0, null);
+ }
+ }
+
+ @Override public boolean onTrackballEvent(MotionEvent event) {
+ boolean oldDown = mCurDown;
+ mCurDown = true;
+ int N = event.getHistorySize();
+ int baseX = mCurX;
+ int baseY = mCurY;
+ final float scaleX = event.getXPrecision();
+ final float scaleY = event.getYPrecision();
+ for (int i=0; i<N; i++) {
+ //Log.i("TouchPaint", "Intermediate trackball #" + i
+ // + ": x=" + event.getHistoricalX(i)
+ // + ", y=" + event.getHistoricalY(i));
+ drawPoint(baseX+event.getHistoricalX(i)*scaleX,
+ baseY+event.getHistoricalY(i)*scaleY,
+ event.getHistoricalPressure(i),
+ event.getHistoricalSize(i));
+ }
+ //Log.i("TouchPaint", "Trackball: x=" + event.getX()
+ // + ", y=" + event.getY());
+ drawPoint(baseX+event.getX()*scaleX, baseY+event.getY()*scaleY,
+ event.getPressure(), event.getSize());
+ mCurDown = oldDown;
+ return true;
+ }
+
+ @Override public boolean onTouchEvent(MotionEvent event) {
+ int action = event.getAction();
+ mCurDown = action == MotionEvent.ACTION_DOWN
+ || action == MotionEvent.ACTION_MOVE;
+ int N = event.getHistorySize();
+ for (int i=0; i<N; i++) {
+ //Log.i("TouchPaint", "Intermediate pointer #" + i);
+ drawPoint(event.getHistoricalX(i), event.getHistoricalY(i),
+ event.getHistoricalPressure(i),
+ event.getHistoricalSize(i));
+ }
+ drawPoint(event.getX(), event.getY(), event.getPressure(),
+ event.getSize());
+ return true;
+ }
+
+ private void drawPoint(float x, float y, float pressure, float size) {
+ //Log.i("TouchPaint", "Drawing: " + x + "x" + y + " p="
+ // + pressure + " s=" + size);
+ mCurX = (int)x;
+ mCurY = (int)y;
+ mCurPressure = pressure;
+ mCurSize = size;
+ mCurWidth = (int)(mCurSize*(getWidth()/3));
+ if (mCurWidth < 1) mCurWidth = 1;
+ if (mCurDown && mBitmap != null) {
+ int pressureLevel = (int)(mCurPressure*255);
+ mPaint.setARGB(pressureLevel, 255, 255, 255);
+ mCanvas.drawCircle(mCurX, mCurY, mCurWidth, mPaint);
+ mRect.set(mCurX-mCurWidth-2, mCurY-mCurWidth-2,
+ mCurX+mCurWidth+2, mCurY+mCurWidth+2);
+ invalidate(mRect);
+ }
+ mFadeSteps = 0;
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java
new file mode 100644
index 0000000..09d3694
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.MotionEvent;
+
+/**
+ * Wrapper activity demonstrating the use of {@link GLSurfaceView}, a view
+ * that uses OpenGL drawing into a dedicated surface.
+ *
+ * Shows:
+ * + How to redraw in response to user input.
+ */
+public class TouchRotateActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mGLSurfaceView = new TouchSurfaceView(this);
+ setContentView(mGLSurfaceView);
+ mGLSurfaceView.requestFocus();
+ mGLSurfaceView.setFocusableInTouchMode(true);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
+
+/**
+ * Implement a simple rotation control.
+ *
+ */
+class TouchSurfaceView extends GLSurfaceView {
+
+ public TouchSurfaceView(Context context) {
+ super(context);
+ mRenderer = new CubeRenderer();
+ setRenderer(mRenderer);
+ setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+ }
+
+ @Override public boolean onTrackballEvent(MotionEvent e) {
+ mRenderer.mAngleX += e.getX() * TRACKBALL_SCALE_FACTOR;
+ mRenderer.mAngleY += e.getY() * TRACKBALL_SCALE_FACTOR;
+ requestRender();
+ return true;
+ }
+
+ @Override public boolean onTouchEvent(MotionEvent e) {
+ float x = e.getX();
+ float y = e.getY();
+ switch (e.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ float dx = x - mPreviousX;
+ float dy = y - mPreviousY;
+ mRenderer.mAngleX += dx * TOUCH_SCALE_FACTOR;
+ mRenderer.mAngleY += dy * TOUCH_SCALE_FACTOR;
+ requestRender();
+ }
+ mPreviousX = x;
+ mPreviousY = y;
+ return true;
+ }
+
+ /**
+ * Render a cube.
+ */
+ private class CubeRenderer implements GLSurfaceView.Renderer {
+ public CubeRenderer() {
+ mCube = new Cube();
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -3.0f);
+ gl.glRotatef(mAngleX, 0, 1, 0);
+ gl.glRotatef(mAngleY, 1, 0, 0);
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+ mCube.draw(gl);
+ }
+
+ public int[] getConfigSpec() {
+ // We want a depth buffer, don't care about the
+ // details of the color buffer.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ gl.glViewport(0, 0, width, height);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) width / height;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+ GL10.GL_FASTEST);
+
+
+ gl.glClearColor(1,1,1,1);
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ }
+ private Cube mCube;
+ public float mAngleX;
+ public float mAngleY;
+ }
+
+ private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
+ private final float TRACKBALL_SCALE_FACTOR = 36.0f;
+ private CubeRenderer mRenderer;
+ private float mPreviousX;
+ private float mPreviousY;
+}
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
new file mode 100644
index 0000000..750a47b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.graphics.PixelFormat;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+
+/**
+ * Wrapper activity demonstrating the use of {@link GLSurfaceView} to
+ * display translucent 3D graphics.
+ */
+public class TranslucentGLSurfaceViewActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mGLSurfaceView = new GLSurfaceView(this);
+ // Tell the cube renderer that we want to render a translucent version
+ // of the cube:
+ mGLSurfaceView.setRenderer(new CubeRenderer(true));
+ // Use a surface format with an Alpha channel:
+ mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
+ setContentView(mGLSurfaceView);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
new file mode 100644
index 0000000..59f3c6c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+public class TriangleActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mGLView = new GLSurfaceView(this);
+ mGLView.setRenderer(new TriangleRenderer(this));
+ setContentView(mGLView);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGLView.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGLView.onResume();
+ }
+
+ private GLSurfaceView mGLView;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
new file mode 100644
index 0000000..451b927
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
+import android.os.SystemClock;
+
+import com.example.android.apis.R;
+
+public class TriangleRenderer implements GLSurfaceView.Renderer{
+
+ public TriangleRenderer(Context context) {
+ mContext = context;
+ mTriangle = new Triangle();
+ }
+
+ public int[] getConfigSpec() {
+ // We don't need a depth buffer, and don't care about our
+ // color depth.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 0,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+ GL10.GL_FASTEST);
+
+ gl.glClearColor(.5f, .5f, .5f, 1);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+
+ /*
+ * Create our texture. This has to be done each time the
+ * surface is created.
+ */
+
+ int[] textures = new int[1];
+ gl.glGenTextures(1, textures, 0);
+
+ mTextureID = textures[0];
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
+ GL10.GL_NEAREST);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D,
+ GL10.GL_TEXTURE_MAG_FILTER,
+ GL10.GL_LINEAR);
+
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+ GL10.GL_CLAMP_TO_EDGE);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+ GL10.GL_CLAMP_TO_EDGE);
+
+ gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+ GL10.GL_REPLACE);
+
+ InputStream is = mContext.getResources()
+ .openRawResource(R.drawable.robot);
+ Bitmap bitmap;
+ try {
+ bitmap = BitmapFactory.decodeStream(is);
+ } finally {
+ try {
+ is.close();
+ } catch(IOException e) {
+ // Ignore.
+ }
+ }
+
+ GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
+ bitmap.recycle();
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+ GL10.GL_MODULATE);
+
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
+ GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+
+ gl.glActiveTexture(GL10.GL_TEXTURE0);
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+ gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+ GL10.GL_REPEAT);
+ gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+ GL10.GL_REPEAT);
+
+ long time = SystemClock.uptimeMillis() % 4000L;
+ float angle = 0.090f * ((int) time);
+
+ gl.glRotatef(angle, 0, 0, 1.0f);
+
+ mTriangle.draw(gl);
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
+ gl.glViewport(0, 0, w, h);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) w / h;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
+
+ }
+
+ private Context mContext;
+ private Triangle mTriangle;
+ private int mTextureID;
+}
+
+class Triangle {
+ public Triangle() {
+
+ // Buffers to be passed to gl*Pointer() functions
+ // must be direct, i.e., they must be placed on the
+ // native heap where the garbage collector cannot
+ // move them.
+ //
+ // Buffers with multi-byte datatypes (e.g., short, int, float)
+ // must have their byte order set to native order
+
+ ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
+ vbb.order(ByteOrder.nativeOrder());
+ mFVertexBuffer = vbb.asFloatBuffer();
+
+ ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
+ tbb.order(ByteOrder.nativeOrder());
+ mTexBuffer = tbb.asFloatBuffer();
+
+ ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2);
+ ibb.order(ByteOrder.nativeOrder());
+ mIndexBuffer = ibb.asShortBuffer();
+
+ // A unit-sided equalateral triangle centered on the origin.
+ float[] coords = {
+ // X, Y, Z
+ -0.5f, -0.25f, 0,
+ 0.5f, -0.25f, 0,
+ 0.0f, 0.559016994f, 0
+ };
+
+ for (int i = 0; i < VERTS; i++) {
+ for(int j = 0; j < 3; j++) {
+ mFVertexBuffer.put(coords[i*3+j] * 2.0f);
+ }
+ }
+
+ for (int i = 0; i < VERTS; i++) {
+ for(int j = 0; j < 2; j++) {
+ mTexBuffer.put(coords[i*3+j] * 2.0f + 0.5f);
+ }
+ }
+
+ for(int i = 0; i < VERTS; i++) {
+ mIndexBuffer.put((short) i);
+ }
+
+ mFVertexBuffer.position(0);
+ mTexBuffer.position(0);
+ mIndexBuffer.position(0);
+ }
+
+ public void draw(GL10 gl) {
+ gl.glFrontFace(GL10.GL_CCW);
+ gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+ gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
+ gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS,
+ GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+ }
+
+ private final static int VERTS = 3;
+
+ private FloatBuffer mFVertexBuffer;
+ private FloatBuffer mTexBuffer;
+ private ShortBuffer mIndexBuffer;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Typefaces.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Typefaces.java
new file mode 100644
index 0000000..aefc311
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Typefaces.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+
+public class Typefaces extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private Typeface mFace;
+
+ public SampleView(Context context) {
+ super(context);
+
+ mFace = Typeface.createFromAsset(getContext().getAssets(),
+ "fonts/samplefont.ttf");
+
+ mPaint.setTextSize(64);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ mPaint.setTypeface(null);
+ canvas.drawText("Default", 10, 100, mPaint);
+ mPaint.setTypeface(mFace);
+ canvas.drawText("Custom", 10, 200, mPaint);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/UnicodeChart.java b/samples/ApiDemos/src/com/example/android/apis/graphics/UnicodeChart.java
new file mode 100644
index 0000000..7ee99d0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/UnicodeChart.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Window;
+
+public class UnicodeChart extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private Paint mBigCharPaint;
+ private Paint mLabelPaint;
+ private final char[] mChars = new char[256];
+ private final float[] mPos = new float[512];
+
+ private int mBase;
+
+ private static final int XMUL = 20;
+ private static final int YMUL = 28;
+ private static final int YBASE = 18;
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ mBigCharPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBigCharPaint.setTextSize(15);
+ mBigCharPaint.setTextAlign(Paint.Align.CENTER);
+
+ mLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mLabelPaint.setTextSize(8);
+ mLabelPaint.setTextAlign(Paint.Align.CENTER);
+
+ // the position array is the same for all charts
+ float[] pos = mPos;
+ int index = 0;
+ for (int col = 0; col < 16; col++) {
+ final float x = col * 20 + 10;
+ for (int row = 0; row < 16; row++) {
+ pos[index++] = x;
+ pos[index++] = row * YMUL + YBASE;
+ }
+ }
+ }
+
+ private float computeX(int index) {
+ return (index >> 4) * 20 + 10;
+ }
+
+ private float computeY(int index) {
+ return (index & 0xF) * YMUL + YMUL;
+ }
+
+ private void drawChart(Canvas canvas, int base) {
+ char[] chars = mChars;
+ for (int i = 0; i < 256; i++) {
+ int unichar = base + i;
+ chars[i] = (char)unichar;
+
+ canvas.drawText(Integer.toHexString(unichar),
+ computeX(i), computeY(i), mLabelPaint);
+ }
+ canvas.drawPosText(chars, 0, 256, mPos, mBigCharPaint);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ canvas.translate(0, 1);
+ drawChart(canvas, mBase * 256);
+ }
+
+ @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (mBase > 0) {
+ mBase -= 1;
+ invalidate();
+ }
+ return true;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ mBase += 1;
+ invalidate();
+ return true;
+ default:
+ break;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Vertices.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Vertices.java
new file mode 100644
index 0000000..1e61906
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Vertices.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 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.graphics;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.drawable.*;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class Vertices extends GraphicsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private final Paint mPaint = new Paint();
+ private final float[] mVerts = new float[10];
+ private final float[] mTexs = new float[10];
+ private final int[] mColors = new int[10];
+ private final short[] mIndices = { 0, 1, 2, 3, 4, 1 };
+
+ private final Matrix mMatrix = new Matrix();
+ private final Matrix mInverse = new Matrix();
+
+ private static void setXY(float[] array, int index, float x, float y) {
+ array[index*2 + 0] = x;
+ array[index*2 + 1] = y;
+ }
+
+ public SampleView(Context context) {
+ super(context);
+ setFocusable(true);
+
+ Bitmap bm = BitmapFactory.decodeResource(getResources(),
+ R.drawable.beach);
+ Shader s = new BitmapShader(bm, Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP);
+ mPaint.setShader(s);
+
+ float w = bm.getWidth();
+ float h = bm.getHeight();
+ // construct our mesh
+ setXY(mTexs, 0, w/2, h/2);
+ setXY(mTexs, 1, 0, 0);
+ setXY(mTexs, 2, w, 0);
+ setXY(mTexs, 3, w, h);
+ setXY(mTexs, 4, 0, h);
+
+ setXY(mVerts, 0, w/2, h/2);
+ setXY(mVerts, 1, 0, 0);
+ setXY(mVerts, 2, w, 0);
+ setXY(mVerts, 3, w, h);
+ setXY(mVerts, 4, 0, h);
+
+ mMatrix.setScale(0.8f, 0.8f);
+ mMatrix.preTranslate(20, 20);
+ mMatrix.invert(mInverse);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(0xFFCCCCCC);
+ canvas.save();
+ canvas.concat(mMatrix);
+
+ canvas.drawVertices(Canvas.VertexMode.TRIANGLE_FAN, 10, mVerts, 0,
+ mTexs, 0, null, 0, null, 0, 0, mPaint);
+
+ canvas.translate(0, 240);
+ canvas.drawVertices(Canvas.VertexMode.TRIANGLE_FAN, 10, mVerts, 0,
+ mTexs, 0, null, 0, mIndices, 0, 6, mPaint);
+
+ canvas.restore();
+ }
+
+ @Override public boolean onTouchEvent(MotionEvent event) {
+ float[] pt = { event.getX(), event.getY() };
+ mInverse.mapPoints(pt);
+ setXY(mVerts, 0, pt[0], pt[1]);
+ invalidate();
+ return true;
+ }
+
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/Xfermodes.java b/samples/ApiDemos/src/com/example/android/apis/graphics/Xfermodes.java
new file mode 100644
index 0000000..b9f8424
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/Xfermodes.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2007 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.graphics;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.Xfermode;
+import android.os.Bundle;
+import android.view.View;
+
+public class Xfermodes extends GraphicsActivity {
+
+ // create a bitmap with a circle, used for the "dst" image
+ static Bitmap makeDst(int w, int h) {
+ Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bm);
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ p.setColor(0xFFFFCC44);
+ c.drawOval(new RectF(0, 0, w*3/4, h*3/4), p);
+ return bm;
+ }
+
+ // create a bitmap with a rect, used for the "src" image
+ static Bitmap makeSrc(int w, int h) {
+ Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bm);
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ p.setColor(0xFF66AAFF);
+ c.drawRect(w/3, h/3, w*19/20, h*19/20, p);
+ return bm;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(new SampleView(this));
+ }
+
+ private static class SampleView extends View {
+ private static final int W = 64;
+ private static final int H = 64;
+ private static final int ROW_MAX = 4; // number of samples per row
+
+ private Bitmap mSrcB;
+ private Bitmap mDstB;
+ private Shader mBG; // background checker-board pattern
+
+ private static final Xfermode[] sModes = {
+ new PorterDuffXfermode(PorterDuff.Mode.CLEAR),
+ new PorterDuffXfermode(PorterDuff.Mode.SRC),
+ new PorterDuffXfermode(PorterDuff.Mode.DST),
+ new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),
+ new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),
+ new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),
+ new PorterDuffXfermode(PorterDuff.Mode.DST_IN),
+ new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),
+ new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),
+ new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),
+ new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),
+ new PorterDuffXfermode(PorterDuff.Mode.XOR),
+ new PorterDuffXfermode(PorterDuff.Mode.DARKEN),
+ new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),
+ new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),
+ new PorterDuffXfermode(PorterDuff.Mode.SCREEN)
+ };
+
+ private static final String[] sLabels = {
+ "Clear", "Src", "Dst", "SrcOver",
+ "DstOver", "SrcIn", "DstIn", "SrcOut",
+ "DstOut", "SrcATop", "DstATop", "Xor",
+ "Darken", "Lighten", "Multiply", "Screen"
+ };
+
+ public SampleView(Context context) {
+ super(context);
+
+ mSrcB = makeSrc(W, H);
+ mDstB = makeDst(W, H);
+
+ // make a ckeckerboard pattern
+ Bitmap bm = Bitmap.createBitmap(new int[] { 0xFFFFFFFF, 0xFFCCCCCC,
+ 0xFFCCCCCC, 0xFFFFFFFF }, 2, 2,
+ Bitmap.Config.RGB_565);
+ mBG = new BitmapShader(bm,
+ Shader.TileMode.REPEAT,
+ Shader.TileMode.REPEAT);
+ Matrix m = new Matrix();
+ m.setScale(6, 6);
+ mBG.setLocalMatrix(m);
+ }
+
+ @Override protected void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.WHITE);
+
+ Paint labelP = new Paint(Paint.ANTI_ALIAS_FLAG);
+ labelP.setTextAlign(Paint.Align.CENTER);
+
+ Paint paint = new Paint();
+ paint.setFilterBitmap(false);
+
+ canvas.translate(15, 35);
+
+ int x = 0;
+ int y = 0;
+ for (int i = 0; i < sModes.length; i++) {
+ // draw the border
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setShader(null);
+ canvas.drawRect(x - 0.5f, y - 0.5f,
+ x + W + 0.5f, y + H + 0.5f, paint);
+
+ // draw the checker-board pattern
+ paint.setStyle(Paint.Style.FILL);
+ paint.setShader(mBG);
+ canvas.drawRect(x, y, x + W, y + H, paint);
+
+ // draw the src/dst example into our offscreen bitmap
+ int sc = canvas.saveLayer(x, y, x + W, y + H, null,
+ Canvas.MATRIX_SAVE_FLAG |
+ Canvas.CLIP_SAVE_FLAG |
+ Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
+ Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
+ Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+ canvas.translate(x, y);
+ canvas.drawBitmap(mDstB, 0, 0, paint);
+ paint.setXfermode(sModes[i]);
+ canvas.drawBitmap(mSrcB, 0, 0, paint);
+ paint.setXfermode(null);
+ canvas.restoreToCount(sc);
+
+ // draw the label
+ canvas.drawText(sLabels[i],
+ x + W/2, y - labelP.getTextSize()/2, labelP);
+
+ x += W + 10;
+
+ // wrap around when we've drawn enough for one row
+ if ((i % ROW_MAX) == ROW_MAX - 1) {
+ x = 0;
+ y += H + 30;
+ }
+ }
+ }
+ }
+}
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/_index.html b/samples/ApiDemos/src/com/example/android/apis/graphics/_index.html
new file mode 100644
index 0000000..cd2ea53
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/_index.html
@@ -0,0 +1,48 @@
+
+<h3>Drawable</h3>
+<dl>
+ <dt><a href="ShapeDrawable1.html">ShapeDrawable</a></dt>
+ <dd>Demonstrates creating Drawables in XML.</dd>
+</dl>
+
+<h3>OpenGL|ES</h3>
+<dl>
+ <dt><a href="CameraPreview.html">CameraPreview</a></dt>
+ <dd> Demonstrates capturing the image stream from the camera, drawing to a surface (extending SurfaceView) on a separate thread (extending Thread).</dd>
+
+ <dt><a href="GLSurfaceViewActivity.html">GL SurfaceView</a></dt>
+ <dd>Demonstrates how to perform OpenGL rendering in to a SurfaceView.
+ <dl>
+ <dt>Code:
+ <dd> <a href="GLSurfaceViewActivity.html">GLSurfaceViewActivity.java</a>,
+ <a href="GLSurfaceView.html">GLSurfaceView.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/hello_world.html">
+ hello_world.xml</a>
+ </dl>
+ </dd>
+
+ <dt><a href="PolyToPoly.html">PolyToPoly</a></dt>
+ <dd>Demonstrates calling the <a href="@{docRoot}reference/android/graphics/Matrix.html#setPolyToPoly(float[],%20int,%20float[],%20int,%20int)">Matrix.setPolyToPoly()</a> method to translate coordinates on a canvas to a new perspective (used to simulate perspective). </dd>
+
+ <dt><a href="DrawPoints.html">DrawPoints</a></dt>
+ <dd>Demonstrates using the <a href="android.graphics.Paint">Paint</a> and <a href="android.graphics.Canvas">Canvas</a> objects to draw random points on the screen, with different colors and strokes. </dd>
+
+ <dt><a href="PathEffects.html">PathEffects</a></dt>
+ <dd> Demonstrates the use of <a href="android.graphics.Path">Path</a> and various <a href="android.graphics.PathEffect">PathEffect</a> subclasses. </dd>
+
+ <dt><a href="SurfaceViewOverlay.html">SurfaceView Overlay</a></dt>
+ <dd>Shows how you can place overlays on top of a SurfaceView.
+ <dl>
+ <dt>Code:
+ <dd> <a href="SurfaceViewOverlay.html">SurfaceViewOverlay.java</a>,
+ <a href="GLSurfaceView.html">GLSurfaceView.java</a>
+ <dt>Layout:
+ <dd> <a href="{@docRoot}samples/ApiDemos/res/layout/surface_view_overlay.html">
+ surface_view_overlay.xml</a>
+ </dl>
+ </dd>
+
+ <dt><a href="TouchPaint.html">TouchPaint</a></dt>
+ <dd> Demonstrates the handling of touch screen events to implement a simple painting app. </dd>
+</dl>
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Cube.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Cube.java
new file mode 100644
index 0000000..015e19e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Cube.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+
+public class Cube extends GLShape {
+
+ public Cube(GLWorld world, float left, float bottom, float back, float right, float top, float front) {
+ super(world);
+ GLVertex leftBottomBack = addVertex(left, bottom, back);
+ GLVertex rightBottomBack = addVertex(right, bottom, back);
+ GLVertex leftTopBack = addVertex(left, top, back);
+ GLVertex rightTopBack = addVertex(right, top, back);
+ GLVertex leftBottomFront = addVertex(left, bottom, front);
+ GLVertex rightBottomFront = addVertex(right, bottom, front);
+ GLVertex leftTopFront = addVertex(left, top, front);
+ GLVertex rightTopFront = addVertex(right, top, front);
+
+ // vertices are added in a clockwise orientation (when viewed from the outside)
+ // bottom
+ addFace(new GLFace(leftBottomBack, leftBottomFront, rightBottomFront, rightBottomBack));
+ // front
+ addFace(new GLFace(leftBottomFront, leftTopFront, rightTopFront, rightBottomFront));
+ // left
+ addFace(new GLFace(leftBottomBack, leftTopBack, leftTopFront, leftBottomFront));
+ // right
+ addFace(new GLFace(rightBottomBack, rightBottomFront, rightTopFront, rightTopBack));
+ // back
+ addFace(new GLFace(leftBottomBack, rightBottomBack, rightTopBack, leftTopBack));
+ // top
+ addFace(new GLFace(leftTopBack, rightTopBack, rightTopFront, leftTopFront));
+
+ }
+
+ public static final int kBottom = 0;
+ public static final int kFront = 1;
+ public static final int kLeft = 2;
+ public static final int kRight = 3;
+ public static final int kBack = 4;
+ public static final int kTop = 5;
+
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLColor.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLColor.java
new file mode 100644
index 0000000..7d4c7c1
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLColor.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+public class GLColor {
+
+ public final int red;
+ public final int green;
+ public final int blue;
+ public final int alpha;
+
+ public GLColor(int red, int green, int blue, int alpha) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = alpha;
+ }
+
+ public GLColor(int red, int green, int blue) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = 0x10000;
+ }
+
+ public boolean equals(Object other) {
+ if (other instanceof GLColor) {
+ GLColor color = (GLColor)other;
+ return (red == color.red && green == color.green &&
+ blue == color.blue && alpha == color.alpha);
+ }
+ return false;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLFace.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLFace.java
new file mode 100644
index 0000000..d6e6754
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLFace.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+import android.util.Log;
+
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+
+public class GLFace {
+
+ public GLFace() {
+
+ }
+
+ // for triangles
+ public GLFace(GLVertex v1, GLVertex v2, GLVertex v3) {
+ addVertex(v1);
+ addVertex(v2);
+ addVertex(v3);
+ }
+ // for quadrilaterals
+ public GLFace(GLVertex v1, GLVertex v2, GLVertex v3, GLVertex v4) {
+ addVertex(v1);
+ addVertex(v2);
+ addVertex(v3);
+ addVertex(v4);
+ }
+
+ public void addVertex(GLVertex v) {
+ mVertexList.add(v);
+ }
+
+ // must be called after all vertices are added
+ public void setColor(GLColor c) {
+
+ int last = mVertexList.size() - 1;
+ if (last < 2) {
+ Log.e("GLFace", "not enough vertices in setColor()");
+ } else {
+ GLVertex vertex = mVertexList.get(last);
+
+ // only need to do this if the color has never been set
+ if (mColor == null) {
+ while (vertex.color != null) {
+ mVertexList.add(0, vertex);
+ mVertexList.remove(last + 1);
+ vertex = mVertexList.get(last);
+ }
+ }
+
+ vertex.color = c;
+ }
+
+ mColor = c;
+ }
+
+ public int getIndexCount() {
+ return (mVertexList.size() - 2) * 3;
+ }
+
+ public void putIndices(ShortBuffer buffer) {
+ int last = mVertexList.size() - 1;
+
+ GLVertex v0 = mVertexList.get(0);
+ GLVertex vn = mVertexList.get(last);
+
+ // push triangles into the buffer
+ for (int i = 1; i < last; i++) {
+ GLVertex v1 = mVertexList.get(i);
+ buffer.put(v0.index);
+ buffer.put(v1.index);
+ buffer.put(vn.index);
+ v0 = v1;
+ }
+ }
+
+ private ArrayList<GLVertex> mVertexList = new ArrayList<GLVertex>();
+ private GLColor mColor;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLShape.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLShape.java
new file mode 100644
index 0000000..2b6a824
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLShape.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class GLShape {
+
+ public GLShape(GLWorld world) {
+ mWorld = world;
+ }
+
+ public void addFace(GLFace face) {
+ mFaceList.add(face);
+ }
+
+ public void setFaceColor(int face, GLColor color) {
+ mFaceList.get(face).setColor(color);
+ }
+
+ public void putIndices(ShortBuffer buffer) {
+ Iterator<GLFace> iter = mFaceList.iterator();
+ while (iter.hasNext()) {
+ GLFace face = iter.next();
+ face.putIndices(buffer);
+ }
+ }
+
+ public int getIndexCount() {
+ int count = 0;
+ Iterator<GLFace> iter = mFaceList.iterator();
+ while (iter.hasNext()) {
+ GLFace face = iter.next();
+ count += face.getIndexCount();
+ }
+ return count;
+ }
+
+ public GLVertex addVertex(float x, float y, float z) {
+
+ // look for an existing GLVertex first
+ Iterator<GLVertex> iter = mVertexList.iterator();
+ while (iter.hasNext()) {
+ GLVertex vertex = iter.next();
+ if (vertex.x == x && vertex.y == y && vertex.z == z) {
+ return vertex;
+ }
+ }
+
+ // doesn't exist, so create new vertex
+ GLVertex vertex = mWorld.addVertex(x, y, z);
+ mVertexList.add(vertex);
+ return vertex;
+ }
+
+ public void animateTransform(M4 transform) {
+ mAnimateTransform = transform;
+
+ if (mTransform != null)
+ transform = mTransform.multiply(transform);
+
+ Iterator<GLVertex> iter = mVertexList.iterator();
+ while (iter.hasNext()) {
+ GLVertex vertex = iter.next();
+ mWorld.transformVertex(vertex, transform);
+ }
+ }
+
+ public void startAnimation() {
+ }
+
+ public void endAnimation() {
+ if (mTransform == null) {
+ mTransform = new M4(mAnimateTransform);
+ } else {
+ mTransform = mTransform.multiply(mAnimateTransform);
+ }
+ }
+
+ public M4 mTransform;
+ public M4 mAnimateTransform;
+ protected ArrayList<GLFace> mFaceList = new ArrayList<GLFace>();
+ protected ArrayList<GLVertex> mVertexList = new ArrayList<GLVertex>();
+ protected ArrayList<Integer> mIndexList = new ArrayList<Integer>(); // make more efficient?
+ protected GLWorld mWorld;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLVertex.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLVertex.java
new file mode 100644
index 0000000..b5cd873
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLVertex.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+import java.nio.IntBuffer;
+
+public class GLVertex {
+
+ public float x;
+ public float y;
+ public float z;
+ final short index; // index in vertex table
+ GLColor color;
+
+ GLVertex() {
+ this.x = 0;
+ this.y = 0;
+ this.z = 0;
+ this.index = -1;
+ }
+
+ GLVertex(float x, float y, float z, int index) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.index = (short)index;
+ }
+
+ public boolean equals(Object other) {
+ if (other instanceof GLVertex) {
+ GLVertex v = (GLVertex)other;
+ return (x == v.x && y == v.y && z == v.z);
+ }
+ return false;
+ }
+
+ static public int toFixed(float x) {
+ return (int)(x*65536.0f);
+ }
+
+ public void put(IntBuffer vertexBuffer, IntBuffer colorBuffer) {
+ vertexBuffer.put(toFixed(x));
+ vertexBuffer.put(toFixed(y));
+ vertexBuffer.put(toFixed(z));
+ if (color == null) {
+ colorBuffer.put(0);
+ colorBuffer.put(0);
+ colorBuffer.put(0);
+ colorBuffer.put(0);
+ } else {
+ colorBuffer.put(color.red);
+ colorBuffer.put(color.green);
+ colorBuffer.put(color.blue);
+ colorBuffer.put(color.alpha);
+ }
+ }
+
+ public void update(IntBuffer vertexBuffer, M4 transform) {
+ // skip to location of vertex in mVertex buffer
+ vertexBuffer.position(index * 3);
+
+ if (transform == null) {
+ vertexBuffer.put(toFixed(x));
+ vertexBuffer.put(toFixed(y));
+ vertexBuffer.put(toFixed(z));
+ } else {
+ GLVertex temp = new GLVertex();
+ transform.multiply(this, temp);
+ vertexBuffer.put(toFixed(temp.x));
+ vertexBuffer.put(toFixed(temp.y));
+ vertexBuffer.put(toFixed(temp.z));
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLWorld.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLWorld.java
new file mode 100644
index 0000000..dd73174
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/GLWorld.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+import javax.microedition.khronos.opengles.GL10;
+
+public class GLWorld {
+
+ public void addShape(GLShape shape) {
+ mShapeList.add(shape);
+ mIndexCount += shape.getIndexCount();
+ }
+
+ public void generate() {
+ ByteBuffer bb = ByteBuffer.allocateDirect(mVertexList.size()*4*4);
+ bb.order(ByteOrder.nativeOrder());
+ mColorBuffer = bb.asIntBuffer();
+
+ bb = ByteBuffer.allocateDirect(mVertexList.size()*4*3);
+ bb.order(ByteOrder.nativeOrder());
+ mVertexBuffer = bb.asIntBuffer();
+
+ bb = ByteBuffer.allocateDirect(mIndexCount*2);
+ bb.order(ByteOrder.nativeOrder());
+ mIndexBuffer = bb.asShortBuffer();
+
+ Iterator<GLVertex> iter2 = mVertexList.iterator();
+ while (iter2.hasNext()) {
+ GLVertex vertex = iter2.next();
+ vertex.put(mVertexBuffer, mColorBuffer);
+ }
+
+ Iterator<GLShape> iter3 = mShapeList.iterator();
+ while (iter3.hasNext()) {
+ GLShape shape = iter3.next();
+ shape.putIndices(mIndexBuffer);
+ }
+ }
+
+ public GLVertex addVertex(float x, float y, float z) {
+ GLVertex vertex = new GLVertex(x, y, z, mVertexList.size());
+ mVertexList.add(vertex);
+ return vertex;
+ }
+
+ public void transformVertex(GLVertex vertex, M4 transform) {
+ vertex.update(mVertexBuffer, transform);
+ }
+
+ int count = 0;
+ public void draw(GL10 gl)
+ {
+ mColorBuffer.position(0);
+ mVertexBuffer.position(0);
+ mIndexBuffer.position(0);
+
+ gl.glFrontFace(GL10.GL_CW);
+ gl.glShadeModel(GL10.GL_FLAT);
+ gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
+ gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
+ gl.glDrawElements(GL10.GL_TRIANGLES, mIndexCount, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+ count++;
+ }
+
+ static public float toFloat(int x) {
+ return x/65536.0f;
+ }
+
+ private ArrayList<GLShape> mShapeList = new ArrayList<GLShape>();
+ private ArrayList<GLVertex> mVertexList = new ArrayList<GLVertex>();
+
+ private int mIndexCount = 0;
+
+ private IntBuffer mVertexBuffer;
+ private IntBuffer mColorBuffer;
+ private ShortBuffer mIndexBuffer;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
new file mode 100644
index 0000000..9332941
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Window;
+
+import android.opengl.GLSurfaceView;
+
+import java.util.Random;
+
+public class Kube extends Activity implements KubeRenderer.AnimationCallback {
+
+ private GLWorld makeGLWorld()
+ {
+ GLWorld world = new GLWorld();
+
+ int one = 0x10000;
+ int half = 0x08000;
+ GLColor red = new GLColor(one, 0, 0);
+ GLColor green = new GLColor(0, one, 0);
+ GLColor blue = new GLColor(0, 0, one);
+ GLColor yellow = new GLColor(one, one, 0);
+ GLColor orange = new GLColor(one, half, 0);
+ GLColor white = new GLColor(one, one, one);
+ GLColor black = new GLColor(0, 0, 0);
+
+ // coordinates for our cubes
+ float c0 = -1.0f;
+ float c1 = -0.38f;
+ float c2 = -0.32f;
+ float c3 = 0.32f;
+ float c4 = 0.38f;
+ float c5 = 1.0f;
+
+ // top back, left to right
+ mCubes[0] = new Cube(world, c0, c4, c0, c1, c5, c1);
+ mCubes[1] = new Cube(world, c2, c4, c0, c3, c5, c1);
+ mCubes[2] = new Cube(world, c4, c4, c0, c5, c5, c1);
+ // top middle, left to right
+ mCubes[3] = new Cube(world, c0, c4, c2, c1, c5, c3);
+ mCubes[4] = new Cube(world, c2, c4, c2, c3, c5, c3);
+ mCubes[5] = new Cube(world, c4, c4, c2, c5, c5, c3);
+ // top front, left to right
+ mCubes[6] = new Cube(world, c0, c4, c4, c1, c5, c5);
+ mCubes[7] = new Cube(world, c2, c4, c4, c3, c5, c5);
+ mCubes[8] = new Cube(world, c4, c4, c4, c5, c5, c5);
+ // middle back, left to right
+ mCubes[9] = new Cube(world, c0, c2, c0, c1, c3, c1);
+ mCubes[10] = new Cube(world, c2, c2, c0, c3, c3, c1);
+ mCubes[11] = new Cube(world, c4, c2, c0, c5, c3, c1);
+ // middle middle, left to right
+ mCubes[12] = new Cube(world, c0, c2, c2, c1, c3, c3);
+ mCubes[13] = null;
+ mCubes[14] = new Cube(world, c4, c2, c2, c5, c3, c3);
+ // middle front, left to right
+ mCubes[15] = new Cube(world, c0, c2, c4, c1, c3, c5);
+ mCubes[16] = new Cube(world, c2, c2, c4, c3, c3, c5);
+ mCubes[17] = new Cube(world, c4, c2, c4, c5, c3, c5);
+ // bottom back, left to right
+ mCubes[18] = new Cube(world, c0, c0, c0, c1, c1, c1);
+ mCubes[19] = new Cube(world, c2, c0, c0, c3, c1, c1);
+ mCubes[20] = new Cube(world, c4, c0, c0, c5, c1, c1);
+ // bottom middle, left to right
+ mCubes[21] = new Cube(world, c0, c0, c2, c1, c1, c3);
+ mCubes[22] = new Cube(world, c2, c0, c2, c3, c1, c3);
+ mCubes[23] = new Cube(world, c4, c0, c2, c5, c1, c3);
+ // bottom front, left to right
+ mCubes[24] = new Cube(world, c0, c0, c4, c1, c1, c5);
+ mCubes[25] = new Cube(world, c2, c0, c4, c3, c1, c5);
+ mCubes[26] = new Cube(world, c4, c0, c4, c5, c1, c5);
+
+ // paint the sides
+ int i, j;
+ // set all faces black by default
+ for (i = 0; i < 27; i++) {
+ Cube cube = mCubes[i];
+ if (cube != null) {
+ for (j = 0; j < 6; j++)
+ cube.setFaceColor(j, black);
+ }
+ }
+
+ // paint top
+ for (i = 0; i < 9; i++)
+ mCubes[i].setFaceColor(Cube.kTop, orange);
+ // paint bottom
+ for (i = 18; i < 27; i++)
+ mCubes[i].setFaceColor(Cube.kBottom, red);
+ // paint left
+ for (i = 0; i < 27; i += 3)
+ mCubes[i].setFaceColor(Cube.kLeft, yellow);
+ // paint right
+ for (i = 2; i < 27; i += 3)
+ mCubes[i].setFaceColor(Cube.kRight, white);
+ // paint back
+ for (i = 0; i < 27; i += 9)
+ for (j = 0; j < 3; j++)
+ mCubes[i + j].setFaceColor(Cube.kBack, blue);
+ // paint front
+ for (i = 6; i < 27; i += 9)
+ for (j = 0; j < 3; j++)
+ mCubes[i + j].setFaceColor(Cube.kFront, green);
+
+ for (i = 0; i < 27; i++)
+ if (mCubes[i] != null)
+ world.addShape(mCubes[i]);
+
+ // initialize our permutation to solved position
+ mPermutation = new int[27];
+ for (i = 0; i < mPermutation.length; i++)
+ mPermutation[i] = i;
+
+ createLayers();
+ updateLayers();
+
+ world.generate();
+
+ return world;
+ }
+
+ private void createLayers() {
+ mLayers[kUp] = new Layer(Layer.kAxisY);
+ mLayers[kDown] = new Layer(Layer.kAxisY);
+ mLayers[kLeft] = new Layer(Layer.kAxisX);
+ mLayers[kRight] = new Layer(Layer.kAxisX);
+ mLayers[kFront] = new Layer(Layer.kAxisZ);
+ mLayers[kBack] = new Layer(Layer.kAxisZ);
+ mLayers[kMiddle] = new Layer(Layer.kAxisX);
+ mLayers[kEquator] = new Layer(Layer.kAxisY);
+ mLayers[kSide] = new Layer(Layer.kAxisZ);
+ }
+
+ private void updateLayers() {
+ Layer layer;
+ GLShape[] shapes;
+ int i, j, k;
+
+ // up layer
+ layer = mLayers[kUp];
+ shapes = layer.mShapes;
+ for (i = 0; i < 9; i++)
+ shapes[i] = mCubes[mPermutation[i]];
+
+ // down layer
+ layer = mLayers[kDown];
+ shapes = layer.mShapes;
+ for (i = 18, k = 0; i < 27; i++)
+ shapes[k++] = mCubes[mPermutation[i]];
+
+ // left layer
+ layer = mLayers[kLeft];
+ shapes = layer.mShapes;
+ for (i = 0, k = 0; i < 27; i += 9)
+ for (j = 0; j < 9; j += 3)
+ shapes[k++] = mCubes[mPermutation[i + j]];
+
+ // right layer
+ layer = mLayers[kRight];
+ shapes = layer.mShapes;
+ for (i = 2, k = 0; i < 27; i += 9)
+ for (j = 0; j < 9; j += 3)
+ shapes[k++] = mCubes[mPermutation[i + j]];
+
+ // front layer
+ layer = mLayers[kFront];
+ shapes = layer.mShapes;
+ for (i = 6, k = 0; i < 27; i += 9)
+ for (j = 0; j < 3; j++)
+ shapes[k++] = mCubes[mPermutation[i + j]];
+
+ // back layer
+ layer = mLayers[kBack];
+ shapes = layer.mShapes;
+ for (i = 0, k = 0; i < 27; i += 9)
+ for (j = 0; j < 3; j++)
+ shapes[k++] = mCubes[mPermutation[i + j]];
+
+ // middle layer
+ layer = mLayers[kMiddle];
+ shapes = layer.mShapes;
+ for (i = 1, k = 0; i < 27; i += 9)
+ for (j = 0; j < 9; j += 3)
+ shapes[k++] = mCubes[mPermutation[i + j]];
+
+ // equator layer
+ layer = mLayers[kEquator];
+ shapes = layer.mShapes;
+ for (i = 9, k = 0; i < 18; i++)
+ shapes[k++] = mCubes[mPermutation[i]];
+
+ // side layer
+ layer = mLayers[kSide];
+ shapes = layer.mShapes;
+ for (i = 3, k = 0; i < 27; i += 9)
+ for (j = 0; j < 3; j++)
+ shapes[k++] = mCubes[mPermutation[i + j]];
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // We don't need a title either.
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ mView = new GLSurfaceView(getApplication());
+ mRenderer = new KubeRenderer(makeGLWorld(), this);
+ mView.setRenderer(mRenderer);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ super.onResume();
+ mView.onResume();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ super.onPause();
+ mView.onPause();
+ }
+
+ public void animate() {
+ // change our angle of view
+ mRenderer.setAngle(mRenderer.getAngle() + 1.2f);
+
+ if (mCurrentLayer == null) {
+ int layerID = mRandom.nextInt(9);
+ mCurrentLayer = mLayers[layerID];
+ mCurrentLayerPermutation = mLayerPermutations[layerID];
+ mCurrentLayer.startAnimation();
+ boolean direction = mRandom.nextBoolean();
+ int count = mRandom.nextInt(3) + 1;
+
+ count = 1;
+ direction = false;
+ mCurrentAngle = 0;
+ if (direction) {
+ mAngleIncrement = (float)Math.PI / 50;
+ mEndAngle = mCurrentAngle + ((float)Math.PI * count) / 2f;
+ } else {
+ mAngleIncrement = -(float)Math.PI / 50;
+ mEndAngle = mCurrentAngle - ((float)Math.PI * count) / 2f;
+ }
+ }
+
+ mCurrentAngle += mAngleIncrement;
+
+ if ((mAngleIncrement > 0f && mCurrentAngle >= mEndAngle) ||
+ (mAngleIncrement < 0f && mCurrentAngle <= mEndAngle)) {
+ mCurrentLayer.setAngle(mEndAngle);
+ mCurrentLayer.endAnimation();
+ mCurrentLayer = null;
+
+ // adjust mPermutation based on the completed layer rotation
+ int[] newPermutation = new int[27];
+ for (int i = 0; i < 27; i++) {
+ newPermutation[i] = mPermutation[mCurrentLayerPermutation[i]];
+ // newPermutation[i] = mCurrentLayerPermutation[mPermutation[i]];
+ }
+ mPermutation = newPermutation;
+ updateLayers();
+
+ } else {
+ mCurrentLayer.setAngle(mCurrentAngle);
+ }
+ }
+
+ GLSurfaceView mView;
+ KubeRenderer mRenderer;
+ Cube[] mCubes = new Cube[27];
+ // a Layer for each possible move
+ Layer[] mLayers = new Layer[9];
+ // permutations corresponding to a pi/2 rotation of each layer about its axis
+ static int[][] mLayerPermutations = {
+ // permutation for UP layer
+ { 2, 5, 8, 1, 4, 7, 0, 3, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
+ // permutation for DOWN layer
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 23, 26, 19, 22, 25, 18, 21, 24 },
+ // permutation for LEFT layer
+ { 6, 1, 2, 15, 4, 5, 24, 7, 8, 3, 10, 11, 12, 13, 14, 21, 16, 17, 0, 19, 20, 9, 22, 23, 18, 25, 26 },
+ // permutation for RIGHT layer
+ { 0, 1, 8, 3, 4, 17, 6, 7, 26, 9, 10, 5, 12, 13, 14, 15, 16, 23, 18, 19, 2, 21, 22, 11, 24, 25, 20 },
+ // permutation for FRONT layer
+ { 0, 1, 2, 3, 4, 5, 24, 15, 6, 9, 10, 11, 12, 13, 14, 25, 16, 7, 18, 19, 20, 21, 22, 23, 26, 17, 8 },
+ // permutation for BACK layer
+ { 18, 9, 0, 3, 4, 5, 6, 7, 8, 19, 10, 1, 12, 13, 14, 15, 16, 17, 20, 11, 2, 21, 22, 23, 24, 25, 26 },
+ // permutation for MIDDLE layer
+ { 0, 7, 2, 3, 16, 5, 6, 25, 8, 9, 4, 11, 12, 13, 14, 15, 22, 17, 18, 1, 20, 21, 10, 23, 24, 19, 26 },
+ // permutation for EQUATOR layer
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 17, 10, 13, 16, 9, 12, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
+ // permutation for SIDE layer
+ { 0, 1, 2, 21, 12, 3, 6, 7, 8, 9, 10, 11, 22, 13, 4, 15, 16, 17, 18, 19, 20, 23, 14, 5, 24, 25, 26 }
+ };
+
+
+
+ // current permutation of starting position
+ int[] mPermutation;
+
+ // for random cube movements
+ Random mRandom = new Random(System.currentTimeMillis());
+ // currently turning layer
+ Layer mCurrentLayer = null;
+ // current and final angle for current Layer animation
+ float mCurrentAngle, mEndAngle;
+ // amount to increment angle
+ float mAngleIncrement;
+ int[] mCurrentLayerPermutation;
+
+ // names for our 9 layers (based on notation from http://www.cubefreak.net/notation.html)
+ static final int kUp = 0;
+ static final int kDown = 1;
+ static final int kLeft = 2;
+ static final int kRight = 3;
+ static final int kFront = 4;
+ static final int kBack = 5;
+ static final int kMiddle = 6;
+ static final int kEquator = 7;
+ static final int kSide = 8;
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
new file mode 100644
index 0000000..252f566
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+import android.opengl.GLSurfaceView;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+
+/**
+ * Example of how to use OpenGL|ES in a custom view
+ *
+ */
+class KubeRenderer implements GLSurfaceView.Renderer {
+ public interface AnimationCallback {
+ void animate();
+ }
+
+ public KubeRenderer(GLWorld world, AnimationCallback callback) {
+ mWorld = world;
+ mCallback = callback;
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ if (mCallback != null) {
+ mCallback.animate();
+ }
+
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear(). However we must make sure to set the scissor
+ * correctly first. The scissor is always specified in window
+ * coordinates:
+ */
+
+ gl.glClearColor(0.5f,0.5f,0.5f,1);
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D object
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -3.0f);
+ gl.glScalef(0.5f, 0.5f, 0.5f);
+ gl.glRotatef(mAngle, 0, 1, 0);
+ gl.glRotatef(mAngle*0.25f, 1, 0, 0);
+
+ gl.glColor4f(0.7f, 0.7f, 0.7f, 1.0f);
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+
+ mWorld.draw(gl);
+ }
+
+ public int[] getConfigSpec() {
+ // Need a depth buffer, don't care about color depth.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ gl.glViewport(0, 0, width, height);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to be set
+ * when the viewport is resized.
+ */
+
+ float ratio = (float)width / height;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 2, 12);
+
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+ gl.glActiveTexture(GL10.GL_TEXTURE0);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ // Nothing special, don't have any textures we need to recreate.
+ }
+
+ public void setAngle(float angle) {
+ mAngle = angle;
+ }
+
+ public float getAngle() {
+ return mAngle;
+ }
+
+ private GLWorld mWorld;
+ private AnimationCallback mCallback;
+ private float mAngle;
+}
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Layer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Layer.java
new file mode 100644
index 0000000..5e27296
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Layer.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+public class Layer {
+
+ public Layer(int axis) {
+ // start with identity matrix for transformation
+ mAxis = axis;
+ mTransform.setIdentity();
+ }
+
+ public void startAnimation() {
+ for (int i = 0; i < mShapes.length; i++) {
+ GLShape shape = mShapes[i];
+ if (shape != null) {
+ shape.startAnimation();
+ }
+ }
+ }
+
+ public void endAnimation() {
+ for (int i = 0; i < mShapes.length; i++) {
+ GLShape shape = mShapes[i];
+ if (shape != null) {
+ shape.endAnimation();
+ }
+ }
+ }
+
+ public void setAngle(float angle) {
+ // normalize the angle
+ float twopi = (float)Math.PI *2f;
+ while (angle >= twopi) angle -= twopi;
+ while (angle < 0f) angle += twopi;
+// mAngle = angle;
+
+ float sin = (float)Math.sin(angle);
+ float cos = (float)Math.cos(angle);
+
+ float[][] m = mTransform.m;
+ switch (mAxis) {
+ case kAxisX:
+ m[1][1] = cos;
+ m[1][2] = sin;
+ m[2][1] = -sin;
+ m[2][2] = cos;
+ m[0][0] = 1f;
+ m[0][1] = m[0][2] = m[1][0] = m[2][0] = 0f;
+ break;
+ case kAxisY:
+ m[0][0] = cos;
+ m[0][2] = sin;
+ m[2][0] = -sin;
+ m[2][2] = cos;
+ m[1][1] = 1f;
+ m[0][1] = m[1][0] = m[1][2] = m[2][1] = 0f;
+ break;
+ case kAxisZ:
+ m[0][0] = cos;
+ m[0][1] = sin;
+ m[1][0] = -sin;
+ m[1][1] = cos;
+ m[2][2] = 1f;
+ m[2][0] = m[2][1] = m[0][2] = m[1][2] = 0f;
+ break;
+ }
+
+ for (int i = 0; i < mShapes.length; i++) {
+ GLShape shape = mShapes[i];
+ if (shape != null) {
+ shape.animateTransform(mTransform);
+ }
+ }
+ }
+
+ GLShape[] mShapes = new GLShape[9];
+ M4 mTransform = new M4();
+// float mAngle;
+
+ // which axis do we rotate around?
+ // 0 for X, 1 for Y, 2 for Z
+ int mAxis;
+ static public final int kAxisX = 0;
+ static public final int kAxisY = 1;
+ static public final int kAxisZ = 2;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/M4.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/M4.java
new file mode 100644
index 0000000..b6cc2fe
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/M4.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008 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.graphics.kube;
+
+/**
+ *
+ * A 4x4 float matrix
+ *
+ */
+public class M4 {
+ public float[][] m = new float[4][4];
+
+ public M4() {
+ }
+
+ public M4(M4 other) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ m[i][j] = other.m[i][j];
+ }
+ }
+ }
+
+ public void multiply(GLVertex src, GLVertex dest) {
+ dest.x = src.x * m[0][0] + src.y * m[1][0] + src.z * m[2][0] + m[3][0];
+ dest.y = src.x * m[0][1] + src.y * m[1][1] + src.z * m[2][1] + m[3][1];
+ dest.z = src.x * m[0][2] + src.y * m[1][2] + src.z * m[2][2] + m[3][2];
+ }
+
+ public M4 multiply(M4 other) {
+ M4 result = new M4();
+ float[][] m1 = m;
+ float[][] m2 = other.m;
+
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ result.m[i][j] = m1[i][0]*m2[0][j] + m1[i][1]*m2[1][j] + m1[i][2]*m2[2][j] + m1[i][3]*m2[3][j];
+ }
+ }
+
+ return result;
+ }
+
+ public void setIdentity() {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ m[i][j] = (i == j ? 1f : 0f);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("[ ");
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ builder.append(m[i][j]);
+ builder.append(" ");
+ }
+ if (i < 2)
+ builder.append("\n ");
+ }
+ builder.append(" ]");
+ return builder.toString();
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/Grid.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/Grid.java
new file mode 100644
index 0000000..81863a0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/Grid.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2007 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.graphics.spritetext;
+
+import java.nio.CharBuffer;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A 2D rectangular mesh. Can be drawn textured or untextured.
+ *
+ */
+class Grid {
+
+ public Grid(int w, int h) {
+ if (w < 0 || w >= 65536) {
+ throw new IllegalArgumentException("w");
+ }
+ if (h < 0 || h >= 65536) {
+ throw new IllegalArgumentException("h");
+ }
+ if (w * h >= 65536) {
+ throw new IllegalArgumentException("w * h >= 65536");
+ }
+
+ mW = w;
+ mH = h;
+ int size = w * h;
+ mVertexArray = new float[size * 3];
+ mVertexBuffer = FloatBuffer.wrap(mVertexArray);
+
+ mTexCoordArray = new float[size * 2];
+ mTexCoordBuffer = FloatBuffer.wrap(mTexCoordArray);
+
+ int quadW = mW - 1;
+ int quadH = mH - 1;
+ int quadCount = quadW * quadH;
+ int indexCount = quadCount * 6;
+ mIndexCount = indexCount;
+ char[] indexArray = new char[indexCount];
+
+ /*
+ * Initialize triangle list mesh.
+ *
+ * [0]-----[ 1] ...
+ * | / |
+ * | / |
+ * | / |
+ * [w]-----[w+1] ...
+ * | |
+ *
+ */
+
+ {
+ int i = 0;
+ for (int y = 0; y < quadH; y++) {
+ for (int x = 0; x < quadW; x++) {
+ char a = (char) (y * mW + x);
+ char b = (char) (y * mW + x + 1);
+ char c = (char) ((y + 1) * mW + x);
+ char d = (char) ((y + 1) * mW + x + 1);
+
+ indexArray[i++] = a;
+ indexArray[i++] = b;
+ indexArray[i++] = c;
+
+ indexArray[i++] = b;
+ indexArray[i++] = c;
+ indexArray[i++] = d;
+ }
+ }
+ }
+
+ mIndexBuffer = CharBuffer.wrap(indexArray);
+ }
+
+ void set(int i, int j, float x, float y, float z, float u, float v) {
+ if (i < 0 || i >= mW) {
+ throw new IllegalArgumentException("i");
+ }
+ if (j < 0 || j >= mH) {
+ throw new IllegalArgumentException("j");
+ }
+
+ int index = mW * j + i;
+
+ int posIndex = index * 3;
+ mVertexArray[posIndex] = x;
+ mVertexArray[posIndex + 1] = y;
+ mVertexArray[posIndex + 2] = z;
+
+ int texIndex = index * 2;
+ mTexCoordArray[texIndex] = u;
+ mTexCoordArray[texIndex + 1] = v;
+ }
+
+ public void draw(GL10 gl, boolean useTexture) {
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
+
+ if (useTexture) {
+ gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+ gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexCoordBuffer);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+ } else {
+ gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+ gl.glDisable(GL10.GL_TEXTURE_2D);
+ }
+
+ gl.glDrawElements(GL10.GL_TRIANGLES, mIndexCount,
+ GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+ gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
+ }
+
+ private FloatBuffer mVertexBuffer;
+ private float[] mVertexArray;
+
+ private FloatBuffer mTexCoordBuffer;
+ private float[] mTexCoordArray;
+
+ private CharBuffer mIndexBuffer;
+
+ private int mW;
+ private int mH;
+ private int mIndexCount;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/LabelMaker.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/LabelMaker.java
new file mode 100644
index 0000000..4bf87f7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/LabelMaker.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2007 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.graphics.spritetext;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Paint.Style;
+import android.graphics.drawable.Drawable;
+import android.opengl.GLUtils;
+
+import java.util.ArrayList;
+
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11Ext;
+
+/**
+ * An OpenGL text label maker.
+ *
+ *
+ * OpenGL labels are implemented by creating a Bitmap, drawing all the labels
+ * into the Bitmap, converting the Bitmap into an Alpha texture, and creating a
+ * mesh for each label
+ *
+ * The benefits of this approach are that the labels are drawn using the high
+ * quality anti-aliased font rasterizer, full character set support, and all the
+ * text labels are stored on a single texture, which makes it faster to use.
+ *
+ * The drawbacks are that you can only have as many labels as will fit onto one
+ * texture, and you have to recreate the whole texture if any label text
+ * changes.
+ *
+ */
+public class LabelMaker {
+ /**
+ * Create a label maker
+ * or maximum compatibility with various OpenGL ES implementations,
+ * the strike width and height must be powers of two,
+ * We want the strike width to be at least as wide as the widest window.
+ *
+ * @param fullColor true if we want a full color backing store (4444),
+ * otherwise we generate a grey L8 backing store.
+ * @param strikeWidth width of strike
+ * @param strikeHeight height of strike
+ */
+ public LabelMaker(boolean fullColor, int strikeWidth, int strikeHeight) {
+ mFullColor = fullColor;
+ mStrikeWidth = strikeWidth;
+ mStrikeHeight = strikeHeight;
+ mTexelWidth = (float) (1.0 / mStrikeWidth);
+ mTexelHeight = (float) (1.0 / mStrikeHeight);
+ mClearPaint = new Paint();
+ mClearPaint.setARGB(0, 0, 0, 0);
+ mClearPaint.setStyle(Style.FILL);
+ mState = STATE_NEW;
+ }
+
+ /**
+ * Call to initialize the class.
+ * Call whenever the surface has been created.
+ *
+ * @param gl
+ */
+ public void initialize(GL10 gl) {
+ mState = STATE_INITIALIZED;
+ int[] textures = new int[1];
+ gl.glGenTextures(1, textures, 0);
+ mTextureID = textures[0];
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+
+ // Use Nearest for performance.
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
+ GL10.GL_NEAREST);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
+ GL10.GL_NEAREST);
+
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+ GL10.GL_CLAMP_TO_EDGE);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+ GL10.GL_CLAMP_TO_EDGE);
+
+ gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+ GL10.GL_REPLACE);
+ }
+
+ /**
+ * Call when the surface has been destroyed
+ */
+ public void shutdown(GL10 gl) {
+ if ( gl != null) {
+ if (mState > STATE_NEW) {
+ int[] textures = new int[1];
+ textures[0] = mTextureID;
+ gl.glDeleteTextures(1, textures, 0);
+ mState = STATE_NEW;
+ }
+ }
+ }
+
+ /**
+ * Call before adding labels. Clears out any existing labels.
+ *
+ * @param gl
+ */
+ public void beginAdding(GL10 gl) {
+ checkState(STATE_INITIALIZED, STATE_ADDING);
+ mLabels.clear();
+ mU = 0;
+ mV = 0;
+ mLineHeight = 0;
+ Bitmap.Config config = mFullColor ?
+ Bitmap.Config.ARGB_4444 : Bitmap.Config.ALPHA_8;
+ mBitmap = Bitmap.createBitmap(mStrikeWidth, mStrikeHeight, config);
+ mCanvas = new Canvas(mBitmap);
+ mBitmap.eraseColor(0);
+ }
+
+ /**
+ * Call to add a label
+ *
+ * @param gl
+ * @param text the text of the label
+ * @param textPaint the paint of the label
+ * @return the id of the label, used to measure and draw the label
+ */
+ public int add(GL10 gl, String text, Paint textPaint) {
+ return add(gl, null, text, textPaint);
+ }
+
+ /**
+ * Call to add a label
+ *
+ * @param gl
+ * @param text the text of the label
+ * @param textPaint the paint of the label
+ * @return the id of the label, used to measure and draw the label
+ */
+ public int add(GL10 gl, Drawable background, String text, Paint textPaint) {
+ return add(gl, background, text, textPaint, 0, 0);
+ }
+
+ /**
+ * Call to add a label
+ * @return the id of the label, used to measure and draw the label
+ */
+ public int add(GL10 gl, Drawable drawable, int minWidth, int minHeight) {
+ return add(gl, drawable, null, null, minWidth, minHeight);
+ }
+
+ /**
+ * Call to add a label
+ *
+ * @param gl
+ * @param text the text of the label
+ * @param textPaint the paint of the label
+ * @return the id of the label, used to measure and draw the label
+ */
+ public int add(GL10 gl, Drawable background, String text, Paint textPaint,
+ int minWidth, int minHeight) {
+ checkState(STATE_ADDING, STATE_ADDING);
+ boolean drawBackground = background != null;
+ boolean drawText = (text != null) && (textPaint != null);
+
+ Rect padding = new Rect();
+ if (drawBackground) {
+ background.getPadding(padding);
+ minWidth = Math.max(minWidth, background.getMinimumWidth());
+ minHeight = Math.max(minHeight, background.getMinimumHeight());
+ }
+
+ int ascent = 0;
+ int descent = 0;
+ int measuredTextWidth = 0;
+ if (drawText) {
+ // Paint.ascent is negative, so negate it.
+ ascent = (int) Math.ceil(-textPaint.ascent());
+ descent = (int) Math.ceil(textPaint.descent());
+ measuredTextWidth = (int) Math.ceil(textPaint.measureText(text));
+ }
+ int textHeight = ascent + descent;
+ int textWidth = Math.min(mStrikeWidth,measuredTextWidth);
+
+ int padHeight = padding.top + padding.bottom;
+ int padWidth = padding.left + padding.right;
+ int height = Math.max(minHeight, textHeight + padHeight);
+ int width = Math.max(minWidth, textWidth + padWidth);
+ int effectiveTextHeight = height - padHeight;
+ int effectiveTextWidth = width - padWidth;
+
+ int centerOffsetHeight = (effectiveTextHeight - textHeight) / 2;
+ int centerOffsetWidth = (effectiveTextWidth - textWidth) / 2;
+
+ // Make changes to the local variables, only commit them
+ // to the member variables after we've decided not to throw
+ // any exceptions.
+
+ int u = mU;
+ int v = mV;
+ int lineHeight = mLineHeight;
+
+ if (width > mStrikeWidth) {
+ width = mStrikeWidth;
+ }
+
+ // Is there room for this string on the current line?
+ if (u + width > mStrikeWidth) {
+ // No room, go to the next line:
+ u = 0;
+ v += lineHeight;
+ lineHeight = 0;
+ }
+ lineHeight = Math.max(lineHeight, height);
+ if (v + lineHeight > mStrikeHeight) {
+ throw new IllegalArgumentException("Out of texture space.");
+ }
+
+ int u2 = u + width;
+ int vBase = v + ascent;
+ int v2 = v + height;
+
+ if (drawBackground) {
+ background.setBounds(u, v, u + width, v + height);
+ background.draw(mCanvas);
+ }
+
+ if (drawText) {
+ mCanvas.drawText(text,
+ u + padding.left + centerOffsetWidth,
+ vBase + padding.top + centerOffsetHeight,
+ textPaint);
+ }
+
+ Grid grid = new Grid(2, 2);
+ // Grid.set arguments: i, j, x, y, z, u, v
+
+ float texU = u * mTexelWidth;
+ float texU2 = u2 * mTexelWidth;
+ float texV = 1.0f - v * mTexelHeight;
+ float texV2 = 1.0f - v2 * mTexelHeight;
+
+ grid.set(0, 0, 0.0f, 0.0f, 0.0f, texU , texV2);
+ grid.set(1, 0, width, 0.0f, 0.0f, texU2, texV2);
+ grid.set(0, 1, 0.0f, height, 0.0f, texU , texV );
+ grid.set(1, 1, width, height, 0.0f, texU2, texV );
+
+ // We know there's enough space, so update the member variables
+ mU = u + width;
+ mV = v;
+ mLineHeight = lineHeight;
+ mLabels.add(new Label(grid, width, height, ascent,
+ u, v + height, width, -height));
+ return mLabels.size() - 1;
+ }
+
+ /**
+ * Call to end adding labels. Must be called before drawing starts.
+ *
+ * @param gl
+ */
+ public void endAdding(GL10 gl) {
+ checkState(STATE_ADDING, STATE_INITIALIZED);
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+ GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
+ // Reclaim storage used by bitmap and canvas.
+ mBitmap.recycle();
+ mBitmap = null;
+ mCanvas = null;
+ }
+
+ /**
+ * Get the width in pixels of a given label.
+ *
+ * @param labelID
+ * @return the width in pixels
+ */
+ public float getWidth(int labelID) {
+ return mLabels.get(labelID).width;
+ }
+
+ /**
+ * Get the height in pixels of a given label.
+ *
+ * @param labelID
+ * @return the height in pixels
+ */
+ public float getHeight(int labelID) {
+ return mLabels.get(labelID).height;
+ }
+
+ /**
+ * Get the baseline of a given label. That's how many pixels from the top of
+ * the label to the text baseline. (This is equivalent to the negative of
+ * the label's paint's ascent.)
+ *
+ * @param labelID
+ * @return the baseline in pixels.
+ */
+ public float getBaseline(int labelID) {
+ return mLabels.get(labelID).baseline;
+ }
+
+ /**
+ * Begin drawing labels. Sets the OpenGL state for rapid drawing.
+ *
+ * @param gl
+ * @param viewWidth
+ * @param viewHeight
+ */
+ public void beginDrawing(GL10 gl, float viewWidth, float viewHeight) {
+ checkState(STATE_INITIALIZED, STATE_DRAWING);
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+ gl.glShadeModel(GL10.GL_FLAT);
+ gl.glEnable(GL10.GL_BLEND);
+ gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
+ gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glPushMatrix();
+ gl.glLoadIdentity();
+ gl.glOrthof(0.0f, viewWidth, 0.0f, viewHeight, 0.0f, 1.0f);
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glPushMatrix();
+ gl.glLoadIdentity();
+ // Magic offsets to promote consistent rasterization.
+ gl.glTranslatef(0.375f, 0.375f, 0.0f);
+ }
+
+ /**
+ * Draw a given label at a given x,y position, expressed in pixels, with the
+ * lower-left-hand-corner of the view being (0,0).
+ *
+ * @param gl
+ * @param x
+ * @param y
+ * @param labelID
+ */
+ public void draw(GL10 gl, float x, float y, int labelID) {
+ checkState(STATE_DRAWING, STATE_DRAWING);
+ gl.glPushMatrix();
+ float snappedX = (float) Math.floor(x);
+ float snappedY = (float) Math.floor(y);
+ gl.glTranslatef(snappedX, snappedY, 0.0f);
+ Label label = mLabels.get(labelID);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+ ((GL11)gl).glTexParameteriv(GL10.GL_TEXTURE_2D,
+ GL11Ext.GL_TEXTURE_CROP_RECT_OES, label.mCrop, 0);
+ ((GL11Ext)gl).glDrawTexiOES((int) snappedX, (int) snappedY, 0,
+ (int) label.width, (int) label.height);
+ gl.glPopMatrix();
+ }
+
+ /**
+ * Ends the drawing and restores the OpenGL state.
+ *
+ * @param gl
+ */
+ public void endDrawing(GL10 gl) {
+ checkState(STATE_DRAWING, STATE_INITIALIZED);
+ gl.glDisable(GL10.GL_BLEND);
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glPopMatrix();
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glPopMatrix();
+ }
+
+ private void checkState(int oldState, int newState) {
+ if (mState != oldState) {
+ throw new IllegalArgumentException("Can't call this method now.");
+ }
+ mState = newState;
+ }
+
+ private static class Label {
+ public Label(Grid grid, float width, float height, float baseLine,
+ int cropU, int cropV, int cropW, int cropH) {
+ this.grid = grid;
+ this.width = width;
+ this.height = height;
+ this.baseline = baseLine;
+ int[] crop = new int[4];
+ crop[0] = cropU;
+ crop[1] = cropV;
+ crop[2] = cropW;
+ crop[3] = cropH;
+ mCrop = crop;
+ }
+
+ public Grid grid;
+ public float width;
+ public float height;
+ public float baseline;
+ public int[] mCrop;
+ }
+
+ private int mStrikeWidth;
+ private int mStrikeHeight;
+ private boolean mFullColor;
+ private Bitmap mBitmap;
+ private Canvas mCanvas;
+ private Paint mClearPaint;
+
+ private int mTextureID;
+
+ private float mTexelWidth; // Convert texel to U
+ private float mTexelHeight; // Convert texel to V
+ private int mU;
+ private int mV;
+ private int mLineHeight;
+ private ArrayList<Label> mLabels = new ArrayList<Label>();
+
+ private static final int STATE_NEW = 0;
+ private static final int STATE_INITIALIZED = 1;
+ private static final int STATE_ADDING = 2;
+ private static final int STATE_DRAWING = 3;
+ private int mState;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixGrabber.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixGrabber.java
new file mode 100644
index 0000000..87c9076
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixGrabber.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 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.graphics.spritetext;
+
+import javax.microedition.khronos.opengles.GL10;
+
+class MatrixGrabber {
+ public MatrixGrabber() {
+ mModelView = new float[16];
+ mProjection = new float[16];
+ }
+
+ /**
+ * Record the current modelView and projection matrix state.
+ * Has the side effect of setting the current matrix state to GL_MODELVIEW
+ * @param gl
+ */
+ public void getCurrentState(GL10 gl) {
+ getCurrentProjection(gl);
+ getCurrentModelView(gl);
+ }
+
+ /**
+ * Record the current modelView matrix state. Has the side effect of
+ * setting the current matrix state to GL_MODELVIEW
+ * @param gl
+ */
+ public void getCurrentModelView(GL10 gl) {
+ getMatrix(gl, GL10.GL_MODELVIEW, mModelView);
+ }
+
+ /**
+ * Record the current projection matrix state. Has the side effect of
+ * setting the current matrix state to GL_PROJECTION
+ * @param gl
+ */
+ public void getCurrentProjection(GL10 gl) {
+ getMatrix(gl, GL10.GL_PROJECTION, mProjection);
+ }
+
+ private void getMatrix(GL10 gl, int mode, float[] mat) {
+ MatrixTrackingGL gl2 = (MatrixTrackingGL) gl;
+ gl2.glMatrixMode(mode);
+ gl2.getMatrix(mat, 0);
+ }
+
+ public float[] mModelView;
+ public float[] mProjection;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixStack.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixStack.java
new file mode 100644
index 0000000..a07f614
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixStack.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2007 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.graphics.spritetext;
+
+import android.opengl.Matrix;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+/**
+ * A matrix stack, similar to OpenGL ES's internal matrix stack.
+ */
+public class MatrixStack {
+ public MatrixStack() {
+ commonInit(DEFAULT_MAX_DEPTH);
+ }
+
+ public MatrixStack(int maxDepth) {
+ commonInit(maxDepth);
+ }
+
+ private void commonInit(int maxDepth) {
+ mMatrix = new float[maxDepth * MATRIX_SIZE];
+ mTemp = new float[MATRIX_SIZE * 2];
+ glLoadIdentity();
+ }
+
+ public void glFrustumf(float left, float right, float bottom, float top,
+ float near, float far) {
+ Matrix.frustumM(mMatrix, mTop, left, right, bottom, top, near, far);
+ }
+
+ public void glFrustumx(int left, int right, int bottom, int top, int near,
+ int far) {
+ glFrustumf(fixedToFloat(left),fixedToFloat(right),
+ fixedToFloat(bottom), fixedToFloat(top),
+ fixedToFloat(near), fixedToFloat(far));
+ }
+
+ public void glLoadIdentity() {
+ Matrix.setIdentityM(mMatrix, mTop);
+ }
+
+ public void glLoadMatrixf(float[] m, int offset) {
+ System.arraycopy(m, offset, mMatrix, mTop, MATRIX_SIZE);
+ }
+
+ public void glLoadMatrixf(FloatBuffer m) {
+ m.get(mMatrix, mTop, MATRIX_SIZE);
+ }
+
+ public void glLoadMatrixx(int[] m, int offset) {
+ for(int i = 0; i < MATRIX_SIZE; i++) {
+ mMatrix[mTop + i] = fixedToFloat(m[offset + i]);
+ }
+ }
+
+ public void glLoadMatrixx(IntBuffer m) {
+ for(int i = 0; i < MATRIX_SIZE; i++) {
+ mMatrix[mTop + i] = fixedToFloat(m.get());
+ }
+ }
+
+ public void glMultMatrixf(float[] m, int offset) {
+ System.arraycopy(mMatrix, mTop, mTemp, 0, MATRIX_SIZE);
+ Matrix.multiplyMM(mMatrix, mTop, mTemp, 0, m, offset);
+ }
+
+ public void glMultMatrixf(FloatBuffer m) {
+ m.get(mTemp, MATRIX_SIZE, MATRIX_SIZE);
+ glMultMatrixf(mTemp, MATRIX_SIZE);
+ }
+
+ public void glMultMatrixx(int[] m, int offset) {
+ for(int i = 0; i < MATRIX_SIZE; i++) {
+ mTemp[MATRIX_SIZE + i] = fixedToFloat(m[offset + i]);
+ }
+ glMultMatrixf(mTemp, MATRIX_SIZE);
+ }
+
+ public void glMultMatrixx(IntBuffer m) {
+ for(int i = 0; i < MATRIX_SIZE; i++) {
+ mTemp[MATRIX_SIZE + i] = fixedToFloat(m.get());
+ }
+ glMultMatrixf(mTemp, MATRIX_SIZE);
+ }
+
+ public void glOrthof(float left, float right, float bottom, float top,
+ float near, float far) {
+ Matrix.orthoM(mMatrix, mTop, left, right, bottom, top, near, far);
+ }
+
+ public void glOrthox(int left, int right, int bottom, int top, int near,
+ int far) {
+ glOrthof(fixedToFloat(left), fixedToFloat(right),
+ fixedToFloat(bottom), fixedToFloat(top),
+ fixedToFloat(near), fixedToFloat(far));
+ }
+
+ public void glPopMatrix() {
+ preflight_adjust(-1);
+ adjust(-1);
+ }
+
+ public void glPushMatrix() {
+ preflight_adjust(1);
+ System.arraycopy(mMatrix, mTop, mMatrix, mTop + MATRIX_SIZE,
+ MATRIX_SIZE);
+ adjust(1);
+ }
+
+ public void glRotatef(float angle, float x, float y, float z) {
+ Matrix.setRotateM(mTemp, 0, angle, x, y, z);
+ System.arraycopy(mMatrix, mTop, mTemp, MATRIX_SIZE, MATRIX_SIZE);
+ Matrix.multiplyMM(mMatrix, mTop, mTemp, MATRIX_SIZE, mTemp, 0);
+ }
+
+ public void glRotatex(int angle, int x, int y, int z) {
+ glRotatef(angle, fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
+ }
+
+ public void glScalef(float x, float y, float z) {
+ Matrix.scaleM(mMatrix, mTop, x, y, z);
+ }
+
+ public void glScalex(int x, int y, int z) {
+ glScalef(fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
+ }
+
+ public void glTranslatef(float x, float y, float z) {
+ Matrix.translateM(mMatrix, mTop, x, y, z);
+ }
+
+ public void glTranslatex(int x, int y, int z) {
+ glTranslatef(fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
+ }
+
+ public void getMatrix(float[] dest, int offset) {
+ System.arraycopy(mMatrix, mTop, dest, offset, MATRIX_SIZE);
+ }
+
+ private float fixedToFloat(int x) {
+ return x * (1.0f / 65536.0f);
+ }
+
+ private void preflight_adjust(int dir) {
+ int newTop = mTop + dir * MATRIX_SIZE;
+ if (newTop < 0) {
+ throw new IllegalArgumentException("stack underflow");
+ }
+ if (newTop + MATRIX_SIZE > mMatrix.length) {
+ throw new IllegalArgumentException("stack overflow");
+ }
+ }
+
+ private void adjust(int dir) {
+ mTop += dir * MATRIX_SIZE;
+ }
+
+ private final static int DEFAULT_MAX_DEPTH = 32;
+ private final static int MATRIX_SIZE = 16;
+ private float[] mMatrix;
+ private int mTop;
+ private float[] mTemp;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixTrackingGL.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixTrackingGL.java
new file mode 100644
index 0000000..a02761d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/MatrixTrackingGL.java
@@ -0,0 +1,1086 @@
+/*
+ * Copyright (C) 2007 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.graphics.spritetext;
+
+import android.util.Log;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.opengles.GL;
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.opengles.GL10Ext;
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11Ext;
+
+/**
+ * Allows retrieving the current matrix even if the current OpenGL ES
+ * driver does not support retrieving the current matrix.
+ *
+ * Note: the actual matrix may differ from the retrieved matrix, due
+ * to differences in the way the math is implemented by GLMatrixWrapper
+ * as compared to the way the math is implemented by the OpenGL ES
+ * driver.
+ */
+class MatrixTrackingGL implements GL, GL10, GL10Ext, GL11, GL11Ext {
+ private GL10 mgl;
+ private GL10Ext mgl10Ext;
+ private GL11 mgl11;
+ private GL11Ext mgl11Ext;
+ private int mMatrixMode;
+ private MatrixStack mCurrent;
+ private MatrixStack mModelView;
+ private MatrixStack mTexture;
+ private MatrixStack mProjection;
+
+ private final static boolean _check = false;
+ ByteBuffer mByteBuffer;
+ FloatBuffer mFloatBuffer;
+ float[] mCheckA;
+ float[] mCheckB;
+
+ public MatrixTrackingGL(GL gl) {
+ mgl = (GL10) gl;
+ if (gl instanceof GL10Ext) {
+ mgl10Ext = (GL10Ext) gl;
+ }
+ if (gl instanceof GL11) {
+ mgl11 = (GL11) gl;
+ }
+ if (gl instanceof GL11Ext) {
+ mgl11Ext = (GL11Ext) gl;
+ }
+ mModelView = new MatrixStack();
+ mProjection = new MatrixStack();
+ mTexture = new MatrixStack();
+ mCurrent = mModelView;
+ mMatrixMode = GL10.GL_MODELVIEW;
+ }
+
+ // ---------------------------------------------------------------------
+ // GL10 methods:
+
+ public void glActiveTexture(int texture) {
+ mgl.glActiveTexture(texture);
+ }
+
+ public void glAlphaFunc(int func, float ref) {
+ mgl.glAlphaFunc(func, ref);
+ }
+
+ public void glAlphaFuncx(int func, int ref) {
+ mgl.glAlphaFuncx(func, ref);
+ }
+
+ public void glBindTexture(int target, int texture) {
+ mgl.glBindTexture(target, texture);
+ }
+
+ public void glBlendFunc(int sfactor, int dfactor) {
+ mgl.glBlendFunc(sfactor, dfactor);
+ }
+
+ public void glClear(int mask) {
+ mgl.glClear(mask);
+ }
+
+ public void glClearColor(float red, float green, float blue, float alpha) {
+ mgl.glClearColor(red, green, blue, alpha);
+ }
+
+ public void glClearColorx(int red, int green, int blue, int alpha) {
+ mgl.glClearColorx(red, green, blue, alpha);
+ }
+
+ public void glClearDepthf(float depth) {
+ mgl.glClearDepthf(depth);
+ }
+
+ public void glClearDepthx(int depth) {
+ mgl.glClearDepthx(depth);
+ }
+
+ public void glClearStencil(int s) {
+ mgl.glClearStencil(s);
+ }
+
+ public void glClientActiveTexture(int texture) {
+ mgl.glClientActiveTexture(texture);
+ }
+
+ public void glColor4f(float red, float green, float blue, float alpha) {
+ mgl.glColor4f(red, green, blue, alpha);
+ }
+
+ public void glColor4x(int red, int green, int blue, int alpha) {
+ mgl.glColor4x(red, green, blue, alpha);
+ }
+
+ public void glColorMask(boolean red, boolean green, boolean blue,
+ boolean alpha) {
+ mgl.glColorMask(red, green, blue, alpha);
+ }
+
+ public void glColorPointer(int size, int type, int stride, Buffer pointer) {
+ mgl.glColorPointer(size, type, stride, pointer);
+ }
+
+ public void glCompressedTexImage2D(int target, int level,
+ int internalformat, int width, int height, int border,
+ int imageSize, Buffer data) {
+ mgl.glCompressedTexImage2D(target, level, internalformat, width,
+ height, border, imageSize, data);
+ }
+
+ public void glCompressedTexSubImage2D(int target, int level, int xoffset,
+ int yoffset, int width, int height, int format, int imageSize,
+ Buffer data) {
+ mgl.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width,
+ height, format, imageSize, data);
+ }
+
+ public void glCopyTexImage2D(int target, int level, int internalformat,
+ int x, int y, int width, int height, int border) {
+ mgl.glCopyTexImage2D(target, level, internalformat, x, y, width,
+ height, border);
+ }
+
+ public void glCopyTexSubImage2D(int target, int level, int xoffset,
+ int yoffset, int x, int y, int width, int height) {
+ mgl.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width,
+ height);
+ }
+
+ public void glCullFace(int mode) {
+ mgl.glCullFace(mode);
+ }
+
+ public void glDeleteTextures(int n, int[] textures, int offset) {
+ mgl.glDeleteTextures(n, textures, offset);
+ }
+
+ public void glDeleteTextures(int n, IntBuffer textures) {
+ mgl.glDeleteTextures(n, textures);
+ }
+
+ public void glDepthFunc(int func) {
+ mgl.glDepthFunc(func);
+ }
+
+ public void glDepthMask(boolean flag) {
+ mgl.glDepthMask(flag);
+ }
+
+ public void glDepthRangef(float near, float far) {
+ mgl.glDepthRangef(near, far);
+ }
+
+ public void glDepthRangex(int near, int far) {
+ mgl.glDepthRangex(near, far);
+ }
+
+ public void glDisable(int cap) {
+ mgl.glDisable(cap);
+ }
+
+ public void glDisableClientState(int array) {
+ mgl.glDisableClientState(array);
+ }
+
+ public void glDrawArrays(int mode, int first, int count) {
+ mgl.glDrawArrays(mode, first, count);
+ }
+
+ public void glDrawElements(int mode, int count, int type, Buffer indices) {
+ mgl.glDrawElements(mode, count, type, indices);
+ }
+
+ public void glEnable(int cap) {
+ mgl.glEnable(cap);
+ }
+
+ public void glEnableClientState(int array) {
+ mgl.glEnableClientState(array);
+ }
+
+ public void glFinish() {
+ mgl.glFinish();
+ }
+
+ public void glFlush() {
+ mgl.glFlush();
+ }
+
+ public void glFogf(int pname, float param) {
+ mgl.glFogf(pname, param);
+ }
+
+ public void glFogfv(int pname, float[] params, int offset) {
+ mgl.glFogfv(pname, params, offset);
+ }
+
+ public void glFogfv(int pname, FloatBuffer params) {
+ mgl.glFogfv(pname, params);
+ }
+
+ public void glFogx(int pname, int param) {
+ mgl.glFogx(pname, param);
+ }
+
+ public void glFogxv(int pname, int[] params, int offset) {
+ mgl.glFogxv(pname, params, offset);
+ }
+
+ public void glFogxv(int pname, IntBuffer params) {
+ mgl.glFogxv(pname, params);
+ }
+
+ public void glFrontFace(int mode) {
+ mgl.glFrontFace(mode);
+ }
+
+ public void glFrustumf(float left, float right, float bottom, float top,
+ float near, float far) {
+ mCurrent.glFrustumf(left, right, bottom, top, near, far);
+ mgl.glFrustumf(left, right, bottom, top, near, far);
+ if ( _check) check();
+ }
+
+ public void glFrustumx(int left, int right, int bottom, int top, int near,
+ int far) {
+ mCurrent.glFrustumx(left, right, bottom, top, near, far);
+ mgl.glFrustumx(left, right, bottom, top, near, far);
+ if ( _check) check();
+ }
+
+ public void glGenTextures(int n, int[] textures, int offset) {
+ mgl.glGenTextures(n, textures, offset);
+ }
+
+ public void glGenTextures(int n, IntBuffer textures) {
+ mgl.glGenTextures(n, textures);
+ }
+
+ public int glGetError() {
+ int result = mgl.glGetError();
+ return result;
+ }
+
+ public void glGetIntegerv(int pname, int[] params, int offset) {
+ mgl.glGetIntegerv(pname, params, offset);
+ }
+
+ public void glGetIntegerv(int pname, IntBuffer params) {
+ mgl.glGetIntegerv(pname, params);
+ }
+
+ public String glGetString(int name) {
+ String result = mgl.glGetString(name);
+ return result;
+ }
+
+ public void glHint(int target, int mode) {
+ mgl.glHint(target, mode);
+ }
+
+ public void glLightModelf(int pname, float param) {
+ mgl.glLightModelf(pname, param);
+ }
+
+ public void glLightModelfv(int pname, float[] params, int offset) {
+ mgl.glLightModelfv(pname, params, offset);
+ }
+
+ public void glLightModelfv(int pname, FloatBuffer params) {
+ mgl.glLightModelfv(pname, params);
+ }
+
+ public void glLightModelx(int pname, int param) {
+ mgl.glLightModelx(pname, param);
+ }
+
+ public void glLightModelxv(int pname, int[] params, int offset) {
+ mgl.glLightModelxv(pname, params, offset);
+ }
+
+ public void glLightModelxv(int pname, IntBuffer params) {
+ mgl.glLightModelxv(pname, params);
+ }
+
+ public void glLightf(int light, int pname, float param) {
+ mgl.glLightf(light, pname, param);
+ }
+
+ public void glLightfv(int light, int pname, float[] params, int offset) {
+ mgl.glLightfv(light, pname, params, offset);
+ }
+
+ public void glLightfv(int light, int pname, FloatBuffer params) {
+ mgl.glLightfv(light, pname, params);
+ }
+
+ public void glLightx(int light, int pname, int param) {
+ mgl.glLightx(light, pname, param);
+ }
+
+ public void glLightxv(int light, int pname, int[] params, int offset) {
+ mgl.glLightxv(light, pname, params, offset);
+ }
+
+ public void glLightxv(int light, int pname, IntBuffer params) {
+ mgl.glLightxv(light, pname, params);
+ }
+
+ public void glLineWidth(float width) {
+ mgl.glLineWidth(width);
+ }
+
+ public void glLineWidthx(int width) {
+ mgl.glLineWidthx(width);
+ }
+
+ public void glLoadIdentity() {
+ mCurrent.glLoadIdentity();
+ mgl.glLoadIdentity();
+ if ( _check) check();
+ }
+
+ public void glLoadMatrixf(float[] m, int offset) {
+ mCurrent.glLoadMatrixf(m, offset);
+ mgl.glLoadMatrixf(m, offset);
+ if ( _check) check();
+ }
+
+ public void glLoadMatrixf(FloatBuffer m) {
+ int position = m.position();
+ mCurrent.glLoadMatrixf(m);
+ m.position(position);
+ mgl.glLoadMatrixf(m);
+ if ( _check) check();
+ }
+
+ public void glLoadMatrixx(int[] m, int offset) {
+ mCurrent.glLoadMatrixx(m, offset);
+ mgl.glLoadMatrixx(m, offset);
+ if ( _check) check();
+ }
+
+ public void glLoadMatrixx(IntBuffer m) {
+ int position = m.position();
+ mCurrent.glLoadMatrixx(m);
+ m.position(position);
+ mgl.glLoadMatrixx(m);
+ if ( _check) check();
+ }
+
+ public void glLogicOp(int opcode) {
+ mgl.glLogicOp(opcode);
+ }
+
+ public void glMaterialf(int face, int pname, float param) {
+ mgl.glMaterialf(face, pname, param);
+ }
+
+ public void glMaterialfv(int face, int pname, float[] params, int offset) {
+ mgl.glMaterialfv(face, pname, params, offset);
+ }
+
+ public void glMaterialfv(int face, int pname, FloatBuffer params) {
+ mgl.glMaterialfv(face, pname, params);
+ }
+
+ public void glMaterialx(int face, int pname, int param) {
+ mgl.glMaterialx(face, pname, param);
+ }
+
+ public void glMaterialxv(int face, int pname, int[] params, int offset) {
+ mgl.glMaterialxv(face, pname, params, offset);
+ }
+
+ public void glMaterialxv(int face, int pname, IntBuffer params) {
+ mgl.glMaterialxv(face, pname, params);
+ }
+
+ public void glMatrixMode(int mode) {
+ switch (mode) {
+ case GL10.GL_MODELVIEW:
+ mCurrent = mModelView;
+ break;
+ case GL10.GL_TEXTURE:
+ mCurrent = mTexture;
+ break;
+ case GL10.GL_PROJECTION:
+ mCurrent = mProjection;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown matrix mode: " + mode);
+ }
+ mgl.glMatrixMode(mode);
+ mMatrixMode = mode;
+ if ( _check) check();
+ }
+
+ public void glMultMatrixf(float[] m, int offset) {
+ mCurrent.glMultMatrixf(m, offset);
+ mgl.glMultMatrixf(m, offset);
+ if ( _check) check();
+ }
+
+ public void glMultMatrixf(FloatBuffer m) {
+ int position = m.position();
+ mCurrent.glMultMatrixf(m);
+ m.position(position);
+ mgl.glMultMatrixf(m);
+ if ( _check) check();
+ }
+
+ public void glMultMatrixx(int[] m, int offset) {
+ mCurrent.glMultMatrixx(m, offset);
+ mgl.glMultMatrixx(m, offset);
+ if ( _check) check();
+ }
+
+ public void glMultMatrixx(IntBuffer m) {
+ int position = m.position();
+ mCurrent.glMultMatrixx(m);
+ m.position(position);
+ mgl.glMultMatrixx(m);
+ if ( _check) check();
+ }
+
+ public void glMultiTexCoord4f(int target,
+ float s, float t, float r, float q) {
+ mgl.glMultiTexCoord4f(target, s, t, r, q);
+ }
+
+ public void glMultiTexCoord4x(int target, int s, int t, int r, int q) {
+ mgl.glMultiTexCoord4x(target, s, t, r, q);
+ }
+
+ public void glNormal3f(float nx, float ny, float nz) {
+ mgl.glNormal3f(nx, ny, nz);
+ }
+
+ public void glNormal3x(int nx, int ny, int nz) {
+ mgl.glNormal3x(nx, ny, nz);
+ }
+
+ public void glNormalPointer(int type, int stride, Buffer pointer) {
+ mgl.glNormalPointer(type, stride, pointer);
+ }
+
+ public void glOrthof(float left, float right, float bottom, float top,
+ float near, float far) {
+ mCurrent.glOrthof(left, right, bottom, top, near, far);
+ mgl.glOrthof(left, right, bottom, top, near, far);
+ if ( _check) check();
+ }
+
+ public void glOrthox(int left, int right, int bottom, int top, int near,
+ int far) {
+ mCurrent.glOrthox(left, right, bottom, top, near, far);
+ mgl.glOrthox(left, right, bottom, top, near, far);
+ if ( _check) check();
+ }
+
+ public void glPixelStorei(int pname, int param) {
+ mgl.glPixelStorei(pname, param);
+ }
+
+ public void glPointSize(float size) {
+ mgl.glPointSize(size);
+ }
+
+ public void glPointSizex(int size) {
+ mgl.glPointSizex(size);
+ }
+
+ public void glPolygonOffset(float factor, float units) {
+ mgl.glPolygonOffset(factor, units);
+ }
+
+ public void glPolygonOffsetx(int factor, int units) {
+ mgl.glPolygonOffsetx(factor, units);
+ }
+
+ public void glPopMatrix() {
+ mCurrent.glPopMatrix();
+ mgl.glPopMatrix();
+ if ( _check) check();
+ }
+
+ public void glPushMatrix() {
+ mCurrent.glPushMatrix();
+ mgl.glPushMatrix();
+ if ( _check) check();
+ }
+
+ public void glReadPixels(int x, int y, int width, int height, int format,
+ int type, Buffer pixels) {
+ mgl.glReadPixels(x, y, width, height, format, type, pixels);
+ }
+
+ public void glRotatef(float angle, float x, float y, float z) {
+ mCurrent.glRotatef(angle, x, y, z);
+ mgl.glRotatef(angle, x, y, z);
+ if ( _check) check();
+ }
+
+ public void glRotatex(int angle, int x, int y, int z) {
+ mCurrent.glRotatex(angle, x, y, z);
+ mgl.glRotatex(angle, x, y, z);
+ if ( _check) check();
+ }
+
+ public void glSampleCoverage(float value, boolean invert) {
+ mgl.glSampleCoverage(value, invert);
+ }
+
+ public void glSampleCoveragex(int value, boolean invert) {
+ mgl.glSampleCoveragex(value, invert);
+ }
+
+ public void glScalef(float x, float y, float z) {
+ mCurrent.glScalef(x, y, z);
+ mgl.glScalef(x, y, z);
+ if ( _check) check();
+ }
+
+ public void glScalex(int x, int y, int z) {
+ mCurrent.glScalex(x, y, z);
+ mgl.glScalex(x, y, z);
+ if ( _check) check();
+ }
+
+ public void glScissor(int x, int y, int width, int height) {
+ mgl.glScissor(x, y, width, height);
+ }
+
+ public void glShadeModel(int mode) {
+ mgl.glShadeModel(mode);
+ }
+
+ public void glStencilFunc(int func, int ref, int mask) {
+ mgl.glStencilFunc(func, ref, mask);
+ }
+
+ public void glStencilMask(int mask) {
+ mgl.glStencilMask(mask);
+ }
+
+ public void glStencilOp(int fail, int zfail, int zpass) {
+ mgl.glStencilOp(fail, zfail, zpass);
+ }
+
+ public void glTexCoordPointer(int size, int type,
+ int stride, Buffer pointer) {
+ mgl.glTexCoordPointer(size, type, stride, pointer);
+ }
+
+ public void glTexEnvf(int target, int pname, float param) {
+ mgl.glTexEnvf(target, pname, param);
+ }
+
+ public void glTexEnvfv(int target, int pname, float[] params, int offset) {
+ mgl.glTexEnvfv(target, pname, params, offset);
+ }
+
+ public void glTexEnvfv(int target, int pname, FloatBuffer params) {
+ mgl.glTexEnvfv(target, pname, params);
+ }
+
+ public void glTexEnvx(int target, int pname, int param) {
+ mgl.glTexEnvx(target, pname, param);
+ }
+
+ public void glTexEnvxv(int target, int pname, int[] params, int offset) {
+ mgl.glTexEnvxv(target, pname, params, offset);
+ }
+
+ public void glTexEnvxv(int target, int pname, IntBuffer params) {
+ mgl.glTexEnvxv(target, pname, params);
+ }
+
+ public void glTexImage2D(int target, int level, int internalformat,
+ int width, int height, int border, int format, int type,
+ Buffer pixels) {
+ mgl.glTexImage2D(target, level, internalformat, width, height, border,
+ format, type, pixels);
+ }
+
+ public void glTexParameterf(int target, int pname, float param) {
+ mgl.glTexParameterf(target, pname, param);
+ }
+
+ public void glTexParameterx(int target, int pname, int param) {
+ mgl.glTexParameterx(target, pname, param);
+ }
+
+ public void glTexParameteriv(int target, int pname, int[] params, int offset) {
+ mgl11.glTexParameteriv(target, pname, params, offset);
+ }
+
+ public void glTexParameteriv(int target, int pname, IntBuffer params) {
+ mgl11.glTexParameteriv(target, pname, params);
+ }
+
+ public void glTexSubImage2D(int target, int level, int xoffset,
+ int yoffset, int width, int height, int format, int type,
+ Buffer pixels) {
+ mgl.glTexSubImage2D(target, level, xoffset, yoffset, width, height,
+ format, type, pixels);
+ }
+
+ public void glTranslatef(float x, float y, float z) {
+ mCurrent.glTranslatef(x, y, z);
+ mgl.glTranslatef(x, y, z);
+ if ( _check) check();
+ }
+
+ public void glTranslatex(int x, int y, int z) {
+ mCurrent.glTranslatex(x, y, z);
+ mgl.glTranslatex(x, y, z);
+ if ( _check) check();
+ }
+
+ public void glVertexPointer(int size, int type,
+ int stride, Buffer pointer) {
+ mgl.glVertexPointer(size, type, stride, pointer);
+ }
+
+ public void glViewport(int x, int y, int width, int height) {
+ mgl.glViewport(x, y, width, height);
+ }
+
+ public void glClipPlanef(int plane, float[] equation, int offset) {
+ mgl11.glClipPlanef(plane, equation, offset);
+ }
+
+ public void glClipPlanef(int plane, FloatBuffer equation) {
+ mgl11.glClipPlanef(plane, equation);
+ }
+
+ public void glClipPlanex(int plane, int[] equation, int offset) {
+ mgl11.glClipPlanex(plane, equation, offset);
+ }
+
+ public void glClipPlanex(int plane, IntBuffer equation) {
+ mgl11.glClipPlanex(plane, equation);
+ }
+
+ // Draw Texture Extension
+
+ public void glDrawTexfOES(float x, float y, float z,
+ float width, float height) {
+ mgl11Ext.glDrawTexfOES(x, y, z, width, height);
+ }
+
+ public void glDrawTexfvOES(float[] coords, int offset) {
+ mgl11Ext.glDrawTexfvOES(coords, offset);
+ }
+
+ public void glDrawTexfvOES(FloatBuffer coords) {
+ mgl11Ext.glDrawTexfvOES(coords);
+ }
+
+ public void glDrawTexiOES(int x, int y, int z, int width, int height) {
+ mgl11Ext.glDrawTexiOES(x, y, z, width, height);
+ }
+
+ public void glDrawTexivOES(int[] coords, int offset) {
+ mgl11Ext.glDrawTexivOES(coords, offset);
+ }
+
+ public void glDrawTexivOES(IntBuffer coords) {
+ mgl11Ext.glDrawTexivOES(coords);
+ }
+
+ public void glDrawTexsOES(short x, short y, short z,
+ short width, short height) {
+ mgl11Ext.glDrawTexsOES(x, y, z, width, height);
+ }
+
+ public void glDrawTexsvOES(short[] coords, int offset) {
+ mgl11Ext.glDrawTexsvOES(coords, offset);
+ }
+
+ public void glDrawTexsvOES(ShortBuffer coords) {
+ mgl11Ext.glDrawTexsvOES(coords);
+ }
+
+ public void glDrawTexxOES(int x, int y, int z, int width, int height) {
+ mgl11Ext.glDrawTexxOES(x, y, z, width, height);
+ }
+
+ public void glDrawTexxvOES(int[] coords, int offset) {
+ mgl11Ext.glDrawTexxvOES(coords, offset);
+ }
+
+ public void glDrawTexxvOES(IntBuffer coords) {
+ mgl11Ext.glDrawTexxvOES(coords);
+ }
+
+ public int glQueryMatrixxOES(int[] mantissa, int mantissaOffset,
+ int[] exponent, int exponentOffset) {
+ return mgl10Ext.glQueryMatrixxOES(mantissa, mantissaOffset,
+ exponent, exponentOffset);
+ }
+
+ public int glQueryMatrixxOES(IntBuffer mantissa, IntBuffer exponent) {
+ return mgl10Ext.glQueryMatrixxOES(mantissa, exponent);
+ }
+
+ // Unsupported GL11 methods
+
+ public void glBindBuffer(int target, int buffer) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glBufferData(int target, int size, Buffer data, int usage) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glBufferSubData(int target, int offset, int size, Buffer data) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glColor4ub(byte red, byte green, byte blue, byte alpha) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glDeleteBuffers(int n, int[] buffers, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glDeleteBuffers(int n, IntBuffer buffers) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGenBuffers(int n, int[] buffers, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGenBuffers(int n, IntBuffer buffers) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetBooleanv(int pname, boolean[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetBooleanv(int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetBufferParameteriv(int target, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetBufferParameteriv(int target, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetClipPlanef(int pname, float[] eqn, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetClipPlanef(int pname, FloatBuffer eqn) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetClipPlanex(int pname, int[] eqn, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetClipPlanex(int pname, IntBuffer eqn) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetFixedv(int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetFixedv(int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetFloatv(int pname, float[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetFloatv(int pname, FloatBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetLightfv(int light, int pname, float[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetLightfv(int light, int pname, FloatBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetLightxv(int light, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetLightxv(int light, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetMaterialfv(int face, int pname, float[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetMaterialfv(int face, int pname, FloatBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetMaterialxv(int face, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetMaterialxv(int face, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexEnviv(int env, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexEnviv(int env, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexEnvxv(int env, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexEnvxv(int env, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexParameterfv(int target, int pname, float[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexParameterfv(int target, int pname, FloatBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexParameteriv(int target, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexParameteriv(int target, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexParameterxv(int target, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetTexParameterxv(int target, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean glIsBuffer(int buffer) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean glIsEnabled(int cap) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean glIsTexture(int texture) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glPointParameterf(int pname, float param) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glPointParameterfv(int pname, float[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glPointParameterfv(int pname, FloatBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glPointParameterx(int pname, int param) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glPointParameterxv(int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glPointParameterxv(int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glPointSizePointerOES(int type, int stride, Buffer pointer) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexEnvi(int target, int pname, int param) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexEnviv(int target, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexEnviv(int target, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexParameterfv(int target, int pname, float[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexParameterfv(int target, int pname, FloatBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexParameteri(int target, int pname, int param) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexParameterxv(int target, int pname, int[] params, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexParameterxv(int target, int pname, IntBuffer params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glColorPointer(int size, int type, int stride, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glDrawElements(int mode, int count, int type, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glGetPointerv(int pname, Buffer[] params) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glNormalPointer(int type, int stride, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glTexCoordPointer(int size, int type, int stride, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glVertexPointer(int size, int type, int stride, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glCurrentPaletteMatrixOES(int matrixpaletteindex) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glLoadPaletteFromModelViewMatrixOES() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glMatrixIndexPointerOES(int size, int type, int stride,
+ Buffer pointer) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glMatrixIndexPointerOES(int size, int type, int stride,
+ int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glWeightPointerOES(int size, int type, int stride,
+ Buffer pointer) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void glWeightPointerOES(int size, int type, int stride, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get the current matrix
+ */
+
+ public void getMatrix(float[] m, int offset) {
+ mCurrent.getMatrix(m, offset);
+ }
+
+ /**
+ * Get the current matrix mode
+ */
+
+ public int getMatrixMode() {
+ return mMatrixMode;
+ }
+
+ private void check() {
+ int oesMode;
+ switch (mMatrixMode) {
+ case GL_MODELVIEW:
+ oesMode = GL11.GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES;
+ break;
+ case GL_PROJECTION:
+ oesMode = GL11.GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES;
+ break;
+ case GL_TEXTURE:
+ oesMode = GL11.GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown matrix mode");
+ }
+
+ if ( mByteBuffer == null) {
+ mCheckA = new float[16];
+ mCheckB = new float[16];
+ mByteBuffer = ByteBuffer.allocateDirect(64);
+ mByteBuffer.order(ByteOrder.nativeOrder());
+ mFloatBuffer = mByteBuffer.asFloatBuffer();
+ }
+ mgl.glGetIntegerv(oesMode, mByteBuffer.asIntBuffer());
+ for(int i = 0; i < 16; i++) {
+ mCheckB[i] = mFloatBuffer.get(i);
+ }
+ mCurrent.getMatrix(mCheckA, 0);
+
+ boolean fail = false;
+ for(int i = 0; i < 16; i++) {
+ if (mCheckA[i] != mCheckB[i]) {
+ Log.d("GLMatWrap", "i:" + i + " a:" + mCheckA[i]
+ + " a:" + mCheckB[i]);
+ fail = true;
+ }
+ }
+ if (fail) {
+ throw new IllegalArgumentException("Matrix math difference.");
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/NumericSprite.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/NumericSprite.java
new file mode 100644
index 0000000..e70dfda
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/NumericSprite.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 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.graphics.spritetext;
+
+import javax.microedition.khronos.opengles.GL10;
+
+import android.graphics.Paint;
+
+public class NumericSprite {
+ public NumericSprite() {
+ mText = "";
+ mLabelMaker = null;
+ }
+
+ public void initialize(GL10 gl, Paint paint) {
+ int height = roundUpPower2((int) paint.getFontSpacing());
+ final float interDigitGaps = 9 * 1.0f;
+ int width = roundUpPower2((int) (interDigitGaps + paint.measureText(sStrike)));
+ mLabelMaker = new LabelMaker(true, width, height);
+ mLabelMaker.initialize(gl);
+ mLabelMaker.beginAdding(gl);
+ for (int i = 0; i < 10; i++) {
+ String digit = sStrike.substring(i, i+1);
+ mLabelId[i] = mLabelMaker.add(gl, digit, paint);
+ mWidth[i] = (int) Math.ceil(mLabelMaker.getWidth(i));
+ }
+ mLabelMaker.endAdding(gl);
+ }
+
+ public void shutdown(GL10 gl) {
+ mLabelMaker.shutdown(gl);
+ mLabelMaker = null;
+ }
+
+ /**
+ * Find the smallest power of two >= the input value.
+ * (Doesn't work for negative numbers.)
+ */
+ private int roundUpPower2(int x) {
+ x = x - 1;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >>16);
+ return x + 1;
+ }
+
+ public void setValue(int value) {
+ mText = format(value);
+ }
+
+ public void draw(GL10 gl, float x, float y,
+ float viewWidth, float viewHeight) {
+ int length = mText.length();
+ mLabelMaker.beginDrawing(gl, viewWidth, viewHeight);
+ for(int i = 0; i < length; i++) {
+ char c = mText.charAt(i);
+ int digit = c - '0';
+ mLabelMaker.draw(gl, x, y, mLabelId[digit]);
+ x += mWidth[digit];
+ }
+ mLabelMaker.endDrawing(gl);
+ }
+
+ public float width() {
+ float width = 0.0f;
+ int length = mText.length();
+ for(int i = 0; i < length; i++) {
+ char c = mText.charAt(i);
+ width += mWidth[c - '0'];
+ }
+ return width;
+ }
+
+ private String format(int value) {
+ return Integer.toString(value);
+ }
+
+ private LabelMaker mLabelMaker;
+ private String mText;
+ private int[] mWidth = new int[10];
+ private int[] mLabelId = new int[10];
+ private final static String sStrike = "0123456789";
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/Projector.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/Projector.java
new file mode 100644
index 0000000..b52fa3e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/Projector.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.graphics.spritetext;
+
+import android.opengl.Matrix;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A utility that projects
+ *
+ */
+class Projector {
+ public Projector() {
+ mMVP = new float[16];
+ mV = new float[4];
+ mGrabber = new MatrixGrabber();
+ }
+
+ public void setCurrentView(int x, int y, int width, int height) {
+ mX = x;
+ mY = y;
+ mViewWidth = width;
+ mViewHeight = height;
+ }
+
+ public void project(float[] obj, int objOffset, float[] win, int winOffset) {
+ if (!mMVPComputed) {
+ Matrix.multiplyMM(mMVP, 0, mGrabber.mProjection, 0, mGrabber.mModelView, 0);
+ mMVPComputed = true;
+ }
+
+ Matrix.multiplyMV(mV, 0, mMVP, 0, obj, objOffset);
+
+ float rw = 1.0f / mV[3];
+
+ win[winOffset] = mX + mViewWidth * (mV[0] * rw + 1.0f) * 0.5f;
+ win[winOffset + 1] = mY + mViewHeight * (mV[1] * rw + 1.0f) * 0.5f;
+ win[winOffset + 2] = (mV[2] * rw + 1.0f) * 0.5f;
+ }
+
+ /**
+ * Get the current projection matrix. Has the side-effect of
+ * setting current matrix mode to GL_PROJECTION
+ * @param gl
+ */
+ public void getCurrentProjection(GL10 gl) {
+ mGrabber.getCurrentProjection(gl);
+ mMVPComputed = false;
+ }
+
+ /**
+ * Get the current model view matrix. Has the side-effect of
+ * setting current matrix mode to GL_MODELVIEW
+ * @param gl
+ */
+ public void getCurrentModelView(GL10 gl) {
+ mGrabber.getCurrentModelView(gl);
+ mMVPComputed = false;
+ }
+
+ private MatrixGrabber mGrabber;
+ private boolean mMVPComputed;
+ private float[] mMVP;
+ private float[] mV;
+ private int mX;
+ private int mY;
+ private int mViewWidth;
+ private int mViewHeight;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
new file mode 100644
index 0000000..1e58dae
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 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.graphics.spritetext;
+
+import javax.microedition.khronos.opengles.GL;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+public class SpriteTextActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mGLSurfaceView = new GLSurfaceView(this);
+ mGLSurfaceView.setGLWrapper(new GLSurfaceView.GLWrapper() {
+ public GL wrap(GL gl) {
+ return new MatrixTrackingGL(gl);
+ }});
+ mGLSurfaceView.setRenderer(new SpriteTextRenderer(this));
+ setContentView(mGLSurfaceView);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGLSurfaceView.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGLSurfaceView.onResume();
+ }
+
+ private GLSurfaceView mGLSurfaceView;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
new file mode 100644
index 0000000..b9369cd
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2008 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.graphics.spritetext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Paint;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
+import android.os.SystemClock;
+
+import com.example.android.apis.R;
+
+public class SpriteTextRenderer implements GLSurfaceView.Renderer{
+
+ public SpriteTextRenderer(Context context) {
+ mContext = context;
+ mTriangle = new Triangle();
+ mProjector = new Projector();
+ mLabelPaint = new Paint();
+ mLabelPaint.setTextSize(32);
+ mLabelPaint.setAntiAlias(true);
+ mLabelPaint.setARGB(0xff, 0x00, 0x00, 0x00);
+ }
+
+ public int[] getConfigSpec() {
+ // We don't need a depth buffer, and don't care about our
+ // color depth.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 0,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+ GL10.GL_FASTEST);
+
+ gl.glClearColor(.5f, .5f, .5f, 1);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+
+ /*
+ * Create our texture. This has to be done each time the
+ * surface is created.
+ */
+
+ int[] textures = new int[1];
+ gl.glGenTextures(1, textures, 0);
+
+ mTextureID = textures[0];
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
+ GL10.GL_NEAREST);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D,
+ GL10.GL_TEXTURE_MAG_FILTER,
+ GL10.GL_LINEAR);
+
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+ GL10.GL_CLAMP_TO_EDGE);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+ GL10.GL_CLAMP_TO_EDGE);
+
+ gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+ GL10.GL_REPLACE);
+
+ InputStream is = mContext.getResources()
+ .openRawResource(R.drawable.robot);
+ Bitmap bitmap;
+ try {
+ bitmap = BitmapFactory.decodeStream(is);
+ } finally {
+ try {
+ is.close();
+ } catch(IOException e) {
+ // Ignore.
+ }
+ }
+
+ GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
+ bitmap.recycle();
+
+ if (mLabels != null) {
+ mLabels.shutdown(gl);
+ } else {
+ mLabels = new LabelMaker(true, 256, 64);
+ }
+ mLabels.initialize(gl);
+ mLabels.beginAdding(gl);
+ mLabelA = mLabels.add(gl, "A", mLabelPaint);
+ mLabelB = mLabels.add(gl, "B", mLabelPaint);
+ mLabelC = mLabels.add(gl, "C", mLabelPaint);
+ mLabelMsPF = mLabels.add(gl, "ms/f", mLabelPaint);
+ mLabels.endAdding(gl);
+
+ if (mNumericSprite != null) {
+ mNumericSprite.shutdown(gl);
+ } else {
+ mNumericSprite = new NumericSprite();
+ }
+ mNumericSprite.initialize(gl, mLabelPaint);
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+ GL10.GL_MODULATE);
+
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
+ GLU.gluLookAt(gl, 0.0f, 0.0f, -2.5f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f);
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+
+ gl.glActiveTexture(GL10.GL_TEXTURE0);
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+ gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+ GL10.GL_REPEAT);
+ gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+ GL10.GL_REPEAT);
+
+ long time = SystemClock.uptimeMillis() % 4000L;
+ float angle = 0.090f * ((int) time);
+
+ gl.glRotatef(angle, 0, 0, 1.0f);
+ gl.glScalef(2.0f, 2.0f, 2.0f);
+
+ mTriangle.draw(gl);
+
+ mProjector.getCurrentModelView(gl);
+ mLabels.beginDrawing(gl, mWidth, mHeight);
+ drawLabel(gl, 0, mLabelA);
+ drawLabel(gl, 1, mLabelB);
+ drawLabel(gl, 2, mLabelC);
+ float msPFX = mWidth - mLabels.getWidth(mLabelMsPF) - 1;
+ mLabels.draw(gl, msPFX, 0, mLabelMsPF);
+ mLabels.endDrawing(gl);
+
+ drawMsPF(gl, msPFX);
+ }
+
+ private void drawMsPF(GL10 gl, float rightMargin) {
+ long time = SystemClock.uptimeMillis();
+ if (mStartTime == 0) {
+ mStartTime = time;
+ }
+ if (mFrames++ == SAMPLE_PERIOD_FRAMES) {
+ mFrames = 0;
+ long delta = time - mStartTime;
+ mStartTime = time;
+ mMsPerFrame = (int) (delta * SAMPLE_FACTOR);
+ }
+ if (mMsPerFrame > 0) {
+ mNumericSprite.setValue(mMsPerFrame);
+ float numWidth = mNumericSprite.width();
+ float x = rightMargin - numWidth;
+ mNumericSprite.draw(gl, x, 0, mWidth, mHeight);
+ }
+ }
+
+ private void drawLabel(GL10 gl, int triangleVertex, int labelId) {
+ float x = mTriangle.getX(triangleVertex);
+ float y = mTriangle.getY(triangleVertex);
+ mScratch[0] = x;
+ mScratch[1] = y;
+ mScratch[2] = 0.0f;
+ mScratch[3] = 1.0f;
+ mProjector.project(mScratch, 0, mScratch, 4);
+ float sx = mScratch[4];
+ float sy = mScratch[5];
+ float height = mLabels.getHeight(labelId);
+ float width = mLabels.getWidth(labelId);
+ float tx = sx - width * 0.5f;
+ float ty = sy - height * 0.5f;
+ mLabels.draw(gl, tx, ty, labelId);
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
+ mWidth = w;
+ mHeight = h;
+ gl.glViewport(0, 0, w, h);
+ mProjector.setCurrentView(0, 0, w, h);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) w / h;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ mProjector.getCurrentProjection(gl);
+ }
+
+ private int mWidth;
+ private int mHeight;
+ private Context mContext;
+ private Triangle mTriangle;
+ private int mTextureID;
+ private int mFrames;
+ private int mMsPerFrame;
+ private final static int SAMPLE_PERIOD_FRAMES = 12;
+ private final static float SAMPLE_FACTOR = 1.0f / SAMPLE_PERIOD_FRAMES;
+ private long mStartTime;
+ private LabelMaker mLabels;
+ private Paint mLabelPaint;
+ private int mLabelA;
+ private int mLabelB;
+ private int mLabelC;
+ private int mLabelMsPF;
+ private Projector mProjector;
+ private NumericSprite mNumericSprite;
+ private float[] mScratch = new float[8];
+}
+
+class Triangle {
+ public Triangle() {
+
+ // Buffers to be passed to gl*Pointer() functions
+ // must be direct, i.e., they must be placed on the
+ // native heap where the garbage collector cannot
+ // move them.
+ //
+ // Buffers with multi-byte datatypes (e.g., short, int, float)
+ // must have their byte order set to native order
+
+ ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
+ vbb.order(ByteOrder.nativeOrder());
+ mFVertexBuffer = vbb.asFloatBuffer();
+
+ ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
+ tbb.order(ByteOrder.nativeOrder());
+ mTexBuffer = tbb.asFloatBuffer();
+
+ ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2);
+ ibb.order(ByteOrder.nativeOrder());
+ mIndexBuffer = ibb.asShortBuffer();
+
+ for (int i = 0; i < VERTS; i++) {
+ for(int j = 0; j < 3; j++) {
+ mFVertexBuffer.put(sCoords[i*3+j]);
+ }
+ }
+
+ for (int i = 0; i < VERTS; i++) {
+ for(int j = 0; j < 2; j++) {
+ mTexBuffer.put(sCoords[i*3+j] * 2.0f + 0.5f);
+ }
+ }
+
+ for(int i = 0; i < VERTS; i++) {
+ mIndexBuffer.put((short) i);
+ }
+
+ mFVertexBuffer.position(0);
+ mTexBuffer.position(0);
+ mIndexBuffer.position(0);
+ }
+
+ public void draw(GL10 gl) {
+ gl.glFrontFace(GL10.GL_CCW);
+ gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+ gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
+ gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS,
+ GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+ }
+
+ public float getX(int vertex) {
+ return sCoords[3*vertex];
+ }
+
+ public float getY(int vertex) {
+ return sCoords[3*vertex+1];
+ }
+
+ private final static int VERTS = 3;
+
+ private FloatBuffer mFVertexBuffer;
+ private FloatBuffer mTexBuffer;
+ private ShortBuffer mIndexBuffer;
+ // A unit-sided equalateral triangle centered on the origin.
+ private final static float[] sCoords = {
+ // X, Y, Z
+ -0.5f, -0.25f, 0,
+ 0.5f, -0.25f, 0,
+ 0.0f, 0.559016994f, 0
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo.java b/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo.java
new file mode 100644
index 0000000..4b89167
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo.java
@@ -0,0 +1,86 @@
+package com.example.android.apis.media;
+
+import com.example.android.apis.R;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class MediaPlayerDemo extends Activity {
+ private Button mlocalvideo;
+ private Button mresourcesvideo;
+ private Button mstreamvideo;
+ private Button mlocalaudio;
+ private Button mresourcesaudio;
+ private Button mstreamaudio;
+ private static final String MEDIA = "media";
+ private static final int LOCAL_AUDIO = 1;
+ private static final int STREAM_AUDIO = 2;
+ private static final int RESOURCES_AUDIO = 3;
+ private static final int LOCAL_VIDEO = 4;
+ private static final int STREAM_VIDEO = 5;
+ private static final int RESOURCES_VIDEO = 6;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ // TODO Auto-generated method stub
+ super.onCreate(icicle);
+ setContentView(R.layout.mediaplayer_1);
+ mlocalaudio = (Button) findViewById(R.id.localaudio);
+ mlocalaudio.setOnClickListener(mLocalAudioListener);
+ mresourcesaudio = (Button) findViewById(R.id.resourcesaudio);
+ mresourcesaudio.setOnClickListener(mResourcesAudioListener);
+
+ mlocalvideo = (Button) findViewById(R.id.localvideo);
+ mlocalvideo.setOnClickListener(mLocalVideoListener);
+ mstreamvideo = (Button) findViewById(R.id.streamvideo);
+ mstreamvideo.setOnClickListener(mStreamVideoListener);
+ }
+
+ private OnClickListener mLocalAudioListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent =
+ new Intent(MediaPlayerDemo.this.getApplication(),
+ MediaPlayerDemo_Audio.class);
+ intent.putExtra(MEDIA, LOCAL_AUDIO);
+ startActivity(intent);
+
+ }
+ };
+ private OnClickListener mResourcesAudioListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent =
+ new Intent(MediaPlayerDemo.this.getApplication(),
+ MediaPlayerDemo_Audio.class);
+ intent.putExtra(MEDIA, RESOURCES_AUDIO);
+ startActivity(intent);
+
+ }
+ };
+
+ private OnClickListener mLocalVideoListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent =
+ new Intent(MediaPlayerDemo.this,
+ MediaPlayerDemo_Video.class);
+ intent.putExtra(MEDIA, LOCAL_VIDEO);
+ startActivity(intent);
+
+ }
+ };
+ private OnClickListener mStreamVideoListener = new OnClickListener() {
+ public void onClick(View v) {
+ Intent intent =
+ new Intent(MediaPlayerDemo.this,
+ MediaPlayerDemo_Video.class);
+ intent.putExtra(MEDIA, STREAM_VIDEO);
+ startActivity(intent);
+
+ }
+ };
+
+
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Audio.java b/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Audio.java
new file mode 100644
index 0000000..39930f6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Audio.java
@@ -0,0 +1,85 @@
+package com.example.android.apis.media;
+
+import android.app.Activity;
+import android.media.MediaPlayer;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.android.apis.R;
+
+public class MediaPlayerDemo_Audio extends Activity {
+
+ private static final String TAG = "MediaPlayerDemo";
+ private MediaPlayer mMediaPlayer;
+ private static final String MEDIA = "media";
+ private static final int LOCAL_AUDIO = 1;
+ private static final int STREAM_AUDIO = 2;
+ private static final int RESOURCES_AUDIO = 3;
+ private static final int LOCAL_VIDEO = 4;
+ private static final int STREAM_VIDEO = 5;
+ private String path;
+
+ private TextView tx;
+
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ tx = new TextView(this);
+ setContentView(tx);
+ Bundle extras = getIntent().getExtras();
+ playAudio(extras.getInt(MEDIA));
+ }
+
+ private void playAudio(Integer media) {
+ try {
+ switch (media) {
+ case LOCAL_AUDIO:
+ /**
+ * TODO: Set the path variable to a local audio file path.
+ */
+ path = "";
+ if (path == "") {
+ // Tell the user to provide an audio file URL.
+ Toast
+ .makeText(
+ MediaPlayerDemo_Audio.this,
+ "Please edit MediaPlayer_Audio Activity, "
+ + "and set the path variable to your audio file path."
+ + " Your audio file must be stored on sdcard.",
+ Toast.LENGTH_LONG).show();
+
+ }
+ mMediaPlayer = new MediaPlayer();
+ mMediaPlayer.setDataSource(path);
+ mMediaPlayer.prepare();
+ mMediaPlayer.start();
+ break;
+ case RESOURCES_AUDIO:
+ /**
+ * TODO: Upload a audio file to res/raw folder and provide
+ * its resid in MediaPlayer.create() method.
+ */
+ mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
+ mMediaPlayer.start();
+
+ }
+ tx.setText("Playing audio...");
+
+ } catch (Exception e) {
+ Log.e(TAG, "error: " + e.getMessage(), e);
+ }
+
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ // TODO Auto-generated method stub
+ if (mMediaPlayer != null) {
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ }
+
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Video.java b/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Video.java
new file mode 100644
index 0000000..fd3c486
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Video.java
@@ -0,0 +1,169 @@
+package com.example.android.apis.media;
+
+import com.example.android.apis.R;
+import com.example.android.apis.app.AlarmController;
+
+import android.app.Activity;
+import android.graphics.PixelFormat;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnBufferingUpdateListener;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+
+public class MediaPlayerDemo_Video extends Activity implements
+ OnBufferingUpdateListener, OnCompletionListener,
+ MediaPlayer.OnPreparedListener, SurfaceHolder.Callback {
+
+ private static final String TAG = "MediaPlayerDemo";
+ private int mVideoWidth;
+ private int mVideoHeight;
+ private MediaPlayer mMediaPlayer;
+ private SurfaceView mPreview;
+ private SurfaceHolder holder;
+ private String path;
+ private Bundle extras;
+ private static final String MEDIA = "media";
+ private static final int LOCAL_AUDIO = 1;
+ private static final int STREAM_AUDIO = 2;
+ private static final int RESOURCES_AUDIO = 3;
+ private static final int LOCAL_VIDEO = 4;
+ private static final int STREAM_VIDEO = 5;
+
+ /**
+ *
+ * Called when the activity is first created.
+ */
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.mediaplayer_2);
+ mPreview = (SurfaceView) findViewById(R.id.surface);
+ holder = mPreview.getHolder();
+ holder.addCallback(this);
+ holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ extras = getIntent().getExtras();
+
+ }
+
+ private void playVideo(Integer Media) {
+ try {
+
+ switch (Media) {
+ case LOCAL_VIDEO:
+ /*
+ * TODO: Set the path variable to a local media file path.
+ */
+ path = "";
+ if (path == "") {
+ // Tell the user to provide a media file URL.
+ Toast
+ .makeText(
+ MediaPlayerDemo_Video.this,
+ "Please edit MediaPlayerDemo_Video Activity, "
+ + "and set the path variable to your media file path."
+ + " Your media file must be stored on sdcard.",
+ Toast.LENGTH_LONG).show();
+
+ }
+ break;
+ case STREAM_VIDEO:
+ /*
+ * TODO: Set path variable to progressive streamable mp4 or
+ * 3gpp format URL. Http protocol should be used.
+ * Mediaplayer can only play "progressive streamable
+ * contents" which basically means: 1. the movie atom has to
+ * precede all the media data atoms. 2. The clip has to be
+ * reasonably interleaved.
+ *
+ */
+ path = "";
+ if (path == "") {
+ // Tell the user to provide a media file URL.
+ Toast
+ .makeText(
+ MediaPlayerDemo_Video.this,
+ "Please edit MediaPlayerDemo_Video Activity,"
+ + " and set the path variable to your media file URL.",
+ Toast.LENGTH_LONG).show();
+
+ }
+
+ break;
+
+
+ }
+
+ // Create a new media player and set the listeners
+ mMediaPlayer = new MediaPlayer();
+ mMediaPlayer.setDataSource(path);
+ mMediaPlayer.setDisplay(holder);
+ mMediaPlayer.prepare();
+ mMediaPlayer.setOnBufferingUpdateListener(this);
+ mMediaPlayer.setOnCompletionListener(this);
+ mMediaPlayer.setOnPreparedListener(this);
+ mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+
+
+ } catch (Exception e) {
+ Log.e(TAG, "error: " + e.getMessage(), e);
+ }
+ }
+
+ public void onBufferingUpdate(MediaPlayer arg0, int percent) {
+ Log.d(TAG, "onBufferingUpdate percent:" + percent);
+
+ }
+
+ public void onCompletion(MediaPlayer arg0) {
+ Log.d(TAG, "onCompletion called");
+ }
+
+ public void onPrepared(MediaPlayer mediaplayer) {
+ Log.d(TAG, "onPrepared called");
+ mVideoWidth = mMediaPlayer.getVideoWidth();
+ mVideoHeight = mMediaPlayer.getVideoHeight();
+ if (mVideoWidth != 0 && mVideoHeight != 0) {
+ holder.setFixedSize(mVideoWidth, mVideoHeight);
+ mMediaPlayer.start();
+ }
+
+ }
+
+ public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
+ Log.d(TAG, "surfaceChanged called");
+
+ }
+
+ public void surfaceDestroyed(SurfaceHolder surfaceholder) {
+ Log.d(TAG, "surfaceDestroyed called");
+ }
+
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ // TODO Auto-generated method stub
+ Log.d(TAG, "surfaceCreated called");
+ playVideo(extras.getInt(MEDIA));
+
+
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ // TODO Auto-generated method stub
+ if (mMediaPlayer != null) {
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ }
+
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/media/VideoViewDemo.java b/samples/ApiDemos/src/com/example/android/apis/media/VideoViewDemo.java
new file mode 100644
index 0000000..a4fcf5f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/media/VideoViewDemo.java
@@ -0,0 +1,48 @@
+package com.example.android.apis.media;
+
+import com.example.android.apis.R;
+import android.app.Activity;
+import android.graphics.PixelFormat;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.MediaController;
+import android.widget.Toast;
+import android.widget.VideoView;
+
+public class VideoViewDemo extends Activity {
+
+ /**
+ * TODO: Set the path variable to a streaming video URL or a local media
+ * file path.
+ */
+ private String path = "";
+ private VideoView mVideoView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.videoview);
+ mVideoView = (VideoView) findViewById(R.id.surface_view);
+
+ if (path == "") {
+ // Tell the user to provide a media file URL/path.
+ Toast.makeText(
+ VideoViewDemo.this,
+ "Please edit VideoViewDemo Activity, and set path"
+ + " variable to your media file URL/path",
+ Toast.LENGTH_LONG).show();
+
+ } else {
+
+ /*
+ * Alternatively,for streaming media you can use
+ * mVideoView.setVideoURI(Uri.parse(URLstring));
+ */
+ mVideoView.setVideoPath(path);
+ mVideoView.setMediaController(new MediaController(this));
+ mVideoView.requestFocus();
+
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/os/MorseCode.java b/samples/ApiDemos/src/com/example/android/apis/os/MorseCode.java
new file mode 100644
index 0000000..dafa192
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/os/MorseCode.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007 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.os;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Vibrator;
+import android.view.View;
+import android.widget.TextView;
+import com.example.android.apis.R;
+
+/**
+ * <h3>App that vibrates the vibrator with the Morse Code for a string.</h3>
+
+<p>This demonstrates the {@link android.os.Vibrator android.os.Vibrator} class.
+
+<h4>Demo</h4>
+OS / Morse Code Vibrator
+
+<h4>Source files</h4>
+ * <table class="LinkTable">
+ * <tr>
+ * <td >src/com.example.android.apis/os/MorseCode.java</td>
+ * <td >The Morse Code Vibrator</td>
+ * </tr>
+ * <tr>
+ * <td >res/any/layout/morse_code.xml</td>
+ * <td >Defines contents of the screen</td>
+ * </tr>
+ * </table>
+ */
+public class MorseCode extends Activity
+{
+ /** Tag string for our debug logs */
+ private static final String TAG = "MorseCode";
+
+ /** Our text view */
+ private TextView mTextView;
+
+ ;
+
+ /**
+ * 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);
+
+ // See assets/res/any/layout/hello_world.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.morse_code);
+
+ // Set the OnClickListener for the button so we see when it's pressed.
+ findViewById(R.id.button).setOnClickListener(mClickListener);
+
+ // Save the text view so we don't have to look it up each time
+ mTextView = (TextView)findViewById(R.id.text);
+ }
+
+ /** Called when the button is pushed */
+ View.OnClickListener mClickListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ // Get the text out of the view
+ String text = mTextView.getText().toString();
+
+ // convert it using the function defined above. See the docs for
+ // android.os.Vibrator for more info about the format of this array
+ long[] pattern = MorseCodeConverter.pattern(text);
+
+ // Start the vibration
+ Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
+ vibrator.vibrate(pattern, -1);
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/os/MorseCodeConverter.java b/samples/ApiDemos/src/com/example/android/apis/os/MorseCodeConverter.java
new file mode 100644
index 0000000..c68fab9
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/os/MorseCodeConverter.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008 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.os;
+
+/** Class that implements the text to morse code coversion */
+class MorseCodeConverter {
+ private static final long SPEED_BASE = 100;
+ static final long DOT = SPEED_BASE;
+ static final long DASH = SPEED_BASE * 3;
+ static final long GAP = SPEED_BASE;
+ static final long LETTER_GAP = SPEED_BASE * 3;
+ static final long WORD_GAP = SPEED_BASE * 7;
+
+ /** The characters from 'A' to 'Z' */
+ private static final long[][] LETTERS = new long[][] {
+ /* A */ new long[] { DOT, GAP, DASH },
+ /* B */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DOT },
+ /* C */ new long[] { DASH, GAP, DOT, GAP, DASH, GAP, DOT },
+ /* D */ new long[] { DASH, GAP, DOT, GAP, DOT },
+ /* E */ new long[] { DOT },
+ /* F */ new long[] { DOT, GAP, DOT, GAP, DASH, GAP, DOT },
+ /* G */ new long[] { DASH, GAP, DASH, GAP, DOT },
+ /* H */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DOT },
+ /* I */ new long[] { DOT, GAP, DOT },
+ /* J */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DASH },
+ /* K */ new long[] { DASH, GAP, DOT, GAP, DASH },
+ /* L */ new long[] { DOT, GAP, DASH, GAP, DOT, GAP, DOT },
+ /* M */ new long[] { DASH, GAP, DASH },
+ /* N */ new long[] { DASH, GAP, DOT },
+ /* O */ new long[] { DASH, GAP, DASH, GAP, DASH },
+ /* P */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DOT },
+ /* Q */ new long[] { DASH, GAP, DASH, GAP, DOT, GAP, DASH },
+ /* R */ new long[] { DOT, GAP, DASH, GAP, DOT },
+ /* S */ new long[] { DOT, GAP, DOT, GAP, DOT },
+ /* T */ new long[] { DASH },
+ /* U */ new long[] { DOT, GAP, DOT, GAP, DASH },
+ /* V */ new long[] { DOT, GAP, DOT, GAP, DASH },
+ /* W */ new long[] { DOT, GAP, DASH, GAP, DASH },
+ /* X */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DASH },
+ /* Y */ new long[] { DASH, GAP, DOT, GAP, DASH, GAP, DASH },
+ /* Z */ new long[] { DASH, GAP, DASH, GAP, DOT, GAP, DOT },
+ };
+
+ /** The characters from '0' to '9' */
+ private static final long[][] NUMBERS = new long[][] {
+ /* 0 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DASH, GAP, DASH },
+ /* 1 */ new long[] { DOT, GAP, DASH, GAP, DASH, GAP, DASH, GAP, DASH },
+ /* 2 */ new long[] { DOT, GAP, DOT, GAP, DASH, GAP, DASH, GAP, DASH },
+ /* 3 */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DASH, GAP, DASH },
+ /* 4 */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DOT, GAP, DASH },
+ /* 5 */ new long[] { DOT, GAP, DOT, GAP, DOT, GAP, DOT, GAP, DOT },
+ /* 6 */ new long[] { DASH, GAP, DOT, GAP, DOT, GAP, DOT, GAP, DOT },
+ /* 7 */ new long[] { DASH, GAP, DASH, GAP, DOT, GAP, DOT, GAP, DOT },
+ /* 8 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DOT, GAP, DOT },
+ /* 9 */ new long[] { DASH, GAP, DASH, GAP, DASH, GAP, DASH, GAP, DOT },
+ };
+
+ private static final long[] ERROR_GAP = new long[] { GAP };
+
+ /** Return the pattern data for a given character */
+ static long[] pattern(char c) {
+ if (c >= 'A' && c <= 'Z') {
+ return LETTERS[c - 'A'];
+ }
+ if (c >= 'a' && c <= 'z') {
+ return LETTERS[c - 'a'];
+ }
+ else if (c >= '0' && c <= '9') {
+ return NUMBERS[c - '0'];
+ }
+ else {
+ return ERROR_GAP;
+ }
+ }
+
+ static long[] pattern(String str) {
+ boolean lastWasWhitespace;
+ int strlen = str.length();
+
+ // Calculate how long our array needs to be.
+ int len = 1;
+ lastWasWhitespace = true;
+ for (int i=0; i<strlen; i++) {
+ char c = str.charAt(i);
+ if (Character.isWhitespace(c)) {
+ if (!lastWasWhitespace) {
+ len++;
+ lastWasWhitespace = true;
+ }
+ } else {
+ if (!lastWasWhitespace) {
+ len++;
+ }
+ lastWasWhitespace = false;
+ len += pattern(c).length;
+ }
+ }
+
+ // Generate the pattern array. Note that we put an extra element of 0
+ // in at the beginning, because the pattern always starts with the pause,
+ // not with the vibration.
+ long[] result = new long[len+1];
+ result[0] = 0;
+ int pos = 1;
+ lastWasWhitespace = true;
+ for (int i=0; i<strlen; i++) {
+ char c = str.charAt(i);
+ if (Character.isWhitespace(c)) {
+ if (!lastWasWhitespace) {
+ result[pos] = WORD_GAP;
+ pos++;
+ lastWasWhitespace = true;
+ }
+ } else {
+ if (!lastWasWhitespace) {
+ result[pos] = LETTER_GAP;
+ pos++;
+ }
+ lastWasWhitespace = false;
+ long[] letter = pattern(c);
+ System.arraycopy(letter, 0, result, pos, letter.length);
+ pos += letter.length;
+ }
+ }
+ return result;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/os/Sensors.java b/samples/ApiDemos/src/com/example/android/apis/os/Sensors.java
new file mode 100644
index 0000000..910961d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/os/Sensors.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007 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.os;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.hardware.SensorManager;
+import android.hardware.SensorListener;
+import android.util.Log;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+/**
+ * <h3>Application that displays the values of the acceleration sensor graphically.</h3>
+
+<p>This demonstrates the {@link android.hardware.SensorManager android.hardware.SensorManager} class.
+
+<h4>Demo</h4>
+OS / Sensors
+
+<h4>Source files</h4>
+ * <table class="LinkTable">
+ * <tr>
+ * <td >src/com.example.android.apis/os/Sensors.java</td>
+ * <td >Sensors</td>
+ * </tr>
+ * </table>
+ */
+public class Sensors extends Activity {
+ /** Tag string for our debug logs */
+ private static final String TAG = "Sensors";
+
+ private SensorManager mSensorManager;
+ private GraphView mGraphView;
+
+ private class GraphView extends View implements SensorListener
+ {
+ private Bitmap mBitmap;
+ private Paint mPaint = new Paint();
+ private Canvas mCanvas = new Canvas();
+ private Path mPath = new Path();
+ private RectF mRect = new RectF();
+ private float mLastValues[] = new float[3*2];
+ private float mOrientationValues[] = new float[3];
+ private int mColors[] = new int[3*2];
+ private float mLastX;
+ private float mScale[] = new float[2];
+ private float mYOffset;
+ private float mMaxX;
+ private float mSpeed = 1.0f;
+ private float mWidth;
+ private float mHeight;
+
+ public GraphView(Context context) {
+ super(context);
+ mColors[0] = Color.argb(192, 255, 64, 64);
+ mColors[1] = Color.argb(192, 64, 128, 64);
+ mColors[2] = Color.argb(192, 64, 64, 255);
+ mColors[3] = Color.argb(192, 64, 255, 255);
+ mColors[4] = Color.argb(192, 128, 64, 128);
+ mColors[5] = Color.argb(192, 255, 255, 64);
+
+ mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ mRect.set(-0.5f, -0.5f, 0.5f, 0.5f);
+ mPath.arcTo(mRect, 0, 180);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
+ mCanvas.setBitmap(mBitmap);
+ mCanvas.drawColor(0xFFFFFFFF);
+ mYOffset = h * 0.5f;
+ mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
+ mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
+ mWidth = w;
+ mHeight = h;
+ if (mWidth < mHeight) {
+ mMaxX = w;
+ } else {
+ mMaxX = w-50;
+ }
+ mLastX = mMaxX;
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ synchronized (this) {
+ if (mBitmap != null) {
+ final Paint paint = mPaint;
+ final Path path = mPath;
+ final int outer = 0xFFC0C0C0;
+ final int inner = 0xFFff7010;
+
+ if (mLastX >= mMaxX) {
+ mLastX = 0;
+ final Canvas cavas = mCanvas;
+ final float yoffset = mYOffset;
+ final float maxx = mMaxX;
+ final float oneG = SensorManager.STANDARD_GRAVITY * mScale[0];
+ paint.setColor(0xFFAAAAAA);
+ cavas.drawColor(0xFFFFFFFF);
+ cavas.drawLine(0, yoffset, maxx, yoffset, paint);
+ cavas.drawLine(0, yoffset+oneG, maxx, yoffset+oneG, paint);
+ cavas.drawLine(0, yoffset-oneG, maxx, yoffset-oneG, paint);
+ }
+ canvas.drawBitmap(mBitmap, 0, 0, null);
+
+ float[] values = mOrientationValues;
+ if (mWidth < mHeight) {
+ float w0 = mWidth * 0.333333f;
+ float w = w0 - 32;
+ float x = w0*0.5f;
+ for (int i=0 ; i<3 ; i++) {
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.translate(x, w*0.5f + 4.0f);
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ paint.setColor(outer);
+ canvas.scale(w, w);
+ canvas.drawOval(mRect, paint);
+ canvas.restore();
+ canvas.scale(w-5, w-5);
+ paint.setColor(inner);
+ canvas.rotate(-values[i]);
+ canvas.drawPath(path, paint);
+ canvas.restore();
+ x += w0;
+ }
+ } else {
+ float h0 = mHeight * 0.333333f;
+ float h = h0 - 32;
+ float y = h0*0.5f;
+ for (int i=0 ; i<3 ; i++) {
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.translate(mWidth - (h*0.5f + 4.0f), y);
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ paint.setColor(outer);
+ canvas.scale(h, h);
+ canvas.drawOval(mRect, paint);
+ canvas.restore();
+ canvas.scale(h-5, h-5);
+ paint.setColor(inner);
+ canvas.rotate(-values[i]);
+ canvas.drawPath(path, paint);
+ canvas.restore();
+ y += h0;
+ }
+ }
+
+ }
+ }
+ }
+
+ public void onSensorChanged(int sensor, float[] values) {
+ //Log.d(TAG, "sensor: " + sensor + ", x: " + values[0] + ", y: " + values[1] + ", z: " + values[2]);
+ synchronized (this) {
+ if (mBitmap != null) {
+ final Canvas canvas = mCanvas;
+ final Paint paint = mPaint;
+ if (sensor == SensorManager.SENSOR_ORIENTATION) {
+ for (int i=0 ; i<3 ; i++) {
+ mOrientationValues[i] = values[i];
+ }
+ } else {
+ float deltaX = mSpeed;
+ float newX = mLastX + deltaX;
+
+ int j = (sensor == SensorManager.SENSOR_MAGNETIC_FIELD) ? 1 : 0;
+ for (int i=0 ; i<3 ; i++) {
+ int k = i+j*3;
+ final float v = mYOffset + values[i] * mScale[j];
+ paint.setColor(mColors[k]);
+ canvas.drawLine(mLastX, mLastValues[k], newX, v, paint);
+ mLastValues[k] = v;
+ }
+ if (sensor == SensorManager.SENSOR_MAGNETIC_FIELD)
+ mLastX += mSpeed;
+ }
+ invalidate();
+ }
+ }
+ }
+
+ public void onAccuracyChanged(int sensor, int accuracy) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ /**
+ * 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);
+
+ mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
+ mGraphView = new GraphView(this);
+ setContentView(mGraphView);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mSensorManager.registerListener(mGraphView,
+ SensorManager.SENSOR_ACCELEROMETER |
+ SensorManager.SENSOR_MAGNETIC_FIELD |
+ SensorManager.SENSOR_ORIENTATION,
+ SensorManager.SENSOR_DELAY_FASTEST);
+ }
+
+ @Override
+ protected void onStop() {
+ mSensorManager.unregisterListener(mGraphView);
+ super.onStop();
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/Link.java b/samples/ApiDemos/src/com/example/android/apis/text/Link.java
new file mode 100644
index 0000000..b569d19
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/text/Link.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.text;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.text.Html;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.style.StyleSpan;
+import android.text.style.URLSpan;
+import android.widget.TextView;
+
+public class Link extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.link);
+
+ // text1 shows the android:autoLink property, which
+ // automatically linkifies things like URLs and phone numbers
+ // found in the text. No java code is needed to make this
+ // work.
+
+ // text2 has links specified by putting <a> tags in the string
+ // resource. By default these links will appear but not
+ // respond to user input. To make them active, you need to
+ // call setMovementMethod() on the TextView object.
+
+ TextView t2 = (TextView) findViewById(R.id.text2);
+ t2.setMovementMethod(LinkMovementMethod.getInstance());
+
+ // text3 shows creating text with links from HTML in the Java
+ // code, rather than from a string resource. Note that for a
+ // fixed string, using a (localizable) resource as shown above
+ // is usually a better way to go; this example is intended to
+ // illustrate how you might display text that came from a
+ // dynamic source (eg, the network).
+
+ TextView t3 = (TextView) findViewById(R.id.text3);
+ t3.setText(
+ Html.fromHtml(
+ "<b>text3:</b> Text with a " +
+ "<a href=\"http://www.google.com\">link</a> " +
+ "created in the Java source code using HTML."));
+ t3.setMovementMethod(LinkMovementMethod.getInstance());
+
+ // text4 illustrates constructing a styled string containing a
+ // link without using HTML at all. Again, for a fixed string
+ // you should probably be using a string resource, not a
+ // hardcoded value.
+
+ SpannableString ss = new SpannableString(
+ "text4: Click here to dial the phone.");
+
+ ss.setSpan(new StyleSpan(Typeface.BOLD), 0, 6,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ss.setSpan(new URLSpan("tel:4155551212"), 13, 17,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ TextView t4 = (TextView) findViewById(R.id.text4);
+ t4.setText(ss);
+ t4.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/LogTextBox.java b/samples/ApiDemos/src/com/example/android/apis/text/LogTextBox.java
new file mode 100644
index 0000000..c78b54b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/text/LogTextBox.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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.text;
+
+import android.widget.TextView;
+import android.content.Context;
+import android.text.method.ScrollingMovementMethod;
+import android.text.method.MovementMethod;
+import android.text.method.KeyListener;
+import android.text.method.TransformationMethod;
+import android.text.Editable;
+import android.util.AttributeSet;
+
+import java.util.Map;
+
+/**
+ * This is a TextView that is Editable and by default scrollable,
+ * like EditText without a cursor.
+ *
+ * <p>
+ * <b>XML attributes</b>
+ * <p>
+ * See
+ * {@link android.R.styleable#TextView TextView Attributes},
+ * {@link android.R.styleable#View View Attributes}
+ */
+public class LogTextBox extends TextView {
+ public LogTextBox(Context context) {
+ this(context, null);
+ }
+
+ public LogTextBox(Context context, AttributeSet attrs) {
+ this(context, attrs, android.R.attr.textViewStyle);
+ }
+
+ public LogTextBox(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected MovementMethod getDefaultMovementMethod() {
+ return ScrollingMovementMethod.getInstance();
+ }
+
+ @Override
+ public Editable getText() {
+ return (Editable) super.getText();
+ }
+
+ @Override
+ public void setText(CharSequence text, BufferType type) {
+ super.setText(text, BufferType.EDITABLE);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/LogTextBox1.java b/samples/ApiDemos/src/com/example/android/apis/text/LogTextBox1.java
new file mode 100644
index 0000000..1813629
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/text/LogTextBox1.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 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.text;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+/**
+ * Using a LogTextBox to display a scrollable text area
+ * to which text is appended.
+ *
+ */
+public class LogTextBox1 extends Activity {
+
+ private LogTextBox mText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.log_text_box_1);
+
+ mText = (LogTextBox) findViewById(R.id.text);
+
+ Button addButton = (Button) findViewById(R.id.add);
+ addButton.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View v) {
+ mText.append("This is a test\n");
+ } });
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java b/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java
new file mode 100644
index 0000000..ba82ed6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 Google Inc.
+ *
+ * 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.text;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Marquee extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.marquee);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/_index.html b/samples/ApiDemos/src/com/example/android/apis/text/_index.html
new file mode 100644
index 0000000..ee1020b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/text/_index.html
@@ -0,0 +1,6 @@
+<dl>
+ <dt><a href="Link.html">Linkify</a></dt>
+ <dd>Demonstrates the {@link android.text.util.Linkify Linkify} class, which converts URLs in a block of text into hyperlinks. </dd>
+</dl>
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Animation1.java b/samples/ApiDemos/src/com/example/android/apis/view/Animation1.java
new file mode 100644
index 0000000..73563f3
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Animation1.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+
+public class Animation1 extends Activity implements View.OnClickListener {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.animation_1);
+
+ View loginButton = findViewById(R.id.login);
+ loginButton.setOnClickListener(this);
+ }
+
+ public void onClick(View v) {
+ Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
+ findViewById(R.id.pw).startAnimation(shake);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Animation2.java b/samples/ApiDemos/src/com/example/android/apis/view/Animation2.java
new file mode 100644
index 0000000..b2236aa
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Animation2.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.ViewFlipper;
+
+
+public class Animation2 extends Activity implements
+ AdapterView.OnItemSelectedListener {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.animation_2);
+
+ mFlipper = ((ViewFlipper) this.findViewById(R.id.flipper));
+ mFlipper.startFlipping();
+
+ Spinner s = (Spinner) findViewById(R.id.spinner);
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, mStrings);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ s.setAdapter(adapter);
+ s.setOnItemSelectedListener(this);
+ }
+
+ public void onItemSelected(AdapterView parent, View v, int position, long id) {
+ switch (position) {
+
+ case 0:
+ mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
+ R.anim.push_up_in));
+ mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,
+ R.anim.push_up_out));
+ break;
+ case 1:
+ mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
+ R.anim.push_left_in));
+ mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,
+ R.anim.push_left_out));
+ break;
+ case 2:
+ mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
+ android.R.anim.fade_in));
+ mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,
+ android.R.anim.fade_out));
+ break;
+ default:
+ mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
+ R.anim.hyperspace_in));
+ mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,
+ R.anim.hyperspace_out));
+ break;
+ }
+ }
+
+ public void onNothingSelected(AdapterView parent) {
+ }
+
+ private String[] mStrings = {
+ "Push up", "Push left", "Cross fade", "Hyperspace"};
+
+ private ViewFlipper mFlipper;
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete1.java b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete1.java
new file mode 100644
index 0000000..f4274e5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete1.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.Spinner;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.os.Bundle;
+import android.view.View;
+
+
+public class AutoComplete1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.autocomplete_1);
+
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_dropdown_item_1line, COUNTRIES);
+ AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
+ textView.setAdapter(adapter);
+ }
+
+ static final String[] COUNTRIES = new String[] {
+ "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+ "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+ "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+ "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+ "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+ "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
+ "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
+ "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+ "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+ "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+ "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+ "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+ "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+ "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+ "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+ "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+ "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+ "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+ "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+ "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+ "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+ "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+ "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+ "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+ "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+ "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+ "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+ "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+ "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+ "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+ "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+ "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+ "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+ "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+ "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+ "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+ "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+ "Ukraine", "United Arab Emirates", "United Kingdom",
+ "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+ "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+ "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete2.java b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete2.java
new file mode 100644
index 0000000..2dcfc12
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete2.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+
+
+public class AutoComplete2 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.autocomplete_2);
+
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_dropdown_item_1line,
+ AutoComplete1.COUNTRIES);
+ AutoCompleteTextView textView = (AutoCompleteTextView)
+ findViewById(R.id.edit);
+ textView.setAdapter(adapter);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete3.java b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete3.java
new file mode 100644
index 0000000..bb9408f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete3.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+
+
+public class AutoComplete3 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.autocomplete_3);
+
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_dropdown_item_1line,
+ AutoComplete1.COUNTRIES);
+ AutoCompleteTextView textView = (AutoCompleteTextView)
+ findViewById(R.id.edit);
+ textView.setAdapter(adapter);
+ textView = (AutoCompleteTextView) findViewById(R.id.edit2);
+ textView.setAdapter(adapter);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete4.java b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete4.java
new file mode 100644
index 0000000..c6fa08b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete4.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Contacts;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AutoCompleteTextView;
+import android.widget.CursorAdapter;
+import android.widget.Filterable;
+import android.widget.TextView;
+
+public class AutoComplete4 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.autocomplete_4);
+
+ ContentResolver content = getContentResolver();
+ Cursor cursor = content.query(Contacts.People.CONTENT_URI,
+ PEOPLE_PROJECTION, null, null, Contacts.People.DEFAULT_SORT_ORDER);
+ ContactListAdapter adapter = new ContactListAdapter(this, cursor);
+
+ AutoCompleteTextView textView = (AutoCompleteTextView)
+ findViewById(R.id.edit);
+ textView.setAdapter(adapter);
+ }
+
+ // XXX compiler bug in javac 1.5.0_07-164, we need to implement Filterable
+ // to make compilation work
+ public static class ContactListAdapter extends CursorAdapter implements Filterable {
+ public ContactListAdapter(Context context, Cursor c) {
+ super(context, c);
+ mContent = context.getContentResolver();
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ final TextView view = (TextView) inflater.inflate(
+ android.R.layout.simple_dropdown_item_1line, parent, false);
+ view.setText(cursor.getString(5));
+ return view;
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ ((TextView) view).setText(cursor.getString(5));
+ }
+
+ @Override
+ public String convertToString(Cursor cursor) {
+ return cursor.getString(5);
+ }
+
+ @Override
+ public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
+ if (getFilterQueryProvider() != null) {
+ return getFilterQueryProvider().runQuery(constraint);
+ }
+
+ StringBuilder buffer = null;
+ String[] args = null;
+ if (constraint != null) {
+ buffer = new StringBuilder();
+ buffer.append("UPPER(");
+ buffer.append(Contacts.ContactMethods.NAME);
+ buffer.append(") GLOB ?");
+ args = new String[] { constraint.toString().toUpperCase() + "*" };
+ }
+
+ return mContent.query(Contacts.People.CONTENT_URI, PEOPLE_PROJECTION,
+ buffer == null ? null : buffer.toString(), args,
+ Contacts.People.DEFAULT_SORT_ORDER);
+ }
+
+ private ContentResolver mContent;
+ }
+
+ private static final String[] PEOPLE_PROJECTION = new String[] {
+ Contacts.People._ID,
+ Contacts.People.PRIMARY_PHONE_ID,
+ Contacts.People.TYPE,
+ Contacts.People.NUMBER,
+ Contacts.People.LABEL,
+ Contacts.People.NAME,
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete5.java b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete5.java
new file mode 100644
index 0000000..7406da4
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete5.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Contacts;
+import android.widget.AutoCompleteTextView;
+
+public class AutoComplete5 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.autocomplete_5);
+
+ ContentResolver content = getContentResolver();
+ Cursor cursor = content.query(Contacts.People.CONTENT_URI,
+ PEOPLE_PROJECTION, null, null, Contacts.People.DEFAULT_SORT_ORDER);
+ AutoComplete4.ContactListAdapter adapter =
+ new AutoComplete4.ContactListAdapter(this, cursor);
+
+ AutoCompleteTextView textView = (AutoCompleteTextView)
+ findViewById(R.id.edit);
+ textView.setAdapter(adapter);
+ }
+
+ private static final String[] PEOPLE_PROJECTION = new String[] {
+ Contacts.People._ID,
+ Contacts.People.PRIMARY_PHONE_ID,
+ Contacts.People.TYPE,
+ Contacts.People.NUMBER,
+ Contacts.People.LABEL,
+ Contacts.People.NAME
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete6.java b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete6.java
new file mode 100644
index 0000000..3573bfb
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete6.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.Spinner;
+import android.widget.ArrayAdapter;
+import android.widget.MultiAutoCompleteTextView;
+import android.os.Bundle;
+import android.view.View;
+
+
+public class AutoComplete6 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.autocomplete_6);
+
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_dropdown_item_1line, COUNTRIES);
+ MultiAutoCompleteTextView textView = (MultiAutoCompleteTextView) findViewById(R.id.edit);
+ textView.setAdapter(adapter);
+ textView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
+ }
+
+ static final String[] COUNTRIES = new String[] {
+ "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+ "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+ "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+ "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+ "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+ "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
+ "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
+ "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+ "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+ "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+ "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+ "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+ "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+ "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+ "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+ "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+ "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+ "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+ "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+ "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+ "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+ "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+ "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+ "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+ "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+ "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+ "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+ "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+ "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+ "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+ "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+ "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+ "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+ "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+ "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+ "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+ "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+ "Ukraine", "United Arab Emirates", "United Kingdom",
+ "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+ "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+ "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Baseline1.java b/samples/ApiDemos/src/com/example/android/apis/view/Baseline1.java
new file mode 100644
index 0000000..c77b71f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Baseline1.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+/**
+ * Baseline alignment in LinearLayout.
+ */
+public class Baseline1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.baseline_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Baseline2.java b/samples/ApiDemos/src/com/example/android/apis/view/Baseline2.java
new file mode 100644
index 0000000..7189fe8
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Baseline2.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+/**
+ * Baseline alignment in LinearLayout with a BOTTOM gravity.
+ */
+public class Baseline2 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.baseline_2);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Baseline3.java b/samples/ApiDemos/src/com/example/android/apis/view/Baseline3.java
new file mode 100644
index 0000000..9261c5c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Baseline3.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+/**
+ * Baseline alignement in LinearLayout with a center_vertical gravity. This sample shows that
+ * using a center_vertical gravity disables baseline alignment.
+ */
+public class Baseline3 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.baseline_3);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Baseline4.java b/samples/ApiDemos/src/com/example/android/apis/view/Baseline4.java
new file mode 100644
index 0000000..bedfde7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Baseline4.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+/**
+ * Baseline alignment in LinearLayout with mixed gravities.
+ */
+public class Baseline4 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.baseline_4);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Baseline6.java b/samples/ApiDemos/src/com/example/android/apis/view/Baseline6.java
new file mode 100644
index 0000000..e96e10a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Baseline6.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+/**
+ * Baseline alignment in RelativeLayout.
+ */
+public class Baseline6 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.baseline_6);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Baseline7.java b/samples/ApiDemos/src/com/example/android/apis/view/Baseline7.java
new file mode 100644
index 0000000..1795e7d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Baseline7.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+/**
+ * Baseline alignment in RelativeLayout with various font weights.
+ */
+public class Baseline7 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.baseline_7);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested1.java b/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested1.java
new file mode 100644
index 0000000..d60e702
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested1.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Baseline alignment includes elements within nested vertical
+ * {@link android.widget.LinearLayout}s.
+ */
+public class BaselineNested1 extends Activity {
+
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.baseline_nested_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested2.java b/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested2.java
new file mode 100644
index 0000000..32574d7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested2.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Baseline alignment includes an element within a nested horizontal
+ * {@link android.widget.LinearLayout}.
+ */
+public class BaselineNested2 extends Activity {
+
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.baseline_nested_2);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested3.java b/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested3.java
new file mode 100644
index 0000000..3377041
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested3.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Baseline alignment includes a {@link android.widget.LinearLayout}
+ * within another {@link android.widget.LinearLayout}.
+ */
+public class BaselineNested3 extends Activity {
+
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.baseline_nested_3);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Buttons1.java b/samples/ApiDemos/src/com/example/android/apis/view/Buttons1.java
new file mode 100644
index 0000000..e2f8cc8
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Buttons1.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.widget.Spinner;
+import android.widget.ArrayAdapter;
+
+
+/**
+ * A gallery of the different styles of buttons.
+ */
+public class Buttons1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.buttons_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ChronometerDemo.java b/samples/ApiDemos/src/com/example/android/apis/view/ChronometerDemo.java
new file mode 100644
index 0000000..752adc6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ChronometerDemo.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.os.SystemClock;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Chronometer;
+
+public class ChronometerDemo extends Activity {
+ Chronometer mChronometer;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.chronometer);
+
+ Button button;
+
+ mChronometer = (Chronometer) findViewById(R.id.chronometer);
+
+ // Watch for button clicks.
+ button = (Button) findViewById(R.id.start);
+ button.setOnClickListener(mStartListener);
+
+ button = (Button) findViewById(R.id.stop);
+ button.setOnClickListener(mStopListener);
+
+ button = (Button) findViewById(R.id.reset);
+ button.setOnClickListener(mResetListener);
+
+ button = (Button) findViewById(R.id.set_format);
+ button.setOnClickListener(mSetFormatListener);
+
+ button = (Button) findViewById(R.id.clear_format);
+ button.setOnClickListener(mClearFormatListener);
+ }
+
+ View.OnClickListener mStartListener = new OnClickListener() {
+ public void onClick(View v) {
+ mChronometer.start();
+ }
+ };
+
+ View.OnClickListener mStopListener = new OnClickListener() {
+ public void onClick(View v) {
+ mChronometer.stop();
+ }
+ };
+
+ View.OnClickListener mResetListener = new OnClickListener() {
+ public void onClick(View v) {
+ mChronometer.setBase(SystemClock.elapsedRealtime());
+ }
+ };
+
+ View.OnClickListener mSetFormatListener = new OnClickListener() {
+ public void onClick(View v) {
+ mChronometer.setFormat("Formatted time (%s)");
+ }
+ };
+
+ View.OnClickListener mClearFormatListener = new OnClickListener() {
+ public void onClick(View v) {
+ mChronometer.setFormat(null);
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Controls1.java b/samples/ApiDemos/src/com/example/android/apis/view/Controls1.java
new file mode 100644
index 0000000..e2d348f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Controls1.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.widget.Spinner;
+import android.widget.ArrayAdapter;
+
+
+/**
+ * A gallery of basic controls: Button, EditText, RadioButton, Checkbox,
+ * Spinner. This example uses the light theme.
+ */
+public class Controls1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.controls_1);
+
+ Spinner s1 = (Spinner) findViewById(R.id.spinner1);
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, mStrings);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ s1.setAdapter(adapter);
+ }
+
+ private static final String[] mStrings = {
+ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Controls2.java b/samples/ApiDemos/src/com/example/android/apis/view/Controls2.java
new file mode 100644
index 0000000..4f4024b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Controls2.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.widget.Spinner;
+import android.widget.ArrayAdapter;
+
+
+/**
+ * A gallery of basic controls: Button, EditText, RadioButton, Checkbox,
+ * Spinner. This example uses the default theme.
+ */
+public class Controls2 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.controls_1);
+
+ Spinner s1 = (Spinner) findViewById(R.id.spinner1);
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, mStrings);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ s1.setAdapter(adapter);
+ }
+
+ private static final String[] mStrings = {
+ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/CustomView1.java b/samples/ApiDemos/src/com/example/android/apis/view/CustomView1.java
new file mode 100644
index 0000000..314738e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/CustomView1.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Demonstrates creating a Screen that uses custom views. This example uses
+ * {@link com.example.android.apis.view.LabelView}, which is defined in
+ * SDK/src/com/example/android/apis/view/LabelView.java.
+ *
+ */
+public class CustomView1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.custom_view_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.java b/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.java
new file mode 100644
index 0000000..f0b1d22
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.DatePickerDialog;
+import android.app.TimePickerDialog;
+import android.app.Dialog;
+import android.os.Bundle;
+import android.widget.TextView;
+import android.widget.Button;
+import android.widget.DatePicker;
+import android.widget.TimePicker;
+import android.view.View;
+
+import java.util.Calendar;
+
+/**
+ * Basic example of using date and time widgets, including
+ * {@link android.app.TimePickerDialog} and {@link android.widget.DatePicker}.
+ *
+ * Also provides a good example of using {@link Activity#onCreateDialog},
+ * {@link Activity#onPrepareDialog} and {@link Activity#showDialog} to have the
+ * activity automatically save and restore the state of the dialogs.
+ */
+public class DateWidgets1 extends Activity {
+
+ // where we display the selected date and time
+ private TextView mDateDisplay;
+
+ // date and time
+ private int mYear;
+ private int mMonth;
+ private int mDay;
+ private int mHour;
+ private int mMinute;
+
+ static final int TIME_DIALOG_ID = 0;
+ static final int DATE_DIALOG_ID = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.date_widgets_example_1);
+
+ mDateDisplay = (TextView) findViewById(R.id.dateDisplay);
+
+ Button pickDate = (Button) findViewById(R.id.pickDate);
+ pickDate.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View v) {
+ showDialog(DATE_DIALOG_ID);
+ }
+ });
+
+ Button pickTime = (Button) findViewById(R.id.pickTime);
+ pickTime.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View v) {
+ showDialog(TIME_DIALOG_ID);
+ }
+ });
+
+ final Calendar c = Calendar.getInstance();
+ mYear = c.get(Calendar.YEAR);
+ mMonth = c.get(Calendar.MONTH);
+ mDay = c.get(Calendar.DAY_OF_MONTH);
+ mHour = c.get(Calendar.HOUR_OF_DAY);
+ mMinute = c.get(Calendar.MINUTE);
+
+ updateDisplay();
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case TIME_DIALOG_ID:
+ return new TimePickerDialog(this,
+ mTimeSetListener, mHour, mMinute, false);
+ case DATE_DIALOG_ID:
+ return new DatePickerDialog(this,
+ mDateSetListener,
+ mYear, mMonth, mDay);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ switch (id) {
+ case TIME_DIALOG_ID:
+ ((TimePickerDialog) dialog).updateTime(mHour, mMinute);
+ break;
+ case DATE_DIALOG_ID:
+ ((DatePickerDialog) dialog).updateDate(mYear, mMonth, mDay);
+ break;
+ }
+ }
+
+ private void updateDisplay() {
+ mDateDisplay.setText(
+ new StringBuilder()
+ // Month is 0 based so add 1
+ .append(mMonth + 1).append("-")
+ .append(mDay).append("-")
+ .append(mYear).append(" ")
+ .append(pad(mHour)).append(":")
+ .append(pad(mMinute)));
+ }
+
+ private DatePickerDialog.OnDateSetListener mDateSetListener =
+ new DatePickerDialog.OnDateSetListener() {
+
+ public void onDateSet(DatePicker view, int year, int monthOfYear,
+ int dayOfMonth) {
+ mYear = year;
+ mMonth = monthOfYear;
+ mDay = dayOfMonth;
+ updateDisplay();
+ }
+ };
+
+ private TimePickerDialog.OnTimeSetListener mTimeSetListener =
+ new TimePickerDialog.OnTimeSetListener() {
+
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ mHour = hourOfDay;
+ mMinute = minute;
+ updateDisplay();
+ }
+ };
+
+ private static String pad(int c) {
+ if (c >= 10)
+ return String.valueOf(c);
+ else
+ return "0" + String.valueOf(c);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets2.java b/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets2.java
new file mode 100644
index 0000000..15123a8
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets2.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.TextView;
+import android.widget.TimePicker;
+import android.os.Bundle;
+
+public class DateWidgets2 extends Activity {
+
+ // where we display the selected date and time
+ private TextView mTimeDisplay;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.date_widgets_example_2);
+
+ TimePicker timePicker = (TimePicker) findViewById(R.id.timePicker);
+ timePicker.setCurrentHour(12);
+ timePicker.setCurrentMinute(15);
+
+ mTimeDisplay = (TextView) findViewById(R.id.dateDisplay);
+
+ updateDisplay(12, 15);
+
+ timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
+
+ public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
+ updateDisplay(hourOfDay, minute);
+ }
+ });
+ }
+
+ private void updateDisplay(int hourOfDay, int minute) {
+ mTimeDisplay.setText(
+ new StringBuilder()
+ .append(pad(hourOfDay)).append(":")
+ .append(pad(minute)));
+ }
+
+ private static String pad(int c) {
+ if (c >= 10)
+ return String.valueOf(c);
+ else
+ return "0" + String.valueOf(c);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList1.java b/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList1.java
new file mode 100644
index 0000000..944db64
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList1.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ExpandableListActivity;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.Gravity;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.widget.AbsListView;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
+
+import com.example.android.apis.R;
+
+/**
+ * Demonstrates expandable lists using a custom {@link ExpandableListAdapter}
+ * from {@link BaseExpandableListAdapter}.
+ */
+public class ExpandableList1 extends ExpandableListActivity {
+
+ ExpandableListAdapter mAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set up our adapter
+ mAdapter = new MyExpandableListAdapter();
+ setListAdapter(mAdapter);
+ registerForContextMenu(getExpandableListView());
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ menu.setHeaderTitle("Sample menu");
+ menu.add(0, 0, 0, R.string.expandable_list_sample_action);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item.getMenuInfo();
+
+ String title = ((TextView) info.targetView).getText().toString();
+
+ int type = ExpandableListView.getPackedPositionType(info.packedPosition);
+ if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
+ int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
+ int childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
+ Toast.makeText(this, title + ": Child " + childPos + " clicked in group " + groupPos,
+ Toast.LENGTH_SHORT).show();
+ return true;
+ } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
+ int groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
+ Toast.makeText(this, title + ": Group " + groupPos + " clicked", Toast.LENGTH_SHORT).show();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * A simple adapter which maintains an ArrayList of photo resource Ids.
+ * Each photo is displayed as an image. This adapter supports clearing the
+ * list of photos and adding a new photo.
+ *
+ */
+ public class MyExpandableListAdapter extends BaseExpandableListAdapter {
+ // Sample data set. children[i] contains the children (String[]) for groups[i].
+ private String[] groups = { "People Names", "Dog Names", "Cat Names", "Fish Names" };
+ private String[][] children = {
+ { "Arnold", "Barry", "Chuck", "David" },
+ { "Ace", "Bandit", "Cha-Cha", "Deuce" },
+ { "Fluffy", "Snuggles" },
+ { "Goldy", "Bubbles" }
+ };
+
+ public Object getChild(int groupPosition, int childPosition) {
+ return children[groupPosition][childPosition];
+ }
+
+ public long getChildId(int groupPosition, int childPosition) {
+ return childPosition;
+ }
+
+ public int getChildrenCount(int groupPosition) {
+ return children[groupPosition].length;
+ }
+
+ public TextView getGenericView() {
+ // Layout parameters for the ExpandableListView
+ AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT, 64);
+
+ TextView textView = new TextView(ExpandableList1.this);
+ textView.setLayoutParams(lp);
+ // Center the text vertically
+ textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
+ // Set the text starting position
+ textView.setPadding(36, 0, 0, 0);
+ return textView;
+ }
+
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+ View convertView, ViewGroup parent) {
+ TextView textView = getGenericView();
+ textView.setText(getChild(groupPosition, childPosition).toString());
+ return textView;
+ }
+
+ public Object getGroup(int groupPosition) {
+ return groups[groupPosition];
+ }
+
+ public int getGroupCount() {
+ return groups.length;
+ }
+
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+ ViewGroup parent) {
+ TextView textView = getGenericView();
+ textView.setText(getGroup(groupPosition).toString());
+ return textView;
+ }
+
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return true;
+ }
+
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList2.java b/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList2.java
new file mode 100644
index 0000000..5784122
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList2.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ExpandableListActivity;
+import android.content.ContentUris;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Contacts.People;
+import android.widget.ExpandableListAdapter;
+import android.widget.SimpleCursorTreeAdapter;
+
+
+/**
+ * Demonstrates expandable lists backed by Cursors
+ */
+public class ExpandableList2 extends ExpandableListActivity {
+ private int mGroupIdColumnIndex;
+
+ private String mPhoneNumberProjection[] = new String[] {
+ People.Phones._ID, People.Phones.NUMBER
+ };
+
+
+ private ExpandableListAdapter mAdapter;
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Query for people
+ Cursor groupCursor = managedQuery(People.CONTENT_URI,
+ new String[] {People._ID, People.NAME}, null, null, null);
+
+ // Cache the ID column index
+ mGroupIdColumnIndex = groupCursor.getColumnIndexOrThrow(People._ID);
+
+ // Set up our adapter
+ mAdapter = new MyExpandableListAdapter(groupCursor,
+ this,
+ android.R.layout.simple_expandable_list_item_1,
+ android.R.layout.simple_expandable_list_item_1,
+ new String[] {People.NAME}, // Name for group layouts
+ new int[] {android.R.id.text1},
+ new String[] {People.NUMBER}, // Number for child layouts
+ new int[] {android.R.id.text1});
+ setListAdapter(mAdapter);
+ }
+
+ public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
+
+ public MyExpandableListAdapter(Cursor cursor, Context context, int groupLayout,
+ int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom,
+ int[] childrenTo) {
+ super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom,
+ childrenTo);
+ }
+
+ @Override
+ protected Cursor getChildrenCursor(Cursor groupCursor) {
+ // Given the group, we return a cursor for all the children within that group
+
+ // Return a cursor that points to this contact's phone numbers
+ Uri.Builder builder = People.CONTENT_URI.buildUpon();
+ ContentUris.appendId(builder, groupCursor.getLong(mGroupIdColumnIndex));
+ builder.appendEncodedPath(People.Phones.CONTENT_DIRECTORY);
+ Uri phoneNumbersUri = builder.build();
+
+ // The returned Cursor MUST be managed by us, so we use Activity's helper
+ // functionality to manage it for us.
+ return managedQuery(phoneNumbersUri, mPhoneNumberProjection, null, null, null);
+ }
+
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList3.java b/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList3.java
new file mode 100644
index 0000000..3a298b3
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList3.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ExpandableListActivity;
+import android.os.Bundle;
+import android.widget.ExpandableListAdapter;
+import android.widget.SimpleExpandableListAdapter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Demonstrates expandable lists backed by a Simple Map-based adapter
+ */
+public class ExpandableList3 extends ExpandableListActivity {
+ private static final String NAME = "NAME";
+ private static final String IS_EVEN = "IS_EVEN";
+
+ private ExpandableListAdapter mAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
+ List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();
+ for (int i = 0; i < 20; i++) {
+ Map<String, String> curGroupMap = new HashMap<String, String>();
+ groupData.add(curGroupMap);
+ curGroupMap.put(NAME, "Group " + i);
+ curGroupMap.put(IS_EVEN, (i % 2 == 0) ? "This group is even" : "This group is odd");
+
+ List<Map<String, String>> children = new ArrayList<Map<String, String>>();
+ for (int j = 0; j < 15; j++) {
+ Map<String, String> curChildMap = new HashMap<String, String>();
+ children.add(curChildMap);
+ curChildMap.put(NAME, "Child " + j);
+ curChildMap.put(IS_EVEN, (j % 2 == 0) ? "This child is even" : "This child is odd");
+ }
+ childData.add(children);
+ }
+
+ // Set up our adapter
+ mAdapter = new SimpleExpandableListAdapter(
+ this,
+ groupData,
+ android.R.layout.simple_expandable_list_item_1,
+ new String[] { NAME, IS_EVEN },
+ new int[] { android.R.id.text1, android.R.id.text2 },
+ childData,
+ android.R.layout.simple_expandable_list_item_2,
+ new String[] { NAME, IS_EVEN },
+ new int[] { android.R.id.text1, android.R.id.text2 }
+ );
+ setListAdapter(mAdapter);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Focus1.java b/samples/ApiDemos/src/com/example/android/apis/view/Focus1.java
new file mode 100644
index 0000000..86f6ee7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Focus1.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.webkit.WebView;
+import android.widget.ListView;
+import android.widget.ArrayAdapter;
+
+
+/**
+ * Demonstrates the use of non-focusable views.
+ */
+public class Focus1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.focus_1);
+
+ WebView webView = (WebView) findViewById(R.id.rssWebView);
+ webView.loadData(
+ "<html><body>Can I focus?<br /><a href=\"#\">No I cannot!</a>.</body></html>",
+ "text/html", "utf-8");
+
+ ListView listView = (ListView) findViewById(R.id.rssListView);
+ listView.setAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1,
+ new String[] {"Ars Technica", "Slashdot", "GameKult"}));
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Focus2.java b/samples/ApiDemos/src/com/example/android/apis/view/Focus2.java
new file mode 100644
index 0000000..77bf8e0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Focus2.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Focus2 extends Activity {
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.focus_2);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Focus3.java b/samples/ApiDemos/src/com/example/android/apis/view/Focus3.java
new file mode 100644
index 0000000..fc3f6df
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Focus3.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Button;
+import com.example.android.apis.R;
+
+public class Focus3 extends Activity {
+ private Button mTopButton;
+ private Button mBottomButton;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.focus_3);
+
+ mTopButton = (Button) findViewById(R.id.top);
+ mBottomButton = (Button) findViewById(R.id.bottom);
+ }
+
+ public Button getTopButton() {
+ return mTopButton;
+ }
+
+ public Button getBottomButton() {
+ return mBottomButton;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Gallery1.java b/samples/ApiDemos/src/com/example/android/apis/view/Gallery1.java
new file mode 100644
index 0000000..a539a5b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Gallery1.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.ImageView;
+import android.widget.Toast;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.AdapterView.OnItemClickListener;
+
+public class Gallery1 extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.gallery_1);
+
+ // Reference the Gallery view
+ Gallery g = (Gallery) findViewById(R.id.gallery);
+ // Set the adapter to our custom adapter (below)
+ g.setAdapter(new ImageAdapter(this));
+
+ // Set a item click listener, and just Toast the clicked position
+ g.setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView parent, View v, int position, long id) {
+ Toast.makeText(Gallery1.this, "" + position, Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ // We also want to show context menu for longpressed items in the gallery
+ registerForContextMenu(g);
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ menu.add(R.string.gallery_2_text);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+ Toast.makeText(this, "Longpress: " + info.position, Toast.LENGTH_SHORT).show();
+ return true;
+ }
+
+ public class ImageAdapter extends BaseAdapter {
+ int mGalleryItemBackground;
+
+ public ImageAdapter(Context c) {
+ mContext = c;
+ // See res/values/attrs.xml for the <declare-styleable> that defines
+ // Gallery1.
+ TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
+ mGalleryItemBackground = a.getResourceId(
+ R.styleable.Gallery1_android_galleryItemBackground, 0);
+ a.recycle();
+ }
+
+ public int getCount() {
+ return mImageIds.length;
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView i = new ImageView(mContext);
+
+ i.setImageResource(mImageIds[position]);
+ i.setScaleType(ImageView.ScaleType.FIT_XY);
+ i.setLayoutParams(new Gallery.LayoutParams(136, 88));
+
+ // The preferred Gallery item background
+ i.setBackgroundResource(mGalleryItemBackground);
+
+ return i;
+ }
+
+ private Context mContext;
+
+ private Integer[] mImageIds = {
+ R.drawable.gallery_photo_1,
+ R.drawable.gallery_photo_2,
+ R.drawable.gallery_photo_3,
+ R.drawable.gallery_photo_4,
+ R.drawable.gallery_photo_5,
+ R.drawable.gallery_photo_6,
+ R.drawable.gallery_photo_7,
+ R.drawable.gallery_photo_8
+ };
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Gallery2.java b/samples/ApiDemos/src/com/example/android/apis/view/Gallery2.java
new file mode 100644
index 0000000..2eea1ff
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Gallery2.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.content.Context;
+import android.database.Cursor;
+import android.provider.Contacts.People;
+import android.os.Bundle;
+import android.widget.Gallery;
+import android.widget.SimpleCursorAdapter;
+import android.widget.SpinnerAdapter;
+
+// 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;
+
+public class Gallery2 extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.gallery_2);
+
+ // Get a cursor with all people
+ Cursor c = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
+ startManagingCursor(c);
+
+ SpinnerAdapter adapter = new SimpleCursorAdapter(this,
+ // Use a template that displays a text view
+ android.R.layout.simple_gallery_item,
+ // Give the cursor to the list adatper
+ c,
+ // Map the NAME column in the people database to...
+ new String[] {People.NAME},
+ // The "text1" view defined in the XML template
+ new int[] { android.R.id.text1 });
+
+ Gallery g = (Gallery) findViewById(R.id.gallery);
+ g.setAdapter(adapter);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Grid1.java b/samples/ApiDemos/src/com/example/android/apis/view/Grid1.java
new file mode 100644
index 0000000..d52d4f5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Grid1.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+import java.util.List;
+
+//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;
+
+
+public class Grid1 extends Activity {
+
+ GridView mGrid;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ loadApps(); // do this in onresume?
+
+ setContentView(R.layout.grid_1);
+ mGrid = (GridView) findViewById(R.id.myGrid);
+ mGrid.setAdapter(new AppsAdapter());
+ }
+
+ private List<ResolveInfo> mApps;
+
+ private void loadApps() {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ mApps = getPackageManager().queryIntentActivities(mainIntent, 0);
+ }
+
+ public class AppsAdapter extends BaseAdapter {
+ public AppsAdapter() {
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView i;
+
+ if (convertView == null) {
+ i = new ImageView(Grid1.this);
+ i.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ i.setLayoutParams(new GridView.LayoutParams(50, 50));
+ } else {
+ i = (ImageView) convertView;
+ }
+
+ ResolveInfo info = mApps.get(position);
+ i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
+
+ return i;
+ }
+
+
+ public final int getCount() {
+ return mApps.size();
+ }
+
+ public final Object getItem(int position) {
+ return mApps.get(position);
+ }
+
+ public final long getItemId(int position) {
+ return position;
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Grid2.java b/samples/ApiDemos/src/com/example/android/apis/view/Grid2.java
new file mode 100644
index 0000000..916eccb
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Grid2.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+/**
+ * A grid that displays a set of framed photos.
+ *
+ */
+public class Grid2 extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.grid_2);
+
+ GridView g = (GridView) findViewById(R.id.myGrid);
+ g.setAdapter(new ImageAdapter(this));
+ }
+
+ public class ImageAdapter extends BaseAdapter {
+ public ImageAdapter(Context c) {
+ mContext = c;
+ }
+
+ public int getCount() {
+ return mThumbIds.length;
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView imageView;
+ if (convertView == null) {
+ imageView = new ImageView(mContext);
+ imageView.setLayoutParams(new GridView.LayoutParams(45, 45));
+ imageView.setAdjustViewBounds(false);
+ imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ imageView.setPadding(8, 8, 8, 8);
+ } else {
+ imageView = (ImageView) convertView;
+ }
+
+ imageView.setImageResource(mThumbIds[position]);
+
+ return imageView;
+ }
+
+ private Context mContext;
+
+ private Integer[] mThumbIds = {
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7,
+ };
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ImageButton1.java b/samples/ApiDemos/src/com/example/android/apis/view/ImageButton1.java
new file mode 100644
index 0000000..5d1fb19
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ImageButton1.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+import com.example.android.apis.R;
+
+
+public class ImageButton1 extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.image_button_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ImageSwitcher1.java b/samples/ApiDemos/src/com/example/android/apis/view/ImageSwitcher1.java
new file mode 100644
index 0000000..f72b623
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ImageSwitcher1.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.animation.AnimationUtils;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.Gallery.LayoutParams;
+import android.widget.ImageSwitcher;
+import android.widget.ImageView;
+import android.widget.ViewSwitcher;
+
+
+public class ImageSwitcher1 extends Activity implements
+ AdapterView.OnItemSelectedListener, ViewSwitcher.ViewFactory {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ setContentView(R.layout.image_switcher_1);
+
+ mSwitcher = (ImageSwitcher) findViewById(R.id.switcher);
+ mSwitcher.setFactory(this);
+ mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
+ android.R.anim.fade_in));
+ mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
+ android.R.anim.fade_out));
+
+ Gallery g = (Gallery) findViewById(R.id.gallery);
+ g.setAdapter(new ImageAdapter(this));
+ g.setOnItemSelectedListener(this);
+ }
+
+ public void onItemSelected(AdapterView parent, View v, int position, long id) {
+ mSwitcher.setImageResource(mImageIds[position]);
+ }
+
+ public void onNothingSelected(AdapterView parent) {
+ }
+
+ public View makeView() {
+ ImageView i = new ImageView(this);
+ i.setBackgroundColor(0xFF000000);
+ i.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ i.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.FILL_PARENT,
+ LayoutParams.FILL_PARENT));
+ return i;
+ }
+
+ private ImageSwitcher mSwitcher;
+
+ public class ImageAdapter extends BaseAdapter {
+ public ImageAdapter(Context c) {
+ mContext = c;
+ }
+
+ public int getCount() {
+ return mThumbIds.length;
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView i = new ImageView(mContext);
+
+ i.setImageResource(mThumbIds[position]);
+ i.setAdjustViewBounds(true);
+ i.setLayoutParams(new Gallery.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ i.setBackgroundResource(R.drawable.picture_frame);
+ return i;
+ }
+
+ private Context mContext;
+
+ }
+
+ private Integer[] mThumbIds = {
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1,
+ R.drawable.sample_thumb_2, R.drawable.sample_thumb_3,
+ R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7};
+
+ private Integer[] mImageIds = {
+ R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2,
+ R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5,
+ R.drawable.sample_6, R.drawable.sample_7};
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ImageView1.java b/samples/ApiDemos/src/com/example/android/apis/view/ImageView1.java
new file mode 100644
index 0000000..f63b01a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ImageView1.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Demonstrates setting size constraints on {@link android.widget.ImageView}
+ *
+ */
+public class ImageView1 extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.image_view_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionFocus.java b/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionFocus.java
new file mode 100644
index 0000000..a664ab9
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionFocus.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+/**
+ * {@link android.view.View#requestFocus(int, android.graphics.Rect)}
+ * and
+ * {@link android.view.View#onFocusChanged(boolean, int, android.graphics.Rect)}
+ * work together to give a newly focused item a hint about the most interesting
+ * rectangle of the previously focused view. The view taking focus can use this
+ * to set an internal selection more appropriate using this rect.
+ *
+ * This Activity excercises that behavior using three adjacent {@link InternalSelectionView}
+ * that report interesting rects when giving up focus, and use interesting rects
+ * when taking focus to best select the internal row to show as selected.
+ *
+ * Were {@link InternalSelectionView} not to override {@link android.view.View#getFocusedRect}, or
+ * {@link android.view.View#onFocusChanged(boolean, int, android.graphics.Rect)}, the focus would
+ * jump to some default internal selection (the top) and not allow for the smooth handoff.
+ */
+public class InternalSelectionFocus extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.HORIZONTAL);
+ layout.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.FILL_PARENT));
+
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,
+ ViewGroup.LayoutParams.FILL_PARENT, 1);
+
+ final InternalSelectionView leftColumn = new InternalSelectionView(this, 5, "left column");
+ leftColumn.setLayoutParams(params);
+ leftColumn.setPadding(10, 10, 10, 10);
+ layout.addView(leftColumn);
+
+ final InternalSelectionView middleColumn = new InternalSelectionView(this, 5, "middle column");
+ middleColumn.setLayoutParams(params);
+ middleColumn.setPadding(10, 10, 10, 10);
+ layout.addView(middleColumn);
+
+ final InternalSelectionView rightColumn = new InternalSelectionView(this, 5, "right column");
+ rightColumn.setLayoutParams(params);
+ rightColumn.setPadding(10, 10, 10, 10);
+ layout.addView(rightColumn);
+
+ setContentView(layout);
+ }
+
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionScroll.java b/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionScroll.java
new file mode 100644
index 0000000..fe607e2
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionScroll.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+/**
+ * Demonstrates how a well behaved view with internal selection
+ * ({@link InternalSelectionView}) can cause its parent {@link android.widget.ScrollView}
+ * to scroll to keep the internally interesting rectangle on the screen.
+ *
+ * {@link InternalSelectionView} achieves this by calling {@link android.view.View#requestRectangleOnScreen}
+ * each time its internal selection changes.
+ *
+ * {@link android.widget.ScrollView}, in turn, implements {@link android.view.View#requestRectangleOnScreen}
+ * thereby acheiving the result. Note that {@link android.widget.ListView} also implements the
+ * method, so views that call {@link android.view.View#requestRectangleOnScreen} that are embedded
+ * within either {@link android.widget.ScrollView}s or {@link android.widget.ListView}s can
+ * expect to keep their internal interesting rectangle visible.
+ */
+public class InternalSelectionScroll extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ScrollView sv = new ScrollView(this);
+ ViewGroup.LayoutParams svLp = new ScrollView.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ LinearLayout ll = new LinearLayout(this);
+ ll.setLayoutParams(svLp);
+ sv.addView(ll);
+
+ InternalSelectionView isv = new InternalSelectionView(this, 10);
+ int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
+ LinearLayout.LayoutParams llLp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ 2 * screenHeight); // 2x screen height to ensure scrolling
+ isv.setLayoutParams(llLp);
+ ll.addView(isv);
+
+ setContentView(sv);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionView.java b/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionView.java
new file mode 100644
index 0000000..3ef8403
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionView.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+
+
+
+/**
+ * A view that has a known number of selectable rows, and maintains a notion of which
+ * row is selected. The rows take up the
+ * entire width of the view. The height of the view is divided evenly among
+ * the rows.
+ *
+ * Notice what this view does to be a good citizen w.r.t its internal selection:
+ * 1) calls {@link View#requestRectangleOnScreen} each time the selection changes due to
+ * internal navigation.
+ * 2) overrides {@link View#getFocusedRect} by filling in the rectangle of the currently
+ * selected row
+ * 3) overrides {@link View#onFocusChanged} and sets selection appropriately according to
+ * the previously focused rectangle.
+ */
+public class InternalSelectionView extends View {
+
+ private Paint mPainter = new Paint();
+ private Paint mTextPaint = new Paint();
+ private Rect mTempRect = new Rect();
+
+ private int mNumRows = 5;
+ private int mSelectedRow = 0;
+ private final int mEstimatedPixelHeight = 10;
+
+ private Integer mDesiredHeight = null;
+ private String mLabel = null;
+
+
+ public InternalSelectionView(Context context, int numRows) {
+ this(context, numRows, "");
+ }
+
+ public InternalSelectionView(Context context, int numRows, String label) {
+ super(context);
+ mNumRows = numRows;
+ mLabel = label;
+ init();
+ }
+
+ public InternalSelectionView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ private void init() {
+ setFocusable(true);
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setTextSize(10);
+ mTextPaint.setColor(Color.WHITE);
+ }
+
+ public int getNumRows() {
+ return mNumRows;
+ }
+
+ public int getSelectedRow() {
+ return mSelectedRow;
+ }
+
+ public void setDesiredHeight(int desiredHeight) {
+ mDesiredHeight = desiredHeight;
+ }
+
+ public String getLabel() {
+ return mLabel;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(
+ measureWidth(widthMeasureSpec),
+ measureHeight(heightMeasureSpec));
+ }
+
+ private int measureWidth(int measureSpec) {
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ int desiredWidth = 300 + getPaddingLeft() + getPaddingRight();
+ if (specMode == MeasureSpec.EXACTLY) {
+ // We were told how big to be
+ return specSize;
+ } else if (specMode == MeasureSpec.AT_MOST) {
+ return desiredWidth < specSize ? desiredWidth : specSize;
+ } else {
+ return desiredWidth;
+ }
+ }
+
+ private int measureHeight(int measureSpec) {
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ int desiredHeight = mDesiredHeight != null ?
+ mDesiredHeight :
+ mNumRows * mEstimatedPixelHeight + getPaddingTop() + getPaddingBottom();
+ if (specMode == MeasureSpec.EXACTLY) {
+ // We were told how big to be
+ return specSize;
+ } else if (specMode == MeasureSpec.AT_MOST) {
+ return desiredHeight < specSize ? desiredHeight : specSize;
+ } else {
+ return desiredHeight;
+ }
+ }
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+
+ int rowHeight = getRowHeight();
+
+ int rectTop = getPaddingTop();
+ int rectLeft = getPaddingLeft();
+ int rectRight = getWidth() - getPaddingRight();
+ for (int i = 0; i < mNumRows; i++) {
+
+ mPainter.setColor(Color.BLACK);
+ mPainter.setAlpha(0x20);
+
+ // draw background rect
+ mTempRect.set(rectLeft, rectTop, rectRight, rectTop + rowHeight);
+ canvas.drawRect(mTempRect, mPainter);
+
+ // draw forground rect
+ if (i == mSelectedRow && hasFocus()) {
+ mPainter.setColor(Color.RED);
+ mPainter.setAlpha(0xF0);
+ mTextPaint.setAlpha(0xFF);
+ } else {
+ mPainter.setColor(Color.BLACK);
+ mPainter.setAlpha(0x40);
+ mTextPaint.setAlpha(0xF0);
+ }
+ mTempRect.set(rectLeft + 2, rectTop + 2,
+ rectRight - 2, rectTop + rowHeight - 2);
+ canvas.drawRect(mTempRect, mPainter);
+
+ // draw text to help when visually inspecting
+ canvas.drawText(
+ Integer.toString(i),
+ rectLeft + 2,
+ rectTop + 2 - (int) mTextPaint.ascent(),
+ mTextPaint);
+
+ rectTop += rowHeight;
+ }
+ }
+
+ private int getRowHeight() {
+ return (getHeight() - getPaddingTop() - getPaddingBottom()) / mNumRows;
+ }
+
+ public void getRectForRow(Rect rect, int row) {
+ final int rowHeight = getRowHeight();
+ final int top = getPaddingTop() + row * rowHeight;
+ rect.set(getPaddingLeft(),
+ top,
+ getWidth() - getPaddingRight(),
+ top + rowHeight);
+ }
+
+
+ void ensureRectVisible() {
+ getRectForRow(mTempRect, mSelectedRow);
+ requestRectangleOnScreen(mTempRect);
+ }
+
+
+ /* (non-Javadoc)
+ * @see android.view.KeyEvent.Callback#onKeyDown(int, android.view.KeyEvent)
+ */
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch(event.getKeyCode()) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (mSelectedRow > 0) {
+ mSelectedRow--;
+ invalidate();
+ ensureRectVisible();
+ return true;
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (mSelectedRow < (mNumRows - 1)) {
+ mSelectedRow++;
+ invalidate();
+ ensureRectVisible();
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
+
+ @Override
+ public void getFocusedRect(Rect r) {
+ getRectForRow(r, mSelectedRow);
+ }
+
+ @Override
+ protected void onFocusChanged(boolean focused, int direction,
+ Rect previouslyFocusedRect) {
+ super.onFocusChanged(focused, direction, previouslyFocusedRect);
+
+ if (focused) {
+ switch (direction) {
+ case View.FOCUS_DOWN:
+ mSelectedRow = 0;
+ break;
+ case View.FOCUS_UP:
+ mSelectedRow = mNumRows - 1;
+ break;
+ case View.FOCUS_LEFT: // fall through
+ case View.FOCUS_RIGHT:
+ // set the row that is closest to the rect
+ if (previouslyFocusedRect != null) {
+ int y = previouslyFocusedRect.top
+ + (previouslyFocusedRect.height() / 2);
+ int yPerRow = getHeight() / mNumRows;
+ mSelectedRow = y / yPerRow;
+ } else {
+ mSelectedRow = 0;
+ }
+ break;
+ default:
+ // can't gleam any useful information about what internal
+ // selection should be...
+ return;
+ }
+ invalidate();
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (mLabel != null) {
+ return mLabel;
+ }
+ return super.toString();
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LabelView.java b/samples/ApiDemos/src/com/example/android/apis/view/LabelView.java
new file mode 100644
index 0000000..b98a5b5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LabelView.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Example of how to write a custom subclass of View. LabelView
+ * is used to draw simple text views. Note that it does not handle
+ * styled text or right-to-left writing systems.
+ *
+ */
+public class LabelView extends View {
+ private Paint mTextPaint;
+ private String mText;
+ private int mAscent;
+
+ /**
+ * Constructor. This version is only needed if you will be instantiating
+ * the object manually (not from a layout XML file).
+ * @param context
+ */
+ public LabelView(Context context) {
+ super(context);
+ initLabelView();
+ }
+
+ /**
+ * Construct object, initializing with any attributes we understand from a
+ * layout file. These attributes are defined in
+ * SDK/assets/res/any/classes.xml.
+ *
+ * @see android.view.View#View(android.content.Context, android.util.AttributeSet)
+ */
+ public LabelView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initLabelView();
+
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ R.styleable.LabelView);
+
+ CharSequence s = a.getString(R.styleable.LabelView_text);
+ if (s != null) {
+ setText(s.toString());
+ }
+
+ // Retrieve the color(s) to be used for this view and apply them.
+ // Note, if you only care about supporting a single color, that you
+ // can instead call a.getColor() and pass that to setTextColor().
+ setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000));
+
+ int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
+ if (textSize > 0) {
+ setTextSize(textSize);
+ }
+
+ a.recycle();
+ }
+
+ private final void initLabelView() {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setTextSize(16);
+ mTextPaint.setColor(0xFF000000);
+ setPadding(3, 3, 3, 3);
+ }
+
+ /**
+ * Sets the text to display in this label
+ * @param text The text to display. This will be drawn as one line.
+ */
+ public void setText(String text) {
+ mText = text;
+ requestLayout();
+ invalidate();
+ }
+
+ /**
+ * Sets the text size for this label
+ * @param size Font size
+ */
+ public void setTextSize(int size) {
+ mTextPaint.setTextSize(size);
+ requestLayout();
+ invalidate();
+ }
+
+ /**
+ * Sets the text color for this label.
+ * @param color ARGB value for the text
+ */
+ public void setTextColor(int color) {
+ mTextPaint.setColor(color);
+ invalidate();
+ }
+
+ /**
+ * @see android.view.View#measure(int, int)
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(measureWidth(widthMeasureSpec),
+ measureHeight(heightMeasureSpec));
+ }
+
+ /**
+ * Determines the width of this view
+ * @param measureSpec A measureSpec packed into an int
+ * @return The width of the view, honoring constraints from measureSpec
+ */
+ private int measureWidth(int measureSpec) {
+ int result = 0;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if (specMode == MeasureSpec.EXACTLY) {
+ // We were told how big to be
+ result = specSize;
+ } else {
+ // Measure the text
+ result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
+ + getPaddingRight();
+ if (specMode == MeasureSpec.AT_MOST) {
+ // Respect AT_MOST value if that was what is called for by measureSpec
+ result = Math.min(result, specSize);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Determines the height of this view
+ * @param measureSpec A measureSpec packed into an int
+ * @return The height of the view, honoring constraints from measureSpec
+ */
+ private int measureHeight(int measureSpec) {
+ int result = 0;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ mAscent = (int) mTextPaint.ascent();
+ if (specMode == MeasureSpec.EXACTLY) {
+ // We were told how big to be
+ result = specSize;
+ } else {
+ // Measure the text (beware: ascent is a negative number)
+ result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
+ + getPaddingBottom();
+ if (specMode == MeasureSpec.AT_MOST) {
+ // Respect AT_MOST value if that was what is called for by measureSpec
+ result = Math.min(result, specSize);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Render the text
+ *
+ * @see android.view.View#onDraw(android.graphics.Canvas)
+ */
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation1.java b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation1.java
new file mode 100644
index 0000000..19e1834
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation1.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+import java.util.List;
+
+public class LayoutAnimation1 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ loadApps();
+
+ setContentView(R.layout.layout_animation_1);
+ GridView grid = (GridView) findViewById(R.id.grid);
+ grid.setAdapter(new LayoutAnimation1.AppsAdapter());
+ }
+
+ private List<ResolveInfo> mApps;
+
+ private void loadApps() {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ mApps = getPackageManager().queryIntentActivities(mainIntent, 0);
+ }
+
+ public class AppsAdapter extends BaseAdapter {
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView i = new ImageView(LayoutAnimation1.this);
+
+ ResolveInfo info = mApps.get(position % mApps.size());
+
+ i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
+ i.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ i.setLayoutParams(new GridView.LayoutParams(36, 36));
+ return i;
+ }
+
+
+ public final int getCount() {
+ return Math.min(32, mApps.size());
+ }
+
+ public final Object getItem(int position) {
+ return mApps.get(position % mApps.size());
+ }
+
+ public final long getItemId(int position) {
+ return position;
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation2.java b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation2.java
new file mode 100644
index 0000000..1c00145
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation2.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.LayoutAnimationController;
+import android.view.animation.TranslateAnimation;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class LayoutAnimation2 extends ListActivity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, mStrings));
+
+ AnimationSet set = new AnimationSet(true);
+
+ Animation animation = new AlphaAnimation(0.0f, 1.0f);
+ animation.setDuration(50);
+ set.addAnimation(animation);
+
+ animation = new TranslateAnimation(
+ Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f,
+ Animation.RELATIVE_TO_SELF, -1.0f,Animation.RELATIVE_TO_SELF, 0.0f
+ );
+ animation.setDuration(100);
+ set.addAnimation(animation);
+
+ LayoutAnimationController controller =
+ new LayoutAnimationController(set, 0.5f);
+ ListView listView = getListView();
+ listView.setLayoutAnimation(controller);
+ }
+
+ private String[] mStrings = {
+ "Bordeaux",
+ "Lyon",
+ "Marseille",
+ "Nancy",
+ "Paris",
+ "Toulouse",
+ "Strasbourg"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation3.java b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation3.java
new file mode 100644
index 0000000..edc2926
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation3.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.view.View;
+
+public class LayoutAnimation3 extends ListActivity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.layout_animation_3);
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, mStrings));
+ }
+
+ private String[] mStrings = {
+ "Bordeaux",
+ "Lyon",
+ "Marseille",
+ "Nancy",
+ "Paris",
+ "Toulouse",
+ "Strasbourg"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation4.java b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation4.java
new file mode 100644
index 0000000..73b338b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation4.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+import java.util.List;
+
+public class LayoutAnimation4 extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ loadApps();
+
+ setContentView(R.layout.layout_animation_4);
+ GridView grid = (GridView) findViewById(R.id.grid);
+ grid.setAdapter(new AppsAdapter());
+
+ }
+
+ private List<ResolveInfo> mApps;
+
+ private void loadApps() {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ mApps = getPackageManager().queryIntentActivities(mainIntent, 0);
+ }
+
+ public class AppsAdapter extends BaseAdapter {
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView i = new ImageView(LayoutAnimation4.this);
+
+ ResolveInfo info = mApps.get(position % mApps.size());
+
+ i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
+ i.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ i.setLayoutParams(new GridView.LayoutParams(36, 36));
+ return i;
+ }
+
+
+ public final int getCount() {
+ return Math.min(32, mApps.size());
+ }
+
+ public final Object getItem(int position) {
+ return mApps.get(position % mApps.size());
+ }
+
+ public final long getItemId(int position) {
+ return position;
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation5.java b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation5.java
new file mode 100644
index 0000000..8ed8a36
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation5.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+import java.util.List;
+
+public class LayoutAnimation5 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ loadApps();
+
+ setContentView(R.layout.layout_animation_5);
+ GridView grid = (GridView) findViewById(R.id.grid);
+ grid.setAdapter(new AppsAdapter());
+ }
+
+ private List<ResolveInfo> mApps;
+
+ private void loadApps() {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ mApps = getPackageManager().queryIntentActivities(mainIntent, 0);
+ }
+
+ public class AppsAdapter extends BaseAdapter {
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView i = new ImageView(LayoutAnimation5.this);
+
+ ResolveInfo info = mApps.get(position % mApps.size());
+
+ i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
+ i.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ i.setLayoutParams(new GridView.LayoutParams(36, 36));
+ return i;
+ }
+
+
+ public final int getCount() {
+ return Math.min(32, mApps.size());
+ }
+
+ public final Object getItem(int position) {
+ return mApps.get(position % mApps.size());
+ }
+
+ public final long getItemId(int position) {
+ return position;
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation6.java b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation6.java
new file mode 100644
index 0000000..ef7917e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation6.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+import java.util.List;
+
+public class LayoutAnimation6 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ loadApps();
+
+ setContentView(R.layout.layout_animation_6);
+ GridView grid = (GridView) findViewById(R.id.grid);
+ grid.setAdapter(new AppsAdapter());
+ }
+
+ private List<ResolveInfo> mApps;
+
+ private void loadApps() {
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ mApps = getPackageManager().queryIntentActivities(mainIntent, 0);
+ }
+
+ public class AppsAdapter extends BaseAdapter {
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView i = new ImageView(LayoutAnimation6.this);
+
+ ResolveInfo info = mApps.get(position % mApps.size());
+
+ i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
+ i.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ i.setLayoutParams(new GridView.LayoutParams(36, 36));
+ return i;
+ }
+
+
+ public final int getCount() {
+ return Math.min(32, mApps.size());
+ }
+
+ public final Object getItem(int position) {
+ return mApps.get(position % mApps.size());
+ }
+
+ public final long getItemId(int position) {
+ return position;
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation7.java b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation7.java
new file mode 100644
index 0000000..6eeb429
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation7.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.GridLayoutAnimationController;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+import java.util.List;
+
+public class LayoutAnimation7 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.layout_animation_7);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout1.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout1.java
new file mode 100644
index 0000000..fcf4924
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout1.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * A simple linear layout where the height of the layout is the sum of its children.
+ */
+public class LinearLayout1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout10.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout10.java
new file mode 100644
index 0000000..eb22d9a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout10.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Demonstrates the use of LinearLayout backgrounds to group labels,
+ * EditTexts, and buttons,
+ */
+public class LinearLayout10 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_10);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout2.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout2.java
new file mode 100644
index 0000000..044f2b6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout2.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * A simple linear layout that fills the screen vertically, but the children are not padded.
+ */
+public class LinearLayout2 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_2);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout3.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout3.java
new file mode 100644
index 0000000..2468dcd
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout3.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * A simple linear layout that fills the screen vertically, and the middle child is padded with extra space.
+ */
+public class LinearLayout3 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_3);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout4.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout4.java
new file mode 100644
index 0000000..f3d1d1b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout4.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Demonstrates a horizontal linear layout with equally sized columns.
+ *
+ */
+public class LinearLayout4 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_4);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout5.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout5.java
new file mode 100644
index 0000000..d3b2a25
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout5.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Demonstrates building a simple form with nested LinearLayouts.
+ *
+ */
+public class LinearLayout5 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_5);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout6.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout6.java
new file mode 100644
index 0000000..88745fb
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout6.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Demonstrates using the uniformSize attribute
+ *
+ */
+public class LinearLayout6 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_6);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout7.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout7.java
new file mode 100644
index 0000000..32c787f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout7.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Demonstrates using fill_parent within a linear layout whose size is not fixed.
+ *
+ */
+public class LinearLayout7 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_7);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout8.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout8.java
new file mode 100644
index 0000000..5896782
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout8.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+//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.os.Bundle;
+import android.view.Menu;
+import android.view.Gravity;
+import android.view.MenuItem;
+import android.widget.LinearLayout;
+
+
+/**
+ * Demonstrates horizontal and vertical gravity
+ */
+public class LinearLayout8 extends Activity {
+
+ private LinearLayout mLinearLayout;
+
+ // Menu item Ids
+ public static final int VERTICAL_ID = Menu.FIRST;
+ public static final int HORIZONTAL_ID = Menu.FIRST + 1;
+
+ public static final int TOP_ID = Menu.FIRST + 2;
+ public static final int MIDDLE_ID = Menu.FIRST + 3;
+ public static final int BOTTOM_ID = Menu.FIRST + 4;
+
+ public static final int LEFT_ID = Menu.FIRST + 5;
+ public static final int CENTER_ID = Menu.FIRST + 6;
+ public static final int RIGHT_ID = Menu.FIRST + 7;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_8);
+ mLinearLayout = (LinearLayout)findViewById(R.id.layout);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.add(0, VERTICAL_ID, 0, R.string.linear_layout_8_vertical);
+ menu.add(0, HORIZONTAL_ID, 0, R.string.linear_layout_8_horizontal);
+ menu.add(0, TOP_ID, 0, R.string.linear_layout_8_top);
+ menu.add(0, MIDDLE_ID, 0, R.string.linear_layout_8_middle);
+ menu.add(0, BOTTOM_ID, 0, R.string.linear_layout_8_bottom);
+ menu.add(0, LEFT_ID, 0, R.string.linear_layout_8_left);
+ menu.add(0, CENTER_ID, 0, R.string.linear_layout_8_center);
+ menu.add(0, RIGHT_ID, 0, R.string.linear_layout_8_right);
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+
+ case VERTICAL_ID:
+ mLinearLayout.setOrientation(LinearLayout.VERTICAL);
+ return true;
+ case HORIZONTAL_ID:
+ mLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
+ return true;
+
+ case TOP_ID:
+ mLinearLayout.setVerticalGravity(Gravity.TOP);
+ return true;
+ case MIDDLE_ID:
+ mLinearLayout.setVerticalGravity(Gravity.CENTER_VERTICAL);
+ return true;
+ case BOTTOM_ID:
+ mLinearLayout.setVerticalGravity(Gravity.BOTTOM);
+ return true;
+
+ case LEFT_ID:
+ mLinearLayout.setHorizontalGravity(Gravity.LEFT);
+ return true;
+ case CENTER_ID:
+ mLinearLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
+ return true;
+ case RIGHT_ID:
+ mLinearLayout.setHorizontalGravity(Gravity.RIGHT);
+ return true;
+
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout9.java b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout9.java
new file mode 100644
index 0000000..d120b1e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout9.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ListView;
+import android.widget.ArrayAdapter;
+
+/**
+ * Demonstrates how the layout_weight attribute can shrink an element too big
+ * to fit on screen.
+ */
+public class LinearLayout9 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.linear_layout_9);
+ ListView list = (ListView) findViewById(R.id.list);
+ list.setAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, AutoComplete1.COUNTRIES));
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List1.java b/samples/ApiDemos/src/com/example/android/apis/view/List1.java
new file mode 100644
index 0000000..5861923
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List1.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+
+
+/**
+ * A list view example where the
+ * data for the list comes from an array of strings.
+ */
+public class List1 extends ListActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Use an existing ListAdapter that will map an array
+ // of strings to TextViews
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, mStrings));
+ getListView().setTextFilterEnabled(true);
+ }
+
+ private String[] mStrings = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
+ "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
+ "Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro", "Appenzell",
+ "Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
+ "Asadero", "Asiago", "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss",
+ "Babybel", "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal", "Banon",
+ "Barry's Bay Cheddar", "Basing", "Basket Cheese", "Bath Cheese", "Bavarian Bergkase",
+ "Baylough", "Beaufort", "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir", "Bierkase", "Bishop Kennedy",
+ "Blarney", "Bleu d'Auvergne", "Bleu de Gex", "Bleu de Laqueuille",
+ "Bleu de Septmoncel", "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini", "Bocconcini (Australian)",
+ "Boeren Leidenkaas", "Bonchester", "Bosworth", "Bougon", "Boule Du Roves",
+ "Boulette d'Avesnes", "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois", "Brebis du Puyfaucon",
+ "Bresse Bleu", "Brick", "Brie", "Brie de Meaux", "Brie de Melun", "Brillat-Savarin",
+ "Brin", "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio", "Broccio Demi-Affine",
+ "Brousse du Rove", "Bruder Basil", "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase", "Button (Innes)",
+ "Buxton Blue", "Cabecou", "Caboc", "Cabrales", "Cachaille", "Caciocavallo", "Caciotta",
+ "Caerphilly", "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux", "Capricorn Goat",
+ "Capriole Banon", "Carre de l'Est", "Casciotta di Urbino", "Cashel Blue", "Castellano",
+ "Castelleno", "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou", "Chabichou du Poitou",
+ "Chabis de Gatine", "Chaource", "Charolais", "Chaumes", "Cheddar",
+ "Cheddar Clothbound", "Cheshire", "Chevres", "Chevrotin des Aravis", "Chontaleno",
+ "Civray", "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby", "Cold Pack",
+ "Comte", "Coolea", "Cooleney", "Coquetdale", "Corleggy", "Cornish Pepper",
+ "Cotherstone", "Cotija", "Cottage Cheese", "Cottage Cheese (Australian)",
+ "Cougar Gold", "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche", "Crescenza",
+ "Croghan", "Crottin de Chavignol", "Crottin du Chavignol", "Crowdie", "Crowley",
+ "Cuajada", "Curd", "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo", "Danish Fontina",
+ "Daralagjazsky", "Dauphin", "Delice des Fiouves", "Denhany Dorset Drum", "Derby",
+ "Dessertnyj Belyj", "Devon Blue", "Devon Garland", "Dolcelatte", "Doolin",
+ "Doppelrhamstufel", "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra", "Dunlop", "Dunsyre Blue",
+ "Duroblando", "Durrus", "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne", "Esbareich",
+ "Esrom", "Etorki", "Evansdale Farmhouse Brie", "Evora De L'Alentejo", "Exmoor Blue",
+ "Explorateur", "Feta", "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis", "Flor de Guia",
+ "Flower Marie", "Folded", "Folded cheese with mint", "Fondant de Brebis",
+ "Fontainebleau", "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire", "Fourme de Montbrison",
+ "Fresh Jack", "Fresh Mozzarella", "Fresh Ricotta", "Fresh Truffles", "Fribourgeois",
+ "Friesekaas", "Friesian", "Friesla", "Frinault", "Fromage a Raclette", "Fromage Corse",
+ "Fromage de Montagne de Savoie", "Fromage Frais", "Fruit Cream Cheese",
+ "Frying Cheese", "Fynbo", "Gabriel", "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail", "Garrotxa", "Gastanberra",
+ "Geitost", "Gippsland Blue", "Gjetost", "Gloucester", "Golden Cross", "Gorgonzola",
+ "Gornyaltajski", "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh", "Greve",
+ "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny", "Halloumi",
+ "Halloumy (Australian)", "Haloumi-Style Cheese", "Harbourne Blue", "Havarti",
+ "Heidi Gruyere", "Hereford Hop", "Herrgardsost", "Herriot Farmhouse", "Herve",
+ "Hipi Iti", "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu", "Isle of Mull", "Jarlsberg",
+ "Jermi Tortes", "Jibneh Arabieh", "Jindi Brie", "Jubilee Blue", "Juustoleipa",
+ "Kadchgall", "Kaseri", "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold", "Klosterkaese",
+ "Knockalara", "Kugelkase", "L'Aveyronnais", "L'Ecir de l'Aubrac", "La Taupiniere",
+ "La Vache Qui Rit", "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin", "Le Fium Orbo", "Le Lacandou",
+ "Le Roule", "Leafield", "Lebbene", "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer", "Little Rydings",
+ "Livarot", "Llanboidy", "Llanglofan Farmhouse", "Loch Arthur Farmhouse",
+ "Loddiswell Avondale", "Longhorn", "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam",
+ "Macconais", "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses", "Maredsous", "Margotin",
+ "Maribo", "Maroilles", "Mascares", "Mascarpone", "Mascarpone (Australian)",
+ "Mascarpone Torta", "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)", "Meyer Vintage Gouda",
+ "Mihalic Peynir", "Milleens", "Mimolette", "Mine-Gabhar", "Mini Baby Bells", "Mixte",
+ "Molbo", "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier", "Morbier Cru de Montagne",
+ "Mothais a la Feuille", "Mozzarella", "Mozzarella (Australian)",
+ "Mozzarella di Bufala", "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais", "Neufchatel",
+ "Neufchatel (Australian)", "Niolo", "Nokkelost", "Northumberland", "Oaxaca",
+ "Olde York", "Olivet au Foin", "Olivet Bleu", "Olivet Cendre",
+ "Orkney Extra Mature Cheddar", "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty",
+ "Oszczypek", "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer", "Panela",
+ "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)", "Parmigiano Reggiano",
+ "Pas de l'Escalette", "Passendale", "Pasteurized Processed", "Pate de Fromage",
+ "Patefine Fort", "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac", "Pave du Berry",
+ "Pecorino", "Pecorino in Walnut Leaves", "Pecorino Romano", "Peekskill Pyramid",
+ "Pelardon des Cevennes", "Pelardon des Corbieres", "Penamellera", "Penbryn",
+ "Pencarreg", "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora", "Pithtviers au Foin",
+ "Plateau de Herve", "Plymouth Cheese", "Podhalanski", "Poivre d'Ane", "Polkolbin",
+ "Pont l'Eveque", "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean", "Processed Cheddar", "Provolone",
+ "Provolone (Australian)", "Pyengana Cheddar", "Pyramide", "Quark",
+ "Quark (Australian)", "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango", "Queso de Murcia",
+ "Queso del Montsec", "Queso del Tietar", "Queso Fresco", "Queso Fresco (Adobera)",
+ "Queso Iberico", "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette", "Ragusano", "Raschera",
+ "Reblochon", "Red Leicester", "Regal de la Dombes", "Reggianito", "Remedou",
+ "Requeson", "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata", "Ridder",
+ "Rigotte", "Rocamadour", "Rollot", "Romano", "Romans Part Dieu", "Roncal", "Roquefort",
+ "Roule", "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu", "Saaland Pfarr",
+ "Saanenkaese", "Saga", "Sage Derby", "Sainte Maure", "Saint-Marcellin",
+ "Saint-Nectaire", "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza", "Schabzieger", "Schloss",
+ "Selles sur Cher", "Selva", "Serat", "Seriously Strong Cheddar", "Serra da Estrela",
+ "Sharpam", "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene", "Smoked Gouda",
+ "Somerset Brie", "Sonoma Jack", "Sottocenare al Tartufo", "Soumaintrain",
+ "Sourire Lozerien", "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote", "Sveciaost", "Swaledale",
+ "Sweet Style Swiss", "Swiss", "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea", "Testouri",
+ "Tete de Moine", "Tetilla", "Texas Goat Cheese", "Tibet", "Tillamook Cheddar",
+ "Tilsit", "Timboon Brie", "Toma", "Tomme Brulee", "Tomme d'Abondance",
+ "Tomme de Chevre", "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans", "Tommes",
+ "Torta del Casar", "Toscanello", "Touree de L'Aubier", "Tourmalet",
+ "Trappe (Veritable)", "Trois Cornes De Vendee", "Tronchon", "Trou du Cru", "Truffe",
+ "Tupi", "Turunmaa", "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco", "Vendomois",
+ "Vieux Corse", "Vignotte", "Vulscombe", "Waimata Farmhouse Blue",
+ "Washed Rind Cheese (Australian)", "Waterloo", "Weichkaese", "Wellington",
+ "Wensleydale", "White Stilton", "Whitestone Farmhouse", "Wigmore", "Woodside Cabecou",
+ "Xanadu", "Xynotyro", "Yarg Cornish", "Yarra Valley Pyramid", "Yorkshire Blue",
+ "Zamorano", "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"};
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List10.java b/samples/ApiDemos/src/com/example/android/apis/view/List10.java
new file mode 100644
index 0000000..57e0bb1
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List10.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * This example shows how to use choice mode on a list. This list is
+ * in CHOICE_MODE_SINGLE mode, which means the items behave like
+ * checkboxes.
+ */
+public class List10 extends ListActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_single_choice, GENRES));
+
+ final ListView listView = getListView();
+
+ listView.setItemsCanFocus(false);
+ listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ }
+
+
+ private static final String[] GENRES = new String[] {
+ "Action", "Adventure", "Animation", "Children", "Comedy", "Documentary", "Drama",
+ "Foreign", "History", "Independent", "Romance", "Sci-Fi", "Television", "Thriller"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List11.java b/samples/ApiDemos/src/com/example/android/apis/view/List11.java
new file mode 100644
index 0000000..71d77e5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List11.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * This example shows how to use choice mode on a list. This list is
+ * in CHOICE_MODE_MULTIPLE mode, which means the items behave like
+ * checkboxes.
+ */
+public class List11 extends ListActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_multiple_choice, GENRES));
+
+ final ListView listView = getListView();
+
+ listView.setItemsCanFocus(false);
+ listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+ }
+
+
+ private static final String[] GENRES = new String[] {
+ "Action", "Adventure", "Animation", "Children", "Comedy", "Documentary", "Drama",
+ "Foreign", "History", "Independent", "Romance", "Sci-Fi", "Television", "Thriller"
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List12.java b/samples/ApiDemos/src/com/example/android/apis/view/List12.java
new file mode 100644
index 0000000..0867fc5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List12.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnKeyListener;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+
+import com.example.android.apis.R;
+
+import java.util.ArrayList;
+
+/**
+ * Demonstrates the using a list view in transcript mode
+ *
+ */
+public class List12 extends ListActivity implements OnClickListener, OnKeyListener {
+
+ private EditText mUserText;
+
+ private ArrayAdapter<String> mAdapter;
+
+ private ArrayList<String> mStrings = new ArrayList<String>();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.list_12);
+
+ mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings);
+
+ setListAdapter(mAdapter);
+
+ mUserText = (EditText) findViewById(R.id.userText);
+
+ mUserText.setOnClickListener(this);
+ mUserText.setOnKeyListener(this);
+ }
+
+ public void onClick(View v) {
+ sendText();
+ }
+
+ private void sendText() {
+ String text = mUserText.getText().toString();
+ mAdapter.add(text);
+ mUserText.setText(null);
+ }
+
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_ENTER:
+ sendText();
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List13.java b/samples/ApiDemos/src/com/example/android/apis/view/List13.java
new file mode 100644
index 0000000..b3087be
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List13.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.AbsListView.OnScrollListener;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Demonstrates how a list can avoid expensive operations during scrolls or flings. In this
+ * case, we pretend that binding a view to its data is slow (even though it really isn't). When
+ * a scroll/fling is happening, the adapter binds the view to temporary data. After the scroll/fling
+ * has finished, the temporary data is replace with the actual data.
+ *
+ */
+public class List13 extends ListActivity implements ListView.OnScrollListener {
+
+ private TextView mStatus;
+
+ private boolean mBusy = false;
+
+ /**
+ * Will not bind views while the list is scrolling
+ *
+ */
+ private class SlowAdapter extends BaseAdapter {
+ private LayoutInflater mInflater;
+
+ public SlowAdapter(Context context) {
+ mContext = context;
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ /**
+ * The number of items in the list is determined by the number of speeches
+ * in our array.
+ *
+ * @see android.widget.ListAdapter#getCount()
+ */
+ public int getCount() {
+ return mStrings.length;
+ }
+
+ /**
+ * Since the data comes from an array, just returning the index is
+ * sufficent to get at the data. If we were using a more complex data
+ * structure, we would return whatever object represents one row in the
+ * list.
+ *
+ * @see android.widget.ListAdapter#getItem(int)
+ */
+ public Object getItem(int position) {
+ return position;
+ }
+
+ /**
+ * Use the array index as a unique id.
+ *
+ * @see android.widget.ListAdapter#getItemId(int)
+ */
+ public long getItemId(int position) {
+ return position;
+ }
+
+ /**
+ * Make a view to hold each row.
+ *
+ * @see android.widget.ListAdapter#getView(int, android.view.View,
+ * android.view.ViewGroup)
+ */
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView text;
+
+ if (convertView == null) {
+ text = (TextView)mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
+ } else {
+ text = (TextView)convertView;
+ }
+
+ if (!mBusy) {
+ text.setText(mStrings[position]);
+ // Null tag means the view has the correct data
+ text.setTag(null);
+ } else {
+ text.setText("Loading...");
+ // Non-null tag means the view still needs to load it's data
+ text.setTag(this);
+ }
+
+ return text;
+ }
+
+ /**
+ * Remember our context so we can use it when constructing views.
+ */
+ private Context mContext;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.list_13);
+ mStatus = (TextView) findViewById(R.id.status);
+ mStatus.setText("Idle");
+
+ // Use an existing ListAdapter that will map an array
+ // of strings to TextViews
+ setListAdapter(new SlowAdapter(this));
+
+ getListView().setOnScrollListener(this);
+ }
+
+
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ }
+
+
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ switch (scrollState) {
+ case OnScrollListener.SCROLL_STATE_IDLE:
+ mBusy = false;
+
+ int first = view.getFirstVisiblePosition();
+ int count = view.getChildCount();
+ for (int i=0; i<count; i++) {
+ TextView t = (TextView)view.getChildAt(i);
+ if (t.getTag() != null) {
+ t.setText(mStrings[first + i]);
+ t.setTag(null);
+ }
+ }
+
+ mStatus.setText("Idle");
+ break;
+ case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
+ mBusy = true;
+ mStatus.setText("Touch scroll");
+ break;
+ case OnScrollListener.SCROLL_STATE_FLING:
+ mBusy = true;
+ mStatus.setText("Fling");
+ break;
+ }
+ }
+
+ private String[] mStrings = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",
+ "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis",
+ "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
+ "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh",
+ "Anthoriro", "Appenzell", "Aragon", "Ardi Gasna", "Ardrahan",
+ "Armenian String", "Aromes au Gene de Marc", "Asadero", "Asiago",
+ "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss", "Babybel",
+ "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal",
+ "Banon", "Barry's Bay Cheddar", "Basing", "Basket Cheese",
+ "Bath Cheese", "Bavarian Bergkase", "Baylough", "Beaufort",
+ "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir",
+ "Bierkase", "Bishop Kennedy", "Blarney", "Bleu d'Auvergne",
+ "Bleu de Gex", "Bleu de Laqueuille", "Bleu de Septmoncel",
+ "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini",
+ "Bocconcini (Australian)", "Boeren Leidenkaas", "Bonchester",
+ "Bosworth", "Bougon", "Boule Du Roves", "Boulette d'Avesnes",
+ "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois",
+ "Brebis du Puyfaucon", "Bresse Bleu", "Brick", "Brie",
+ "Brie de Meaux", "Brie de Melun", "Brillat-Savarin", "Brin",
+ "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio",
+ "Broccio Demi-Affine", "Brousse du Rove", "Bruder Basil",
+ "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase",
+ "Button (Innes)", "Buxton Blue", "Cabecou", "Caboc", "Cabrales",
+ "Cachaille", "Caciocavallo", "Caciotta", "Caerphilly",
+ "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux",
+ "Capricorn Goat", "Capriole Banon", "Carre de l'Est",
+ "Casciotta di Urbino", "Cashel Blue", "Castellano", "Castelleno",
+ "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou",
+ "Chabichou du Poitou", "Chabis de Gatine", "Chaource", "Charolais",
+ "Chaumes", "Cheddar", "Cheddar Clothbound", "Cheshire", "Chevres",
+ "Chevrotin des Aravis", "Chontaleno", "Civray",
+ "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby",
+ "Cold Pack", "Comte", "Coolea", "Cooleney", "Coquetdale",
+ "Corleggy", "Cornish Pepper", "Cotherstone", "Cotija",
+ "Cottage Cheese", "Cottage Cheese (Australian)", "Cougar Gold",
+ "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche",
+ "Crescenza", "Croghan", "Crottin de Chavignol",
+ "Crottin du Chavignol", "Crowdie", "Crowley", "Cuajada", "Curd",
+ "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo",
+ "Danish Fontina", "Daralagjazsky", "Dauphin", "Delice des Fiouves",
+ "Denhany Dorset Drum", "Derby", "Dessertnyj Belyj", "Devon Blue",
+ "Devon Garland", "Dolcelatte", "Doolin", "Doppelrhamstufel",
+ "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra",
+ "Dunlop", "Dunsyre Blue", "Duroblando", "Durrus",
+ "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne",
+ "Esbareich", "Esrom", "Etorki", "Evansdale Farmhouse Brie",
+ "Evora De L'Alentejo", "Exmoor Blue", "Explorateur", "Feta",
+ "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis",
+ "Flor de Guia", "Flower Marie", "Folded",
+ "Folded cheese with mint", "Fondant de Brebis", "Fontainebleau",
+ "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire",
+ "Fourme de Montbrison", "Fresh Jack", "Fresh Mozzarella",
+ "Fresh Ricotta", "Fresh Truffles", "Fribourgeois", "Friesekaas",
+ "Friesian", "Friesla", "Frinault", "Fromage a Raclette",
+ "Fromage Corse", "Fromage de Montagne de Savoie", "Fromage Frais",
+ "Fruit Cream Cheese", "Frying Cheese", "Fynbo", "Gabriel",
+ "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail",
+ "Garrotxa", "Gastanberra", "Geitost", "Gippsland Blue", "Gjetost",
+ "Gloucester", "Golden Cross", "Gorgonzola", "Gornyaltajski",
+ "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh",
+ "Greve", "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny",
+ "Halloumi", "Halloumy (Australian)", "Haloumi-Style Cheese",
+ "Harbourne Blue", "Havarti", "Heidi Gruyere", "Hereford Hop",
+ "Herrgardsost", "Herriot Farmhouse", "Herve", "Hipi Iti",
+ "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu",
+ "Isle of Mull", "Jarlsberg", "Jermi Tortes", "Jibneh Arabieh",
+ "Jindi Brie", "Jubilee Blue", "Juustoleipa", "Kadchgall", "Kaseri",
+ "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold",
+ "Klosterkaese", "Knockalara", "Kugelkase", "L'Aveyronnais",
+ "L'Ecir de l'Aubrac", "La Taupiniere", "La Vache Qui Rit",
+ "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin",
+ "Le Fium Orbo", "Le Lacandou", "Le Roule", "Leafield", "Lebbene",
+ "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer",
+ "Little Rydings", "Livarot", "Llanboidy", "Llanglofan Farmhouse",
+ "Loch Arthur Farmhouse", "Loddiswell Avondale", "Longhorn",
+ "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam", "Macconais",
+ "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses",
+ "Maredsous", "Margotin", "Maribo", "Maroilles", "Mascares",
+ "Mascarpone", "Mascarpone (Australian)", "Mascarpone Torta",
+ "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)",
+ "Meyer Vintage Gouda", "Mihalic Peynir", "Milleens", "Mimolette",
+ "Mine-Gabhar", "Mini Baby Bells", "Mixte", "Molbo",
+ "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier",
+ "Morbier Cru de Montagne", "Mothais a la Feuille", "Mozzarella",
+ "Mozzarella (Australian)", "Mozzarella di Bufala",
+ "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais",
+ "Neufchatel", "Neufchatel (Australian)", "Niolo", "Nokkelost",
+ "Northumberland", "Oaxaca", "Olde York", "Olivet au Foin",
+ "Olivet Bleu", "Olivet Cendre", "Orkney Extra Mature Cheddar",
+ "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty", "Oszczypek",
+ "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer",
+ "Panela", "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)",
+ "Parmigiano Reggiano", "Pas de l'Escalette", "Passendale",
+ "Pasteurized Processed", "Pate de Fromage", "Patefine Fort",
+ "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac",
+ "Pave du Berry", "Pecorino", "Pecorino in Walnut Leaves",
+ "Pecorino Romano", "Peekskill Pyramid", "Pelardon des Cevennes",
+ "Pelardon des Corbieres", "Penamellera", "Penbryn", "Pencarreg",
+ "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora",
+ "Pithtviers au Foin", "Plateau de Herve", "Plymouth Cheese",
+ "Podhalanski", "Poivre d'Ane", "Polkolbin", "Pont l'Eveque",
+ "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean",
+ "Processed Cheddar", "Provolone", "Provolone (Australian)",
+ "Pyengana Cheddar", "Pyramide", "Quark", "Quark (Australian)",
+ "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango",
+ "Queso de Murcia", "Queso del Montsec", "Queso del Tietar",
+ "Queso Fresco", "Queso Fresco (Adobera)", "Queso Iberico",
+ "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette",
+ "Ragusano", "Raschera", "Reblochon", "Red Leicester",
+ "Regal de la Dombes", "Reggianito", "Remedou", "Requeson",
+ "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata",
+ "Ridder", "Rigotte", "Rocamadour", "Rollot", "Romano",
+ "Romans Part Dieu", "Roncal", "Roquefort", "Roule",
+ "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu",
+ "Saaland Pfarr", "Saanenkaese", "Saga", "Sage Derby",
+ "Sainte Maure", "Saint-Marcellin", "Saint-Nectaire",
+ "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza",
+ "Schabzieger", "Schloss", "Selles sur Cher", "Selva", "Serat",
+ "Seriously Strong Cheddar", "Serra da Estrela", "Sharpam",
+ "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene",
+ "Smoked Gouda", "Somerset Brie", "Sonoma Jack",
+ "Sottocenare al Tartufo", "Soumaintrain", "Sourire Lozerien",
+ "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote",
+ "Sveciaost", "Swaledale", "Sweet Style Swiss", "Swiss",
+ "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea",
+ "Testouri", "Tete de Moine", "Tetilla", "Texas Goat Cheese",
+ "Tibet", "Tillamook Cheddar", "Tilsit", "Timboon Brie", "Toma",
+ "Tomme Brulee", "Tomme d'Abondance", "Tomme de Chevre",
+ "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans",
+ "Tommes", "Torta del Casar", "Toscanello", "Touree de L'Aubier",
+ "Tourmalet", "Trappe (Veritable)", "Trois Cornes De Vendee",
+ "Tronchon", "Trou du Cru", "Truffe", "Tupi", "Turunmaa",
+ "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco",
+ "Vendomois", "Vieux Corse", "Vignotte", "Vulscombe",
+ "Waimata Farmhouse Blue", "Washed Rind Cheese (Australian)",
+ "Waterloo", "Weichkaese", "Wellington", "Wensleydale",
+ "White Stilton", "Whitestone Farmhouse", "Wigmore",
+ "Woodside Cabecou", "Xanadu", "Xynotyro", "Yarg Cornish",
+ "Yarra Valley Pyramid", "Yorkshire Blue", "Zamorano",
+ "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"};
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List14.java b/samples/ApiDemos/src/com/example/android/apis/view/List14.java
new file mode 100644
index 0000000..41eb481
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List14.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+import android.widget.ImageView;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import com.example.android.apis.R;
+
+/**
+ * Demonstrates how to write an efficient list adapter. The adapter used in this example binds
+ * to an ImageView and to a TextView for each row in the list.
+ *
+ * To work efficiently the adapter implemented here uses two techniques:
+ * - It reuses the convertView passed to getView() to avoid inflating View when it is not necessary
+ * - It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary
+ *
+ * The ViewHolder pattern consists in storing a data structure in the tag of the view returned by
+ * getView(). This data structures contains references to the views we want to bind data to, thus
+ * avoiding calls to findViewById() every time getView() is invoked.
+ */
+public class List14 extends ListActivity {
+
+ private static class EfficientAdapter extends BaseAdapter {
+ private LayoutInflater mInflater;
+ private Bitmap mIcon1;
+ private Bitmap mIcon2;
+
+ public EfficientAdapter(Context context) {
+ // Cache the LayoutInflate to avoid asking for a new one each time.
+ mInflater = LayoutInflater.from(context);
+
+ // Icons bound to the rows.
+ mIcon1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_1);
+ mIcon2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_2);
+ }
+
+ /**
+ * The number of items in the list is determined by the number of speeches
+ * in our array.
+ *
+ * @see android.widget.ListAdapter#getCount()
+ */
+ public int getCount() {
+ return DATA.length;
+ }
+
+ /**
+ * Since the data comes from an array, just returning the index is
+ * sufficent to get at the data. If we were using a more complex data
+ * structure, we would return whatever object represents one row in the
+ * list.
+ *
+ * @see android.widget.ListAdapter#getItem(int)
+ */
+ public Object getItem(int position) {
+ return position;
+ }
+
+ /**
+ * Use the array index as a unique id.
+ *
+ * @see android.widget.ListAdapter#getItemId(int)
+ */
+ public long getItemId(int position) {
+ return position;
+ }
+
+ /**
+ * Make a view to hold each row.
+ *
+ * @see android.widget.ListAdapter#getView(int, android.view.View,
+ * android.view.ViewGroup)
+ */
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // A ViewHolder keeps references to children views to avoid unneccessary calls
+ // to findViewById() on each row.
+ ViewHolder holder;
+
+ // When convertView is not null, we can reuse it directly, there is no need
+ // to reinflate it. We only inflate a new View when the convertView supplied
+ // by ListView is null.
+ if (convertView == null) {
+ convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
+
+ // Creates a ViewHolder and store references to the two children views
+ // we want to bind data to.
+ holder = new ViewHolder();
+ holder.text = (TextView) convertView.findViewById(R.id.text);
+ holder.icon = (ImageView) convertView.findViewById(R.id.icon);
+
+ convertView.setTag(holder);
+ } else {
+ // Get the ViewHolder back to get fast access to the TextView
+ // and the ImageView.
+ holder = (ViewHolder) convertView.getTag();
+ }
+
+ // Bind the data efficiently with the holder.
+ holder.text.setText(DATA[position]);
+ holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
+
+ return convertView;
+ }
+
+ static class ViewHolder {
+ TextView text;
+ ImageView icon;
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setListAdapter(new EfficientAdapter(this));
+ }
+
+ private static final String[] DATA = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",
+ "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis",
+ "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
+ "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh",
+ "Anthoriro", "Appenzell", "Aragon", "Ardi Gasna", "Ardrahan",
+ "Armenian String", "Aromes au Gene de Marc", "Asadero", "Asiago",
+ "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss", "Babybel",
+ "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal",
+ "Banon", "Barry's Bay Cheddar", "Basing", "Basket Cheese",
+ "Bath Cheese", "Bavarian Bergkase", "Baylough", "Beaufort",
+ "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir",
+ "Bierkase", "Bishop Kennedy", "Blarney", "Bleu d'Auvergne",
+ "Bleu de Gex", "Bleu de Laqueuille", "Bleu de Septmoncel",
+ "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini",
+ "Bocconcini (Australian)", "Boeren Leidenkaas", "Bonchester",
+ "Bosworth", "Bougon", "Boule Du Roves", "Boulette d'Avesnes",
+ "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois",
+ "Brebis du Puyfaucon", "Bresse Bleu", "Brick", "Brie",
+ "Brie de Meaux", "Brie de Melun", "Brillat-Savarin", "Brin",
+ "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio",
+ "Broccio Demi-Affine", "Brousse du Rove", "Bruder Basil",
+ "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase",
+ "Button (Innes)", "Buxton Blue", "Cabecou", "Caboc", "Cabrales",
+ "Cachaille", "Caciocavallo", "Caciotta", "Caerphilly",
+ "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux",
+ "Capricorn Goat", "Capriole Banon", "Carre de l'Est",
+ "Casciotta di Urbino", "Cashel Blue", "Castellano", "Castelleno",
+ "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou",
+ "Chabichou du Poitou", "Chabis de Gatine", "Chaource", "Charolais",
+ "Chaumes", "Cheddar", "Cheddar Clothbound", "Cheshire", "Chevres",
+ "Chevrotin des Aravis", "Chontaleno", "Civray",
+ "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby",
+ "Cold Pack", "Comte", "Coolea", "Cooleney", "Coquetdale",
+ "Corleggy", "Cornish Pepper", "Cotherstone", "Cotija",
+ "Cottage Cheese", "Cottage Cheese (Australian)", "Cougar Gold",
+ "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche",
+ "Crescenza", "Croghan", "Crottin de Chavignol",
+ "Crottin du Chavignol", "Crowdie", "Crowley", "Cuajada", "Curd",
+ "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo",
+ "Danish Fontina", "Daralagjazsky", "Dauphin", "Delice des Fiouves",
+ "Denhany Dorset Drum", "Derby", "Dessertnyj Belyj", "Devon Blue",
+ "Devon Garland", "Dolcelatte", "Doolin", "Doppelrhamstufel",
+ "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra",
+ "Dunlop", "Dunsyre Blue", "Duroblando", "Durrus",
+ "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne",
+ "Esbareich", "Esrom", "Etorki", "Evansdale Farmhouse Brie",
+ "Evora De L'Alentejo", "Exmoor Blue", "Explorateur", "Feta",
+ "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis",
+ "Flor de Guia", "Flower Marie", "Folded",
+ "Folded cheese with mint", "Fondant de Brebis", "Fontainebleau",
+ "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire",
+ "Fourme de Montbrison", "Fresh Jack", "Fresh Mozzarella",
+ "Fresh Ricotta", "Fresh Truffles", "Fribourgeois", "Friesekaas",
+ "Friesian", "Friesla", "Frinault", "Fromage a Raclette",
+ "Fromage Corse", "Fromage de Montagne de Savoie", "Fromage Frais",
+ "Fruit Cream Cheese", "Frying Cheese", "Fynbo", "Gabriel",
+ "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail",
+ "Garrotxa", "Gastanberra", "Geitost", "Gippsland Blue", "Gjetost",
+ "Gloucester", "Golden Cross", "Gorgonzola", "Gornyaltajski",
+ "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh",
+ "Greve", "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny",
+ "Halloumi", "Halloumy (Australian)", "Haloumi-Style Cheese",
+ "Harbourne Blue", "Havarti", "Heidi Gruyere", "Hereford Hop",
+ "Herrgardsost", "Herriot Farmhouse", "Herve", "Hipi Iti",
+ "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu",
+ "Isle of Mull", "Jarlsberg", "Jermi Tortes", "Jibneh Arabieh",
+ "Jindi Brie", "Jubilee Blue", "Juustoleipa", "Kadchgall", "Kaseri",
+ "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold",
+ "Klosterkaese", "Knockalara", "Kugelkase", "L'Aveyronnais",
+ "L'Ecir de l'Aubrac", "La Taupiniere", "La Vache Qui Rit",
+ "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin",
+ "Le Fium Orbo", "Le Lacandou", "Le Roule", "Leafield", "Lebbene",
+ "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer",
+ "Little Rydings", "Livarot", "Llanboidy", "Llanglofan Farmhouse",
+ "Loch Arthur Farmhouse", "Loddiswell Avondale", "Longhorn",
+ "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam", "Macconais",
+ "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses",
+ "Maredsous", "Margotin", "Maribo", "Maroilles", "Mascares",
+ "Mascarpone", "Mascarpone (Australian)", "Mascarpone Torta",
+ "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)",
+ "Meyer Vintage Gouda", "Mihalic Peynir", "Milleens", "Mimolette",
+ "Mine-Gabhar", "Mini Baby Bells", "Mixte", "Molbo",
+ "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier",
+ "Morbier Cru de Montagne", "Mothais a la Feuille", "Mozzarella",
+ "Mozzarella (Australian)", "Mozzarella di Bufala",
+ "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais",
+ "Neufchatel", "Neufchatel (Australian)", "Niolo", "Nokkelost",
+ "Northumberland", "Oaxaca", "Olde York", "Olivet au Foin",
+ "Olivet Bleu", "Olivet Cendre", "Orkney Extra Mature Cheddar",
+ "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty", "Oszczypek",
+ "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer",
+ "Panela", "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)",
+ "Parmigiano Reggiano", "Pas de l'Escalette", "Passendale",
+ "Pasteurized Processed", "Pate de Fromage", "Patefine Fort",
+ "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac",
+ "Pave du Berry", "Pecorino", "Pecorino in Walnut Leaves",
+ "Pecorino Romano", "Peekskill Pyramid", "Pelardon des Cevennes",
+ "Pelardon des Corbieres", "Penamellera", "Penbryn", "Pencarreg",
+ "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora",
+ "Pithtviers au Foin", "Plateau de Herve", "Plymouth Cheese",
+ "Podhalanski", "Poivre d'Ane", "Polkolbin", "Pont l'Eveque",
+ "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean",
+ "Processed Cheddar", "Provolone", "Provolone (Australian)",
+ "Pyengana Cheddar", "Pyramide", "Quark", "Quark (Australian)",
+ "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango",
+ "Queso de Murcia", "Queso del Montsec", "Queso del Tietar",
+ "Queso Fresco", "Queso Fresco (Adobera)", "Queso Iberico",
+ "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette",
+ "Ragusano", "Raschera", "Reblochon", "Red Leicester",
+ "Regal de la Dombes", "Reggianito", "Remedou", "Requeson",
+ "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata",
+ "Ridder", "Rigotte", "Rocamadour", "Rollot", "Romano",
+ "Romans Part Dieu", "Roncal", "Roquefort", "Roule",
+ "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu",
+ "Saaland Pfarr", "Saanenkaese", "Saga", "Sage Derby",
+ "Sainte Maure", "Saint-Marcellin", "Saint-Nectaire",
+ "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza",
+ "Schabzieger", "Schloss", "Selles sur Cher", "Selva", "Serat",
+ "Seriously Strong Cheddar", "Serra da Estrela", "Sharpam",
+ "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene",
+ "Smoked Gouda", "Somerset Brie", "Sonoma Jack",
+ "Sottocenare al Tartufo", "Soumaintrain", "Sourire Lozerien",
+ "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote",
+ "Sveciaost", "Swaledale", "Sweet Style Swiss", "Swiss",
+ "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea",
+ "Testouri", "Tete de Moine", "Tetilla", "Texas Goat Cheese",
+ "Tibet", "Tillamook Cheddar", "Tilsit", "Timboon Brie", "Toma",
+ "Tomme Brulee", "Tomme d'Abondance", "Tomme de Chevre",
+ "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans",
+ "Tommes", "Torta del Casar", "Toscanello", "Touree de L'Aubier",
+ "Tourmalet", "Trappe (Veritable)", "Trois Cornes De Vendee",
+ "Tronchon", "Trou du Cru", "Truffe", "Tupi", "Turunmaa",
+ "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco",
+ "Vendomois", "Vieux Corse", "Vignotte", "Vulscombe",
+ "Waimata Farmhouse Blue", "Washed Rind Cheese (Australian)",
+ "Waterloo", "Weichkaese", "Wellington", "Wensleydale",
+ "White Stilton", "Whitestone Farmhouse", "Wigmore",
+ "Woodside Cabecou", "Xanadu", "Xynotyro", "Yarg Cornish",
+ "Yarra Valley Pyramid", "Yorkshire Blue", "Zamorano",
+ "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"};
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List2.java b/samples/ApiDemos/src/com/example/android/apis/view/List2.java
new file mode 100644
index 0000000..4f37dd8
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List2.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ListActivity;
+import android.database.Cursor;
+import android.provider.Contacts.People;
+import android.os.Bundle;
+import android.widget.ListAdapter;
+import android.widget.SimpleCursorAdapter;
+
+/**
+ * A list view example where the
+ * data comes from a cursor.
+ */
+public class List2 extends ListActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Get a cursor with all people
+ Cursor c = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
+ startManagingCursor(c);
+
+ ListAdapter adapter = new SimpleCursorAdapter(this,
+ // Use a template that displays a text view
+ android.R.layout.simple_list_item_1,
+ // Give the cursor to the list adatper
+ c,
+ // Map the NAME column in the people database to...
+ new String[] {People.NAME} ,
+ // The "text1" view defined in the XML template
+ new int[] {android.R.id.text1});
+ setListAdapter(adapter);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List3.java b/samples/ApiDemos/src/com/example/android/apis/view/List3.java
new file mode 100644
index 0000000..17e59f1
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List3.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+
+import android.app.ListActivity;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Contacts.Phones;
+import android.widget.ListAdapter;
+import android.widget.SimpleCursorAdapter;
+
+ /**
+ * A list view example where the
+ * data comes from a cursor, and a
+ * SimpleCursorListAdapter is used to map each item to a two-line
+ * display.
+ */
+public class List3 extends ListActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Get a cursor with all phones
+ Cursor c = getContentResolver().query(Phones.CONTENT_URI, null, null, null, null);
+ startManagingCursor(c);
+
+ // Map Cursor columns to views defined in simple_list_item_2.xml
+ ListAdapter adapter = new SimpleCursorAdapter(this,
+ android.R.layout.simple_list_item_2, c,
+ new String[] { Phones.NAME, Phones.NUMBER },
+ new int[] { android.R.id.text1, android.R.id.text2 });
+ setListAdapter(adapter);
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List4.java b/samples/ApiDemos/src/com/example/android/apis/view/List4.java
new file mode 100644
index 0000000..2bd589d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List4.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+//Need the following import to get access to the app resources, since this
+//class is in a sub-package.
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+
+/**
+ * A list view example where the data comes from a custom ListAdapter
+ */
+public class List4 extends ListActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Use our own list adapter
+ setListAdapter(new SpeechListAdapter(this));
+ }
+
+
+ /**
+ * A sample ListAdapter that presents content from arrays of speeches and
+ * text.
+ *
+ */
+ private class SpeechListAdapter extends BaseAdapter {
+ public SpeechListAdapter(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * The number of items in the list is determined by the number of speeches
+ * in our array.
+ *
+ * @see android.widget.ListAdapter#getCount()
+ */
+ public int getCount() {
+ return mTitles.length;
+ }
+
+ /**
+ * Since the data comes from an array, just returning the index is
+ * sufficent to get at the data. If we were using a more complex data
+ * structure, we would return whatever object represents one row in the
+ * list.
+ *
+ * @see android.widget.ListAdapter#getItem(int)
+ */
+ public Object getItem(int position) {
+ return position;
+ }
+
+ /**
+ * Use the array index as a unique id.
+ *
+ * @see android.widget.ListAdapter#getItemId(int)
+ */
+ public long getItemId(int position) {
+ return position;
+ }
+
+ /**
+ * Make a SpeechView to hold each row.
+ *
+ * @see android.widget.ListAdapter#getView(int, android.view.View,
+ * android.view.ViewGroup)
+ */
+ public View getView(int position, View convertView, ViewGroup parent) {
+ SpeechView sv;
+ if (convertView == null) {
+ sv = new SpeechView(mContext, mTitles[position],
+ mDialogue[position]);
+ } else {
+ sv = (SpeechView) convertView;
+ sv.setTitle(mTitles[position]);
+ sv.setDialogue(mDialogue[position]);
+ }
+
+ return sv;
+ }
+
+ /**
+ * Remember our context so we can use it when constructing views.
+ */
+ private Context mContext;
+
+ /**
+ * Our data, part 1.
+ */
+ private String[] mTitles =
+ {
+ "Henry IV (1)",
+ "Henry V",
+ "Henry VIII",
+ "Richard II",
+ "Richard III",
+ "Merchant of Venice",
+ "Othello",
+ "King Lear"
+ };
+
+ /**
+ * Our data, part 2.
+ */
+ private String[] mDialogue =
+ {
+ "So shaken as we are, so wan with care," +
+ "Find we a time for frighted peace to pant," +
+ "And breathe short-winded accents of new broils" +
+ "To be commenced in strands afar remote." +
+ "No more the thirsty entrance of this soil" +
+ "Shall daub her lips with her own children's blood;" +
+ "Nor more shall trenching war channel her fields," +
+ "Nor bruise her flowerets with the armed hoofs" +
+ "Of hostile paces: those opposed eyes," +
+ "Which, like the meteors of a troubled heaven," +
+ "All of one nature, of one substance bred," +
+ "Did lately meet in the intestine shock" +
+ "And furious close of civil butchery" +
+ "Shall now, in mutual well-beseeming ranks," +
+ "March all one way and be no more opposed" +
+ "Against acquaintance, kindred and allies:" +
+ "The edge of war, like an ill-sheathed knife," +
+ "No more shall cut his master. Therefore, friends," +
+ "As far as to the sepulchre of Christ," +
+ "Whose soldier now, under whose blessed cross" +
+ "We are impressed and engaged to fight," +
+ "Forthwith a power of English shall we levy;" +
+ "Whose arms were moulded in their mothers' womb" +
+ "To chase these pagans in those holy fields" +
+ "Over whose acres walk'd those blessed feet" +
+ "Which fourteen hundred years ago were nail'd" +
+ "For our advantage on the bitter cross." +
+ "But this our purpose now is twelve month old," +
+ "And bootless 'tis to tell you we will go:" +
+ "Therefore we meet not now. Then let me hear" +
+ "Of you, my gentle cousin Westmoreland," +
+ "What yesternight our council did decree" +
+ "In forwarding this dear expedience.",
+
+ "Hear him but reason in divinity," +
+ "And all-admiring with an inward wish" +
+ "You would desire the king were made a prelate:" +
+ "Hear him debate of commonwealth affairs," +
+ "You would say it hath been all in all his study:" +
+ "List his discourse of war, and you shall hear" +
+ "A fearful battle render'd you in music:" +
+ "Turn him to any cause of policy," +
+ "The Gordian knot of it he will unloose," +
+ "Familiar as his garter: that, when he speaks," +
+ "The air, a charter'd libertine, is still," +
+ "And the mute wonder lurketh in men's ears," +
+ "To steal his sweet and honey'd sentences;" +
+ "So that the art and practic part of life" +
+ "Must be the mistress to this theoric:" +
+ "Which is a wonder how his grace should glean it," +
+ "Since his addiction was to courses vain," +
+ "His companies unletter'd, rude and shallow," +
+ "His hours fill'd up with riots, banquets, sports," +
+ "And never noted in him any study," +
+ "Any retirement, any sequestration" +
+ "From open haunts and popularity.",
+
+ "I come no more to make you laugh: things now," +
+ "That bear a weighty and a serious brow," +
+ "Sad, high, and working, full of state and woe," +
+ "Such noble scenes as draw the eye to flow," +
+ "We now present. Those that can pity, here" +
+ "May, if they think it well, let fall a tear;" +
+ "The subject will deserve it. Such as give" +
+ "Their money out of hope they may believe," +
+ "May here find truth too. Those that come to see" +
+ "Only a show or two, and so agree" +
+ "The play may pass, if they be still and willing," +
+ "I'll undertake may see away their shilling" +
+ "Richly in two short hours. Only they" +
+ "That come to hear a merry bawdy play," +
+ "A noise of targets, or to see a fellow" +
+ "In a long motley coat guarded with yellow," +
+ "Will be deceived; for, gentle hearers, know," +
+ "To rank our chosen truth with such a show" +
+ "As fool and fight is, beside forfeiting" +
+ "Our own brains, and the opinion that we bring," +
+ "To make that only true we now intend," +
+ "Will leave us never an understanding friend." +
+ "Therefore, for goodness' sake, and as you are known" +
+ "The first and happiest hearers of the town," +
+ "Be sad, as we would make ye: think ye see" +
+ "The very persons of our noble story" +
+ "As they were living; think you see them great," +
+ "And follow'd with the general throng and sweat" +
+ "Of thousand friends; then in a moment, see" +
+ "How soon this mightiness meets misery:" +
+ "And, if you can be merry then, I'll say" +
+ "A man may weep upon his wedding-day.",
+
+ "First, heaven be the record to my speech!" +
+ "In the devotion of a subject's love," +
+ "Tendering the precious safety of my prince," +
+ "And free from other misbegotten hate," +
+ "Come I appellant to this princely presence." +
+ "Now, Thomas Mowbray, do I turn to thee," +
+ "And mark my greeting well; for what I speak" +
+ "My body shall make good upon this earth," +
+ "Or my divine soul answer it in heaven." +
+ "Thou art a traitor and a miscreant," +
+ "Too good to be so and too bad to live," +
+ "Since the more fair and crystal is the sky," +
+ "The uglier seem the clouds that in it fly." +
+ "Once more, the more to aggravate the note," +
+ "With a foul traitor's name stuff I thy throat;" +
+ "And wish, so please my sovereign, ere I move," +
+ "What my tongue speaks my right drawn sword may prove.",
+
+ "Now is the winter of our discontent" +
+ "Made glorious summer by this sun of York;" +
+ "And all the clouds that lour'd upon our house" +
+ "In the deep bosom of the ocean buried." +
+ "Now are our brows bound with victorious wreaths;" +
+ "Our bruised arms hung up for monuments;" +
+ "Our stern alarums changed to merry meetings," +
+ "Our dreadful marches to delightful measures." +
+ "Grim-visaged war hath smooth'd his wrinkled front;" +
+ "And now, instead of mounting barded steeds" +
+ "To fright the souls of fearful adversaries," +
+ "He capers nimbly in a lady's chamber" +
+ "To the lascivious pleasing of a lute." +
+ "But I, that am not shaped for sportive tricks," +
+ "Nor made to court an amorous looking-glass;" +
+ "I, that am rudely stamp'd, and want love's majesty" +
+ "To strut before a wanton ambling nymph;" +
+ "I, that am curtail'd of this fair proportion," +
+ "Cheated of feature by dissembling nature," +
+ "Deformed, unfinish'd, sent before my time" +
+ "Into this breathing world, scarce half made up," +
+ "And that so lamely and unfashionable" +
+ "That dogs bark at me as I halt by them;" +
+ "Why, I, in this weak piping time of peace," +
+ "Have no delight to pass away the time," +
+ "Unless to spy my shadow in the sun" +
+ "And descant on mine own deformity:" +
+ "And therefore, since I cannot prove a lover," +
+ "To entertain these fair well-spoken days," +
+ "I am determined to prove a villain" +
+ "And hate the idle pleasures of these days." +
+ "Plots have I laid, inductions dangerous," +
+ "By drunken prophecies, libels and dreams," +
+ "To set my brother Clarence and the king" +
+ "In deadly hate the one against the other:" +
+ "And if King Edward be as true and just" +
+ "As I am subtle, false and treacherous," +
+ "This day should Clarence closely be mew'd up," +
+ "About a prophecy, which says that 'G'" +
+ "Of Edward's heirs the murderer shall be." +
+ "Dive, thoughts, down to my soul: here" +
+ "Clarence comes.",
+
+ "To bait fish withal: if it will feed nothing else," +
+ "it will feed my revenge. He hath disgraced me, and" +
+ "hindered me half a million; laughed at my losses," +
+ "mocked at my gains, scorned my nation, thwarted my" +
+ "bargains, cooled my friends, heated mine" +
+ "enemies; and what's his reason? I am a Jew. Hath" +
+ "not a Jew eyes? hath not a Jew hands, organs," +
+ "dimensions, senses, affections, passions? fed with" +
+ "the same food, hurt with the same weapons, subject" +
+ "to the same diseases, healed by the same means," +
+ "warmed and cooled by the same winter and summer, as" +
+ "a Christian is? If you prick us, do we not bleed?" +
+ "if you tickle us, do we not laugh? if you poison" +
+ "us, do we not die? and if you wrong us, shall we not" +
+ "revenge? If we are like you in the rest, we will" +
+ "resemble you in that. If a Jew wrong a Christian," +
+ "what is his humility? Revenge. If a Christian" +
+ "wrong a Jew, what should his sufferance be by" +
+ "Christian example? Why, revenge. The villany you" +
+ "teach me, I will execute, and it shall go hard but I" +
+ "will better the instruction.",
+
+ "Virtue! a fig! 'tis in ourselves that we are thus" +
+ "or thus. Our bodies are our gardens, to the which" +
+ "our wills are gardeners: so that if we will plant" +
+ "nettles, or sow lettuce, set hyssop and weed up" +
+ "thyme, supply it with one gender of herbs, or" +
+ "distract it with many, either to have it sterile" +
+ "with idleness, or manured with industry, why, the" +
+ "power and corrigible authority of this lies in our" +
+ "wills. If the balance of our lives had not one" +
+ "scale of reason to poise another of sensuality, the" +
+ "blood and baseness of our natures would conduct us" +
+ "to most preposterous conclusions: but we have" +
+ "reason to cool our raging motions, our carnal" +
+ "stings, our unbitted lusts, whereof I take this that" +
+ "you call love to be a sect or scion.",
+
+ "Blow, winds, and crack your cheeks! rage! blow!" +
+ "You cataracts and hurricanoes, spout" +
+ "Till you have drench'd our steeples, drown'd the cocks!" +
+ "You sulphurous and thought-executing fires," +
+ "Vaunt-couriers to oak-cleaving thunderbolts," +
+ "Singe my white head! And thou, all-shaking thunder," +
+ "Smite flat the thick rotundity o' the world!" +
+ "Crack nature's moulds, an germens spill at once," +
+ "That make ingrateful man!"
+ };
+ }
+
+ /**
+ * We will use a SpeechView to display each speech. It's just a LinearLayout
+ * with two text fields.
+ *
+ */
+ private class SpeechView extends LinearLayout {
+ public SpeechView(Context context, String title, String words) {
+ super(context);
+
+ this.setOrientation(VERTICAL);
+
+ // Here we build the child views in code. They could also have
+ // been specified in an XML file.
+
+ mTitle = new TextView(context);
+ mTitle.setText(title);
+ addView(mTitle, new LinearLayout.LayoutParams(
+ LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+
+ mDialogue = new TextView(context);
+ mDialogue.setText(words);
+ addView(mDialogue, new LinearLayout.LayoutParams(
+ LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+ }
+
+ /**
+ * Convenience method to set the title of a SpeechView
+ */
+ public void setTitle(String title) {
+ mTitle.setText(title);
+ }
+
+ /**
+ * Convenience method to set the dialogue of a SpeechView
+ */
+ public void setDialogue(String words) {
+ mDialogue.setText(words);
+ }
+
+ private TextView mTitle;
+ private TextView mDialogue;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List5.java b/samples/ApiDemos/src/com/example/android/apis/view/List5.java
new file mode 100644
index 0000000..72a8b82
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List5.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+
+/**
+ * A list view example with separators.
+ */
+public class List5 extends ListActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setListAdapter(new MyListAdapter(this));
+ }
+
+ private class MyListAdapter extends BaseAdapter {
+ public MyListAdapter(Context context) {
+ mContext = context;
+ }
+
+ public int getCount() {
+ return mStrings.length;
+ }
+
+ public boolean areAllItemsEnabled() {
+ return false;
+ }
+
+ public boolean isEnabled(int position) {
+ return !mStrings[position].startsWith("-");
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView tv;
+ if (convertView == null) {
+ tv = (TextView) LayoutInflater.from(mContext).inflate(
+ android.R.layout.simple_expandable_list_item_1, parent, false);
+ } else {
+ tv = (TextView) convertView;
+ }
+ tv.setText(mStrings[position]);
+ return tv;
+ }
+
+ private Context mContext;
+ }
+
+ private String[] mStrings = {
+ "----------",
+ "----------",
+ "Abbaye de Belloc",
+ "Abbaye du Mont des Cats",
+ "Abertam",
+ "----------",
+ "Abondance",
+ "----------",
+ "Ackawi",
+ "Acorn",
+ "Adelost",
+ "Affidelice au Chablis",
+ "Afuega'l Pitu",
+ "Airag",
+ "----------",
+ "Airedale",
+ "Aisy Cendre",
+ "----------",
+ "Allgauer Emmentaler",
+ "Alverca",
+ "Ambert",
+ "American Cheese",
+ "Ami du Chambertin",
+ "----------",
+ "----------",
+ "Anejo Enchilado",
+ "Anneau du Vic-Bilh",
+ "Anthoriro",
+ "----------",
+ "----------"
+ };
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List6.java b/samples/ApiDemos/src/com/example/android/apis/view/List6.java
new file mode 100644
index 0000000..9bb5b14
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List6.java
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+
+
+/**
+ * A list view example where the
+ * data comes from a custom
+ * ListAdapter
+ */
+public class List6 extends ListActivity
+{
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // Use our own list adapter
+ setListAdapter(new SpeechListAdapter(this));
+ }
+
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id)
+ {
+ ((SpeechListAdapter)getListAdapter()).toggle(position);
+ }
+
+ /**
+ * A sample ListAdapter that presents content
+ * from arrays of speeches and text.
+ *
+ */
+ private class SpeechListAdapter extends BaseAdapter {
+ public SpeechListAdapter(Context context)
+ {
+ mContext = context;
+ }
+
+
+ /**
+ * The number of items in the list is determined by the number of speeches
+ * in our array.
+ *
+ * @see android.widget.ListAdapter#getCount()
+ */
+ public int getCount() {
+ return mTitles.length;
+ }
+
+ /**
+ * Since the data comes from an array, just returning
+ * the index is sufficent to get at the data. If we
+ * were using a more complex data structure, we
+ * would return whatever object represents one
+ * row in the list.
+ *
+ * @see android.widget.ListAdapter#getItem(int)
+ */
+ public Object getItem(int position) {
+ return position;
+ }
+
+ /**
+ * Use the array index as a unique id.
+ * @see android.widget.ListAdapter#getItemId(int)
+ */
+ public long getItemId(int position) {
+ return position;
+ }
+
+ /**
+ * Make a SpeechView to hold each row.
+ * @see android.widget.ListAdapter#getView(int, android.view.View, android.view.ViewGroup)
+ */
+ public View getView(int position, View convertView, ViewGroup parent) {
+ SpeechView sv;
+ if (convertView == null) {
+ sv = new SpeechView(mContext, mTitles[position], mDialogue[position], mExpanded[position]);
+ } else {
+ sv = (SpeechView)convertView;
+ sv.setTitle(mTitles[position]);
+ sv.setDialogue(mDialogue[position]);
+ sv.setExpanded(mExpanded[position]);
+ }
+
+ return sv;
+ }
+
+ public void toggle(int position) {
+ mExpanded[position] = !mExpanded[position];
+ notifyDataSetChanged();
+ }
+
+ /**
+ * Remember our context so we can use it when constructing views.
+ */
+ private Context mContext;
+
+ /**
+ * Our data, part 1.
+ */
+ private String[] mTitles =
+ {
+ "Henry IV (1)",
+ "Henry V",
+ "Henry VIII",
+ "Richard II",
+ "Richard III",
+ "Merchant of Venice",
+ "Othello",
+ "King Lear"
+ };
+
+ /**
+ * Our data, part 2.
+ */
+ private String[] mDialogue =
+ {
+ "So shaken as we are, so wan with care," +
+ "Find we a time for frighted peace to pant," +
+ "And breathe short-winded accents of new broils" +
+ "To be commenced in strands afar remote." +
+ "No more the thirsty entrance of this soil" +
+ "Shall daub her lips with her own children's blood;" +
+ "Nor more shall trenching war channel her fields," +
+ "Nor bruise her flowerets with the armed hoofs" +
+ "Of hostile paces: those opposed eyes," +
+ "Which, like the meteors of a troubled heaven," +
+ "All of one nature, of one substance bred," +
+ "Did lately meet in the intestine shock" +
+ "And furious close of civil butchery" +
+ "Shall now, in mutual well-beseeming ranks," +
+ "March all one way and be no more opposed" +
+ "Against acquaintance, kindred and allies:" +
+ "The edge of war, like an ill-sheathed knife," +
+ "No more shall cut his master. Therefore, friends," +
+ "As far as to the sepulchre of Christ," +
+ "Whose soldier now, under whose blessed cross" +
+ "We are impressed and engaged to fight," +
+ "Forthwith a power of English shall we levy;" +
+ "Whose arms were moulded in their mothers' womb" +
+ "To chase these pagans in those holy fields" +
+ "Over whose acres walk'd those blessed feet" +
+ "Which fourteen hundred years ago were nail'd" +
+ "For our advantage on the bitter cross." +
+ "But this our purpose now is twelve month old," +
+ "And bootless 'tis to tell you we will go:" +
+ "Therefore we meet not now. Then let me hear" +
+ "Of you, my gentle cousin Westmoreland," +
+ "What yesternight our council did decree" +
+ "In forwarding this dear expedience.",
+
+ "Hear him but reason in divinity," +
+ "And all-admiring with an inward wish" +
+ "You would desire the king were made a prelate:" +
+ "Hear him debate of commonwealth affairs," +
+ "You would say it hath been all in all his study:" +
+ "List his discourse of war, and you shall hear" +
+ "A fearful battle render'd you in music:" +
+ "Turn him to any cause of policy," +
+ "The Gordian knot of it he will unloose," +
+ "Familiar as his garter: that, when he speaks," +
+ "The air, a charter'd libertine, is still," +
+ "And the mute wonder lurketh in men's ears," +
+ "To steal his sweet and honey'd sentences;" +
+ "So that the art and practic part of life" +
+ "Must be the mistress to this theoric:" +
+ "Which is a wonder how his grace should glean it," +
+ "Since his addiction was to courses vain," +
+ "His companies unletter'd, rude and shallow," +
+ "His hours fill'd up with riots, banquets, sports," +
+ "And never noted in him any study," +
+ "Any retirement, any sequestration" +
+ "From open haunts and popularity.",
+
+ "I come no more to make you laugh: things now," +
+ "That bear a weighty and a serious brow," +
+ "Sad, high, and working, full of state and woe," +
+ "Such noble scenes as draw the eye to flow," +
+ "We now present. Those that can pity, here" +
+ "May, if they think it well, let fall a tear;" +
+ "The subject will deserve it. Such as give" +
+ "Their money out of hope they may believe," +
+ "May here find truth too. Those that come to see" +
+ "Only a show or two, and so agree" +
+ "The play may pass, if they be still and willing," +
+ "I'll undertake may see away their shilling" +
+ "Richly in two short hours. Only they" +
+ "That come to hear a merry bawdy play," +
+ "A noise of targets, or to see a fellow" +
+ "In a long motley coat guarded with yellow," +
+ "Will be deceived; for, gentle hearers, know," +
+ "To rank our chosen truth with such a show" +
+ "As fool and fight is, beside forfeiting" +
+ "Our own brains, and the opinion that we bring," +
+ "To make that only true we now intend," +
+ "Will leave us never an understanding friend." +
+ "Therefore, for goodness' sake, and as you are known" +
+ "The first and happiest hearers of the town," +
+ "Be sad, as we would make ye: think ye see" +
+ "The very persons of our noble story" +
+ "As they were living; think you see them great," +
+ "And follow'd with the general throng and sweat" +
+ "Of thousand friends; then in a moment, see" +
+ "How soon this mightiness meets misery:" +
+ "And, if you can be merry then, I'll say" +
+ "A man may weep upon his wedding-day.",
+
+ "First, heaven be the record to my speech!" +
+ "In the devotion of a subject's love," +
+ "Tendering the precious safety of my prince," +
+ "And free from other misbegotten hate," +
+ "Come I appellant to this princely presence." +
+ "Now, Thomas Mowbray, do I turn to thee," +
+ "And mark my greeting well; for what I speak" +
+ "My body shall make good upon this earth," +
+ "Or my divine soul answer it in heaven." +
+ "Thou art a traitor and a miscreant," +
+ "Too good to be so and too bad to live," +
+ "Since the more fair and crystal is the sky," +
+ "The uglier seem the clouds that in it fly." +
+ "Once more, the more to aggravate the note," +
+ "With a foul traitor's name stuff I thy throat;" +
+ "And wish, so please my sovereign, ere I move," +
+ "What my tongue speaks my right drawn sword may prove.",
+
+ "Now is the winter of our discontent" +
+ "Made glorious summer by this sun of York;" +
+ "And all the clouds that lour'd upon our house" +
+ "In the deep bosom of the ocean buried." +
+ "Now are our brows bound with victorious wreaths;" +
+ "Our bruised arms hung up for monuments;" +
+ "Our stern alarums changed to merry meetings," +
+ "Our dreadful marches to delightful measures." +
+ "Grim-visaged war hath smooth'd his wrinkled front;" +
+ "And now, instead of mounting barded steeds" +
+ "To fright the souls of fearful adversaries," +
+ "He capers nimbly in a lady's chamber" +
+ "To the lascivious pleasing of a lute." +
+ "But I, that am not shaped for sportive tricks," +
+ "Nor made to court an amorous looking-glass;" +
+ "I, that am rudely stamp'd, and want love's majesty" +
+ "To strut before a wanton ambling nymph;" +
+ "I, that am curtail'd of this fair proportion," +
+ "Cheated of feature by dissembling nature," +
+ "Deformed, unfinish'd, sent before my time" +
+ "Into this breathing world, scarce half made up," +
+ "And that so lamely and unfashionable" +
+ "That dogs bark at me as I halt by them;" +
+ "Why, I, in this weak piping time of peace," +
+ "Have no delight to pass away the time," +
+ "Unless to spy my shadow in the sun" +
+ "And descant on mine own deformity:" +
+ "And therefore, since I cannot prove a lover," +
+ "To entertain these fair well-spoken days," +
+ "I am determined to prove a villain" +
+ "And hate the idle pleasures of these days." +
+ "Plots have I laid, inductions dangerous," +
+ "By drunken prophecies, libels and dreams," +
+ "To set my brother Clarence and the king" +
+ "In deadly hate the one against the other:" +
+ "And if King Edward be as true and just" +
+ "As I am subtle, false and treacherous," +
+ "This day should Clarence closely be mew'd up," +
+ "About a prophecy, which says that 'G'" +
+ "Of Edward's heirs the murderer shall be." +
+ "Dive, thoughts, down to my soul: here" +
+ "Clarence comes.",
+
+ "To bait fish withal: if it will feed nothing else," +
+ "it will feed my revenge. He hath disgraced me, and" +
+ "hindered me half a million; laughed at my losses," +
+ "mocked at my gains, scorned my nation, thwarted my" +
+ "bargains, cooled my friends, heated mine" +
+ "enemies; and what's his reason? I am a Jew. Hath" +
+ "not a Jew eyes? hath not a Jew hands, organs," +
+ "dimensions, senses, affections, passions? fed with" +
+ "the same food, hurt with the same weapons, subject" +
+ "to the same diseases, healed by the same means," +
+ "warmed and cooled by the same winter and summer, as" +
+ "a Christian is? If you prick us, do we not bleed?" +
+ "if you tickle us, do we not laugh? if you poison" +
+ "us, do we not die? and if you wrong us, shall we not" +
+ "revenge? If we are like you in the rest, we will" +
+ "resemble you in that. If a Jew wrong a Christian," +
+ "what is his humility? Revenge. If a Christian" +
+ "wrong a Jew, what should his sufferance be by" +
+ "Christian example? Why, revenge. The villany you" +
+ "teach me, I will execute, and it shall go hard but I" +
+ "will better the instruction.",
+
+ "Virtue! a fig! 'tis in ourselves that we are thus" +
+ "or thus. Our bodies are our gardens, to the which" +
+ "our wills are gardeners: so that if we will plant" +
+ "nettles, or sow lettuce, set hyssop and weed up" +
+ "thyme, supply it with one gender of herbs, or" +
+ "distract it with many, either to have it sterile" +
+ "with idleness, or manured with industry, why, the" +
+ "power and corrigible authority of this lies in our" +
+ "wills. If the balance of our lives had not one" +
+ "scale of reason to poise another of sensuality, the" +
+ "blood and baseness of our natures would conduct us" +
+ "to most preposterous conclusions: but we have" +
+ "reason to cool our raging motions, our carnal" +
+ "stings, our unbitted lusts, whereof I take this that" +
+ "you call love to be a sect or scion.",
+
+ "Blow, winds, and crack your cheeks! rage! blow!" +
+ "You cataracts and hurricanoes, spout" +
+ "Till you have drench'd our steeples, drown'd the cocks!" +
+ "You sulphurous and thought-executing fires," +
+ "Vaunt-couriers to oak-cleaving thunderbolts," +
+ "Singe my white head! And thou, all-shaking thunder," +
+ "Smite flat the thick rotundity o' the world!" +
+ "Crack nature's moulds, an germens spill at once," +
+ "That make ingrateful man!"
+ };
+
+ /**
+ * Our data, part 3.
+ */
+ private boolean[] mExpanded =
+ {
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+ }
+
+ /**
+ * We will use a SpeechView to display each speech. It's just a LinearLayout
+ * with two text fields.
+ *
+ */
+ private class SpeechView extends LinearLayout {
+ public SpeechView(Context context, String title, String dialogue, boolean expanded) {
+ super(context);
+
+ this.setOrientation(VERTICAL);
+
+ // Here we build the child views in code. They could also have
+ // been specified in an XML file.
+
+ mTitle = new TextView(context);
+ mTitle.setText(title);
+ addView(mTitle, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+
+ mDialogue = new TextView(context);
+ mDialogue.setText(dialogue);
+ addView(mDialogue, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
+
+ mDialogue.setVisibility(expanded ? VISIBLE : GONE);
+ }
+
+ /**
+ * Convenience method to set the title of a SpeechView
+ */
+ public void setTitle(String title) {
+ mTitle.setText(title);
+ }
+
+ /**
+ * Convenience method to set the dialogue of a SpeechView
+ */
+ public void setDialogue(String words) {
+ mDialogue.setText(words);
+ }
+
+ /**
+ * Convenience method to expand or hide the dialogue
+ */
+ public void setExpanded(boolean expanded) {
+ mDialogue.setVisibility(expanded ? VISIBLE : GONE);
+ }
+
+ private TextView mTitle;
+ private TextView mDialogue;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List7.java b/samples/ApiDemos/src/com/example/android/apis/view/List7.java
new file mode 100644
index 0000000..d44ed56
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List7.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.ListActivity;
+import android.database.Cursor;
+import android.provider.Contacts.People;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ListAdapter;
+import android.widget.SimpleCursorAdapter;
+import android.widget.TextView;
+
+/**
+ * A list view example where the data comes from a cursor.
+ */
+public class List7 extends ListActivity implements OnItemSelectedListener {
+ private static String[] PROJECTION = new String[] {
+ People._ID, People.NAME, People.NUMBER
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.list_7);
+ mPhone = (TextView) findViewById(R.id.phone);
+ getListView().setOnItemSelectedListener(this);
+
+ // Get a cursor with all people
+ Cursor c = getContentResolver().query(People.CONTENT_URI, PROJECTION, null, null, null);
+ startManagingCursor(c);
+ mPhoneColumnIndex = c.getColumnIndex(People.NUMBER);
+
+ ListAdapter adapter = new SimpleCursorAdapter(this,
+ android.R.layout.simple_list_item_1, // Use a template
+ // that displays a
+ // text view
+ c, // Give the cursor to the list adatper
+ new String[] {People.NAME}, // Map the NAME column in the
+ // people database to...
+ new int[] {android.R.id.text1}); // The "text1" view defined in
+ // the XML template
+ setListAdapter(adapter);
+ }
+
+ public void onItemSelected(AdapterView parent, View v, int position, long id) {
+ if (position >= 0) {
+ Cursor c = (Cursor) parent.getItemAtPosition(position);
+ mPhone.setText(c.getString(mPhoneColumnIndex));
+ }
+ }
+
+ public void onNothingSelected(AdapterView parent) {
+ mPhone.setText(R.string.list_7_nothing);
+
+ }
+
+ private int mPhoneColumnIndex;
+ private TextView mPhone;
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List8.java b/samples/ApiDemos/src/com/example/android/apis/view/List8.java
new file mode 100644
index 0000000..1a54aa7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List8.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.AbsListView;
+
+import java.util.ArrayList;
+
+
+/**
+ * A list view that demonstrates the use of setEmptyView. This example alos uses
+ * a custom layout file that adds some extra buttons to the screen.
+ */
+public class List8 extends ListActivity {
+
+ PhotoAdapter mAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Use a custom layout file
+ setContentView(R.layout.list_8);
+
+ // Tell the list view which view to display when the list is empty
+ getListView().setEmptyView(findViewById(R.id.empty));
+
+ // Set up our adapter
+ mAdapter = new PhotoAdapter(this);
+ setListAdapter(mAdapter);
+
+ // Wire up the clear button to remove all photos
+ Button clear = (Button) findViewById(R.id.clear);
+ clear.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View v) {
+ mAdapter.clearPhotos();
+ } });
+
+ // Wire up the add button to add a new photo
+ Button add = (Button) findViewById(R.id.add);
+ add.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View v) {
+ mAdapter.addPhotos();
+ } });
+ }
+
+ /**
+ * A simple adapter which maintains an ArrayList of photo resource Ids.
+ * Each photo is displayed as an image. This adapter supports clearing the
+ * list of photos and adding a new photo.
+ *
+ */
+ public class PhotoAdapter extends BaseAdapter {
+
+ private Integer[] mPhotoPool = {
+ R.drawable.sample_thumb_0, R.drawable.sample_thumb_1, R.drawable.sample_thumb_2,
+ R.drawable.sample_thumb_3, R.drawable.sample_thumb_4, R.drawable.sample_thumb_5,
+ R.drawable.sample_thumb_6, R.drawable.sample_thumb_7};
+
+ private ArrayList<Integer> mPhotos = new ArrayList<Integer>();
+
+ public PhotoAdapter(Context c) {
+ mContext = c;
+ }
+
+ public int getCount() {
+ return mPhotos.size();
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // Make an ImageView to show a photo
+ ImageView i = new ImageView(mContext);
+
+ i.setImageResource(mPhotos.get(position));
+ i.setAdjustViewBounds(true);
+ i.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+ // Give it a nice background
+ i.setBackgroundResource(R.drawable.picture_frame);
+ return i;
+ }
+
+ private Context mContext;
+
+ public void clearPhotos() {
+ mPhotos.clear();
+ notifyDataSetChanged();
+ }
+
+ public void addPhotos() {
+ int whichPhoto = (int)Math.round(Math.random() * (mPhotoPool.length - 1));
+ int newPhoto = mPhotoPool[whichPhoto];
+ mPhotos.add(newPhoto);
+ notifyDataSetChanged();
+ }
+
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/List9.java b/samples/ApiDemos/src/com/example/android/apis/view/List9.java
new file mode 100644
index 0000000..15b3cc1
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/List9.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.LayoutInflater;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.AbsListView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+
+/**
+ * Another variation of the list of cheeses. In this case, we use
+ * {@link AbsListView#setOnScrollListener(AbsListView.OnScrollListener)
+ * AbsListView#setOnItemScrollListener(AbsListView.OnItemScrollListener)} to display the
+ * first letter of the visible range of cheeses.
+ */
+public class List9 extends ListActivity implements ListView.OnScrollListener {
+
+ private final class RemoveWindow implements Runnable {
+ public void run() {
+ removeWindow();
+ }
+ }
+
+ private RemoveWindow mRemoveWindow = new RemoveWindow();
+ Handler mHandler = new Handler();
+ private WindowManager mWindowManager;
+ private TextView mDialogText;
+ private boolean mShowing;
+ private boolean mReady;
+ private char mPrevLetter = Character.MIN_VALUE;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
+
+ // Use an existing ListAdapter that will map an array
+ // of strings to TextViews
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, mStrings));
+
+ getListView().setOnScrollListener(this);
+
+ LayoutInflater inflate = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ mDialogText = (TextView) inflate.inflate(R.layout.list_position, null);
+ mDialogText.setVisibility(View.INVISIBLE);
+
+ mHandler.post(new Runnable() {
+
+ public void run() {
+ mReady = true;
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.TYPE_APPLICATION,
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT);
+ mWindowManager.addView(mDialogText, lp);
+ }});
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mReady = true;
+ }
+
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ removeWindow();
+ mReady = false;
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mWindowManager.removeView(mDialogText);
+ mReady = false;
+ }
+
+
+
+
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+ int lastItem = firstVisibleItem + visibleItemCount - 1;
+ if (mReady) {
+ char firstLetter = mStrings[firstVisibleItem].charAt(0);
+
+ if (!mShowing && firstLetter != mPrevLetter) {
+
+ mShowing = true;
+ mDialogText.setVisibility(View.VISIBLE);
+
+
+ }
+ mDialogText.setText(((Character)firstLetter).toString());
+ mHandler.removeCallbacks(mRemoveWindow);
+ mHandler.postDelayed(mRemoveWindow, 3000);
+ mPrevLetter = firstLetter;
+ }
+ }
+
+
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ }
+
+
+ private void removeWindow() {
+ if (mShowing) {
+ mShowing = false;
+ mDialogText.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ private String[] mStrings = {
+ "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",
+ "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis",
+ "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
+ "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
+ "Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh",
+ "Anthoriro", "Appenzell", "Aragon", "Ardi Gasna", "Ardrahan",
+ "Armenian String", "Aromes au Gene de Marc", "Asadero", "Asiago",
+ "Aubisque Pyrenees", "Autun", "Avaxtskyr", "Baby Swiss", "Babybel",
+ "Baguette Laonnaise", "Bakers", "Baladi", "Balaton", "Bandal",
+ "Banon", "Barry's Bay Cheddar", "Basing", "Basket Cheese",
+ "Bath Cheese", "Bavarian Bergkase", "Baylough", "Beaufort",
+ "Beauvoorde", "Beenleigh Blue", "Beer Cheese", "Bel Paese",
+ "Bergader", "Bergere Bleue", "Berkswell", "Beyaz Peynir",
+ "Bierkase", "Bishop Kennedy", "Blarney", "Bleu d'Auvergne",
+ "Bleu de Gex", "Bleu de Laqueuille", "Bleu de Septmoncel",
+ "Bleu Des Causses", "Blue", "Blue Castello", "Blue Rathgore",
+ "Blue Vein (Australian)", "Blue Vein Cheeses", "Bocconcini",
+ "Bocconcini (Australian)", "Boeren Leidenkaas", "Bonchester",
+ "Bosworth", "Bougon", "Boule Du Roves", "Boulette d'Avesnes",
+ "Boursault", "Boursin", "Bouyssou", "Bra", "Braudostur",
+ "Breakfast Cheese", "Brebis du Lavort", "Brebis du Lochois",
+ "Brebis du Puyfaucon", "Bresse Bleu", "Brick", "Brie",
+ "Brie de Meaux", "Brie de Melun", "Brillat-Savarin", "Brin",
+ "Brin d' Amour", "Brin d'Amour", "Brinza (Burduf Brinza)",
+ "Briquette de Brebis", "Briquette du Forez", "Broccio",
+ "Broccio Demi-Affine", "Brousse du Rove", "Bruder Basil",
+ "Brusselae Kaas (Fromage de Bruxelles)", "Bryndza",
+ "Buchette d'Anjou", "Buffalo", "Burgos", "Butte", "Butterkase",
+ "Button (Innes)", "Buxton Blue", "Cabecou", "Caboc", "Cabrales",
+ "Cachaille", "Caciocavallo", "Caciotta", "Caerphilly",
+ "Cairnsmore", "Calenzana", "Cambazola", "Camembert de Normandie",
+ "Canadian Cheddar", "Canestrato", "Cantal", "Caprice des Dieux",
+ "Capricorn Goat", "Capriole Banon", "Carre de l'Est",
+ "Casciotta di Urbino", "Cashel Blue", "Castellano", "Castelleno",
+ "Castelmagno", "Castelo Branco", "Castigliano", "Cathelain",
+ "Celtic Promise", "Cendre d'Olivet", "Cerney", "Chabichou",
+ "Chabichou du Poitou", "Chabis de Gatine", "Chaource", "Charolais",
+ "Chaumes", "Cheddar", "Cheddar Clothbound", "Cheshire", "Chevres",
+ "Chevrotin des Aravis", "Chontaleno", "Civray",
+ "Coeur de Camembert au Calvados", "Coeur de Chevre", "Colby",
+ "Cold Pack", "Comte", "Coolea", "Cooleney", "Coquetdale",
+ "Corleggy", "Cornish Pepper", "Cotherstone", "Cotija",
+ "Cottage Cheese", "Cottage Cheese (Australian)", "Cougar Gold",
+ "Coulommiers", "Coverdale", "Crayeux de Roncq", "Cream Cheese",
+ "Cream Havarti", "Crema Agria", "Crema Mexicana", "Creme Fraiche",
+ "Crescenza", "Croghan", "Crottin de Chavignol",
+ "Crottin du Chavignol", "Crowdie", "Crowley", "Cuajada", "Curd",
+ "Cure Nantais", "Curworthy", "Cwmtawe Pecorino",
+ "Cypress Grove Chevre", "Danablu (Danish Blue)", "Danbo",
+ "Danish Fontina", "Daralagjazsky", "Dauphin", "Delice des Fiouves",
+ "Denhany Dorset Drum", "Derby", "Dessertnyj Belyj", "Devon Blue",
+ "Devon Garland", "Dolcelatte", "Doolin", "Doppelrhamstufel",
+ "Dorset Blue Vinney", "Double Gloucester", "Double Worcester",
+ "Dreux a la Feuille", "Dry Jack", "Duddleswell", "Dunbarra",
+ "Dunlop", "Dunsyre Blue", "Duroblando", "Durrus",
+ "Dutch Mimolette (Commissiekaas)", "Edam", "Edelpilz",
+ "Emental Grand Cru", "Emlett", "Emmental", "Epoisses de Bourgogne",
+ "Esbareich", "Esrom", "Etorki", "Evansdale Farmhouse Brie",
+ "Evora De L'Alentejo", "Exmoor Blue", "Explorateur", "Feta",
+ "Feta (Australian)", "Figue", "Filetta", "Fin-de-Siecle",
+ "Finlandia Swiss", "Finn", "Fiore Sardo", "Fleur du Maquis",
+ "Flor de Guia", "Flower Marie", "Folded",
+ "Folded cheese with mint", "Fondant de Brebis", "Fontainebleau",
+ "Fontal", "Fontina Val d'Aosta", "Formaggio di capra", "Fougerus",
+ "Four Herb Gouda", "Fourme d' Ambert", "Fourme de Haute Loire",
+ "Fourme de Montbrison", "Fresh Jack", "Fresh Mozzarella",
+ "Fresh Ricotta", "Fresh Truffles", "Fribourgeois", "Friesekaas",
+ "Friesian", "Friesla", "Frinault", "Fromage a Raclette",
+ "Fromage Corse", "Fromage de Montagne de Savoie", "Fromage Frais",
+ "Fruit Cream Cheese", "Frying Cheese", "Fynbo", "Gabriel",
+ "Galette du Paludier", "Galette Lyonnaise",
+ "Galloway Goat's Milk Gems", "Gammelost", "Gaperon a l'Ail",
+ "Garrotxa", "Gastanberra", "Geitost", "Gippsland Blue", "Gjetost",
+ "Gloucester", "Golden Cross", "Gorgonzola", "Gornyaltajski",
+ "Gospel Green", "Gouda", "Goutu", "Gowrie", "Grabetto", "Graddost",
+ "Grafton Village Cheddar", "Grana", "Grana Padano", "Grand Vatel",
+ "Grataron d' Areches", "Gratte-Paille", "Graviera", "Greuilh",
+ "Greve", "Gris de Lille", "Gruyere", "Gubbeen", "Guerbigny",
+ "Halloumi", "Halloumy (Australian)", "Haloumi-Style Cheese",
+ "Harbourne Blue", "Havarti", "Heidi Gruyere", "Hereford Hop",
+ "Herrgardsost", "Herriot Farmhouse", "Herve", "Hipi Iti",
+ "Hubbardston Blue Cow", "Hushallsost", "Iberico", "Idaho Goatster",
+ "Idiazabal", "Il Boschetto al Tartufo", "Ile d'Yeu",
+ "Isle of Mull", "Jarlsberg", "Jermi Tortes", "Jibneh Arabieh",
+ "Jindi Brie", "Jubilee Blue", "Juustoleipa", "Kadchgall", "Kaseri",
+ "Kashta", "Kefalotyri", "Kenafa", "Kernhem", "Kervella Affine",
+ "Kikorangi", "King Island Cape Wickham Brie", "King River Gold",
+ "Klosterkaese", "Knockalara", "Kugelkase", "L'Aveyronnais",
+ "L'Ecir de l'Aubrac", "La Taupiniere", "La Vache Qui Rit",
+ "Laguiole", "Lairobell", "Lajta", "Lanark Blue", "Lancashire",
+ "Langres", "Lappi", "Laruns", "Lavistown", "Le Brin",
+ "Le Fium Orbo", "Le Lacandou", "Le Roule", "Leafield", "Lebbene",
+ "Leerdammer", "Leicester", "Leyden", "Limburger",
+ "Lincolnshire Poacher", "Lingot Saint Bousquet d'Orb", "Liptauer",
+ "Little Rydings", "Livarot", "Llanboidy", "Llanglofan Farmhouse",
+ "Loch Arthur Farmhouse", "Loddiswell Avondale", "Longhorn",
+ "Lou Palou", "Lou Pevre", "Lyonnais", "Maasdam", "Macconais",
+ "Mahoe Aged Gouda", "Mahon", "Malvern", "Mamirolle", "Manchego",
+ "Manouri", "Manur", "Marble Cheddar", "Marbled Cheeses",
+ "Maredsous", "Margotin", "Maribo", "Maroilles", "Mascares",
+ "Mascarpone", "Mascarpone (Australian)", "Mascarpone Torta",
+ "Matocq", "Maytag Blue", "Meira", "Menallack Farmhouse",
+ "Menonita", "Meredith Blue", "Mesost", "Metton (Cancoillotte)",
+ "Meyer Vintage Gouda", "Mihalic Peynir", "Milleens", "Mimolette",
+ "Mine-Gabhar", "Mini Baby Bells", "Mixte", "Molbo",
+ "Monastery Cheeses", "Mondseer", "Mont D'or Lyonnais", "Montasio",
+ "Monterey Jack", "Monterey Jack Dry", "Morbier",
+ "Morbier Cru de Montagne", "Mothais a la Feuille", "Mozzarella",
+ "Mozzarella (Australian)", "Mozzarella di Bufala",
+ "Mozzarella Fresh, in water", "Mozzarella Rolls", "Munster",
+ "Murol", "Mycella", "Myzithra", "Naboulsi", "Nantais",
+ "Neufchatel", "Neufchatel (Australian)", "Niolo", "Nokkelost",
+ "Northumberland", "Oaxaca", "Olde York", "Olivet au Foin",
+ "Olivet Bleu", "Olivet Cendre", "Orkney Extra Mature Cheddar",
+ "Orla", "Oschtjepka", "Ossau Fermier", "Ossau-Iraty", "Oszczypek",
+ "Oxford Blue", "P'tit Berrichon", "Palet de Babligny", "Paneer",
+ "Panela", "Pannerone", "Pant ys Gawn", "Parmesan (Parmigiano)",
+ "Parmigiano Reggiano", "Pas de l'Escalette", "Passendale",
+ "Pasteurized Processed", "Pate de Fromage", "Patefine Fort",
+ "Pave d'Affinois", "Pave d'Auge", "Pave de Chirac",
+ "Pave du Berry", "Pecorino", "Pecorino in Walnut Leaves",
+ "Pecorino Romano", "Peekskill Pyramid", "Pelardon des Cevennes",
+ "Pelardon des Corbieres", "Penamellera", "Penbryn", "Pencarreg",
+ "Perail de Brebis", "Petit Morin", "Petit Pardou", "Petit-Suisse",
+ "Picodon de Chevre", "Picos de Europa", "Piora",
+ "Pithtviers au Foin", "Plateau de Herve", "Plymouth Cheese",
+ "Podhalanski", "Poivre d'Ane", "Polkolbin", "Pont l'Eveque",
+ "Port Nicholson", "Port-Salut", "Postel", "Pouligny-Saint-Pierre",
+ "Pourly", "Prastost", "Pressato", "Prince-Jean",
+ "Processed Cheddar", "Provolone", "Provolone (Australian)",
+ "Pyengana Cheddar", "Pyramide", "Quark", "Quark (Australian)",
+ "Quartirolo Lombardo", "Quatre-Vents", "Quercy Petit",
+ "Queso Blanco", "Queso Blanco con Frutas --Pina y Mango",
+ "Queso de Murcia", "Queso del Montsec", "Queso del Tietar",
+ "Queso Fresco", "Queso Fresco (Adobera)", "Queso Iberico",
+ "Queso Jalapeno", "Queso Majorero", "Queso Media Luna",
+ "Queso Para Frier", "Queso Quesadilla", "Rabacal", "Raclette",
+ "Ragusano", "Raschera", "Reblochon", "Red Leicester",
+ "Regal de la Dombes", "Reggianito", "Remedou", "Requeson",
+ "Richelieu", "Ricotta", "Ricotta (Australian)", "Ricotta Salata",
+ "Ridder", "Rigotte", "Rocamadour", "Rollot", "Romano",
+ "Romans Part Dieu", "Roncal", "Roquefort", "Roule",
+ "Rouleau De Beaulieu", "Royalp Tilsit", "Rubens", "Rustinu",
+ "Saaland Pfarr", "Saanenkaese", "Saga", "Sage Derby",
+ "Sainte Maure", "Saint-Marcellin", "Saint-Nectaire",
+ "Saint-Paulin", "Salers", "Samso", "San Simon", "Sancerre",
+ "Sap Sago", "Sardo", "Sardo Egyptian", "Sbrinz", "Scamorza",
+ "Schabzieger", "Schloss", "Selles sur Cher", "Selva", "Serat",
+ "Seriously Strong Cheddar", "Serra da Estrela", "Sharpam",
+ "Shelburne Cheddar", "Shropshire Blue", "Siraz", "Sirene",
+ "Smoked Gouda", "Somerset Brie", "Sonoma Jack",
+ "Sottocenare al Tartufo", "Soumaintrain", "Sourire Lozerien",
+ "Spenwood", "Sraffordshire Organic", "St. Agur Blue Cheese",
+ "Stilton", "Stinking Bishop", "String", "Sussex Slipcote",
+ "Sveciaost", "Swaledale", "Sweet Style Swiss", "Swiss",
+ "Syrian (Armenian String)", "Tala", "Taleggio", "Tamie",
+ "Tasmania Highland Chevre Log", "Taupiniere", "Teifi", "Telemea",
+ "Testouri", "Tete de Moine", "Tetilla", "Texas Goat Cheese",
+ "Tibet", "Tillamook Cheddar", "Tilsit", "Timboon Brie", "Toma",
+ "Tomme Brulee", "Tomme d'Abondance", "Tomme de Chevre",
+ "Tomme de Romans", "Tomme de Savoie", "Tomme des Chouans",
+ "Tommes", "Torta del Casar", "Toscanello", "Touree de L'Aubier",
+ "Tourmalet", "Trappe (Veritable)", "Trois Cornes De Vendee",
+ "Tronchon", "Trou du Cru", "Truffe", "Tupi", "Turunmaa",
+ "Tymsboro", "Tyn Grug", "Tyning", "Ubriaco", "Ulloa",
+ "Vacherin-Fribourgeois", "Valencay", "Vasterbottenost", "Venaco",
+ "Vendomois", "Vieux Corse", "Vignotte", "Vulscombe",
+ "Waimata Farmhouse Blue", "Washed Rind Cheese (Australian)",
+ "Waterloo", "Weichkaese", "Wellington", "Wensleydale",
+ "White Stilton", "Whitestone Farmhouse", "Wigmore",
+ "Woodside Cabecou", "Xanadu", "Xynotyro", "Yarg Cornish",
+ "Yarra Valley Pyramid", "Yorkshire Blue", "Zamorano",
+ "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"};
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar1.java b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar1.java
new file mode 100644
index 0000000..d9bf360
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar1.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+
+
+/**
+ * Demonstrates how to use progress bars as widgets and in the title bar. The progress bar
+ * in the title will be shown until the progress is complete, at which point it fades away.
+ */
+public class ProgressBar1 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Request the progress bar to be shown in the title
+ requestWindowFeature(Window.FEATURE_PROGRESS);
+ setContentView(R.layout.progressbar_1);
+ setProgressBarVisibility(true);
+
+ final ProgressBar progressHorizontal = (ProgressBar) findViewById(R.id.progress_horizontal);
+ setProgress(progressHorizontal.getProgress() * 100);
+ setSecondaryProgress(progressHorizontal.getSecondaryProgress() * 100);
+
+ Button button = (Button) findViewById(R.id.increase);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ progressHorizontal.incrementProgressBy(1);
+ // Title progress is in range 0..10000
+ setProgress(100 * progressHorizontal.getProgress());
+ }
+ });
+
+ button = (Button) findViewById(R.id.decrease);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ progressHorizontal.incrementProgressBy(-1);
+ // Title progress is in range 0..10000
+ setProgress(100 * progressHorizontal.getProgress());
+ }
+ });
+
+ button = (Button) findViewById(R.id.increase_secondary);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ progressHorizontal.incrementSecondaryProgressBy(1);
+ // Title progress is in range 0..10000
+ setSecondaryProgress(100 * progressHorizontal.getSecondaryProgress());
+ }
+ });
+
+ button = (Button) findViewById(R.id.decrease_secondary);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ progressHorizontal.incrementSecondaryProgressBy(-1);
+ // Title progress is in range 0..10000
+ setSecondaryProgress(100 * progressHorizontal.getSecondaryProgress());
+ }
+ });
+
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar2.java b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar2.java
new file mode 100644
index 0000000..1c41b78
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar2.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Window;
+
+
+/**
+ * Demonstrates the use of indeterminate progress bars as widgets and in the
+ * window's title bar. The widgets show the 3 different sizes of circular
+ * progress bars that can be used.
+ */
+public class ProgressBar2 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Request for the progress bar to be shown in the title
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+
+ setContentView(R.layout.progressbar_2);
+
+ // Make sure the progress bar is visible
+ setProgressBarVisibility(true);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar3.java b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar3.java
new file mode 100644
index 0000000..285f07b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar3.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+/**
+ * Demonstrates the use of progress dialogs. Uses {@link Activity#onCreateDialog}
+ * and {@link Activity#showDialog} to ensure the dialogs will be properly saved
+ * and restored.
+ */
+public class ProgressBar3 extends Activity {
+
+ ProgressDialog mDialog1;
+ ProgressDialog mDialog2;
+
+ private static final int DIALOG1_KEY = 0;
+ private static final int DIALOG2_KEY = 1;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.progressbar_3);
+
+ Button button = (Button) findViewById(R.id.showIndeterminate);
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG1_KEY);
+ }
+ });
+
+ button = (Button) findViewById(R.id.showIndeterminateNoTitle);
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ showDialog(DIALOG2_KEY);
+ }
+ });
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DIALOG1_KEY: {
+ ProgressDialog dialog = new ProgressDialog(this);
+ dialog.setTitle("Indeterminate");
+ dialog.setMessage("Please wait while loading...");
+ dialog.setIndeterminate(true);
+ dialog.setCancelable(true);
+ return dialog;
+ }
+ case DIALOG2_KEY: {
+ ProgressDialog dialog = new ProgressDialog(this);
+ dialog.setMessage("Please wait while loading...");
+ dialog.setIndeterminate(true);
+ dialog.setCancelable(true);
+ return dialog;
+ }
+ }
+ return null;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar4.java b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar4.java
new file mode 100644
index 0000000..ee396b3
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar4.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Window;
+import android.view.View;
+import android.widget.Button;
+
+
+/**
+ * Demonstrates how to use an indetermiate progress indicator in the window's title bar.
+ */
+public class ProgressBar4 extends Activity {
+ private boolean mToggleIndeterminate = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Request progress bar
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.progressbar_4);
+ setProgressBarIndeterminateVisibility(mToggleIndeterminate);
+
+ Button button = (Button) findViewById(R.id.toggle);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ mToggleIndeterminate = !mToggleIndeterminate;
+ setProgressBarIndeterminateVisibility(mToggleIndeterminate);
+ }
+ });
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/RadioGroup1.java b/samples/ApiDemos/src/com/example/android/apis/view/RadioGroup1.java
new file mode 100644
index 0000000..4d91192
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/RadioGroup1.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.RadioGroup;
+import android.widget.Button;
+import android.widget.RadioButton;
+import android.widget.LinearLayout;
+
+
+public class RadioGroup1 extends Activity implements RadioGroup.OnCheckedChangeListener,
+ View.OnClickListener {
+
+ private TextView mChoice;
+ private RadioGroup mRadioGroup;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.radio_group_1);
+ mRadioGroup = (RadioGroup) findViewById(R.id.menu);
+
+ // test adding a radio button programmatically
+ RadioButton newRadioButton = new RadioButton(this);
+ newRadioButton.setText(R.string.radio_group_snack);
+ newRadioButton.setId(R.id.snack);
+ LinearLayout.LayoutParams layoutParams = new RadioGroup.LayoutParams(
+ RadioGroup.LayoutParams.WRAP_CONTENT,
+ RadioGroup.LayoutParams.WRAP_CONTENT);
+ mRadioGroup.addView(newRadioButton, 0, layoutParams);
+
+ // test listening to checked change events
+ String selection = getString(R.string.radio_group_selection);
+ mRadioGroup.setOnCheckedChangeListener(this);
+ mChoice = (TextView) findViewById(R.id.choice);
+ mChoice.setText(selection + mRadioGroup.getCheckedRadioButtonId());
+
+ // test clearing the selection
+ Button clearButton = (Button) findViewById(R.id.clear);
+ clearButton.setOnClickListener(this);
+ }
+
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ String selection = getString(R.string.radio_group_selection);
+ String none = getString(R.string.radio_group_none);
+ mChoice.setText(selection +
+ (checkedId == View.NO_ID ? none : checkedId));
+ }
+
+ public void onClick(View v) {
+ mRadioGroup.clearCheck();
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/RatingBar1.java b/samples/ApiDemos/src/com/example/android/apis/view/RatingBar1.java
new file mode 100644
index 0000000..97416d4
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/RatingBar1.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.RatingBar;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.example.android.apis.R;
+
+/**
+ * Demonstrates how to use a rating bar
+ */
+public class RatingBar1 extends Activity implements RatingBar.OnRatingBarChangeListener {
+ RatingBar mSmallRatingBar;
+ RatingBar mIndicatorRatingBar;
+ TextView mRatingText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.ratingbar_1);
+
+ mRatingText = (TextView) findViewById(R.id.rating);
+
+ // We copy the most recently changed rating on to these indicator-only
+ // rating bars
+ mIndicatorRatingBar = (RatingBar) findViewById(R.id.indicator_ratingbar);
+ mSmallRatingBar = (RatingBar) findViewById(R.id.small_ratingbar);
+
+ // The different rating bars in the layout. Assign the listener to us.
+ ((RatingBar)findViewById(R.id.ratingbar1)).setOnRatingBarChangeListener(this);
+ ((RatingBar)findViewById(R.id.ratingbar2)).setOnRatingBarChangeListener(this);
+ }
+
+ public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromTouch) {
+ final int numStars = ratingBar.getNumStars();
+ mRatingText.setText(
+ getString(R.string.ratingbar_rating) + " " + rating + "/" + numStars);
+
+ // Since this rating bar is updated to reflect any of the other rating
+ // bars, we should update it to the current values.
+ if (mIndicatorRatingBar.getNumStars() != numStars) {
+ mIndicatorRatingBar.setNumStars(numStars);
+ mSmallRatingBar.setNumStars(numStars);
+ }
+ if (mIndicatorRatingBar.getRating() != rating) {
+ mIndicatorRatingBar.setRating(rating);
+ mSmallRatingBar.setRating(rating);
+ }
+ final float ratingBarStepSize = ratingBar.getStepSize();
+ if (mIndicatorRatingBar.getStepSize() != ratingBarStepSize) {
+ mIndicatorRatingBar.setStepSize(ratingBarStepSize);
+ mSmallRatingBar.setStepSize(ratingBarStepSize);
+ }
+ }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout1.java b/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout1.java
new file mode 100644
index 0000000..1c9f824
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout1.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * A simple layout which demonstrates stretching a view to fill the space between two other views.
+ */
+public class RelativeLayout1 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.relative_layout_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout2.java b/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout2.java
new file mode 100644
index 0000000..635d9f3
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout2.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Builds building a simple form using a RelativeLayout
+ *
+ */
+public class RelativeLayout2 extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.relative_layout_2);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar1.java b/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar1.java
new file mode 100644
index 0000000..0b3c19a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar1.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class ScrollBar1 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.scrollbar1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar2.java b/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar2.java
new file mode 100644
index 0000000..09a8bb0
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar2.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class ScrollBar2 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.scrollbar2);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar3.java b/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar3.java
new file mode 100644
index 0000000..74c5876
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar3.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+import com.example.android.apis.R;
+
+
+public class ScrollBar3 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.scrollbar3);
+
+ findViewById(R.id.view3).setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ScrollView1.java b/samples/ApiDemos/src/com/example/android/apis/view/ScrollView1.java
new file mode 100644
index 0000000..b3a903a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ScrollView1.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+
+
+/**
+ * Demonstrates wrapping a layout in a ScrollView.
+ *
+ */
+public class ScrollView1 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.scroll_view_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/ScrollView2.java b/samples/ApiDemos/src/com/example/android/apis/view/ScrollView2.java
new file mode 100644
index 0000000..89e4003
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/ScrollView2.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Button;
+
+
+/**
+ * Demonstrates wrapping a layout in a ScrollView.
+ *
+ */
+public class ScrollView2 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.scroll_view_2);
+
+ LinearLayout layout = (LinearLayout) findViewById(R.id.layout);
+ for (int i = 2; i < 64; i++) {
+ TextView textView = new TextView(this);
+ textView.setText("Text View " + i);
+ LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.FILL_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ layout.addView(textView, p);
+
+ Button buttonView = new Button(this);
+ buttonView.setText("Button " + i);
+ layout.addView(buttonView, p);
+ }
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/SeekBar1.java b/samples/ApiDemos/src/com/example/android/apis/view/SeekBar1.java
new file mode 100644
index 0000000..15bb013
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/SeekBar1.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Demonstrates how to use a seek bar
+ */
+public class SeekBar1 extends Activity implements SeekBar.OnSeekBarChangeListener {
+
+ SeekBar mSeekBar;
+ TextView mProgressText;
+ TextView mTrackingText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.seekbar_1);
+
+ mSeekBar = (SeekBar)findViewById(R.id.seek);
+ mSeekBar.setOnSeekBarChangeListener(this);
+ mProgressText = (TextView)findViewById(R.id.progress);
+ mTrackingText = (TextView)findViewById(R.id.tracking);
+ }
+
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
+ mProgressText.setText(progress + " " +
+ getString(R.string.seekbar_from_touch) + "=" + fromTouch);
+ }
+
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mTrackingText.setText(getString(R.string.seekbar_tracking_on));
+ }
+
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ mTrackingText.setText(getString(R.string.seekbar_tracking_off));
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Spinner1.java b/samples/ApiDemos/src/com/example/android/apis/view/Spinner1.java
new file mode 100644
index 0000000..a35a909
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Spinner1.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+
+
+public class Spinner1 extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.spinner_1);
+
+ Spinner s1 = (Spinner) findViewById(R.id.spinner1);
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
+ this, R.array.colors, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ s1.setAdapter(adapter);
+
+ Spinner s2 = (Spinner) findViewById(R.id.spinner2);
+ adapter = ArrayAdapter.createFromResource(this, R.array.planets,
+ android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ s2.setAdapter(adapter);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout1.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout1.java
new file mode 100644
index 0000000..98f6b31
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout1.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class TableLayout1 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_1);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout10.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout10.java
new file mode 100644
index 0000000..f1f8f24
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout10.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.TableLayout;
+import android.widget.Button;
+import android.os.Bundle;
+import android.view.View;
+
+
+public class TableLayout10 extends Activity {
+ private boolean mShrink;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_10);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout11.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout11.java
new file mode 100644
index 0000000..770238f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout11.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * <p>This example shows how to use horizontal gravity in a table layout.</p>
+ */
+public class TableLayout11 extends Activity {
+ private boolean mShrink;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_11);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout12.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout12.java
new file mode 100644
index 0000000..14cbd0d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout12.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * <p>This example shows how to use cell spanning in a table layout.</p>
+ */
+public class TableLayout12 extends Activity {
+ private boolean mShrink;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_12);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout2.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout2.java
new file mode 100644
index 0000000..3e60563
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout2.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class TableLayout2 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_2);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout3.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout3.java
new file mode 100644
index 0000000..82a545c
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout3.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class TableLayout3 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_3);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout4.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout4.java
new file mode 100644
index 0000000..53a1055
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout4.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class TableLayout4 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_4);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout5.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout5.java
new file mode 100644
index 0000000..9422218
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout5.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class TableLayout5 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_5);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout6.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout6.java
new file mode 100644
index 0000000..b6a9125
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout6.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+public class TableLayout6 extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_6);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout7.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout7.java
new file mode 100644
index 0000000..22fc4a5
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout7.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TableLayout;
+import android.widget.TableRow;
+import android.widget.TextView;
+
+
+public class TableLayout7 extends Activity {
+ private boolean mShortcutsCollapsed;
+ private boolean mCheckmarksCollapsed;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_7);
+
+ final TableLayout table = (TableLayout) findViewById(R.id.menu);
+ Button button = (Button) findViewById(R.id.toggle1);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ mShortcutsCollapsed = !mShortcutsCollapsed;
+ table.setColumnCollapsed(2, mShortcutsCollapsed);
+ }
+ });
+ button = (Button) findViewById(R.id.toggle2);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ mCheckmarksCollapsed = !mCheckmarksCollapsed;
+ table.setColumnCollapsed(0, mCheckmarksCollapsed);
+ }
+ });
+
+ mCheckmarksCollapsed = table.isColumnCollapsed(0);
+ mShortcutsCollapsed = table.isColumnCollapsed(2);
+
+ appendRow(table);
+ }
+
+ private void appendRow(TableLayout table) {
+ TableRow row = new TableRow(this);
+
+ TextView label = new TextView(this);
+ label.setText(R.string.table_layout_7_quit);
+ label.setPadding(3, 3, 3, 3);
+
+ TextView shortcut = new TextView(this);
+ shortcut.setText(R.string.table_layout_7_ctrlq);
+ shortcut.setPadding(3, 3, 3, 3);
+ shortcut.setGravity(Gravity.RIGHT | Gravity.TOP);
+
+ row.addView(label, new TableRow.LayoutParams(1));
+ row.addView(shortcut, new TableRow.LayoutParams());
+
+ table.addView(row, new TableLayout.LayoutParams());
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout8.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout8.java
new file mode 100644
index 0000000..99ca4ac
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout8.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.TableLayout;
+import android.widget.Button;
+import android.widget.TableRow;
+import android.widget.TextView;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+
+
+public class TableLayout8 extends Activity {
+ private boolean mStretch;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_8);
+
+ final TableLayout table = (TableLayout) findViewById(R.id.menu);
+ Button button = (Button) findViewById(R.id.toggle);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ mStretch = !mStretch;
+ table.setColumnStretchable(1, mStretch);
+ }
+ });
+
+ mStretch = table.isColumnStretchable(1);
+
+ appendRow(table);
+ }
+
+ private void appendRow(TableLayout table) {
+ TableRow row = new TableRow(this);
+
+ TextView label = new TextView(this);
+ label.setText(R.string.table_layout_8_quit);
+ label.setPadding(3, 3, 3, 3);
+
+ TextView shortcut = new TextView(this);
+ shortcut.setText(R.string.table_layout_8_ctrlq);
+ shortcut.setPadding(3, 3, 3, 3);
+ shortcut.setGravity(Gravity.RIGHT | Gravity.TOP);
+
+ row.addView(label, new TableRow.LayoutParams(1));
+ row.addView(shortcut, new TableRow.LayoutParams());
+
+ table.addView(row, new TableLayout.LayoutParams());
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TableLayout9.java b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout9.java
new file mode 100644
index 0000000..f99111d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TableLayout9.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.widget.TableLayout;
+import android.widget.Button;
+import android.os.Bundle;
+import android.view.View;
+
+
+public class TableLayout9 extends Activity {
+ private boolean mShrink;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.table_layout_9);
+
+ final TableLayout table = (TableLayout) findViewById(R.id.menu);
+ Button button = (Button) findViewById(R.id.toggle);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ mShrink = !mShrink;
+ table.setColumnShrinkable(0, mShrink);
+ }
+ });
+
+ mShrink = table.isColumnShrinkable(0);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Tabs1.java b/samples/ApiDemos/src/com/example/android/apis/view/Tabs1.java
new file mode 100644
index 0000000..455969e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Tabs1.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.TabActivity;
+import android.os.Bundle;
+import android.widget.TabHost;
+import android.widget.TabHost.TabSpec;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.example.android.apis.R;
+
+/**
+ * An example of tabs that uses labels ({@link TabSpec#setIndicator(CharSequence)})
+ * for its indicators and views by id from a layout file ({@link TabSpec#setContent(int)}).
+ */
+public class Tabs1 extends TabActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TabHost tabHost = getTabHost();
+
+ LayoutInflater.from(this).inflate(R.layout.tabs1, tabHost.getTabContentView(), true);
+
+ tabHost.addTab(tabHost.newTabSpec("tab1")
+ .setIndicator("tab1")
+ .setContent(R.id.view1));
+ tabHost.addTab(tabHost.newTabSpec("tab3")
+ .setIndicator("tab2")
+ .setContent(R.id.view2));
+ tabHost.addTab(tabHost.newTabSpec("tab3")
+ .setIndicator("tab3")
+ .setContent(R.id.view3));
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Tabs2.java b/samples/ApiDemos/src/com/example/android/apis/view/Tabs2.java
new file mode 100644
index 0000000..795a86b
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Tabs2.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.TabActivity;
+import android.os.Bundle;
+import android.widget.TabHost;
+import android.widget.TextView;
+import android.view.View;
+import com.example.android.apis.R;
+
+/**
+ * Example of using a tab content factory for the content via {@link TabHost.TabSpec#setContent(android.widget.TabHost.TabContentFactory)}
+ *
+ * It also demonstrates using an icon on one of the tabs via {@link TabHost.TabSpec#setIndicator(CharSequence, android.graphics.drawable.Drawable)}
+ *
+ */
+public class Tabs2 extends TabActivity implements TabHost.TabContentFactory {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final TabHost tabHost = getTabHost();
+ tabHost.addTab(tabHost.newTabSpec("tab1")
+ .setIndicator("tab1", getResources().getDrawable(R.drawable.star_big_on))
+ .setContent(this));
+ tabHost.addTab(tabHost.newTabSpec("tab2")
+ .setIndicator("tab2")
+ .setContent(this));
+ tabHost.addTab(tabHost.newTabSpec("tab3")
+ .setIndicator("tab3")
+ .setContent(this));
+ }
+
+ /** {@inheritDoc} */
+ public View createTabContent(String tag) {
+ final TextView tv = new TextView(this);
+ tv.setText("Content for tab with tag " + tag);
+ return tv;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Tabs3.java b/samples/ApiDemos/src/com/example/android/apis/view/Tabs3.java
new file mode 100644
index 0000000..e09f041
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Tabs3.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import android.app.TabActivity;
+import android.os.Bundle;
+import android.widget.TabHost;
+import android.content.Intent;
+
+/**
+ * An example of tab content that launches an activity via {@link android.widget.TabHost.TabSpec#setContent(android.content.Intent)}
+ */
+public class Tabs3 extends TabActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final TabHost tabHost = getTabHost();
+
+ tabHost.addTab(tabHost.newTabSpec("tab1")
+ .setIndicator("list")
+ .setContent(new Intent(this, List1.class)));
+
+ tabHost.addTab(tabHost.newTabSpec("tab2")
+ .setIndicator("photo list")
+ .setContent(new Intent(this, List8.class)));
+
+ // This tab sets the intent flag so that it is recreated each time
+ // the tab is clicked.
+ tabHost.addTab(tabHost.newTabSpec("tab3")
+ .setIndicator("destroy")
+ .setContent(new Intent(this, Controls2.class)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)));
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/TextSwitcher1.java b/samples/ApiDemos/src/com/example/android/apis/view/TextSwitcher1.java
new file mode 100644
index 0000000..b964512
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/TextSwitcher1.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.Button;
+import android.widget.TextSwitcher;
+import android.widget.TextView;
+import android.widget.ViewSwitcher;
+
+/**
+ * Uses a TextSwitcher.
+ */
+public class TextSwitcher1 extends Activity implements ViewSwitcher.ViewFactory,
+ View.OnClickListener {
+
+ private TextSwitcher mSwitcher;
+
+ private int mCounter = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.text_switcher_1);
+
+ mSwitcher = (TextSwitcher) findViewById(R.id.switcher);
+ mSwitcher.setFactory(this);
+
+ Animation in = AnimationUtils.loadAnimation(this,
+ android.R.anim.fade_in);
+ Animation out = AnimationUtils.loadAnimation(this,
+ android.R.anim.fade_out);
+ mSwitcher.setInAnimation(in);
+ mSwitcher.setOutAnimation(out);
+
+ Button nextButton = (Button) findViewById(R.id.next);
+ nextButton.setOnClickListener(this);
+
+ updateCounter();
+ }
+
+ public void onClick(View v) {
+ mCounter++;
+ updateCounter();
+ }
+
+ private void updateCounter() {
+ mSwitcher.setText(String.valueOf(mCounter));
+ }
+
+ public View makeView() {
+ TextView t = new TextView(this);
+ t.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
+ t.setTextSize(36);
+ return t;
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Visibility1.java b/samples/ApiDemos/src/com/example/android/apis/view/Visibility1.java
new file mode 100644
index 0000000..243eba7
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Visibility1.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+// 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.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+
+/**
+ * Demonstrates making a view VISIBLE, INVISIBLE and GONE
+ *
+ */
+public class Visibility1 extends Activity {
+
+ private View mVictim;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.visibility_1);
+
+ // Find the view whose visibility will change
+ mVictim = findViewById(R.id.victim);
+
+ // Find our buttons
+ Button visibleButton = (Button) findViewById(R.id.vis);
+ Button invisibleButton = (Button) findViewById(R.id.invis);
+ Button goneButton = (Button) findViewById(R.id.gone);
+
+ // Wire each button to a click listener
+ visibleButton.setOnClickListener(mVisibleListener);
+ invisibleButton.setOnClickListener(mInvisibleListener);
+ goneButton.setOnClickListener(mGoneListener);
+ }
+
+ OnClickListener mVisibleListener = new OnClickListener() {
+ public void onClick(View v) {
+ mVictim.setVisibility(View.VISIBLE);
+ }
+ };
+
+ OnClickListener mInvisibleListener = new OnClickListener() {
+ public void onClick(View v) {
+ mVictim.setVisibility(View.INVISIBLE);
+ }
+ };
+
+ OnClickListener mGoneListener = new OnClickListener() {
+ public void onClick(View v) {
+ mVictim.setVisibility(View.GONE);
+ }
+ };
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/WebView1.java b/samples/ApiDemos/src/com/example/android/apis/view/WebView1.java
new file mode 100644
index 0000000..1cef034
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/WebView1.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 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.view;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.webkit.WebView;
+
+import com.example.android.apis.R;
+
+
+/**
+ * Sample creating 10 webviews.
+ */
+public class WebView1 extends Activity {
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setContentView(R.layout.webview_1);
+
+ final String mimeType = "text/html";
+ final String encoding = "utf-8";
+
+ WebView wv;
+
+ wv = (WebView) findViewById(R.id.wv1);
+ wv.loadData("<a href='x'>Hello World! - 1</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv2);
+ wv.loadData("<a href='x'>Hello World! - 2</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv3);
+ wv.loadData("<a href='x'>Hello World! - 3</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv4);
+ wv.loadData("<a href='x'>Hello World! - 4</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv5);
+ wv.loadData("<a href='x'>Hello World! - 5</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv6);
+ wv.loadData("<a href='x'>Hello World! - 6</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv7);
+ wv.loadData("<a href='x'>Hello World! - 7</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv8);
+ wv.loadData("<a href='x'>Hello World! - 8</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv9);
+ wv.loadData("<a href='x'>Hello World! - 9</a>", mimeType, encoding);
+
+ wv = (WebView) findViewById(R.id.wv10);
+ wv.loadData("<a href='x'>Hello World! - 10</a>", mimeType, encoding);
+ }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/_index.html b/samples/ApiDemos/src/com/example/android/apis/view/_index.html
new file mode 100644
index 0000000..9497f8e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/_index.html
@@ -0,0 +1,298 @@
+<h3>RelativeLayout</h3>
+<dl>
+ <dt><a href="RelativeLayout1.html">1. Vertical</a></dt>
+ <dd>Demonstrates a simple relative layout.</dd>
+
+ <dt><a href="RelativeLayout2.html">2. Simple Form</a></dt>
+ <dd>Demonstrates a more complex relative layout to create a form. </dd>
+</dl>
+
+<h3>LinearLayout</h3>
+<dl>
+ <dt><a href="LinearLayout1.html">1. Vertical</a></dt>
+ <dd>Demonstrates a simple LinearLayout, with child width set to WRAP_CONTENT. </dd>
+
+ <dt><a href="LinearLayout2.html">2. Vertical (Fill Screen)</a></dt>
+ <dd>Demonstrates a simple LinearLayout, with child width set to FILL_PARENT.</dd>
+
+ <dt><a href="LinearLayout3.html">3. Vertical (Padded)</a></dt>
+ <dd>Demonstrates a LinearLayout where one of the elements can expand to fill any remaining screen space (weight=1). </dd>
+
+ <dt><a href="LinearLayout4.html">4. Horizontal</a></dt>
+ <dd>Demonstrates a horizontal LinearLayout, plus an expanding column. </dd>
+
+ <dt><a href="LinearLayout5.html">5. Simple Form</a></dt>
+ <dd>Demonstrates nested layouts to create a user form.</dd>
+
+ <dt><a href="LinearLayout6.html">6. Uniform Size</a></dt>
+ <dd>LinearLayout which uses a combination of wrap_content on itself and fill_parent on its children to get every item to be the same width.</dd>
+
+ <dt><a href="LinearLayout7.html">7. Fill Parent</a></dt>
+ <dd>Demonstrates a horizontal linear layout with equally sized columns. Some columns force their height to match the parent.</dd>
+
+ <dt><a href="LinearLayout8.html">8. Gravity</a></dt>
+ <dd>Demonstrates a simple linear layout with menu options demonstrating horizontal and vertical gravity options.</dd>
+
+ <dt><a href="LinearLayout9.html">9. Layout Weight</a></dt>
+ <dd> Demonstrates how the layout_weight attribute can shrink an element too big to fit on screen.</dd>
+
+</dl>
+
+<h3>ScrollView</h3>
+<dl>
+ <dt><a href="ScrollView1.html">1. Short</a></dt>
+ <dd>Demonstrates scrolling screen with buttons altermating with a text view. </dd>
+
+ <dt><a href="ScrollView2.html">2. Long</a></dt>
+ <dd>Demonstrates a longer scrolling screen similar to ScrollView1. </dd>
+</dl>
+
+<h3>TableLayout</h3>
+<dl>
+ <dt><a href="TableLayout1.html">1. Basic</a></dt>
+ <dd>Demonstrates a basic TableLayout with identical children. </dd>
+
+ <dt><a href="TableLayout2.html">2. Empty Cells</a></dt>
+ <dd>Demonstrates a TableLayout with column-spanning rows and different child objects. </dd>
+
+ <dt><a href="TableLayout3.html">3. Long Content</a></dt>
+ <dd>Rows have different number of columns and content doesn't fit on screen: column 4 of row 2 shrinks all of the other columns </dd>
+
+ <dt><a href="TableLayout4.html">4. Stretchable</a></dt>
+ <dd>Demonstrates a TableLayout with a stretchable column. </dd>
+
+ <dt><a href="TableLayout5.html">5. Spanning and Stretchable</a></dt>
+ <dd>Demonstrates a complex TableLayout with spanning columns and stretchable columns to create a menu-like layout. </dd>
+
+ <dt><a href="TableLayout6.html">6. More Spanning and Stretchable</a></dt>
+ <dd>Similar to example 5, but with an additional "checked" column. </dd>
+
+ <dt><a href="TableLayout7.html">7. Column Collapse</a></dt>
+ <dd>Similar to example 6, but now with buttons on the bottom of the screen that enable you dynamically hide or show columns. </dd>
+
+ <dt><a href="TableLayout8.html">8. Toggle Stretch</a></dt>
+ <dd>Demonstrates toggling the "stretch" value on a column to fill the screen width. </dd>
+
+ <dt><a href="TableLayout9.html">9. Toggle Shrink</a></dt>
+ <dd>Demonstrates toggling the "shrink" value on a column to make an over-wide table shrink to fit the screen size. </dd>
+
+ <dt><a href="TableLayout10.html">10. Simple Form</a></dt>
+ <dd>Demonstrates using a table to design a user form. </dd>
+
+ <dt><a href="TableLayout11.html">11. Gravity</a></dt>
+ <dd>Demonstrates the use of advanced gravity attributes, such as <em>center_horizontal</em> and <em>right|bottom</em> to align cell contents in a table. </dd>
+
+ <dt><a href="TableLayout12.html">12. Various Widths</a></dt>
+ <dd>Demonstrates the use of elements of various widths in a table. </dd>
+</dl>
+
+<h3>Baseline</h3>
+<p>Demonstrates the use of the <em>android:layout_alignBaseline</em> XML attribute in various page layouts.</p>
+<dl>
+ <dt><a href="Baseline1.html">1. Top</a></dt>
+ <dd>Demonstrates the default baseline alignment in a simple LinearLayout with items at the top of the screen. </dd>
+
+ <dt><a href="Baseline2.html">2. Bottom</a></dt>
+ <dd>Demonstrates the default baseline alignment in a simple LinearLayout with items at the bottom of the screen.</dd>
+
+ <dt><a href="Baseline3.html">3. Center</a></dt>
+ <dd>Demonstrates the default baseline alignment in a simple LinearLayout with items in the center of the screen.</dd>
+
+ <dt><a href="Baseline4.html">4. Everywhere</a></dt>
+ <dd>Demonstrates the default baseline alignment in a complex LinearLayout.</dd>
+
+ <dt><a href="Baseline5.html">5. Everywhere</a></dt>
+ <dd>Demonstrates turning off baseline alignment in a LinearLayout. </dd>
+
+ <dt><a href="Baseline6.html">6. Multi-line</a></dt>
+ <dd>Demonstrates a baseline alignment with a multiline field. </dd>
+
+ <dt><a href="Baseline7.html">7. Relative</a></dt>
+ <dd>Demonstrates baseline alignment in a RelativeLayout. </dd>
+
+ <dt><a href="BaselineNested1.html">BaselineNested1</a></dt>
+ <dd>Demonstrates baseline aligning specific elements in three parallel vertical LinearLayout objects.</dd>
+
+ <dt><a href="BaselineNested2.html">BaselineNested2</a></dt>
+ <dd>Demonstrates baseline aligning specific elements in three mixed vertical and horizontal LinearLayout objects.</dd>
+
+ <dt><a href="BaselineNested3.html">BaselineNested3</a></dt>
+ <dd>Demonstrates baseline alignment within nested LinearLayout objects. </dd>
+</dl>
+
+<h3>Radio Group</h3>
+<dl>
+ <dt><a href="RadioGroup1.html">Radio Group</a></dt>
+ <dd>Demonstrates using radio buttons and capturing the selected item. </dd>
+</dl>
+
+<h3>ScrollBars</h3>
+<dl>
+ <dt><a href="ScrollBar1.html">1. Basic</a></dt>
+ <dd>Demonstrates a scrollable LinearLayout object. </dd>
+
+ <dt><a href="ScrollBar2.html">2. Fancy</a></dt>
+ <dd>Demonstrates a scrollable LinearLayout object with a custom thumb slider image. </dd>
+</dl>
+
+<h3>Visibility</h3>
+<dl>
+ <dt><a href="Visibility1.html">Visibility</a></dt>
+ <dd>Demonstrates toggling the visibility of a View object between visible, invisible, and gone. </dd>
+</dl>
+
+<h3>Lists</h3>
+<dl>
+ <dt><a href="List1.html">1. Array</a></dt>
+ <dd> Demonstrates binding a ListAdapter to a string array as a data source, and displaying the elements on the screen. </dd>
+
+ <dt><a href="List2.html">2. Cursor (People)</a></dt>
+ <dd> Demonstrates binding results from a database query to a field in a template. </dd>
+
+ <dt><a href="List3.html">3. Cursor (Phones)</a></dt>
+ <dd> Demonstrates binding multiple columns from a database query to fields in a template. </dd>
+
+ <dt><a href="List4.html">4. ListAdapter</a></dt>
+ <dd> Demonstrates implementing a custom ListAdapter to return View objects laid out in a custom manner. </dd>
+
+ <dt><a href="List5.html">5. Separators</a></dt>
+ <dd> Demonstrates implementing a custom ListAdapter that includes separators between some items. </dd>
+
+ <dt><a href="List6.html">6. ListAdapter Collapsed</a></dt>
+ <dd>Demonstrates another custom list adapter with that returns expandible items. </dd>
+
+ <dt><a href="List7.html">7. Cursor (Phones)</a></dt>
+ <dd> Demonstrates a list adapter where data comes from a Cursor object. </dd>
+
+ <dt><a href="List8.html">8. Photos</a></dt>
+ <dd> Demonstrates a list activity that uses a custom ListAdapter, setting the view for an empty item, and also how to customize the layout of a ListActivity. </dd>
+</dl>
+
+
+
+<h3>Custom</h3>
+<dl>
+ <dt><a href="CustomView1.html">CustomView</a></dt>
+ <dd>Demonstrates implementing a custom view subclass. </dd>
+</dl>
+
+<h3>ImageButton</h3>
+<dl>
+ <dt><a href="ImageButton1.html">ImageButton</a></dt>
+ <dd>Demonstrates an ImageButton: a button with an arbitrary graphic on it. </dd>
+</dl>
+
+<h3>Date Widgets</h3>
+<dl>
+ <dt><a href="DateWidgets1.html">1. Dialog</a></dt>
+ <dd>Demonstrates the DatePickerDialog and TimePickerDialog picker dialogs.</dd>
+
+ <dt><a href="DateWidgets2.html">2. Inline</a></dt>
+ <dd>Demonstrates using a TimePicker directly in a layout without using a confirmation button or dialog.</dd>
+</dl>
+
+<h3>Gallery</h3>
+<dl>
+ <dt><a href="Gallery1.html">1. Icons</a></dt>
+ <dd> Demonstrates implementing a Gallery widget and extending GalleryAdapter to create a custom class to serve out source images to the widget. </dd>
+
+ <dt><a href="Gallery2.html">2. People</a></dt>
+ <dd>Demonstrates populating a Gallery with images from the contacts photos. </dd>
+</dl>
+
+<h3>Spinner</h3>
+<dl>
+ <dt><a href="Spinner1.html">Spinner</a></dt>
+ <dd> Demonstrates populating two Spinner widgets with values. </dd>
+</dl>
+
+<h3>Grid</h3>
+<dl>
+ <dt><a href="Grid1.html">1. Icon Grid</a></dt>
+ <dd> Demonstrates populating a GridView widget with a list of applications using a custom ListAdapter object.</dd>
+
+ <dt><a href="Grid2.html">2. Photo Grid</a></dt>
+ <dd> Demonstrates populating a GridView widget with images using a custom ListAdapter object. </dd>
+</dl>
+
+<h3>Ticker</h3>
+<dl>
+ <dt><a href="Ticker1.html">Ticker</a></dt>
+ <dd> Demonstrates a Ticker widget, which scrolls text across the screen.</dd>
+</dl>
+
+<h3>ImageSwitcher</h3>
+<dl>
+ <dt><a href="ImageSwitcher1.html">ImageSwitcher</a></dt>
+ <dd>Demonstrates using the ImageSwitcher widget with a custom Adapter.</dd>
+</dl>
+
+<h3>TextSwitcher</h3>
+<dl>
+ <dt><a href="TextSwitcher1.html">TextSwitcher</a></dt>
+ <dd>Demonstrates using the TextSwitcher widget. </dd>
+</dl>
+
+<h3>Animation</h3>
+<dl>
+ <dt><a href="Animation1.html">1. Shake</a></dt>
+ <dd>Demonstrates a simple tweened animation (android.view.animation.Animation). </dd>
+
+ <dt><a href="Animation2.html">2. Push</a></dt>
+ <dd>Demonstrates a variety of transformations (android.view.animation.Animation), including fading, motion, and rotation. </dd>
+</dl>
+
+<h3>Controls</h3>
+<dl>
+ <dt><a href="Controls1.html">1. Theme White</a></dt>
+ <dd>Demonstrates a variety of common form type widgets, such as check boxes and radio buttons using the white theme. </dd>
+</dl>
+<dl>
+ <dt><a href="Controls2.html">2. Theme Dark</a></dt>
+ <dd>Demonstrates a variety of common form type widgets, such as check boxes and radio buttons using the dark theme. </dd>
+</dl>
+
+<h3>Auto Complete</h3>
+<dl>
+ <dt><a href="AutoComplete1.html">1. Screen Top</a></dt>
+ <dd>Demonstrates the use of AutoCompleteTextView, an autocomplete dropdown box below a text box, with data taken from an array. </dd>
+
+ <dt><a href="AutoComplete2.html">2. Screen Bottom</a></dt>
+ <dd>Demonstrates an autocomplete box above a text box.</dd>
+
+ <dt><a href="AutoComplete3.html">3. Scroll</a></dt>
+ <dd>Demonstrates an autocomplete text box in the midst of a vertical list. </dd>
+
+ <dt><a href="AutoComplete4.html">4. Contacts</a></dt>
+ <dd>Demonstrates an autocomplete text box that gets its content from a database query. </dd>
+
+ <dt><a href="AutoComplete5.html">5. Contacts with Hint</a></dt>
+ <dd>Demonstates an autocomplete text box that understands the * wildcard. </dd>
+</dl>
+
+<h3>Progress Bar</h3>
+<dl>
+ <dt><a href="ProgressBar1.html">1. Incremental</a></dt>
+ <dd>Demonstrates large and small rotating progress indicators that can be incremented or decremented in units. </dd>
+
+ <dt><a href="ProgressBar2.html">2. Smooth</a></dt>
+ <dd>Demonstrates large and small continuously rotating progress indicators used to indicate a generic "busy" message. </dd>
+
+ <dt><a href="ProgressBar3.html">3. Dialogs</a></dt>
+ <dd>Demonstrates a ProgressDialog, a popup dialog that hosts a progress bar. This example demonstrates both determinate and indeterminate progress indicators. </dd>
+
+ <dt><a href="ProgressBar4.html">4. In Title Bar</a></dt>
+ <dd>Demonstrates an Activity screen with a progress indicator loaded by setting the WindowPolicy's progress indicator feature. </dd>
+</dl>
+
+<h3>Focus</h3>
+<dl>
+ <dt><a href="Focus1.html">1. Vertical</a></dt>
+ <dd>Demonstrates how to block selection of a specific screen element. </dd>
+
+ <dt><a href="Focus2.html">2. Horizontal</a></dt>
+ <dd>Demonstrates how to change the order of which screen element is selected when the user presses arrow keys. </dd>
+
+ <dt><a href="Focus3.html">3. Circular</a></dt>
+ <dd>Another version of Focus2. </dd>
+</dl>
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/_package.html b/samples/ApiDemos/src/com/example/android/apis/view/_package.html
new file mode 100644
index 0000000..3217336
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/_package.html
@@ -0,0 +1,589 @@
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="assets/style.css" />
+<script type="text/javascript" src="http://www.corp.google.com/style/prettify.js"></script>
+<script src="http://www.corp.google.com/eng/techpubs/include/navbar.js" type="text/javascript"></script>
+
+
+
+</head>
+
+<body>
+
+<p>
+Examples of how to use the android.view and android.widget platform APIs.
+
+For information about view and widget objects, see the topic "Designing
+the UI for an Android application" in the SDK documentation.
+<ol>
+ <li>Layouts
+ <ol>
+ <li>RelativeLayout
+ <ol>
+ <li>{@link com.android.samples.view.RelativeLayout1
+ Example 1}</li>
+ <li>{@link com.android.samples.view.RelativeLayout2
+ Example 2}</li>
+ </ol>
+ </li>
+ <li>LinearLayout
+ <ol>
+ <li>{@link com.android.samples.view.LinearLayout1
+ Example 1}</li>
+ <li>{@link com.android.samples.view.LinearLayout2 Example
+ 2}</li>
+ <li>{@link com.android.samples.view.LinearLayout3 Example
+ 3}</li>
+ <li>{@link com.android.samples.view.LinearLayout4 Example
+ 4}</li>
+ <li>{@link com.android.samples.view.LinearLayout5 Example
+ 5}</li>
+ <li>{@link com.android.samples.view.LinearLayout6 Example
+ 6}</li>
+ <li>{@link com.android.samples.view.LinearLayout7 Example
+ 7}</li>
+ <li>{@link com.android.samples.view.LinearLayout8 Example
+ 8}</li>
+ </ol>
+ </li>
+ <li>ScrollView
+ <ol>
+ <li>{@link com.android.samples.view.ScrollView1
+ Example 1} </li>
+ <li>{@link com.android.samples.view.ScrollView2 Example
+ 2} </li>
+ </ol>
+ </li>
+ <li>TableLayout
+ <ol>
+ <li>{@link com.android.samples.view.TableLayout1
+ Example 1}</li>
+ <li>{@link com.android.samples.view.TableLayout2 Example
+ 2}</li>
+ <li>{@link com.android.samples.view.TableLayout3 Example
+ 3}</li>
+ <li>{@link com.android.samples.view.TableLayout4 Example
+ 4}</li>
+ <li>{@link com.android.samples.view.TableLayout5 Example
+ 5}</li>
+ <li>{@link com.android.samples.view.TableLayout6 Example
+ 6}</li>
+ <li>{@link com.android.samples.view.TableLayout7 Example
+ 7}</li>
+ <li>{@link com.android.samples.view.TableLayout8 Example
+ 8}</li>
+ <li>{@link com.android.samples.view.TableLayout9 Example
+ 9}</li>
+ <li>{@link com.android.samples.view.TableLayout10 Example
+ 10}</li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>Radio Group
+ <ol>
+ <li>{@link com.android.samples.view.RadioGroup1 Example 1}</li>
+ </ol>
+ </li>
+ <li>ScrollBars
+ <ol>
+ <li>{@link com.android.samples.view.ScrollBar1 Example 1}</li>
+ <li>{@link com.android.samples.view.ScrollBar2 Example 2}</li>
+ </ol>
+ </li>
+ <li>Visibility
+ <ol>
+ <li>{@link com.android.samples.view.Visibility1 Example 1}</li>
+ </ol>
+ </li>
+ <li>Lists
+ <ol>
+ <li>{@link com.android.samples.view.List1 Example 1} </li>
+ <li>{@link com.android.samples.view.List2 Example 2}</li>
+ <li>{@link com.android.samples.view.List3 Example 3}</li>
+ <li>{@link com.android.samples.view.List4 Example 4}</li>
+ <li>{@link com.android.samples.view.List5 Example 5}</li>
+ <li>{@link com.android.samples.view.List6 Example 6}</li>
+ <li>{@link com.android.samples.view.List7 Example 7}</li>
+ </ol>
+ </li>
+ <li>Custom
+ <ol>
+ <li>{@link com.android.samples.view.CustomView1 Example 1}</li>
+ </ol>
+ </li>
+ <li>Gallery
+ <ol>
+ <li>{@link com.android.samples.view.Gallery1 Example 1}</li>
+ <li>{@link com.android.samples.view.Gallery2 Example 2}</li>
+ </ol>
+ </li>
+ <li>Spinner
+ <ol>
+ <li>{@link com.android.samples.view.Spinner1 Example 1}</li>
+ </ol>
+ </li>
+ <li>Grid
+ <ol>
+ <li>{@link com.android.samples.view.Grid1 Example 1}</li>
+ </ol>
+ </li>
+ <li>ImageSwitcher
+ <ol>
+ <li>{@link com.android.samples.view.ImageSwitcher1 Example
+ 1}</li>
+ </ol>
+ </li>
+ <li>Animation
+ <ol>
+ <li>{@link com.android.samples.view.Animation1 Example 1}</li>
+ <li>{@link com.android.samples.view.Animation2 Example 1}</li>
+ </ol>
+ </li>
+ <li>Controls
+ <ol>
+ <li>{@link com.android.samples.view.Controls1 Example 1}</li>
+ </ol>
+ </li>
+</ol>
+<p></p>
+
+<h3>LinearLayout Example 1: Stacking Views</h3>
+This example shows a simple use of a LinearLayout. The LinearLayout's height is set to
+<code>android:layout_height="wrap-content"</code>,
+as is the height of each child. Each text view is as tall as it needs
+to be, and the height of the LinearLayout itself is the sum of the height of its children.
+
+<h4>Demo</h4>
+Views/Layouts/LinearLayout/Example 1
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/LinearLayout1.java</a></td>
+ <td class="DescrColumn">Loads the linear_layout_1 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/linear_layout_1.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+
+
+<h3>LinearLayout Example 2: Stacking Views Again</h3>
+In this example, the LinearLayout's height is set
+to <code>android:layout_height="fill-parent"</code>,
+so the LinearLayout fills the screen. Each text view is as tall as it needs
+to be, so the LinearLayout just stacks them from top to bottom.
+
+<h4>Demo</h4>
+Views/Layouts/LinearLayout/Example 2
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/LinearLayout2.java</a></td>
+ <td class="DescrColumn">Loads the linear_layout_2 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/linear_layout_2.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+
+
+<h3>LinearLayout Example 3: Distributing Extra Space</h3>
+In this example, the LinearLayout's height is set
+to "fill-parent", so the LinearLayout fills the screen. Each text view is as tall as it needs
+to be. However, the middle text view has set <code>android:layout_weight="1"</code>. This means that it
+will get all of the extra space left over after the LinearLayout has sized all of its children.
+
+<h4>Demo</h4>
+Views/Layouts/LinearLayout/Example 3
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/LinearLayout3.java</a></td>
+ <td class="DescrColumn">Loads the linear_layout_3 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/linear_layout_3.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+
+
+<h3>LinearLayout Example 4: Columns</h3>
+This time, the orientation of the LinearLayout is set to horizontal.
+Each of the four child text views has set <code>android:layout_weight="1"</code>
+and <code>android:layout_width="0"</code>.
+This means that each child is initially given a width of 0, and then all of the
+remaining space (the width of the screen) is divided equally among the four
+views.
+
+<h4>Demo</h4>
+Views/Layouts/LinearLayout/Example 4
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/LinearLayout4.java</a></td>
+ <td class="DescrColumn">Loads the linear_layout_4 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/linear_layout_4.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+
+
+<h3>LinearLayout Example 5: A Simple Form</h3>
+This is a more complete example. It shows:
+<ul>
+ <li>Using nested LinearLayouts (a horizontal layout inside a vertical layout)
+ <li>Using padding on the outer layout
+ <li>Using the <code>layout_gravity</code> attribute to position the horizontal layout
+ on the right side of the screen
+ <li>Using a margin to put some space between buttons
+</ul>
+
+<h4>Demo</h4>
+Views/Layouts/LinearLayout/Example 5
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/LinearLayout5.java</a></td>
+ <td class="DescrColumn">Loads the linear_layout_5 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/linear_layout_5.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+<h3>RelativeLayout Example 1: Stretching</h3>
+There are three views in this example. The first view (view1) is pinned to the top of the screen through the use of this
+attribute: <code>android:layout_alignParentTop="true"</code>.
+The second view (view2) is pinned to the bottom of the screen: <code>android:layout_alignParentBottom="true"</code>.
+This demonstrates how views can be positioned relative to the RelativeLayout itself.
+
+<p>Views can also be positioned relative to each other as well. In this example, view3 is below view1 and above
+view2: <code>android:layout_above="view2" android:layout_below="view1"</code>. This has the effect of making
+view3 stretch between view1 and view2.</p>
+
+<p>Note that since view3 depends on the positions of both view1 and view2, it is defined after them in the layout
+file.</p>
+
+<h4>Demo</h4>
+Views/Layouts/RelativeLayout/Example 1
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/RelativeLayout1.java</a></td>
+ <td class="DescrColumn">Loads the relative_layout_1 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/relative_layout_1.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+<h3>RelativeLayout Example 2: A Simple Form Revisited</h3>
+The form created in LinearLayout Example 5 is recreated using a RelativeLayout. This example demonstrates:
+
+<ul>
+ <li>Using padding on the outer layout
+ <li>Positioning views realtive to one another using the <code>android:layout_below</code> and
+ <code>android:layout_below</code> and <code>android:layout_toLeft<code> attributes.
+ <li>Aligning the top edges of the buttons with the <code>android:layout_alignTop<code> attribute
+ <li>Right-aligning the OK button with <code>android:layout_alignParentRight</code>
+ <li>Using a margin to put some space between buttons
+</ul>
+
+<h4>Demo</h4>
+Views/Layouts/RelativeLayout/Example 2
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/RelativeLayout2.java</a></td>
+ <td class="DescrColumn">Loads the relative_layout_2 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/relative_layout_2.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+<h3>Scrolling Example 1</h3>
+All of the layout classes discussed above do not scroll.
+They simply arrange their children within whatever space is made available to them.
+
+<p>The ScrollView is used to implement vertical scrolling. It does not display any
+content of its own. Instead, it assumes it has one child and pans up and down to keep
+the interesting area of its child in view.</p>
+
+<p>In this example, a ScrollView is used to wrap a LinearLayout. The LinearLayout
+in turn contains a stack of TextViews and Buttons. The ScrollView is as wide as
+the screen (<code>android:layout_width="fill-parent"</code>) and tall enough to
+wrap the LinearLayout (<code>android:layout_height="wrap-content"</code>). The
+LinearLayout uses the same parameters, so it is also as wide as the screen and is as
+tall as the sum of the heigts of all of its children.</p>
+
+<h4>Demo</h4>
+Views/Layouts/ScrollView/Example 1
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/ScrollView1.java</a></td>
+ <td class="DescrColumn">Loads the scroll_view_1 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/scroll_view_1.xml</a></td>
+ <td class="DescrColumn">Defines the layout</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+<h2><a name="Lists">Lists</a></h2>
+<h3>ListView Example 1: A "Hello World" List</h3>
+
+ListViews are used to display vertically scrolling list of information. Unlike the ScrollView, which pans up and
+down through a set of views that have already been built, the ListView is "virtualized", meaning that views are
+created only as necessary in order to display what is actually on the screen. ListViews can thus be used to
+efficiently display very large sets of data. (In this example, the list displays over 600 kinds of cheese.)
+
+<p>ListViews are highly customizable: you can change where the underlying data comes from, the internal
+representation of the data, and the Views that are used to display the data on the screen. All of this is
+done with a ListAdapter class. The Android platform includes some ListAdapters that are ready to use, or
+you can make your own to display custom information. (See ListView Example 4 and ListView Example 5.)</p>
+
+<p>This example uses an existing ListAdapter called ArrayListAdapter. This adapter uses generics to map
+an array of objects to TextViews. In this case we are using an array of Strings.</p>
+
+<p>Note that this example does not have a layout file. This is because the List1 class derives from
+ListScreen, which will provide a default layout if your activity does not provide an override.</p>
+
+<h4>Demo</h4>
+Views/Lists/Example 1
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/List1.java</a></td>
+ <td class="DescrColumn">Contains code for the List1 class</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+<h3>ListView Example 2: Displaying Data from a Cursor </h3>
+
+It is very common to display data from a database in a ListView. The easiest way to do this is to use a
+SimpleCursorListAdapter. This is a class that will get data from a Cursor and display the data in
+each row in Views defined in an XML template.
+
+<p>In this example, the SimpleCursorListAdapter is provided with a cursor that contains a list of all
+people. Each row will be displayed using the Views defined in this XL file:
+<a href="" onClick="findCode(this)">//device/apps/common/assets/res/any/layout/simple_list_item_1.xml</a>.
+</p>
+
+<p>When creating a SimpleCursorListAdapter, you also provide a mapping from column names in the
+Cursor to view ids in the template file. In this case we are mapping the People.NAME column to the
+"text1" TextView.
+</p>
+
+<h4>Demo</h4>
+Views/Lists/Example 2
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/List2.java</a></td>
+ <td class="DescrColumn">Contains code for the List2 class</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/apps/common/assets/res/any/layout/simple_list_item_1.xml</a></td>
+ <td class="DescrColumn">Defines the XML template used for each row.
+ (Note that this file is provided as part of the Android platform.)</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+<h3>ListView Example 3: Displaying Data from a Cursor, Fancier Version </h3>
+
+This example extends the idea presented in Example 2. Instead of just presenting a list of names, though,
+it shows two lines of information for the selected item (name and phone number). It shows just the name for unselected items.
+
+<p>
+This example still uses a SimpleCursorListAdapter, but changes the following:</p>
+
+<ul>
+ <li>The Cursor now contains all phone numbers
+ <li>It uses a different template for each row: <a href="" onClick="findCode(this)">//device/apps/common/assets/res/any/layout/simple_list_item_2.xml</a>
+ <li>Since simple_list_item_2.xml contains two views, were mapping two columns
+ <code>{ Phones.NAME, Phones.NUMBER }</code> to the two views
+ <code>{ "text1", "text2"}</code>
+ <li>The simple_list_item_2.xml uses a TwoLineListItem view, which is a subclass of LinearLayout that knows to only show
+ the second item when it is selected.
+</ul>
+
+<h4>Demo</h4>
+Views/Lists/Example 3
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/List3.java</a></td>
+ <td class="DescrColumn">Contains code for the List3 class</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/apps/common/assets/res/any/layout/simple_list_item_2.xml</a></td>
+ <td class="DescrColumn">Defines the XML template used for each row.
+ (Note that this file is provided as part of the Android platform.)</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+
+<h3>ListView Example 4: Writing a Custom ListAdapter </h3>
+
+The previous examples all used standard ListAdapters. It is also possible to write your own ListAdapters
+to access data from custom sources.
+
+<p>
+This example introduces a SongListAdapter, which gets its data from an array of titles and an array of lyrics.
+The SongListAdapter then produces a SongView which is capable of displaying this data.
+</p>
+
+<p>
+This example also shows how the ListView handles scrolling large items.
+
+<h4>Demo</h4>
+Views/Lists/Example 4
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/List4.java</a></td>
+ <td class="DescrColumn">Contains code for the List4 class, along with a custom ListAdapter and custom View to display the data.</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+
+
+<h3>ListView Example 5: List Separators </h3>
+
+ListView supports the concept of non-selectable "separators" between items. The ListView delegated to its ListAdapter the
+task of deciding whether a given position in the list is a separator or selectable data.
+
+<p><i>This example needs some cleanup.</i></p>
+
+<h4>Demo</h4>
+Views/Lists/Example 5
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/List5.java</a></td>
+ <td class="DescrColumn">Contains code for the List5 class, along with a custom ListAdapter.</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+
+<h2><a name="Working">Working with Views</a></h2>
+
+<h3>Custom View Example 1: LabelView</h3>
+
+
+
+<p>
+Note: This example does not support multi-line or right-to-left text. It is sample code only
+and should not be used in place of the TextView.
+</p>
+
+
+<h4>Demo</h4>
+Views/Custom/Example 1
+
+<h4>Source files</h4>
+<table class="LinkTable">
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/CustomView1.java</a></td>
+ <td class="DescrColumn">Loads the custom_view_3 layout resource</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/src/com/android/sdk/view/LabelView.java</a></td>
+ <td class="DescrColumn">Implementation of the custom view</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/assets/res/any/layout/custom_view_1.xml</a></td>
+ <td class="DescrColumn">Defines a layout that uses LabelViews</td>
+ </tr>
+ <tr>
+ <td class="LinkColumn"><a href="" onClick="findCode(this)">//device/samples/SampleCode/AndroidManifest.xml</a></td>
+ <td class="DescrColumn">Defines the activity</td>
+ </tr>
+</table>
+</body>
+</html>
diff --git a/samples/ApiDemos/tests/Android.mk b/samples/ApiDemos/tests/Android.mk
new file mode 100644
index 0000000..f975662
--- /dev/null
+++ b/samples/ApiDemos/tests/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Notice that we don't have to include the src files of ApiDemos because, by
+# running the tests using an instrumentation targeting ApiDemos, we
+# automatically get all of its classes loaded into our environment.
+
+LOCAL_PACKAGE_NAME := ApiDemosTests
+
+LOCAL_INSTRUMENTATION_FOR := ApiDemos
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
diff --git a/samples/ApiDemos/tests/AndroidManifest.xml b/samples/ApiDemos/tests/AndroidManifest.xml
new file mode 100644
index 0000000..084c88d
--- /dev/null
+++ b/samples/ApiDemos/tests/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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 name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.apis.tests">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <!--
+ This declares that this app uses the instrumentation test runner targeting
+ the package of com.example.android.apis. To run the tests use the command:
+ "adb shell am instrument -w com.example.android.apis.tests/android.test.InstrumentationTestRunner"
+ -->
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.apis"
+ android:label="Tests for Api Demos."/>
+
+</manifest>
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/AllTests.java b/samples/ApiDemos/tests/src/com/example/android/apis/AllTests.java
new file mode 100644
index 0000000..edacb47
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/AllTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 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;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import android.test.suitebuilder.TestSuiteBuilder;
+
+/**
+ * A test suite containing all tests for ApiDemos.
+ *
+ * To run all suites found in this apk:
+ * $ adb shell am instrument -w \
+ * com.example.android.apis.tests/android.test.InstrumentationTestRunner
+ *
+ * To run just this suite from the command line:
+ * $ adb shell am instrument -w \
+ * -e class com.example.android.apis.AllTests \
+ * com.example.android.apis.tests/android.test.InstrumentationTestRunner
+ *
+ * To run an individual test case, e.g. {@link com.example.android.apis.os.MorseCodeConverterTest}:
+ * $ adb shell am instrument -w \
+ * -e class com.example.android.apis.os.MorseCodeConverterTest \
+ * com.example.android.apis.tests/android.test.InstrumentationTestRunner
+ *
+ * To run an individual test, e.g. {@link com.example.android.apis.os.MorseCodeConverterTest#testCharacterS()}:
+ * $ adb shell am instrument -w \
+ * -e class com.example.android.apis.os.MorseCodeConverterTest#testCharacterS \
+ * com.example.android.apis.tests/android.test.InstrumentationTestRunner
+ */
+public class AllTests extends TestSuite {
+
+ public static Test suite() {
+ return new TestSuiteBuilder(AllTests.class)
+ .includeAllPackagesUnderHere()
+ .build();
+ }
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
new file mode 100644
index 0000000..3074ca6
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 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;
+
+import android.test.ApplicationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * This is a simple framework for a test of an Application. See
+ * {@link android.test.ApplicationTestCase ApplicationTestCase} for more information on
+ * how to write and extend Application tests.
+ *
+ * To run this test, you can type:
+ * adb shell am instrument -w \
+ * -e class com.example.android.apis.ApiDemosApplicationTests \
+ * com.example.android.apis.tests/android.test.InstrumentationTestRunner
+ */
+public class ApiDemosApplicationTests extends ApplicationTestCase<ApiDemosApplication> {
+
+ public ApiDemosApplicationTests() {
+ super(ApiDemosApplication.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /**
+ * The name 'test preconditions' is a convention to signal that if this
+ * test doesn't pass, the test case was not set up properly and it might
+ * explain any and all failures in other tests. This is not guaranteed
+ * to run before other tests, as junit uses reflection to find the tests.
+ */
+ @SmallTest
+ public void testPreconditions() {
+ }
+
+ /**
+ * Test basic startup/shutdown of Application
+ */
+ @MediumTest
+ public void testSimpleCreate() {
+ createApplication();
+ }
+
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosTest.java
new file mode 100644
index 0000000..0103da8
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 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;
+
+import android.test.ActivityInstrumentationTestCase;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link ActivityInstrumentationTestCase#testActivityTestCaseSetUpProperly}.
+ */
+public class ApiDemosTest extends ActivityInstrumentationTestCase<ApiDemos> {
+
+ public ApiDemosTest() {
+ super("com.example.android.apis", ApiDemos.class);
+ }
+
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
new file mode 100644
index 0000000..340bedb
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2008 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;
+
+import com.example.android.apis.R;
+import com.example.android.apis.view.Focus2ActivityTest;
+
+import android.content.Context;
+import android.content.Intent;
+import android.test.ActivityUnitTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+
+/**
+ * This demonstrates completely isolated "unit test" of an Activity class.
+ *
+ * <p>This model for testing creates the entire Activity (like {@link Focus2ActivityTest}) but does
+ * not attach it to the system (for example, it cannot launch another Activity). It allows you to
+ * inject additional behaviors via the
+ * {@link android.test.ActivityUnitTestCase#setActivityContext(Context)} and
+ * {@link android.test.ActivityUnitTestCase#setApplication(android.app.Application)} methods.
+ * It also allows you to more carefully test your Activity's performance
+ * Writing unit tests in this manner requires more care and attention, but allows you to test
+ * very specific behaviors, and can also be an easier way to test error conditions.
+ *
+ * <p>Because ActivityUnitTestCase creates the Activity under test completely outside of
+ * the usual system, tests of layout and point-click UI interaction are much less useful
+ * in this configuration. It's more useful here to concentrate on tests that involve the
+ * underlying data model, internal business logic, or exercising your Activity's life cycle.
+ *
+ * <p>See {@link com.example.android.apis.AllTests} for documentation on running
+ * all tests and individual tests in this application.
+ */
+public class ForwardingTest extends ActivityUnitTestCase<Forwarding> {
+
+ private Intent mStartIntent;
+ private Button mButton;
+
+ public ForwardingTest() {
+ super(Forwarding.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // In setUp, you can create any shared test data, or set up mock components to inject
+ // into your Activity. But do not call startActivity() until the actual test methods.
+ mStartIntent = new Intent(Intent.ACTION_MAIN);
+ }
+
+ /**
+ * The name 'test preconditions' is a convention to signal that if this
+ * test doesn't pass, the test case was not set up properly and it might
+ * explain any and all failures in other tests. This is not guaranteed
+ * to run before other tests, as junit uses reflection to find the tests.
+ */
+ @MediumTest
+ public void testPreconditions() {
+ startActivity(mStartIntent, null, null);
+ mButton = (Button) getActivity().findViewById(R.id.go);
+
+ assertNotNull(getActivity());
+ assertNotNull(mButton);
+ }
+
+ /**
+ * This test demonstrates examining the way that activity calls startActivity() to launch
+ * other activities.
+ */
+ @MediumTest
+ public void testSubLaunch() {
+ Forwarding activity = startActivity(mStartIntent, null, null);
+ mButton = (Button) activity.findViewById(R.id.go);
+
+ // This test confirms that when you click the button, the activity attempts to open
+ // another activity (by calling startActivity) and close itself (by calling finish()).
+ mButton.performClick();
+
+ assertNotNull(getStartedActivityIntent());
+ assertTrue(isFinishCalled());
+ }
+
+ /**
+ * This test demonstrates ways to exercise the Activity's life cycle.
+ */
+ @MediumTest
+ public void testLifeCycleCreate() {
+ Forwarding activity = startActivity(mStartIntent, null, null);
+
+ // At this point, onCreate() has been called, but nothing else
+ // Complete the startup of the activity
+ getInstrumentation().callActivityOnStart(activity);
+ getInstrumentation().callActivityOnResume(activity);
+
+ // At this point you could test for various configuration aspects, or you could
+ // use a Mock Context to confirm that your activity has made certain calls to the system
+ // and set itself up properly.
+
+ getInstrumentation().callActivityOnPause(activity);
+
+ // At this point you could confirm that the activity has paused properly, as if it is
+ // no longer the topmost activity on screen.
+
+ getInstrumentation().callActivityOnStop(activity);
+
+ // At this point, you could confirm that the activity has shut itself down appropriately,
+ // or you could use a Mock Context to confirm that your activity has released any system
+ // resources it should no longer be holding.
+
+ // ActivityUnitTestCase.tearDown(), which is always automatically called, will take care
+ // of calling onDestroy().
+ }
+
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
new file mode 100644
index 0000000..78fee41
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008 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;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.test.MoreAsserts;
+import android.test.ServiceTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * This is a simple framework for a test of a Service. See {@link android.test.ServiceTestCase
+ * ServiceTestCase} for more information on how to write and extend service tests.
+ *
+ * To run this test, you can type:
+ * adb shell am instrument -w \
+ * -e class com.example.android.apis.app.LocalServiceTest \
+ * com.example.android.apis.tests/android.test.InstrumentationTestRunner
+ */
+public class LocalServiceTest extends ServiceTestCase<LocalService> {
+
+ public LocalServiceTest() {
+ super(LocalService.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /**
+ * The name 'test preconditions' is a convention to signal that if this
+ * test doesn't pass, the test case was not set up properly and it might
+ * explain any and all failures in other tests. This is not guaranteed
+ * to run before other tests, as junit uses reflection to find the tests.
+ */
+ @SmallTest
+ public void testPreconditions() {
+ }
+
+ /**
+ * Test basic startup/shutdown of Service
+ */
+ @SmallTest
+ public void testStartable() {
+ Intent startIntent = new Intent();
+ startIntent.setClass(getContext(), LocalService.class);
+ startService(startIntent);
+ }
+
+ /**
+ * Test binding to service
+ */
+ @MediumTest
+ public void testBindable() {
+ Intent startIntent = new Intent();
+ startIntent.setClass(getContext(), LocalService.class);
+ IBinder service = bindService(startIntent);
+ }
+
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
new file mode 100644
index 0000000..7cf0395
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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.os;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * An example of a true unit test that tests the utility class {@link MorseCodeConverter}.
+ * Since this test doesn't need a {@link android.content.Context}, or any other
+ * dependencies injected, it simply extends the standard {@link TestCase}.
+ *
+ * See {@link com.example.android.apis.AllTests} for documentation on running
+ * all tests and individual tests in this application.
+ */
+public class MorseCodeConverterTest extends TestCase {
+
+ @SmallTest
+ public void testCharacterS() throws Exception {
+
+ long[] expectedBeeps = {
+ MorseCodeConverter.DOT,
+ MorseCodeConverter.DOT,
+ MorseCodeConverter.DOT,
+ MorseCodeConverter.DOT,
+ MorseCodeConverter.DOT};
+ long[] beeps = MorseCodeConverter.pattern('s');
+
+ assertArraysEqual(expectedBeeps, beeps);
+ }
+
+ private void assertArraysEqual(long[] expected, long[] actual) {
+ assertEquals("Unexpected array length.", expected.length, actual.length);
+ for (int i = 0; i < expected.length; i++) {
+ long expectedLong = expected[i];
+ long actualLong = actual[i];
+ assertEquals("Unexpected long at index: " + i, expectedLong, actualLong);
+ }
+ }
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
new file mode 100644
index 0000000..91f712f
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import com.example.android.apis.R;
+
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+
+/**
+ * An example of an {@link ActivityInstrumentationTestCase} of a specific activity {@link Focus2}.
+ * By virtue of extending {@link ActivityInstrumentationTestCase}, the target activity is automatically
+ * launched and finished before and after each test. This also extends
+ * {@link android.test.InstrumentationTestCase}, which provides
+ * access to methods for sending events to the target activity, such as key and
+ * touch events. See {@link #sendKeys}.
+ *
+ * In general, {@link android.test.InstrumentationTestCase}s and {@link ActivityInstrumentationTestCase}s
+ * are heavier weight functional tests available for end to end testing of your
+ * user interface. When run via a {@link android.test.InstrumentationTestRunner},
+ * the necessary {@link android.app.Instrumentation} will be injected for you to
+ * user via {@link #getInstrumentation} in your tests.
+ *
+ * See {@link com.example.android.apis.app.ForwardingTest} for an example of an Activity unit test.
+ *
+ * See {@link com.example.android.apis.AllTests} for documentation on running
+ * all tests and individual tests in this application.
+ */
+public class Focus2ActivityTest extends ActivityInstrumentationTestCase<Focus2> {
+
+ private Button mLeftButton;
+ private Button mCenterButton;
+ private Button mRightButton;
+
+
+ public Focus2ActivityTest() {
+ super("com.example.android.apis", Focus2.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Focus2 a = getActivity();
+ mLeftButton = (Button) a.findViewById(R.id.leftButton);
+ mCenterButton = (Button) a.findViewById(R.id.centerButton);
+ mRightButton = (Button) a.findViewById(R.id.rightButton);
+ }
+
+ /**
+ * The name 'test preconditions' is a convention to signal that if this
+ * test doesn't pass, the test case was not set up properly and it might
+ * explain any and all failures in other tests. This is not guaranteed
+ * to run before other tests, as junit uses reflection to find the tests.
+ */
+ @MediumTest
+ public void testPreconditions() {
+ assertTrue("center button should be right of left button",
+ mLeftButton.getRight() < mCenterButton.getLeft());
+ assertTrue("right button should be right of center button",
+ mCenterButton.getRight() < mRightButton.getLeft());
+ assertTrue("left button should be focused", mLeftButton.isFocused());
+ }
+
+ @MediumTest
+ public void testGoingRightFromLeftButtonJumpsOverCenterToRight() {
+ sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
+ assertTrue("right button should be focused", mRightButton.isFocused());
+ }
+
+ @MediumTest
+ public void testGoingLeftFromRightButtonGoesToCenter() {
+ // Give right button focus by having it request focus. We post it
+ // to the UI thread because we are not running on the same thread, and
+ // any direct api calls that change state must be made from the UI thread.
+ // This is in contrast to instrumentation calls that send events that are
+ // processed through the framework and eventually find their way to
+ // affecting the ui thread.
+ getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ mRightButton.requestFocus();
+ }
+ });
+ // wait for the request to go through
+ getInstrumentation().waitForIdleSync();
+
+ assertTrue(mRightButton.isFocused());
+
+ sendKeys(KeyEvent.KEYCODE_DPAD_LEFT);
+ assertTrue("center button should be focused", mCenterButton.isFocused());
+ }
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
new file mode 100644
index 0000000..b52e4b8
--- /dev/null
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2008 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.view;
+
+import com.example.android.apis.R;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.FocusFinder;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+/**
+ * This exercises the same logic as {@link Focus2ActivityTest} but in a lighter
+ * weight manner; it doesn't need to launch the activity, and it can test the
+ * focus behavior by calling {@link FocusFinder} methods directly.
+ *
+ * {@link Focus2ActivityTest} is still useful to verify that, at an end to end
+ * level, key events actually translate to focus transitioning in the way we expect.
+ * A good complementary way to use both types of tests might be to have more exhaustive
+ * coverage in the lighter weight test case, and a few end to end scenarios in the
+ * functional {@link android.test.ActivityInstrumentationTestCase}. This would provide reasonable
+ * assurance that the end to end system is working, while avoiding the overhead of
+ * having every corner case exercised in the slower, heavier weight way.
+ *
+ * Even as a lighter weight test, this test still needs access to a {@link Context}
+ * to inflate the file, which is why it extends {@link AndroidTestCase}.
+ *
+ * If you ever need a context to do your work in tests, you can extend
+ * {@link AndroidTestCase}, and when run via an {@link android.test.InstrumentationTestRunner},
+ * the context will be injected for you.
+ *
+ * See {@link com.example.android.apis.app.ForwardingTest} for an example of an Activity unit test.
+ *
+ * See {@link com.example.android.apis.AllTests} for documentation on running
+ * all tests and individual tests in this application.
+ */
+public class Focus2AndroidTest extends AndroidTestCase {
+
+ private FocusFinder mFocusFinder;
+
+ private ViewGroup mRoot;
+
+ private Button mLeftButton;
+ private Button mCenterButton;
+ private Button mRightButton;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mFocusFinder = FocusFinder.getInstance();
+
+ // inflate the layout
+ final Context context = getContext();
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ mRoot = (ViewGroup) inflater.inflate(R.layout.focus_2, null);
+
+ // manually measure it, and lay it out
+ mRoot.measure(500, 500);
+ mRoot.layout(0, 0, 500, 500);
+
+ mLeftButton = (Button) mRoot.findViewById(R.id.leftButton);
+ mCenterButton = (Button) mRoot.findViewById(R.id.centerButton);
+ mRightButton = (Button) mRoot.findViewById(R.id.rightButton);
+ }
+
+ /**
+ * The name 'test preconditions' is a convention to signal that if this
+ * test doesn't pass, the test case was not set up properly and it might
+ * explain any and all failures in other tests. This is not guaranteed
+ * to run before other tests, as junit uses reflection to find the tests.
+ */
+ @SmallTest
+ public void testPreconditions() {
+ assertNotNull(mLeftButton);
+ assertTrue("center button should be right of left button",
+ mLeftButton.getRight() < mCenterButton.getLeft());
+ assertTrue("right button should be right of center button",
+ mCenterButton.getRight() < mRightButton.getLeft());
+ }
+
+ @SmallTest
+ public void testGoingRightFromLeftButtonJumpsOverCenterToRight() {
+ assertEquals("right should be next focus from left",
+ mRightButton,
+ mFocusFinder.findNextFocus(mRoot, mLeftButton, View.FOCUS_RIGHT));
+ }
+
+ @SmallTest
+ public void testGoingLeftFromRightButtonGoesToCenter() {
+ assertEquals("center should be next focus from right",
+ mCenterButton,
+ mFocusFinder.findNextFocus(mRoot, mRightButton, View.FOCUS_LEFT));
+ }
+}
diff --git a/samples/Compass/Android.mk b/samples/Compass/Android.mk
new file mode 100644
index 0000000..9434582
--- /dev/null
+++ b/samples/Compass/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := Compass
+
+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/Compass/AndroidManifest.xml b/samples/Compass/AndroidManifest.xml
new file mode 100644
index 0000000..9aa5636
--- /dev/null
+++ b/samples/Compass/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- This file describes the code in the Compass package, which is
+ used by the system to determine how to start your application and
+ integrate it with the rest of the system. -->
+
+<!-- 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.compass">
+
+ <!-- This package contains an application... The 'label' is the name
+ to display to the user for the overall application, and provides
+ a default label for all following components. The syntax here is a
+ reference to one of our string resources.-->
+ <application android:label="@string/compass_app">
+
+ <!-- An Activity in the application - this is something the user
+ can launch and interact with. The "name" attribute is the
+ name of the class within your package that implements this
+ activity. -->
+ <activity android:name="CompassActivity">
+
+ <!-- An IntentFilter tells the system when it should use your
+ activity. This allows the user to get to your activity
+ without someone having to explicitly know to launch your
+ class "com.example.android.compass_app.CompassActivity". -->
+ <intent-filter>
+ <!-- The MAIN action describes a main entry point into an
+ activity, without any associated data. -->
+ <action android:name="android.intent.action.MAIN" />
+
+ <!-- This places this activity into the main app list. -->
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/samples/Compass/res/values/strings.xml b/samples/Compass/res/values/strings.xml
new file mode 100644
index 0000000..7cf3da4
--- /dev/null
+++ b/samples/Compass/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+ them to be changed based on the locale and options. -->
+
+<resources>
+ <!-- Simple strings. -->
+ <string name="compass_app">Compass</string>
+</resources>
+
diff --git a/samples/Compass/src/com/example/android/compass/CompassActivity.java b/samples/Compass/src/com/example/android/compass/CompassActivity.java
new file mode 100644
index 0000000..c4b9566
--- /dev/null
+++ b/samples/Compass/src/com/example/android/compass/CompassActivity.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2008 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.compass;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+import static javax.microedition.khronos.opengles.GL10.*;
+
+import android.app.Activity;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLSurfaceView.Renderer;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * This class provides a basic demonstration of how to use the
+ * {@link android.hardware.SensorManager SensorManager} API to draw
+ * a 3D compass.
+ */
+public class CompassActivity extends Activity implements Renderer, SensorEventListener {
+ private GLSurfaceView mGLSurfaceView;
+ private SensorManager mSensorManager;
+ private float[] mGData = new float[3];
+ private float[] mMData = new float[3];
+ private float[] mR = new float[16];
+ private float[] mI = new float[16];
+ private FloatBuffer mVertexBuffer;
+ private FloatBuffer mColorBuffer;
+ private ByteBuffer mIndexBuffer;
+ private float[] mOrientation = new float[3];
+ private int mCount;
+
+ public CompassActivity() {
+ }
+
+ /** Called with the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ mGLSurfaceView = new GLSurfaceView(this);
+ mGLSurfaceView.setRenderer(this);
+ setContentView(mGLSurfaceView);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mGLSurfaceView.onResume();
+ Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
+ mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);
+ mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_GAME);
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mGLSurfaceView.onPause();
+ mSensorManager.unregisterListener(this);
+ }
+
+ public int[] getConfigSpec() {
+ // We want a depth buffer, don't care about the
+ // details of the color buffer.
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ return configSpec;
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ /*
+ * Usually, the first thing one might want to do is to clear
+ * the screen. The most efficient way of doing this is to use
+ * glClear().
+ */
+
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+ /*
+ * Now we're ready to draw some 3D objects
+ */
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0, 0, -2);
+
+ /*
+ * All the magic happens here. The rotation matrix mR reported by
+ * SensorManager.getRotationMatrix() is a 4x4 row-major matrix.
+ * We need to use its inverse for rendering. The inverse is
+ * simply calculated by taking the matrix' transpose. However, since
+ * glMultMatrixf() expects a column-major matrix, we can use mR
+ * directly!
+ */
+ gl.glMultMatrixf(mR, 0);
+ // some test code which will be used/cleaned up before we ship this.
+ //gl.glMultMatrixf(mI, 0);
+
+ gl.glVertexPointer(3, GL_FLOAT, 0, mVertexBuffer);
+ gl.glColorPointer(4, GL_FLOAT, 0, mColorBuffer);
+ gl.glDrawElements(GL_LINES, 6, GL_UNSIGNED_BYTE, mIndexBuffer);
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ gl.glViewport(0, 0, width, height);
+
+ /*
+ * Set our projection matrix. This doesn't have to be done
+ * each time we draw, but usually a new projection needs to
+ * be set when the viewport is resized.
+ */
+
+ float ratio = (float) width / height;
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ /*
+ * By default, OpenGL enables features that improve quality
+ * but reduce performance. One might want to tweak that
+ * especially on software renderer.
+ */
+ gl.glDisable(GL10.GL_DITHER);
+
+ /*
+ * Some one-time OpenGL initialization can be made here
+ * probably based on features of this particular context
+ */
+ gl.glClearColor(1,1,1,1);
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glShadeModel(GL10.GL_SMOOTH);
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+
+ /*
+ * create / load the our 3D models here
+ */
+
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+ float vertices[] = {
+ 0,0,0,
+ 1,0,0,
+ 0,1,0,
+ 0,0,1
+ };
+ float colors[] = {
+ 0,0,0,0,
+ 1,0,0,1,
+ 0,1,0,1,
+ 0,0,1,1
+ };
+ byte indices[] = { 0, 1, 0, 2, 0, 3 };
+
+ // Buffers to be passed to gl*Pointer() functions
+ // must be direct, i.e., they must be placed on the
+ // native heap where the garbage collector cannot
+ // move them.
+ //
+ // Buffers with multi-byte datatypes (e.g., short, int, float)
+ // must have their byte order set to native order
+
+ ByteBuffer vbb;
+ vbb = ByteBuffer.allocateDirect(vertices.length*4);
+ vbb.order(ByteOrder.nativeOrder());
+ mVertexBuffer = vbb.asFloatBuffer();
+ mVertexBuffer.put(vertices);
+ mVertexBuffer.position(0);
+
+ vbb = ByteBuffer.allocateDirect(colors.length*4);
+ vbb.order(ByteOrder.nativeOrder());
+ mColorBuffer = vbb.asFloatBuffer();
+ mColorBuffer.put(colors);
+ mColorBuffer.position(0);
+
+ mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
+ mIndexBuffer.put(indices);
+ mIndexBuffer.position(0);
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ public void onSensorChanged(SensorEvent event) {
+ int type = event.sensor.getType();
+ float[] data;
+ if (type == Sensor.TYPE_ACCELEROMETER) {
+ data = mGData;
+ } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
+ data = mMData;
+ } else {
+ // we should not be here.
+ return;
+ }
+ for (int i=0 ; i<3 ; i++)
+ data[i] = event.values[i];
+
+ SensorManager.getRotationMatrix(mR, mI, mGData, mMData);
+// some test code which will be used/cleaned up before we ship this.
+// SensorManager.remapCoordinateSystem(mR,
+// SensorManager.AXIS_X, SensorManager.AXIS_Z, mR);
+// SensorManager.remapCoordinateSystem(mR,
+// SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, mR);
+ SensorManager.getOrientation(mR, mOrientation);
+ float incl = SensorManager.getInclination(mI);
+
+ if (mCount++ > 50) {
+ final float rad2deg = (float)(180.0f/Math.PI);
+ mCount = 0;
+ Log.d("Compass", "yaw: " + (int)(mOrientation[0]*rad2deg) +
+ " pitch: " + (int)(mOrientation[1]*rad2deg) +
+ " roll: " + (int)(mOrientation[2]*rad2deg) +
+ " incl: " + (int)(incl*rad2deg)
+ );
+ }
+ }
+}
diff --git a/samples/GlobalTime/Android.mk b/samples/GlobalTime/Android.mk
new file mode 100644
index 0000000..deb82f5
--- /dev/null
+++ b/samples/GlobalTime/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := GlobalTime
+
+include $(BUILD_PACKAGE)
diff --git a/samples/GlobalTime/AndroidManifest.xml b/samples/GlobalTime/AndroidManifest.xml
new file mode 100644
index 0000000..7aee91b
--- /dev/null
+++ b/samples/GlobalTime/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.globaltime">
+ <application android:icon="@drawable/app_global_time"
+ android:label="Global Time">
+ <activity android:name="GlobalTime"
+ android:theme="@style/Theme">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/samples/GlobalTime/MODULE_LICENSE_APACHE2 b/samples/GlobalTime/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/GlobalTime/MODULE_LICENSE_APACHE2
diff --git a/samples/GlobalTime/NOTICE b/samples/GlobalTime/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/samples/GlobalTime/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/samples/GlobalTime/assets/cities_en.dat b/samples/GlobalTime/assets/cities_en.dat
new file mode 100644
index 0000000..c982ef4
--- /dev/null
+++ b/samples/GlobalTime/assets/cities_en.dat
Binary files differ
diff --git a/samples/GlobalTime/assets/earth.raw b/samples/GlobalTime/assets/earth.raw
new file mode 100644
index 0000000..f884e75
--- /dev/null
+++ b/samples/GlobalTime/assets/earth.raw
Binary files differ
diff --git a/samples/GlobalTime/assets/lights.dat b/samples/GlobalTime/assets/lights.dat
new file mode 100644
index 0000000..14d4f36
--- /dev/null
+++ b/samples/GlobalTime/assets/lights.dat
Binary files differ
diff --git a/samples/GlobalTime/assets/tz512.raw b/samples/GlobalTime/assets/tz512.raw
new file mode 100644
index 0000000..3ce1d5c
--- /dev/null
+++ b/samples/GlobalTime/assets/tz512.raw
Binary files differ
diff --git a/samples/GlobalTime/assets/world.gles b/samples/GlobalTime/assets/world.gles
new file mode 100644
index 0000000..815db1e
--- /dev/null
+++ b/samples/GlobalTime/assets/world.gles
Binary files differ
diff --git a/samples/GlobalTime/res/drawable/app_global_time.png b/samples/GlobalTime/res/drawable/app_global_time.png
new file mode 100644
index 0000000..914977d
--- /dev/null
+++ b/samples/GlobalTime/res/drawable/app_global_time.png
Binary files differ
diff --git a/samples/GlobalTime/res/layout/global_time.xml b/samples/GlobalTime/res/layout/global_time.xml
new file mode 100644
index 0000000..237207f
--- /dev/null
+++ b/samples/GlobalTime/res/layout/global_time.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<EditText xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:textSize="18sp"
+ android:text="@string/global_time_text_text" />
+
+
diff --git a/samples/GlobalTime/res/values/strings.xml b/samples/GlobalTime/res/values/strings.xml
new file mode 100644
index 0000000..d35c059
--- /dev/null
+++ b/samples/GlobalTime/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2007 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="global_time_text_text">Global Time</string>
+
+</resources>
diff --git a/samples/GlobalTime/res/values/styles.xml b/samples/GlobalTime/res/values/styles.xml
new file mode 100644
index 0000000..6051f0f
--- /dev/null
+++ b/samples/GlobalTime/res/values/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/Calendar/assets/res/any/styles.xml
+**
+** Copyright 2006, 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>
+ <style name="Theme" parent="android:Theme.Black">
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowBackground">@null</item>
+ <!-- <item name="android:windowFrame">@null</item> -->
+ </style>
+</resources>
diff --git a/samples/GlobalTime/src/com/android/globaltime/Annulus.java b/samples/GlobalTime/src/com/android/globaltime/Annulus.java
new file mode 100644
index 0000000..b811d88
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/Annulus.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A class that draws a ring with a given center and inner and outer radii.
+ * The inner and outer rings each have a color and the remaining pixels are
+ * colored by interpolation. GlobalTime uses this class to simulate an
+ * "atmosphere" around the earth.
+ */
+public class Annulus extends Shape {
+
+ /**
+ * Constructs an annulus.
+ *
+ * @param centerX the X coordinate of the center point
+ * @param centerY the Y coordinate of the center point
+ * @param Z the fixed Z for the entire ring
+ * @param innerRadius the inner radius
+ * @param outerRadius the outer radius
+ * @param rInner the red channel of the color of the inner ring
+ * @param gInner the green channel of the color of the inner ring
+ * @param bInner the blue channel of the color of the inner ring
+ * @param aInner the alpha channel of the color of the inner ring
+ * @param rOuter the red channel of the color of the outer ring
+ * @param gOuter the green channel of the color of the outer ring
+ * @param bOuter the blue channel of the color of the outer ring
+ * @param aOuter the alpha channel of the color of the outer ring
+ * @param sectors the number of sectors used to approximate curvature
+ */
+ public Annulus(float centerX, float centerY, float Z,
+ float innerRadius, float outerRadius,
+ float rInner, float gInner, float bInner, float aInner,
+ float rOuter, float gOuter, float bOuter, float aOuter,
+ int sectors) {
+ super(GL10.GL_TRIANGLES, GL10.GL_UNSIGNED_SHORT,
+ false, false, true);
+
+ int radii = sectors + 1;
+
+ int[] vertices = new int[2 * 3 * radii];
+ int[] colors = new int[2 * 4 * radii];
+ short[] indices = new short[2 * 3 * radii];
+
+ int vidx = 0;
+ int cidx = 0;
+ int iidx = 0;
+
+ for (int i = 0; i < radii; i++) {
+ float theta = (i * TWO_PI) / (radii - 1);
+ float cosTheta = (float) Math.cos(theta);
+ float sinTheta = (float) Math.sin(theta);
+
+ vertices[vidx++] = toFixed(centerX + innerRadius * cosTheta);
+ vertices[vidx++] = toFixed(centerY + innerRadius * sinTheta);
+ vertices[vidx++] = toFixed(Z);
+
+ vertices[vidx++] = toFixed(centerX + outerRadius * cosTheta);
+ vertices[vidx++] = toFixed(centerY + outerRadius * sinTheta);
+ vertices[vidx++] = toFixed(Z);
+
+ colors[cidx++] = toFixed(rInner);
+ colors[cidx++] = toFixed(gInner);
+ colors[cidx++] = toFixed(bInner);
+ colors[cidx++] = toFixed(aInner);
+
+ colors[cidx++] = toFixed(rOuter);
+ colors[cidx++] = toFixed(gOuter);
+ colors[cidx++] = toFixed(bOuter);
+ colors[cidx++] = toFixed(aOuter);
+ }
+
+ for (int i = 0; i < sectors; i++) {
+ indices[iidx++] = (short) (2 * i);
+ indices[iidx++] = (short) (2 * i + 1);
+ indices[iidx++] = (short) (2 * i + 2);
+
+ indices[iidx++] = (short) (2 * i + 1);
+ indices[iidx++] = (short) (2 * i + 3);
+ indices[iidx++] = (short) (2 * i + 2);
+ }
+
+ allocateBuffers(vertices, null, null, colors, indices);
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/City.java b/samples/GlobalTime/src/com/android/globaltime/City.java
new file mode 100644
index 0000000..0b4cb84
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/City.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TimeZone;
+
+/**
+ * A class representing a city, with an associated position, time zone name,
+ * and raw offset from UTC.
+ */
+public class City implements Comparable<City> {
+
+ private static Map<String,City> cities = new HashMap<String,City>();
+ private static City[] citiesByRawOffset;
+
+ private String name;
+ private String timeZoneID;
+ private TimeZone timeZone = null;
+ private int rawOffset;
+ private float latitude, longitude;
+ private float x, y, z;
+
+ /**
+ * Loads the city database. The cities must be stored in order by raw
+ * offset from UTC.
+ */
+ public static void loadCities(InputStream is) throws IOException {
+ DataInputStream dis = new DataInputStream(is);
+ int numCities = dis.readInt();
+ citiesByRawOffset = new City[numCities];
+
+ byte[] buf = new byte[24];
+ for (int i = 0; i < numCities; i++) {
+ String name = dis.readUTF();
+ String tzid = dis.readUTF();
+ dis.read(buf);
+
+// The code below is a faster version of:
+// int rawOffset = dis.readInt();
+// float latitude = dis.readFloat();
+// float longitude = dis.readFloat();
+// float cx = dis.readFloat();
+// float cy = dis.readFloat();
+// float cz = dis.readFloat();
+
+ int rawOffset =
+ (buf[ 0] << 24) | ((buf[ 1] & 0xff) << 16) |
+ ((buf[ 2] & 0xff) << 8) | (buf[ 3] & 0xff);
+ int ilat = (buf[ 4] << 24) | ((buf[ 5] & 0xff) << 16) |
+ ((buf[ 6] & 0xff) << 8) | (buf[ 7] & 0xff);
+ int ilon = (buf[ 8] << 24) | ((buf[ 9] & 0xff) << 16) |
+ ((buf[10] & 0xff) << 8) | (buf[11] & 0xff);
+ int icx = (buf[12] << 24) | ((buf[13] & 0xff) << 16) |
+ ((buf[14] & 0xff) << 8) | (buf[15] & 0xff);
+ int icy = (buf[16] << 24) | ((buf[17] & 0xff) << 16) |
+ ((buf[18] & 0xff) << 8) | (buf[19] & 0xff);
+ int icz = (buf[20] << 24) | ((buf[21] & 0xff) << 16) |
+ ((buf[22] & 0xff) << 8) | (buf[23] & 0xff);
+ float latitude = Float.intBitsToFloat(ilat);
+ float longitude = Float.intBitsToFloat(ilon);
+ float cx = Float.intBitsToFloat(icx);
+ float cy = Float.intBitsToFloat(icy);
+ float cz = Float.intBitsToFloat(icz);
+
+ City city = new City(name, tzid, rawOffset,
+ latitude, longitude, cx, cy, cz);
+
+ cities.put(name, city);
+ citiesByRawOffset[i] = city;
+ }
+ }
+
+ /**
+ * Returns the cities, ordered by name.
+ */
+ public static City[] getCitiesByName() {
+ City[] ocities = new City[cities.size()];
+ Iterator<City> iter = cities.values().iterator();
+ int idx = 0;
+ while (iter.hasNext()) {
+ ocities[idx++] = iter.next();
+ }
+ Arrays.sort(ocities);
+ return ocities;
+ }
+
+ /**
+ * Returns the cities, ordered by offset, accounting for summer/daylight
+ * savings time. This requires reading the entire time zone database
+ * behind the scenes.
+ */
+ public static City[] getCitiesByOffset() {
+ City[] ocities = new City[cities.size()];
+ Iterator<City> iter = cities.values().iterator();
+ int idx = 0;
+ while (iter.hasNext()) {
+ ocities[idx++] = iter.next();
+ }
+ Arrays.sort(ocities, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ long now = System.currentTimeMillis();
+ City c1 = (City)o1;
+ City c2 = (City)o2;
+ TimeZone tz1 = c1.getTimeZone();
+ TimeZone tz2 = c2.getTimeZone();
+ int off1 = tz1.getOffset(now);
+ int off2 = tz2.getOffset(now);
+ if (off1 == off2) {
+ float dlat = c2.getLatitude() - c1.getLatitude();
+ if (dlat < 0.0f) return -1;
+ if (dlat > 0.0f) return 1;
+ return 0;
+ }
+ return off1 - off2;
+ }
+ });
+ return ocities;
+ }
+
+
+ /**
+ * Returns the cities, ordered by offset, accounting for summer/daylight
+ * savings time. This does not require reading the time zone database
+ * since the cities are pre-sorted.
+ */
+ public static City[] getCitiesByRawOffset() {
+ return citiesByRawOffset;
+ }
+
+ /**
+ * Returns an Iterator over all cities, in raw offset order.
+ */
+ public static Iterator<City> iterator() {
+ return cities.values().iterator();
+ }
+
+ /**
+ * Returns the total number of cities.
+ */
+ public static int numCities() {
+ return cities.size();
+ }
+
+ /**
+ * Constructs a city with the given name, time zone name, raw offset,
+ * latitude, longitude, and 3D (X, Y, Z) coordinate.
+ */
+ public City(String name, String timeZoneID,
+ int rawOffset,
+ float latitude, float longitude,
+ float x, float y, float z) {
+ this.name = name;
+ this.timeZoneID = timeZoneID;
+ this.rawOffset = rawOffset;
+ this.latitude = latitude;
+ this.longitude = longitude;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public TimeZone getTimeZone() {
+ if (timeZone == null) {
+ timeZone = TimeZone.getTimeZone(timeZoneID);
+ }
+ return timeZone;
+ }
+
+ public float getLongitude() {
+ return longitude;
+ }
+
+ public float getLatitude() {
+ return latitude;
+ }
+
+ public float getX() {
+ return x;
+ }
+
+ public float getY() {
+ return y;
+ }
+
+ public float getZ() {
+ return z;
+ }
+
+ public float getRawOffset() {
+ return rawOffset / 3600000.0f;
+ }
+
+ public int getRawOffsetMillis() {
+ return rawOffset;
+ }
+
+ /**
+ * Returns this city's offset from UTC, taking summer/daylight savigns
+ * time into account.
+ */
+ public float getOffset() {
+ long now = System.currentTimeMillis();
+ if (timeZone == null) {
+ timeZone = TimeZone.getTimeZone(timeZoneID);
+ }
+ return timeZone.getOffset(now) / 3600000.0f;
+ }
+
+ /**
+ * Compares this city to another by name.
+ */
+ public int compareTo(City o) {
+ return name.compareTo(o.name);
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/Clock.java b/samples/GlobalTime/src/com/android/globaltime/Clock.java
new file mode 100644
index 0000000..9aad71a
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/Clock.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.text.format.DateUtils;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+/**
+ * A class that draws an analog clock face with information about the current
+ * time in a given city.
+ */
+public class Clock {
+
+ static final int MILLISECONDS_PER_MINUTE = 60 * 1000;
+ static final int MILLISECONDS_PER_HOUR = 60 * 60 * 1000;
+
+ private City mCity = null;
+ private long mCitySwitchTime;
+ private long mTime;
+
+ private float mColorRed = 1.0f;
+ private float mColorGreen = 1.0f;
+ private float mColorBlue = 1.0f;
+
+ private long mOldOffset;
+
+ private Interpolator mClockHandInterpolator =
+ new AccelerateDecelerateInterpolator();
+
+ public Clock() {
+ // Empty constructor
+ }
+
+ /**
+ * Adds a line to the given Path. The line extends from
+ * radius r0 to radius r1 about the center point (cx, cy),
+ * at an angle given by pos.
+ *
+ * @param path the Path to draw to
+ * @param radius the radius of the outer rim of the clock
+ * @param pos the angle, with 0 and 1 at 12:00
+ * @param cx the X coordinate of the clock center
+ * @param cy the Y coordinate of the clock center
+ * @param r0 the starting radius for the line
+ * @param r1 the ending radius for the line
+ */
+ private static void drawLine(Path path,
+ float radius, float pos, float cx, float cy, float r0, float r1) {
+ float theta = pos * Shape.TWO_PI - Shape.PI_OVER_TWO;
+ float dx = (float) Math.cos(theta);
+ float dy = (float) Math.sin(theta);
+ float p0x = cx + dx * r0;
+ float p0y = cy + dy * r0;
+ float p1x = cx + dx * r1;
+ float p1y = cy + dy * r1;
+
+ float ox = (p1y - p0y);
+ float oy = -(p1x - p0x);
+
+ float norm = (radius / 2.0f) / (float) Math.sqrt(ox * ox + oy * oy);
+ ox *= norm;
+ oy *= norm;
+
+ path.moveTo(p0x - ox, p0y - oy);
+ path.lineTo(p1x - ox, p1y - oy);
+ path.lineTo(p1x + ox, p1y + oy);
+ path.lineTo(p0x + ox, p0y + oy);
+ path.close();
+ }
+
+ /**
+ * Adds a vertical arrow to the given Path.
+ *
+ * @param path the Path to draw to
+ */
+ private static void drawVArrow(Path path,
+ float cx, float cy, float width, float height) {
+ path.moveTo(cx - width / 2.0f, cy);
+ path.lineTo(cx, cy + height);
+ path.lineTo(cx + width / 2.0f, cy);
+ path.close();
+ }
+
+ /**
+ * Adds a horizontal arrow to the given Path.
+ *
+ * @param path the Path to draw to
+ */
+ private static void drawHArrow(Path path,
+ float cx, float cy, float width, float height) {
+ path.moveTo(cx, cy - height / 2.0f);
+ path.lineTo(cx + width, cy);
+ path.lineTo(cx, cy + height / 2.0f);
+ path.close();
+ }
+
+ /**
+ * Returns an offset in milliseconds to be subtracted from the current time
+ * in order to obtain an smooth interpolation between the previously
+ * displayed time and the current time.
+ */
+ private long getOffset(float lerp) {
+ long doffset = (long) (mCity.getOffset() *
+ (float) MILLISECONDS_PER_HOUR - mOldOffset);
+ int sign;
+ if (doffset < 0) {
+ doffset = -doffset;
+ sign = -1;
+ } else {
+ sign = 1;
+ }
+
+ while (doffset > 12L * MILLISECONDS_PER_HOUR) {
+ doffset -= 12L * MILLISECONDS_PER_HOUR;
+ }
+ if (doffset > 6L * MILLISECONDS_PER_HOUR) {
+ doffset = 12L * MILLISECONDS_PER_HOUR - doffset;
+ sign = -sign;
+ }
+
+ // Interpolate doffset towards 0
+ doffset = (long)((1.0f - lerp)*doffset);
+
+ // Keep the same seconds count
+ long dh = doffset / (MILLISECONDS_PER_HOUR);
+ doffset -= dh * MILLISECONDS_PER_HOUR;
+ long dm = doffset / MILLISECONDS_PER_MINUTE;
+ doffset = sign * (60 * dh + dm) * MILLISECONDS_PER_MINUTE;
+
+ return doffset;
+ }
+
+ /**
+ * Set the city to be displayed. setCity(null) resets things so the clock
+ * hand animation won't occur next time.
+ */
+ public void setCity(City city) {
+ if (mCity != city) {
+ if (mCity != null) {
+ mOldOffset =
+ (long) (mCity.getOffset() * (float) MILLISECONDS_PER_HOUR);
+ } else if (city != null) {
+ mOldOffset =
+ (long) (city.getOffset() * (float) MILLISECONDS_PER_HOUR);
+ } else {
+ mOldOffset = 0L; // this will never be used
+ }
+ this.mCitySwitchTime = System.currentTimeMillis();
+ this.mCity = city;
+ }
+ }
+
+ public void setTime(long time) {
+ this.mTime = time;
+ }
+
+ /**
+ * Draws the clock face.
+ *
+ * @param canvas the Canvas to draw to
+ * @param cx the X coordinate of the clock center
+ * @param cy the Y coordinate of the clock center
+ * @param radius the radius of the clock face
+ * @param alpha the translucency of the clock face
+ * @param textAlpha the translucency of the text
+ * @param showCityName if true, display the city name
+ * @param showTime if true, display the time digitally
+ * @param showUpArrow if true, display an up arrow
+ * @param showDownArrow if true, display a down arrow
+ * @param showLeftRightArrows if true, display left and right arrows
+ * @param prefixChars number of characters of the city name to draw in bold
+ */
+ public void drawClock(Canvas canvas,
+ float cx, float cy, float radius, float alpha, float textAlpha,
+ boolean showCityName, boolean showTime,
+ boolean showUpArrow, boolean showDownArrow, boolean showLeftRightArrows,
+ int prefixChars) {
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+
+ int iradius = (int)radius;
+
+ TimeZone tz = mCity.getTimeZone();
+
+ // Compute an interpolated time to animate between the previously
+ // displayed time and the current time
+ float lerp = Math.min(1.0f,
+ (System.currentTimeMillis() - mCitySwitchTime) / 500.0f);
+ lerp = mClockHandInterpolator.getInterpolation(lerp);
+ long doffset = lerp < 1.0f ? getOffset(lerp) : 0L;
+
+ // Determine the interpolated time for the given time zone
+ Calendar cal = Calendar.getInstance(tz);
+ cal.setTimeInMillis(mTime - doffset);
+ int hour = cal.get(Calendar.HOUR_OF_DAY);
+ int minute = cal.get(Calendar.MINUTE);
+ int second = cal.get(Calendar.SECOND);
+ int milli = cal.get(Calendar.MILLISECOND);
+
+ float offset = tz.getRawOffset() / (float) MILLISECONDS_PER_HOUR;
+ float daylightOffset = tz.inDaylightTime(new Date(mTime)) ?
+ tz.getDSTSavings() / (float) MILLISECONDS_PER_HOUR : 0.0f;
+
+ float absOffset = offset < 0 ? -offset : offset;
+ int offsetH = (int) absOffset;
+ int offsetM = (int) (60.0f * (absOffset - offsetH));
+ hour %= 12;
+
+ // Get the city name and digital time strings
+ String cityName = mCity.getName();
+ cal.setTimeInMillis(mTime);
+ String time = DateUtils.timeString(cal.getTimeInMillis()) + " " +
+ DateUtils.getDayOfWeekString(cal.get(Calendar.DAY_OF_WEEK),
+ DateUtils.LENGTH_SHORT) + " " +
+ " (UTC" +
+ (offset >= 0 ? "+" : "-") +
+ offsetH +
+ (offsetM == 0 ? "" : ":" + offsetM) +
+ (daylightOffset == 0 ? "" : "+" + daylightOffset) +
+ ")";
+
+ float th = paint.getTextSize();
+ float tw;
+
+ // Set the text color
+ paint.setARGB((int) (textAlpha * 255.0f),
+ (int) (mColorRed * 255.0f),
+ (int) (mColorGreen * 255.0f),
+ (int) (mColorBlue * 255.0f));
+
+ tw = paint.measureText(cityName);
+ if (showCityName) {
+ // Increment prefixChars to include any spaces
+ for (int i = 0; i < prefixChars; i++) {
+ if (cityName.charAt(i) == ' ') {
+ ++prefixChars;
+ }
+ }
+
+ // Draw the city name
+ canvas.drawText(cityName, cx - tw / 2, cy - radius - th, paint);
+ // Overstrike the first 'prefixChars' characters
+ canvas.drawText(cityName.substring(0, prefixChars),
+ cx - tw / 2 + 1, cy - radius - th, paint);
+ }
+ tw = paint.measureText(time);
+ if (showTime) {
+ canvas.drawText(time, cx - tw / 2, cy + radius + th + 5, paint);
+ }
+
+ paint.setARGB((int)(alpha * 255.0f),
+ (int)(mColorRed * 255.0f),
+ (int)(mColorGreen * 255.0f),
+ (int)(mColorBlue * 255.0f));
+
+ paint.setStyle(Paint.Style.FILL);
+ canvas.drawOval(new RectF(cx - 2, cy - 2, cx + 2, cy + 2), paint);
+
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(radius * 0.12f);
+
+ canvas.drawOval(new RectF(cx - iradius, cy - iradius,
+ cx + iradius, cy + iradius),
+ paint);
+
+ float r0 = radius * 0.1f;
+ float r1 = radius * 0.4f;
+ float r2 = radius * 0.6f;
+ float r3 = radius * 0.65f;
+ float r4 = radius * 0.7f;
+ float r5 = radius * 0.9f;
+
+ Path path = new Path();
+
+ float ss = second + milli / 1000.0f;
+ float mm = minute + ss / 60.0f;
+ float hh = hour + mm / 60.0f;
+
+ // Tics for the hours
+ for (int i = 0; i < 12; i++) {
+ drawLine(path, radius * 0.12f, i / 12.0f, cx, cy, r4, r5);
+ }
+
+ // Hour hand
+ drawLine(path, radius * 0.12f, hh / 12.0f, cx, cy, r0, r1);
+ // Minute hand
+ drawLine(path, radius * 0.12f, mm / 60.0f, cx, cy, r0, r2);
+ // Second hand
+ drawLine(path, radius * 0.036f, ss / 60.0f, cx, cy, r0, r3);
+
+ if (showUpArrow) {
+ drawVArrow(path, cx + radius * 1.13f, cy - radius,
+ radius * 0.15f, -radius * 0.1f);
+ }
+ if (showDownArrow) {
+ drawVArrow(path, cx + radius * 1.13f, cy + radius,
+ radius * 0.15f, radius * 0.1f);
+ }
+ if (showLeftRightArrows) {
+ drawHArrow(path, cx - radius * 1.3f, cy, -radius * 0.1f,
+ radius * 0.15f);
+ drawHArrow(path, cx + radius * 1.3f, cy, radius * 0.1f,
+ radius * 0.15f);
+ }
+
+ paint.setStyle(Paint.Style.FILL);
+ canvas.drawPath(path, paint);
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/GLView.java b/samples/GlobalTime/src/com/android/globaltime/GLView.java
new file mode 100644
index 0000000..4253717
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/GLView.java
@@ -0,0 +1,927 @@
+/*
+ * Copyright (C) 2006 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.android.globaltime;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.view.KeyEvent;
+
+class Message {
+
+ private String mText;
+ private long mExpirationTime;
+
+ public Message(String text, long expirationTime) {
+ this.mText = text;
+ this.mExpirationTime = expirationTime;
+ }
+
+ public String getText() {
+ return mText;
+ }
+
+ public long getExpirationTime() {
+ return mExpirationTime;
+ }
+}
+
+/**
+ * A helper class to simplify writing an Activity that renders using
+ * OpenGL ES.
+ *
+ * <p> A GLView object stores common elements of GL state and allows
+ * them to be modified interactively. This is particularly useful for
+ * determining the proper settings of parameters such as the view
+ * frustum and light intensities during application development.
+ *
+ * <p> A GLView is not an actual View; instead, it is meant to be
+ * called from within a View to perform event processing on behalf of the
+ * actual View.
+ *
+ * <p> By passing key events to the GLView object from the View,
+ * the application can automatically allow certain parameters to
+ * be user-controlled from the keyboard. Key events may be passed as
+ * shown below:
+ *
+ * <pre>
+ * GLView mGlView = new GLView();
+ *
+ * public boolean onKeyDown(int keyCode, KeyEvent event) {
+ * // Hand the key to the GLView object first
+ * if (mGlView.processKey(keyCode)) {
+ * return;
+ * }
+ *
+ * switch (keyCode) {
+ * case KeyEvent.KEY_CODE_X:
+ * // perform app processing
+ * break;
+ *
+ * default:
+ * super.onKeyDown(keyCode, event);
+ * break;
+ * }
+ * }
+ * </pre>
+ *
+ * <p> During drawing of a frame, the GLView object should be given the
+ * opportunity to manage GL parameters as shown below:
+ *
+ * OpenGLContext mGLContext; // initialization not shown
+ * int mNumTrianglesDrawn = 0;
+ *
+ * protected void onDraw(Canvas canvas) {
+ * int w = getWidth();
+ * int h = getHeight();
+ *
+ * float ratio = (float) w / h;
+ * mGLView.setAspectRatio(ratio);
+ *
+ * GL10 gl = (GL10) mGLContext.getGL();
+ * mGLContext.waitNative(canvas, this);
+ *
+ * // Enable a light for the GLView to manipulate
+ * gl.glEnable(GL10.GL_LIGHTING);
+ * gl.glEnable(GL10.GL_LIGHT0);
+ *
+ * // Allow the GLView to set GL parameters
+ * mGLView.setTextureParameters(gl);
+ * mGLView.setProjection(gl);
+ * mGLView.setView(gl);
+ * mGLView.setLights(gl, GL10.GL_LIGHT0);
+ *
+ * // Draw some stuff (not shown)
+ * mNumTrianglesDrawn += <num triangles just drawn>;
+ *
+ * // Wait for GL drawing to complete
+ * mGLContext.waitGL();
+ *
+ * // Inform the GLView of what was drawn, and ask it to display statistics
+ * mGLView.setNumTriangles(mNumTrianglesDrawn);
+ * mGLView.showMessages(canvas);
+ * mGLView.showStatistics(canvas, w);
+ * }
+ * </pre>
+ *
+ * <p> At the end of each frame, following the call to
+ * GLContext.waitGL, the showStatistics and showMessages methods
+ * will cause additional information to be displayed.
+ *
+ * <p> To enter the interactive command mode, the 'tab' key must be
+ * pressed twice in succession. A subsequent press of the 'tab' key
+ * exits the interactive command mode. Entering a multi-letter code
+ * sets the parameter to be modified. The 'newline' key erases the
+ * current code, and the 'del' key deletes the last letter of
+ * the code. The parameter value may be modified by pressing the
+ * keypad left or up to decrement the value and right or down to
+ * increment the value. The current value will be displayed as an
+ * overlay above the GL rendered content.
+ *
+ * <p> The supported keyboard commands are as follows:
+ *
+ * <ul>
+ * <li> h - display a list of commands
+ * <li> fn - near frustum
+ * <li> ff - far frustum
+ * <li> tx - translate x
+ * <li> ty - translate y
+ * <li> tz - translate z
+ * <li> z - zoom (frustum size)
+ * <li> la - ambient light (all RGB channels)
+ * <li> lar - ambient light red channel
+ * <li> lag - ambient light green channel
+ * <li> lab - ambient light blue channel
+ * <li> ld - diffuse light (all RGB channels)
+ * <li> ldr - diffuse light red channel
+ * <li> ldg - diffuse light green channel
+ * <li> ldb - diffuse light blue channel
+ * <li> ls - specular light (all RGB channels)
+ * <li> lsr - specular light red channel
+ * <li> lsg - specular light green channel
+ * <li> lsb - specular light blue channel
+ * <li> lma - light model ambient (all RGB channels)
+ * <li> lmar - light model ambient light red channel
+ * <li> lmag - light model ambient green channel
+ * <li> lmab - light model ambient blue channel
+ * <li> tmin - texture min filter
+ * <li> tmag - texture mag filter
+ * <li> tper - texture perspective correction
+ * </ul>
+ *
+ * {@hide}
+ */
+public class GLView {
+
+ private static final int DEFAULT_DURATION_MILLIS = 1000;
+ private static final int STATE_KEY = KeyEvent.KEYCODE_TAB;
+ private static final int HAVE_NONE = 0;
+ private static final int HAVE_ONE = 1;
+ private static final int HAVE_TWO = 2;
+
+ private static final float MESSAGE_Y_SPACING = 12.0f;
+
+ private int mState = HAVE_NONE;
+
+ private static final int NEAR_FRUSTUM = 0;
+ private static final int FAR_FRUSTUM = 1;
+ private static final int TRANSLATE_X = 2;
+ private static final int TRANSLATE_Y = 3;
+ private static final int TRANSLATE_Z = 4;
+ private static final int ZOOM_EXPONENT = 5;
+
+ private static final int AMBIENT_INTENSITY = 6;
+ private static final int AMBIENT_RED = 7;
+ private static final int AMBIENT_GREEN = 8;
+ private static final int AMBIENT_BLUE = 9;
+
+ private static final int DIFFUSE_INTENSITY = 10;
+ private static final int DIFFUSE_RED = 11;
+ private static final int DIFFUSE_GREEN = 12;
+ private static final int DIFFUSE_BLUE = 13;
+
+ private static final int SPECULAR_INTENSITY = 14;
+ private static final int SPECULAR_RED = 15;
+ private static final int SPECULAR_GREEN = 16;
+ private static final int SPECULAR_BLUE = 17;
+
+ private static final int LIGHT_MODEL_AMBIENT_INTENSITY = 18;
+ private static final int LIGHT_MODEL_AMBIENT_RED = 19;
+ private static final int LIGHT_MODEL_AMBIENT_GREEN = 20;
+ private static final int LIGHT_MODEL_AMBIENT_BLUE = 21;
+
+ private static final int TEXTURE_MIN_FILTER = 22;
+ private static final int TEXTURE_MAG_FILTER = 23;
+ private static final int TEXTURE_PERSPECTIVE_CORRECTION = 24;
+
+ private static final String[] commands = {
+ "fn",
+ "ff",
+ "tx",
+ "ty",
+ "tz",
+ "z",
+ "la", "lar", "lag", "lab",
+ "ld", "ldr", "ldg", "ldb",
+ "ls", "lsr", "lsg", "lsb",
+ "lma", "lmar", "lmag", "lmab",
+ "tmin", "tmag", "tper"
+ };
+
+ private static final String[] labels = {
+ "Near Frustum",
+ "Far Frustum",
+ "Translate X",
+ "Translate Y",
+ "Translate Z",
+ "Zoom",
+ "Ambient Intensity",
+ "Ambient Red",
+ "Ambient Green",
+ "Ambient Blue",
+ "Diffuse Intensity",
+ "Diffuse Red",
+ "Diffuse Green",
+ "Diffuse Blue",
+ "Specular Intenstity",
+ "Specular Red",
+ "Specular Green",
+ "Specular Blue",
+ "Light Model Ambient Intensity",
+ "Light Model Ambient Red",
+ "Light Model Ambient Green",
+ "Light Model Ambient Blue",
+ "Texture Min Filter",
+ "Texture Mag Filter",
+ "Texture Perspective Correction",
+ };
+
+ private static final float[] defaults = {
+ 5.0f, 100.0f,
+ 0.0f, 0.0f, -50.0f,
+ 0,
+ 0.125f, 1.0f, 1.0f, 1.0f,
+ 0.125f, 1.0f, 1.0f, 1.0f,
+ 0.125f, 1.0f, 1.0f, 1.0f,
+ 0.125f, 1.0f, 1.0f, 1.0f,
+ GL10.GL_NEAREST, GL10.GL_NEAREST,
+ GL10.GL_FASTEST
+ };
+
+ private static final float[] increments = {
+ 0.01f, 0.5f,
+ 0.125f, 0.125f, 0.125f,
+ 1.0f,
+ 0.03125f, 0.1f, 0.1f, 0.1f,
+ 0.03125f, 0.1f, 0.1f, 0.1f,
+ 0.03125f, 0.1f, 0.1f, 0.1f,
+ 0.03125f, 0.1f, 0.1f, 0.1f,
+ 0, 0, 0
+ };
+
+ private float[] params = new float[commands.length];
+
+ private static final float mZoomScale = 0.109f;
+ private static final float mZoomBase = 1.01f;
+
+ private int mParam = -1;
+ private float mIncr = 0;
+
+ private Paint mPaint = new Paint();
+
+ private float mAspectRatio = 1.0f;
+
+ private float mZoom;
+
+ // private boolean mPerspectiveCorrection = false;
+ // private int mTextureMinFilter = GL10.GL_NEAREST;
+ // private int mTextureMagFilter = GL10.GL_NEAREST;
+
+ // Counters for FPS calculation
+ private boolean mDisplayFPS = false;
+ private boolean mDisplayCounts = false;
+ private int mFramesFPS = 10;
+ private long[] mTimes = new long[mFramesFPS];
+ private int mTimesIdx = 0;
+
+ private Map<String,Message> mMessages = new HashMap<String,Message>();
+
+ /**
+ * Constructs a new GLView.
+ */
+ public GLView() {
+ mPaint.setColor(0xffffffff);
+ reset();
+ }
+
+ /**
+ * Sets the aspect ratio (width/height) of the screen.
+ *
+ * @param aspectRatio the screen width divided by the screen height
+ */
+ public void setAspectRatio(float aspectRatio) {
+ this.mAspectRatio = aspectRatio;
+ }
+
+ /**
+ * Sets the overall ambient light intensity. This intensity will
+ * be used to modify the ambient light value for each of the red,
+ * green, and blue channels passed to glLightfv(...GL_AMBIENT...).
+ * The default value is 0.125f.
+ *
+ * @param intensity a floating-point value controlling the overall
+ * ambient light intensity.
+ */
+ public void setAmbientIntensity(float intensity) {
+ params[AMBIENT_INTENSITY] = intensity;
+ }
+
+ /**
+ * Sets the light model ambient intensity. This intensity will be
+ * used to modify the ambient light value for each of the red,
+ * green, and blue channels passed to
+ * glLightModelfv(GL_LIGHT_MODEL_AMBIENT...). The default value
+ * is 0.125f.
+ *
+ * @param intensity a floating-point value controlling the overall
+ * light model ambient intensity.
+ */
+ public void setLightModelAmbientIntensity(float intensity) {
+ params[LIGHT_MODEL_AMBIENT_INTENSITY] = intensity;
+ }
+
+ /**
+ * Sets the ambient color for the red, green, and blue channels
+ * that will be multiplied by the value of setAmbientIntensity and
+ * passed to glLightfv(...GL_AMBIENT...). The default values are
+ * {1, 1, 1}.
+ *
+ * @param ambient an arry of three floats containing ambient
+ * red, green, and blue intensity values.
+ */
+ public void setAmbientColor(float[] ambient) {
+ params[AMBIENT_RED] = ambient[0];
+ params[AMBIENT_GREEN] = ambient[1];
+ params[AMBIENT_BLUE] = ambient[2];
+ }
+
+ /**
+ * Sets the overall diffuse light intensity. This intensity will
+ * be used to modify the diffuse light value for each of the red,
+ * green, and blue channels passed to glLightfv(...GL_DIFFUSE...).
+ * The default value is 0.125f.
+ *
+ * @param intensity a floating-point value controlling the overall
+ * ambient light intensity.
+ */
+ public void setDiffuseIntensity(float intensity) {
+ params[DIFFUSE_INTENSITY] = intensity;
+ }
+
+ /**
+ * Sets the diffuse color for the red, green, and blue channels
+ * that will be multiplied by the value of setDiffuseIntensity and
+ * passed to glLightfv(...GL_DIFFUSE...). The default values are
+ * {1, 1, 1}.
+ *
+ * @param diffuse an array of three floats containing diffuse
+ * red, green, and blue intensity values.
+ */
+ public void setDiffuseColor(float[] diffuse) {
+ params[DIFFUSE_RED] = diffuse[0];
+ params[DIFFUSE_GREEN] = diffuse[1];
+ params[DIFFUSE_BLUE] = diffuse[2];
+ }
+
+ /**
+ * Sets the overall specular light intensity. This intensity will
+ * be used to modify the diffuse light value for each of the red,
+ * green, and blue channels passed to glLightfv(...GL_SPECULAR...).
+ * The default value is 0.125f.
+ *
+ * @param intensity a floating-point value controlling the overall
+ * ambient light intensity.
+ */
+ public void setSpecularIntensity(float intensity) {
+ params[SPECULAR_INTENSITY] = intensity;
+ }
+
+ /**
+ * Sets the specular color for the red, green, and blue channels
+ * that will be multiplied by the value of setSpecularIntensity and
+ * passed to glLightfv(...GL_SPECULAR...). The default values are
+ * {1, 1, 1}.
+ *
+ * @param specular an array of three floats containing specular
+ * red, green, and blue intensity values.
+ */
+ public void setSpecularColor(float[] specular) {
+ params[SPECULAR_RED] = specular[0];
+ params[SPECULAR_GREEN] = specular[1];
+ params[SPECULAR_BLUE] = specular[2];
+ }
+
+ /**
+ * Returns the current X translation of the modelview
+ * transformation as passed to glTranslatef. The default value is
+ * 0.0f.
+ *
+ * @return the X modelview translation as a float.
+ */
+ public float getTranslateX() {
+ return params[TRANSLATE_X];
+ }
+
+ /**
+ * Returns the current Y translation of the modelview
+ * transformation as passed to glTranslatef. The default value is
+ * 0.0f.
+ *
+ * @return the Y modelview translation as a float.
+ */
+ public float getTranslateY() {
+ return params[TRANSLATE_Y];
+ }
+
+ /**
+ * Returns the current Z translation of the modelview
+ * transformation as passed to glTranslatef. The default value is
+ * -50.0f.
+ *
+ * @return the Z modelview translation as a float.
+ */
+ public float getTranslateZ() {
+ return params[TRANSLATE_Z];
+ }
+
+ /**
+ * Sets the position of the near frustum clipping plane as passed
+ * to glFrustumf. The default value is 5.0f;
+ *
+ * @param nearFrustum the near frustum clipping plane distance as
+ * a float.
+ */
+ public void setNearFrustum(float nearFrustum) {
+ params[NEAR_FRUSTUM] = nearFrustum;
+ }
+
+ /**
+ * Sets the position of the far frustum clipping plane as passed
+ * to glFrustumf. The default value is 100.0f;
+ *
+ * @param farFrustum the far frustum clipping plane distance as a
+ * float.
+ */
+ public void setFarFrustum(float farFrustum) {
+ params[FAR_FRUSTUM] = farFrustum;
+ }
+
+ private void computeZoom() {
+ mZoom = mZoomScale*(float)Math.pow(mZoomBase, -params[ZOOM_EXPONENT]);
+ }
+
+ /**
+ * Resets all parameters to their default values.
+ */
+ public void reset() {
+ for (int i = 0; i < params.length; i++) {
+ params[i] = defaults[i];
+ }
+ computeZoom();
+ }
+
+ private void removeExpiredMessages() {
+ long now = System.currentTimeMillis();
+
+ List<String> toBeRemoved = new ArrayList<String>();
+
+ Iterator<String> keyIter = mMessages.keySet().iterator();
+ while (keyIter.hasNext()) {
+ String key = keyIter.next();
+ Message msg = mMessages.get(key);
+ if (msg.getExpirationTime() < now) {
+ toBeRemoved.add(key);
+ }
+ }
+
+ Iterator<String> tbrIter = toBeRemoved.iterator();
+ while (tbrIter.hasNext()) {
+ String key = tbrIter.next();
+ mMessages.remove(key);
+ }
+ }
+
+ /**
+ * Displays the message overlay on the given Canvas. The
+ * GLContext.waitGL method should be called prior to calling this
+ * method. The interactive command display is drawn by this
+ * method.
+ *
+ * @param canvas the Canvas on which messages are to appear.
+ */
+ public void showMessages(Canvas canvas) {
+ removeExpiredMessages();
+
+ float y = 10.0f;
+
+ List<String> l = new ArrayList<String>();
+ l.addAll(mMessages.keySet());
+ Collections.sort(l);
+
+ Iterator<String> iter = l.iterator();
+ while (iter.hasNext()) {
+ String key = iter.next();
+ String text = mMessages.get(key).getText();
+ canvas.drawText(text, 10.0f, y, mPaint);
+ y += MESSAGE_Y_SPACING;
+ }
+ }
+
+ private int mTriangles;
+
+ /**
+ * Sets the number of triangles drawn in the previous frame for
+ * display by the showStatistics method. The number of triangles
+ * is not computed by GLView but must be supplied by the
+ * calling Activity.
+ *
+ * @param triangles an Activity-supplied estimate of the number of
+ * triangles drawn in the previous frame.
+ */
+ public void setNumTriangles(int triangles) {
+ this.mTriangles = triangles;
+ }
+
+ /**
+ * Displays statistics on frames and triangles per second. The
+ * GLContext.waitGL method should be called prior to calling this
+ * method.
+ *
+ * @param canvas the Canvas on which statistics are to appear.
+ * @param width the width of the Canvas.
+ */
+ public void showStatistics(Canvas canvas, int width) {
+ long endTime = mTimes[mTimesIdx] = System.currentTimeMillis();
+ mTimesIdx = (mTimesIdx + 1) % mFramesFPS;
+
+ float th = mPaint.getTextSize();
+
+ if (mDisplayFPS) {
+ // Use end time from mFramesFPS frames ago
+ long startTime = mTimes[mTimesIdx];
+ String fps = "" + (1000.0f*mFramesFPS/(endTime - startTime));
+
+ // Normalize fps to XX.XX format
+ if (fps.indexOf(".") == 1) {
+ fps = " " + fps;
+ }
+ int len = fps.length();
+ if (len == 2) {
+ fps += ".00";
+ } else if (len == 4) {
+ fps += "0";
+ } else if (len > 5) {
+ fps = fps.substring(0, 5);
+ }
+
+ canvas.drawText(fps + " fps", width - 60.0f, 10.0f, mPaint);
+ }
+
+ if (mDisplayCounts) {
+ canvas.drawText(mTriangles + " triangles",
+ width - 100.0f, 10.0f + th + 5, mPaint);
+ }
+ }
+
+ private void addMessage(String key, String text, int durationMillis) {
+ long expirationTime = System.currentTimeMillis() + durationMillis;
+
+ mMessages.put(key, new Message(text, expirationTime));
+ }
+
+ private void addMessage(String key, String text) {
+ addMessage(key, text, DEFAULT_DURATION_MILLIS);
+ }
+
+ private void addMessage(String text) {
+ addMessage(text, text, DEFAULT_DURATION_MILLIS);
+ }
+
+ private void clearMessages() {
+ mMessages.clear();
+ }
+
+ String command = "";
+
+ private void toggleFilter() {
+ if (params[mParam] == GL10.GL_NEAREST) {
+ params[mParam] = GL10.GL_LINEAR;
+ } else {
+ params[mParam] = GL10.GL_NEAREST;
+ }
+ addMessage(commands[mParam],
+ "Texture " +
+ (mParam == TEXTURE_MIN_FILTER ? "min" : "mag") +
+ " filter = " +
+ (params[mParam] == GL10.GL_NEAREST ?
+ "nearest" : "linear"));
+ }
+
+ private void togglePerspectiveCorrection() {
+ if (params[mParam] == GL10.GL_NICEST) {
+ params[mParam] = GL10.GL_FASTEST;
+ } else {
+ params[mParam] = GL10.GL_NICEST;
+ }
+ addMessage(commands[mParam],
+ "Texture perspective correction = " +
+ (params[mParam] == GL10.GL_FASTEST ?
+ "fastest" : "nicest"));
+ }
+
+ private String valueString() {
+ if (mParam == TEXTURE_MIN_FILTER ||
+ mParam == TEXTURE_MAG_FILTER) {
+ if (params[mParam] == GL10.GL_NEAREST) {
+ return "nearest";
+ }
+ if (params[mParam] == GL10.GL_LINEAR) {
+ return "linear";
+ }
+ }
+ if (mParam == TEXTURE_PERSPECTIVE_CORRECTION) {
+ if (params[mParam] == GL10.GL_FASTEST) {
+ return "fastest";
+ }
+ if (params[mParam] == GL10.GL_NICEST) {
+ return "nicest";
+ }
+ }
+ return "" + params[mParam];
+ }
+
+ /**
+ *
+ * @return true if the view
+ */
+ public boolean hasMessages() {
+ return mState == HAVE_TWO || mDisplayFPS || mDisplayCounts;
+ }
+
+ /**
+ * Process a key stroke. The calling Activity should pass all
+ * keys from its onKeyDown method to this method. If the key is
+ * part of a GLView command, true is returned and the calling
+ * Activity should ignore the key event. Otherwise, false is
+ * returned and the calling Activity may process the key event
+ * normally.
+ *
+ * @param keyCode the key code as passed to Activity.onKeyDown.
+ *
+ * @return true if the key is part of a GLView command sequence,
+ * false otherwise.
+ */
+ public boolean processKey(int keyCode) {
+ // Pressing the state key twice enters the UI
+ // Pressing it again exits the UI
+ if ((keyCode == STATE_KEY) ||
+ (keyCode == KeyEvent.KEYCODE_SLASH) ||
+ (keyCode == KeyEvent.KEYCODE_PERIOD))
+ {
+ mState = (mState + 1) % 3;
+ if (mState == HAVE_NONE) {
+ clearMessages();
+ }
+ if (mState == HAVE_TWO) {
+ clearMessages();
+ addMessage("aaaa", "GL", Integer.MAX_VALUE);
+ addMessage("aaab", "", Integer.MAX_VALUE);
+ command = "";
+ }
+ return true;
+ } else {
+ if (mState == HAVE_ONE) {
+ mState = HAVE_NONE;
+ return false;
+ }
+ }
+
+ // If we're not in the UI, exit without handling the key
+ if (mState != HAVE_TWO) {
+ return false;
+ }
+
+ if (keyCode == KeyEvent.KEYCODE_ENTER) {
+ command = "";
+ } else if (keyCode == KeyEvent.KEYCODE_DEL) {
+ if (command.length() > 0) {
+ command = command.substring(0, command.length() - 1);
+ }
+
+ } else if (keyCode >= KeyEvent.KEYCODE_A &&
+ keyCode <= KeyEvent.KEYCODE_Z) {
+ command += "" + (char)(keyCode - KeyEvent.KEYCODE_A + 'a');
+ }
+
+ addMessage("aaaa", "GL " + command, Integer.MAX_VALUE);
+
+ if (command.equals("h")) {
+ addMessage("aaaa", "GL", Integer.MAX_VALUE);
+ addMessage("h - help");
+ addMessage("fn/ff - frustum near/far clip Z");
+ addMessage("la/lar/lag/lab - abmient intensity/r/g/b");
+ addMessage("ld/ldr/ldg/ldb - diffuse intensity/r/g/b");
+ addMessage("ls/lsr/lsg/lsb - specular intensity/r/g/b");
+ addMessage("s - toggle statistics display");
+ addMessage("tmin/tmag - texture min/mag filter");
+ addMessage("tpersp - texture perspective correction");
+ addMessage("tx/ty/tz - view translate x/y/z");
+ addMessage("z - zoom");
+ command = "";
+ return true;
+ } else if (command.equals("s")) {
+ mDisplayCounts = !mDisplayCounts;
+ mDisplayFPS = !mDisplayFPS;
+ command = "";
+ return true;
+ }
+
+ mParam = -1;
+ for (int i = 0; i < commands.length; i++) {
+ if (command.equals(commands[i])) {
+ mParam = i;
+ mIncr = increments[i];
+ }
+ }
+ if (mParam == -1) {
+ return true;
+ }
+
+ boolean addMessage = true;
+
+ // Increment or decrement
+ if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ||
+ keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (mParam == ZOOM_EXPONENT) {
+ params[mParam] += mIncr;
+ computeZoom();
+ } else if ((mParam == TEXTURE_MIN_FILTER) ||
+ (mParam == TEXTURE_MAG_FILTER)) {
+ toggleFilter();
+ } else if (mParam == TEXTURE_PERSPECTIVE_CORRECTION) {
+ togglePerspectiveCorrection();
+ } else {
+ params[mParam] += mIncr;
+ }
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP ||
+ keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
+ if (mParam == ZOOM_EXPONENT) {
+ params[mParam] -= mIncr;
+ computeZoom();
+ } else if ((mParam == TEXTURE_MIN_FILTER) ||
+ (mParam == TEXTURE_MAG_FILTER)) {
+ toggleFilter();
+ } else if (mParam == TEXTURE_PERSPECTIVE_CORRECTION) {
+ togglePerspectiveCorrection();
+ } else {
+ params[mParam] -= mIncr;
+ }
+ }
+
+ if (addMessage) {
+ addMessage(commands[mParam],
+ labels[mParam] + ": " + valueString());
+ }
+
+ return true;
+ }
+
+ /**
+ * Zoom in by a given number of steps. A negative value of steps
+ * zooms out. Each step zooms in by 1%.
+ *
+ * @param steps the number of steps to zoom by.
+ */
+ public void zoom(int steps) {
+ params[ZOOM_EXPONENT] += steps;
+ computeZoom();
+ }
+
+ /**
+ * Set the projection matrix using glFrustumf. The left and right
+ * clipping planes are set at -+(aspectRatio*zoom), the bottom and
+ * top clipping planes are set at -+zoom, and the near and far
+ * clipping planes are set to the values set by setNearFrustum and
+ * setFarFrustum or interactively.
+ *
+ * <p> GL side effects:
+ * <ul>
+ * <li>overwrites the matrix mode</li>
+ * <li>overwrites the projection matrix</li>
+ * </ul>
+ *
+ * @param gl a GL10 instance whose projection matrix is to be modified.
+ */
+ public void setProjection(GL10 gl) {
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+
+ if (mAspectRatio >= 1.0f) {
+ gl.glFrustumf(-mAspectRatio*mZoom, mAspectRatio*mZoom,
+ -mZoom, mZoom,
+ params[NEAR_FRUSTUM], params[FAR_FRUSTUM]);
+ } else {
+ gl.glFrustumf(-mZoom, mZoom,
+ -mZoom / mAspectRatio, mZoom / mAspectRatio,
+ params[NEAR_FRUSTUM], params[FAR_FRUSTUM]);
+ }
+ }
+
+ /**
+ * Set the modelview matrix using glLoadIdentity and glTranslatef.
+ * The translation values are set interactively.
+ *
+ * <p> GL side effects:
+ * <ul>
+ * <li>overwrites the matrix mode</li>
+ * <li>overwrites the modelview matrix</li>
+ * </ul>
+ *
+ * @param gl a GL10 instance whose modelview matrix is to be modified.
+ */
+ public void setView(GL10 gl) {
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
+ // Move the viewpoint backwards
+ gl.glTranslatef(params[TRANSLATE_X],
+ params[TRANSLATE_Y],
+ params[TRANSLATE_Z]);
+ }
+
+ /**
+ * Sets texture parameters.
+ *
+ * <p> GL side effects:
+ * <ul>
+ * <li>sets the GL_PERSPECTIVE_CORRECTION_HINT</li>
+ * <li>sets the GL_TEXTURE_MIN_FILTER texture parameter</li>
+ * <li>sets the GL_TEXTURE_MAX_FILTER texture parameter</li>
+ * </ul>
+ *
+ * @param gl a GL10 instance whose texture parameters are to be modified.
+ */
+ public void setTextureParameters(GL10 gl) {
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+ (int)params[TEXTURE_PERSPECTIVE_CORRECTION]);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D,
+ GL10.GL_TEXTURE_MIN_FILTER,
+ params[TEXTURE_MIN_FILTER]);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D,
+ GL10.GL_TEXTURE_MAG_FILTER,
+ params[TEXTURE_MAG_FILTER]);
+ }
+
+ /**
+ * Sets the lighting parameters for the given light.
+ *
+ * <p> GL side effects:
+ * <ul>
+ * <li>sets the GL_LIGHT_MODEL_AMBIENT intensities
+ * <li>sets the GL_AMBIENT intensities for the given light</li>
+ * <li>sets the GL_DIFFUSE intensities for the given light</li>
+ * <li>sets the GL_SPECULAR intensities for the given light</li>
+ * </ul>
+ *
+ * @param gl a GL10 instance whose texture parameters are to be modified.
+ */
+ public void setLights(GL10 gl, int lightNum) {
+ float[] light = new float[4];
+ light[3] = 1.0f;
+
+ float lmi = params[LIGHT_MODEL_AMBIENT_INTENSITY];
+ light[0] = params[LIGHT_MODEL_AMBIENT_RED]*lmi;
+ light[1] = params[LIGHT_MODEL_AMBIENT_GREEN]*lmi;
+ light[2] = params[LIGHT_MODEL_AMBIENT_BLUE]*lmi;
+ gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, light, 0);
+
+ float ai = params[AMBIENT_INTENSITY];
+ light[0] = params[AMBIENT_RED]*ai;
+ light[1] = params[AMBIENT_GREEN]*ai;
+ light[2] = params[AMBIENT_BLUE]*ai;
+ gl.glLightfv(lightNum, GL10.GL_AMBIENT, light, 0);
+
+ float di = params[DIFFUSE_INTENSITY];
+ light[0] = params[DIFFUSE_RED]*di;
+ light[1] = params[DIFFUSE_GREEN]*di;
+ light[2] = params[DIFFUSE_BLUE]*di;
+ gl.glLightfv(lightNum, GL10.GL_DIFFUSE, light, 0);
+
+ float si = params[SPECULAR_INTENSITY];
+ light[0] = params[SPECULAR_RED]*si;
+ light[1] = params[SPECULAR_GREEN]*si;
+ light[2] = params[SPECULAR_BLUE]*si;
+ gl.glLightfv(lightNum, GL10.GL_SPECULAR, light, 0);
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/GlobalTime.java b/samples/GlobalTime/src/com/android/globaltime/GlobalTime.java
new file mode 100644
index 0000000..d96b644
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/GlobalTime.java
@@ -0,0 +1,1488 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.microedition.khronos.egl.*;
+import javax.microedition.khronos.opengles.*;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.graphics.Canvas;
+import android.opengl.Object3D;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.MessageQueue;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+/**
+ * The main View of the GlobalTime Activity.
+ */
+class GTView extends SurfaceView implements SurfaceHolder.Callback {
+
+ /**
+ * A TimeZone object used to compute the current UTC time.
+ */
+ private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("utc");
+
+ /**
+ * The Sun's color is close to that of a 5780K blackbody.
+ */
+ private static final float[] SUNLIGHT_COLOR = {
+ 1.0f, 0.9375f, 0.91015625f, 1.0f
+ };
+
+ /**
+ * The inclination of the earth relative to the plane of the ecliptic
+ * is 23.45 degrees.
+ */
+ private static final float EARTH_INCLINATION = 23.45f * Shape.PI / 180.0f;
+
+ /** Seconds in a day */
+ private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+
+ /** Flag for the depth test */
+ private static final boolean PERFORM_DEPTH_TEST= false;
+
+ /** Use raw time zone offsets, disregarding "summer time." If false,
+ * current offsets will be used, which requires a much longer startup time
+ * in order to sort the city database.
+ */
+ private static final boolean USE_RAW_OFFSETS = true;
+
+ /**
+ * The earth's atmosphere.
+ */
+ private static final Annulus ATMOSPHERE =
+ new Annulus(0.0f, 0.0f, 1.75f, 0.9f, 1.08f, 0.4f, 0.4f, 0.8f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f, 50);
+
+ /**
+ * The tesselation of the earth by latitude.
+ */
+ private static final int SPHERE_LATITUDES = 25;
+
+ /**
+ * The tesselation of the earth by longitude.
+ */
+ private static int SPHERE_LONGITUDES = 25;
+
+ /**
+ * A flattened version of the earth. The normals are computed identically
+ * to those of the round earth, allowing the day/night lighting to be
+ * applied to the flattened surface.
+ */
+ private static Sphere worldFlat = new LatLongSphere(0.0f, 0.0f, 0.0f, 1.0f,
+ SPHERE_LATITUDES, SPHERE_LONGITUDES,
+ 0.0f, 360.0f, true, true, false, true);
+
+ /**
+ * The earth.
+ */
+ private Object3D mWorld;
+
+ /**
+ * Geometry of the city lights
+ */
+ private PointCloud mLights;
+
+ /**
+ * True if the activiy has been initialized.
+ */
+ boolean mInitialized = false;
+
+ /**
+ * True if we're in alphabetic entry mode.
+ */
+ private boolean mAlphaKeySet = false;
+
+ private EGLContext mEGLContext;
+ private EGLSurface mEGLSurface;
+ private EGLDisplay mEGLDisplay;
+ private EGLConfig mEGLConfig;
+ GLView mGLView;
+
+ // Rotation and tilt of the Earth
+ private float mRotAngle = 0.0f;
+ private float mTiltAngle = 0.0f;
+
+ // Rotational velocity of the orbiting viewer
+ private float mRotVelocity = 1.0f;
+
+ // Rotation of the flat view
+ private float mWrapX = 0.0f;
+ private float mWrapVelocity = 0.0f;
+ private float mWrapVelocityFactor = 0.01f;
+
+ // Toggle switches
+ private boolean mDisplayAtmosphere = true;
+ private boolean mDisplayClock = false;
+ private boolean mClockShowing = false;
+ private boolean mDisplayLights = false;
+ private boolean mDisplayWorld = true;
+ private boolean mDisplayWorldFlat = false;
+ private boolean mSmoothShading = true;
+
+ // City search string
+ private String mCityName = "";
+
+ // List of all cities
+ private List<City> mClockCities;
+
+ // List of cities matching a user-supplied prefix
+ private List<City> mCityNameMatches = new ArrayList<City>();
+
+ private List<City> mCities;
+
+ // Start time for clock fade animation
+ private long mClockFadeTime;
+
+ // Interpolator for clock fade animation
+ private Interpolator mClockSizeInterpolator =
+ new DecelerateInterpolator(1.0f);
+
+ // Index of current clock
+ private int mCityIndex;
+
+ // Current clock
+ private Clock mClock;
+
+ // City-to-city flight animation parameters
+ private boolean mFlyToCity = false;
+ private long mCityFlyStartTime;
+ private float mCityFlightTime;
+ private float mRotAngleStart, mRotAngleDest;
+ private float mTiltAngleStart, mTiltAngleDest;
+
+ // Interpolator for flight motion animation
+ private Interpolator mFlyToCityInterpolator =
+ new AccelerateDecelerateInterpolator();
+
+ private static int sNumLights;
+ private static int[] sLightCoords;
+
+ // static Map<Float,int[]> cityCoords = new HashMap<Float,int[]>();
+
+ // Arrays for GL calls
+ private float[] mClipPlaneEquation = new float[4];
+ private float[] mLightDir = new float[4];
+
+ // Calendar for computing the Sun's position
+ Calendar mSunCal = Calendar.getInstance(UTC_TIME_ZONE);
+
+ // Triangles drawn per frame
+ private int mNumTriangles;
+
+ private long startTime;
+
+ private static final int MOTION_NONE = 0;
+ private static final int MOTION_X = 1;
+ private static final int MOTION_Y = 2;
+
+ private static final int MIN_MANHATTAN_DISTANCE = 20;
+ private static final float ROTATION_FACTOR = 1.0f / 30.0f;
+ private static final float TILT_FACTOR = 0.35f;
+
+ // Touchscreen support
+ private float mMotionStartX;
+ private float mMotionStartY;
+ private float mMotionStartRotVelocity;
+ private float mMotionStartTiltAngle;
+ private int mMotionDirection;
+
+ private boolean mPaused = true;
+ private boolean mHaveSurface = false;
+ private boolean mStartAnimating = false;
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ mHaveSurface = true;
+ startEGL();
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ mHaveSurface = false;
+ stopEGL();
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ // nothing to do
+ }
+
+ /**
+ * Set up the view.
+ *
+ * @param context the Context
+ * @param am an AssetManager to retrieve the city database from
+ */
+ public GTView(Context context) {
+ super(context);
+
+ getHolder().addCallback(this);
+ getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
+
+ startTime = System.currentTimeMillis();
+
+ mClock = new Clock();
+
+ startEGL();
+
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ }
+
+ /**
+ * Creates an egl context. If the state of the activity is right, also
+ * creates the egl surface. Otherwise the surface will be created in a
+ * future call to createEGLSurface().
+ */
+ private void startEGL() {
+ EGL10 egl = (EGL10)EGLContext.getEGL();
+
+ if (mEGLContext == null) {
+ EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ int[] version = new int[2];
+ egl.eglInitialize(dpy, version);
+ int[] configSpec = {
+ EGL10.EGL_DEPTH_SIZE, 16,
+ EGL10.EGL_NONE
+ };
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] num_config = new int[1];
+ egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config);
+ mEGLConfig = configs[0];
+
+ mEGLContext = egl.eglCreateContext(dpy, mEGLConfig,
+ EGL10.EGL_NO_CONTEXT, null);
+ mEGLDisplay = dpy;
+
+ AssetManager am = mContext.getAssets();
+ try {
+ loadAssets(am);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ throw new RuntimeException(ioe);
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ aioobe.printStackTrace();
+ throw new RuntimeException(aioobe);
+ }
+ }
+
+ if (mEGLSurface == null && !mPaused && mHaveSurface) {
+ mEGLSurface = egl.eglCreateWindowSurface(mEGLDisplay, mEGLConfig,
+ this, null);
+ egl.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface,
+ mEGLContext);
+ mInitialized = false;
+ if (mStartAnimating) {
+ startAnimating();
+ mStartAnimating = false;
+ }
+ }
+ }
+
+ /**
+ * Destroys the egl context. If an egl surface has been created, it is
+ * destroyed as well.
+ */
+ private void stopEGL() {
+ EGL10 egl = (EGL10)EGLContext.getEGL();
+ if (mEGLSurface != null) {
+ egl.eglMakeCurrent(mEGLDisplay,
+ egl.EGL_NO_SURFACE, egl.EGL_NO_SURFACE, egl.EGL_NO_CONTEXT);
+ egl.eglDestroySurface(mEGLDisplay, mEGLSurface);
+ mEGLSurface = null;
+ }
+
+ if (mEGLContext != null) {
+ egl.eglDestroyContext(mEGLDisplay, mEGLContext);
+ egl.eglTerminate(mEGLDisplay);
+ mEGLContext = null;
+ mEGLDisplay = null;
+ mEGLConfig = null;
+ }
+ }
+
+ public void onPause() {
+ mPaused = true;
+ stopAnimating();
+ stopEGL();
+ }
+
+ public void onResume() {
+ mPaused = false;
+ startEGL();
+ }
+
+ public void destroy() {
+ stopAnimating();
+ stopEGL();
+ }
+
+ /**
+ * Begin animation.
+ */
+ public void startAnimating() {
+ if (mEGLSurface == null) {
+ mStartAnimating = true; // will start when egl surface is created
+ } else {
+ mHandler.sendEmptyMessage(INVALIDATE);
+ }
+ }
+
+ /**
+ * Quit animation.
+ */
+ public void stopAnimating() {
+ mHandler.removeMessages(INVALIDATE);
+ }
+
+ /**
+ * Read a two-byte integer from the input stream.
+ */
+ private int readInt16(InputStream is) throws IOException {
+ int lo = is.read();
+ int hi = is.read();
+ return (hi << 8) | lo;
+ }
+
+ /**
+ * Returns the offset from UTC for the given city. If USE_RAW_OFFSETS
+ * is true, summer/daylight savings is ignored.
+ */
+ private static float getOffset(City c) {
+ return USE_RAW_OFFSETS ? c.getRawOffset() : c.getOffset();
+ }
+
+ private InputStream cache(InputStream is) throws IOException {
+ int nbytes = is.available();
+ byte[] data = new byte[nbytes];
+ int nread = 0;
+ while (nread < nbytes) {
+ nread += is.read(data, nread, nbytes - nread);
+ }
+ return new ByteArrayInputStream(data);
+ }
+
+ /**
+ * Load the city and lights databases.
+ *
+ * @param am the AssetManager to load from.
+ */
+ private void loadAssets(final AssetManager am) throws IOException {
+ Locale locale = Locale.getDefault();
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+
+ InputStream cis = null;
+ try {
+ // Look for (e.g.) cities_fr_FR.dat or cities_fr_CA.dat
+ cis = am.open("cities_" + language + "_" + country + ".dat");
+ } catch (FileNotFoundException e1) {
+ try {
+ // Look for (e.g.) cities_fr.dat or cities_fr.dat
+ cis = am.open("cities_" + language + ".dat");
+ } catch (FileNotFoundException e2) {
+ try {
+ // Use English city names by default
+ cis = am.open("cities_en.dat");
+ } catch (FileNotFoundException e3) {
+ throw e3;
+ }
+ }
+ }
+
+ cis = cache(cis);
+ City.loadCities(cis);
+ City[] cities;
+ if (USE_RAW_OFFSETS) {
+ cities = City.getCitiesByRawOffset();
+ } else {
+ cities = City.getCitiesByOffset();
+ }
+
+ mClockCities = new ArrayList<City>(cities.length);
+ for (int i = 0; i < cities.length; i++) {
+ mClockCities.add(cities[i]);
+ }
+ mCities = mClockCities;
+ mCityIndex = 0;
+
+ this.mWorld = new Object3D() {
+ @Override
+ public InputStream readFile(String filename)
+ throws IOException {
+ return cache(am.open(filename));
+ }
+ };
+
+ mWorld.load("world.gles");
+
+ // lights.dat has the following format. All integers
+ // are 16 bits, low byte first.
+ //
+ // width
+ // height
+ // N [# of lights]
+ // light 0 X [in the range 0 to (width - 1)]
+ // light 0 Y ]in the range 0 to (height - 1)]
+ // light 1 X [in the range 0 to (width - 1)]
+ // light 1 Y ]in the range 0 to (height - 1)]
+ // ...
+ // light (N - 1) X [in the range 0 to (width - 1)]
+ // light (N - 1) Y ]in the range 0 to (height - 1)]
+ //
+ // For a larger number of lights, it could make more
+ // sense to store the light positions in a bitmap
+ // and extract them manually
+ InputStream lis = am.open("lights.dat");
+ lis = cache(lis);
+
+ int lightWidth = readInt16(lis);
+ int lightHeight = readInt16(lis);
+ sNumLights = readInt16(lis);
+ sLightCoords = new int[3 * sNumLights];
+
+ int lidx = 0;
+ float lightRadius = 1.009f;
+ float lightScale = 65536.0f * lightRadius;
+
+ float[] cosTheta = new float[lightWidth];
+ float[] sinTheta = new float[lightWidth];
+ float twoPi = (float) (2.0 * Math.PI);
+ float scaleW = twoPi / lightWidth;
+ for (int i = 0; i < lightWidth; i++) {
+ float theta = twoPi - i * scaleW;
+ cosTheta[i] = (float)Math.cos(theta);
+ sinTheta[i] = (float)Math.sin(theta);
+ }
+
+ float[] cosPhi = new float[lightHeight];
+ float[] sinPhi = new float[lightHeight];
+ float scaleH = (float) (Math.PI / lightHeight);
+ for (int j = 0; j < lightHeight; j++) {
+ float phi = j * scaleH;
+ cosPhi[j] = (float)Math.cos(phi);
+ sinPhi[j] = (float)Math.sin(phi);
+ }
+
+ int nbytes = 4 * sNumLights;
+ byte[] ilights = new byte[nbytes];
+ int nread = 0;
+ while (nread < nbytes) {
+ nread += lis.read(ilights, nread, nbytes - nread);
+ }
+
+ int idx = 0;
+ for (int i = 0; i < sNumLights; i++) {
+ int lx = (((ilights[idx + 1] & 0xff) << 8) |
+ (ilights[idx ] & 0xff));
+ int ly = (((ilights[idx + 3] & 0xff) << 8) |
+ (ilights[idx + 2] & 0xff));
+ idx += 4;
+
+ float sin = sinPhi[ly];
+ float x = cosTheta[lx]*sin;
+ float y = cosPhi[ly];
+ float z = sinTheta[lx]*sin;
+
+ sLightCoords[lidx++] = (int) (x * lightScale);
+ sLightCoords[lidx++] = (int) (y * lightScale);
+ sLightCoords[lidx++] = (int) (z * lightScale);
+ }
+ mLights = new PointCloud(sLightCoords);
+ }
+
+ /**
+ * Returns true if two time zone offsets are equal. We assume distinct
+ * time zone offsets will differ by at least a few minutes.
+ */
+ private boolean tzEqual(float o1, float o2) {
+ return Math.abs(o1 - o2) < 0.001;
+ }
+
+ /**
+ * Move to a different time zone.
+ *
+ * @param incr The increment between the current and future time zones.
+ */
+ private void shiftTimeZone(int incr) {
+ // If only 1 city in the current set, there's nowhere to go
+ if (mCities.size() <= 1) {
+ return;
+ }
+
+ float offset = getOffset(mCities.get(mCityIndex));
+ do {
+ mCityIndex = (mCityIndex + mCities.size() + incr) % mCities.size();
+ } while (tzEqual(getOffset(mCities.get(mCityIndex)), offset));
+
+ offset = getOffset(mCities.get(mCityIndex));
+ locateCity(true, offset);
+ goToCity();
+ }
+
+ /**
+ * Returns true if there is another city within the current time zone
+ * that is the given increment away from the current city.
+ *
+ * @param incr the increment, +1 or -1
+ * @return
+ */
+ private boolean atEndOfTimeZone(int incr) {
+ if (mCities.size() <= 1) {
+ return true;
+ }
+
+ float offset = getOffset(mCities.get(mCityIndex));
+ int nindex = (mCityIndex + mCities.size() + incr) % mCities.size();
+ if (tzEqual(getOffset(mCities.get(nindex)), offset)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Shifts cities within the current time zone.
+ *
+ * @param incr the increment, +1 or -1
+ */
+ private void shiftWithinTimeZone(int incr) {
+ float offset = getOffset(mCities.get(mCityIndex));
+ int nindex = (mCityIndex + mCities.size() + incr) % mCities.size();
+ if (tzEqual(getOffset(mCities.get(nindex)), offset)) {
+ mCityIndex = nindex;
+ goToCity();
+ }
+ }
+
+ /**
+ * Returns true if the city name matches the given prefix, ignoring spaces.
+ */
+ private boolean nameMatches(City city, String prefix) {
+ String cityName = city.getName().replaceAll("[ ]", "");
+ return prefix.regionMatches(true, 0,
+ cityName, 0,
+ prefix.length());
+ }
+
+ /**
+ * Returns true if there are cities matching the given name prefix.
+ */
+ private boolean hasMatches(String prefix) {
+ for (int i = 0; i < mClockCities.size(); i++) {
+ City city = mClockCities.get(i);
+ if (nameMatches(city, prefix)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Shifts to the nearest city that matches the new prefix.
+ */
+ private void shiftByName() {
+ // Attempt to keep current city if it matches
+ City finalCity = null;
+ City currCity = mCities.get(mCityIndex);
+ if (nameMatches(currCity, mCityName)) {
+ finalCity = currCity;
+ }
+
+ mCityNameMatches.clear();
+ for (int i = 0; i < mClockCities.size(); i++) {
+ City city = mClockCities.get(i);
+ if (nameMatches(city, mCityName)) {
+ mCityNameMatches.add(city);
+ }
+ }
+
+ mCities = mCityNameMatches;
+
+ if (finalCity != null) {
+ for (int i = 0; i < mCityNameMatches.size(); i++) {
+ if (mCityNameMatches.get(i) == finalCity) {
+ mCityIndex = i;
+ break;
+ }
+ }
+ } else {
+ // Find the closest matching city
+ locateCity(false, 0.0f);
+ }
+ goToCity();
+ }
+
+ /**
+ * Increases or decreases the rotational speed of the earth.
+ */
+ private void incrementRotationalVelocity(float incr) {
+ if (mDisplayWorldFlat) {
+ mWrapVelocity -= incr;
+ } else {
+ mRotVelocity -= incr;
+ }
+ }
+
+ /**
+ * Clears the current matching prefix, while keeping the focus on
+ * the current city.
+ */
+ private void clearCityMatches() {
+ // Determine the global city index that matches the current city
+ if (mCityNameMatches.size() > 0) {
+ City city = mCityNameMatches.get(mCityIndex);
+ for (int i = 0; i < mClockCities.size(); i++) {
+ City ncity = mClockCities.get(i);
+ if (city.equals(ncity)) {
+ mCityIndex = i;
+ break;
+ }
+ }
+ }
+
+ mCityName = "";
+ mCityNameMatches.clear();
+ mCities = mClockCities;
+ goToCity();
+ }
+
+ /**
+ * Fade the clock in or out.
+ */
+ private void enableClock(boolean enabled) {
+ mClockFadeTime = System.currentTimeMillis();
+ mDisplayClock = enabled;
+ mClockShowing = true;
+ mAlphaKeySet = enabled;
+ if (enabled) {
+ // Find the closest matching city
+ locateCity(false, 0.0f);
+ }
+ clearCityMatches();
+ }
+
+ /**
+ * Use the touchscreen to alter the rotational velocity or the
+ * tilt of the earth.
+ */
+ @Override public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mMotionStartX = event.getX();
+ mMotionStartY = event.getY();
+ mMotionStartRotVelocity = mDisplayWorldFlat ?
+ mWrapVelocity : mRotVelocity;
+ mMotionStartTiltAngle = mTiltAngle;
+
+ // Stop the rotation
+ if (mDisplayWorldFlat) {
+ mWrapVelocity = 0.0f;
+ } else {
+ mRotVelocity = 0.0f;
+ }
+ mMotionDirection = MOTION_NONE;
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ // Disregard motion events when the clock is displayed
+ float dx = event.getX() - mMotionStartX;
+ float dy = event.getY() - mMotionStartY;
+ float delx = Math.abs(dx);
+ float dely = Math.abs(dy);
+
+ // Determine the direction of motion (major axis)
+ // Once if has been determined, it's locked in until
+ // we receive ACTION_UP or ACTION_CANCEL
+ if ((mMotionDirection == MOTION_NONE) &&
+ (delx + dely > MIN_MANHATTAN_DISTANCE)) {
+ if (delx > dely) {
+ mMotionDirection = MOTION_X;
+ } else {
+ mMotionDirection = MOTION_Y;
+ }
+ }
+
+ // If the clock is displayed, don't actually rotate or tilt;
+ // just use mMotionDirection to record whether motion occurred
+ if (!mDisplayClock) {
+ if (mMotionDirection == MOTION_X) {
+ if (mDisplayWorldFlat) {
+ mWrapVelocity = mMotionStartRotVelocity +
+ dx * ROTATION_FACTOR;
+ } else {
+ mRotVelocity = mMotionStartRotVelocity +
+ dx * ROTATION_FACTOR;
+ }
+ mClock.setCity(null);
+ } else if (mMotionDirection == MOTION_Y &&
+ !mDisplayWorldFlat) {
+ mTiltAngle = mMotionStartTiltAngle + dy * TILT_FACTOR;
+ if (mTiltAngle < -90.0f) {
+ mTiltAngle = -90.0f;
+ }
+ if (mTiltAngle > 90.0f) {
+ mTiltAngle = 90.0f;
+ }
+ mClock.setCity(null);
+ }
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ mMotionDirection = MOTION_NONE;
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ mTiltAngle = mMotionStartTiltAngle;
+ if (mDisplayWorldFlat) {
+ mWrapVelocity = mMotionStartRotVelocity;
+ } else {
+ mRotVelocity = mMotionStartRotVelocity;
+ }
+ mMotionDirection = MOTION_NONE;
+ break;
+ }
+ return true;
+ }
+
+ @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (mInitialized && mGLView.processKey(keyCode)) {
+ boolean drawing = (mClockShowing || mGLView.hasMessages());
+ this.setWillNotDraw(!drawing);
+ return true;
+ }
+
+ boolean handled = false;
+
+ // If we're not in alphabetical entry mode, convert letters
+ // to their digit equivalents
+ if (!mAlphaKeySet) {
+ char numChar = event.getNumber();
+ if (numChar >= '0' && numChar <= '9') {
+ keyCode = KeyEvent.KEYCODE_0 + (numChar - '0');
+ }
+ }
+
+ switch (keyCode) {
+ // The 'space' key toggles the clock
+ case KeyEvent.KEYCODE_SPACE:
+ mAlphaKeySet = !mAlphaKeySet;
+ enableClock(mAlphaKeySet);
+ handled = true;
+ break;
+
+ // The 'left' and 'right' buttons shift time zones if the clock is
+ // displayed, otherwise they alters the rotational speed of the earthh
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (mDisplayClock) {
+ shiftTimeZone(-1);
+ } else {
+ mClock.setCity(null);
+ incrementRotationalVelocity(1.0f);
+ }
+ handled = true;
+ break;
+
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (mDisplayClock) {
+ shiftTimeZone(1);
+ } else {
+ mClock.setCity(null);
+ incrementRotationalVelocity(-1.0f);
+ }
+ handled = true;
+ break;
+
+ // The 'up' and 'down' buttons shift cities within a time zone if the
+ // clock is displayed, otherwise they tilt the earth
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (mDisplayClock) {
+ shiftWithinTimeZone(-1);
+ } else {
+ mClock.setCity(null);
+ if (!mDisplayWorldFlat) {
+ mTiltAngle += 360.0f / 48.0f;
+ }
+ }
+ handled = true;
+ break;
+
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (mDisplayClock) {
+ shiftWithinTimeZone(1);
+ } else {
+ mClock.setCity(null);
+ if (!mDisplayWorldFlat) {
+ mTiltAngle -= 360.0f / 48.0f;
+ }
+ }
+ handled = true;
+ break;
+
+ // The center key stops the earth's rotation, then toggles between the
+ // round and flat views of the earth
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if ((!mDisplayWorldFlat && mRotVelocity == 0.0f) ||
+ (mDisplayWorldFlat && mWrapVelocity == 0.0f)) {
+ mDisplayWorldFlat = !mDisplayWorldFlat;
+ } else {
+ if (mDisplayWorldFlat) {
+ mWrapVelocity = 0.0f;
+ } else {
+ mRotVelocity = 0.0f;
+ }
+ }
+ handled = true;
+ break;
+
+ // The 'L' key toggles the city lights
+ case KeyEvent.KEYCODE_L:
+ if (!mAlphaKeySet && !mDisplayWorldFlat) {
+ mDisplayLights = !mDisplayLights;
+ handled = true;
+ }
+ break;
+
+
+ // The 'W' key toggles the earth (just for fun)
+ case KeyEvent.KEYCODE_W:
+ if (!mAlphaKeySet && !mDisplayWorldFlat) {
+ mDisplayWorld = !mDisplayWorld;
+ handled = true;
+ }
+ break;
+
+ // The 'A' key toggles the atmosphere
+ case KeyEvent.KEYCODE_A:
+ if (!mAlphaKeySet && !mDisplayWorldFlat) {
+ mDisplayAtmosphere = !mDisplayAtmosphere;
+ handled = true;
+ }
+ break;
+
+ // The '2' key zooms out
+ case KeyEvent.KEYCODE_2:
+ if (!mAlphaKeySet && !mDisplayWorldFlat) {
+ mGLView.zoom(-2);
+ handled = true;
+ }
+ break;
+
+ // The '8' key zooms in
+ case KeyEvent.KEYCODE_8:
+ if (!mAlphaKeySet && !mDisplayWorldFlat) {
+ mGLView.zoom(2);
+ handled = true;
+ }
+ break;
+ }
+
+ // Handle letters in city names
+ if (!handled && mAlphaKeySet) {
+ switch (keyCode) {
+ // Add a letter to the city name prefix
+ case KeyEvent.KEYCODE_A:
+ case KeyEvent.KEYCODE_B:
+ case KeyEvent.KEYCODE_C:
+ case KeyEvent.KEYCODE_D:
+ case KeyEvent.KEYCODE_E:
+ case KeyEvent.KEYCODE_F:
+ case KeyEvent.KEYCODE_G:
+ case KeyEvent.KEYCODE_H:
+ case KeyEvent.KEYCODE_I:
+ case KeyEvent.KEYCODE_J:
+ case KeyEvent.KEYCODE_K:
+ case KeyEvent.KEYCODE_L:
+ case KeyEvent.KEYCODE_M:
+ case KeyEvent.KEYCODE_N:
+ case KeyEvent.KEYCODE_O:
+ case KeyEvent.KEYCODE_P:
+ case KeyEvent.KEYCODE_Q:
+ case KeyEvent.KEYCODE_R:
+ case KeyEvent.KEYCODE_S:
+ case KeyEvent.KEYCODE_T:
+ case KeyEvent.KEYCODE_U:
+ case KeyEvent.KEYCODE_V:
+ case KeyEvent.KEYCODE_W:
+ case KeyEvent.KEYCODE_X:
+ case KeyEvent.KEYCODE_Y:
+ case KeyEvent.KEYCODE_Z:
+ char c = (char)(keyCode - KeyEvent.KEYCODE_A + 'A');
+ if (hasMatches(mCityName + c)) {
+ mCityName += c;
+ shiftByName();
+ }
+ handled = true;
+ break;
+
+ // Remove a letter from the city name prefix
+ case KeyEvent.KEYCODE_DEL:
+ if (mCityName.length() > 0) {
+ mCityName = mCityName.substring(0, mCityName.length() - 1);
+ shiftByName();
+ } else {
+ clearCityMatches();
+ }
+ handled = true;
+ break;
+
+ // Clear the city name prefix
+ case KeyEvent.KEYCODE_ENTER:
+ clearCityMatches();
+ handled = true;
+ break;
+ }
+ }
+
+ boolean drawing = (mClockShowing ||
+ ((mGLView != null) && (mGLView.hasMessages())));
+ this.setWillNotDraw(!drawing);
+
+ // Let the system handle other keypresses
+ if (!handled) {
+ return super.onKeyDown(keyCode, event);
+ }
+ return true;
+ }
+
+ /**
+ * Initialize OpenGL ES drawing.
+ */
+ private synchronized void init(GL10 gl) {
+ mGLView = new GLView();
+ mGLView.setNearFrustum(5.0f);
+ mGLView.setFarFrustum(50.0f);
+ mGLView.setLightModelAmbientIntensity(0.225f);
+ mGLView.setAmbientIntensity(0.0f);
+ mGLView.setDiffuseIntensity(1.5f);
+ mGLView.setDiffuseColor(SUNLIGHT_COLOR);
+ mGLView.setSpecularIntensity(0.0f);
+ mGLView.setSpecularColor(SUNLIGHT_COLOR);
+
+ if (PERFORM_DEPTH_TEST) {
+ gl.glEnable(GL10.GL_DEPTH_TEST);
+ }
+ gl.glDisable(GL10.GL_SCISSOR_TEST);
+ gl.glClearColor(0, 0, 0, 1);
+ gl.glHint(GL10.GL_POINT_SMOOTH_HINT, GL10.GL_NICEST);
+
+ mInitialized = true;
+ }
+
+ /**
+ * Computes the vector from the center of the earth to the sun for a
+ * particular moment in time.
+ */
+ private void computeSunDirection() {
+ mSunCal.setTimeInMillis(System.currentTimeMillis());
+ int day = mSunCal.get(Calendar.DAY_OF_YEAR);
+ int seconds = 3600 * mSunCal.get(Calendar.HOUR_OF_DAY) +
+ 60 * mSunCal.get(Calendar.MINUTE) + mSunCal.get(Calendar.SECOND);
+ day += (float) seconds / SECONDS_PER_DAY;
+
+ // Approximate declination of the sun, changes sinusoidally
+ // during the year. The winter solstice occurs 10 days before
+ // the start of the year.
+ float decl = (float) (EARTH_INCLINATION *
+ Math.cos(Shape.TWO_PI * (day + 10) / 365.0));
+
+ // Subsolar latitude, convert from (-PI/2, PI/2) -> (0, PI) form
+ float phi = decl + Shape.PI_OVER_TWO;
+ // Subsolar longitude
+ float theta = Shape.TWO_PI * seconds / SECONDS_PER_DAY;
+
+ float sinPhi = (float) Math.sin(phi);
+ float cosPhi = (float) Math.cos(phi);
+ float sinTheta = (float) Math.sin(theta);
+ float cosTheta = (float) Math.cos(theta);
+
+ // Convert from polar to rectangular coordinates
+ float x = cosTheta * sinPhi;
+ float y = cosPhi;
+ float z = sinTheta * sinPhi;
+
+ // Directional light -> w == 0
+ mLightDir[0] = x;
+ mLightDir[1] = y;
+ mLightDir[2] = z;
+ mLightDir[3] = 0.0f;
+ }
+
+ /**
+ * Computes the approximate spherical distance between two
+ * (latitude, longitude) coordinates.
+ */
+ private float distance(float lat1, float lon1,
+ float lat2, float lon2) {
+ lat1 *= Shape.DEGREES_TO_RADIANS;
+ lat2 *= Shape.DEGREES_TO_RADIANS;
+ lon1 *= Shape.DEGREES_TO_RADIANS;
+ lon2 *= Shape.DEGREES_TO_RADIANS;
+
+ float r = 6371.0f; // Earth's radius in km
+ float dlat = lat2 - lat1;
+ float dlon = lon2 - lon1;
+ double sinlat2 = Math.sin(dlat / 2.0f);
+ sinlat2 *= sinlat2;
+ double sinlon2 = Math.sin(dlon / 2.0f);
+ sinlon2 *= sinlon2;
+
+ double a = sinlat2 + Math.cos(lat1) * Math.cos(lat2) * sinlon2;
+ double c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ return (float) (r * c);
+ }
+
+ /**
+ * Locates the closest city to the currently displayed center point,
+ * optionally restricting the search to cities within a given time zone.
+ */
+ private void locateCity(boolean useOffset, float offset) {
+ float mindist = Float.MAX_VALUE;
+ int minidx = -1;
+ for (int i = 0; i < mCities.size(); i++) {
+ City city = mCities.get(i);
+ if (useOffset && !tzEqual(getOffset(city), offset)) {
+ continue;
+ }
+ float dist = distance(city.getLatitude(), city.getLongitude(),
+ mTiltAngle, mRotAngle - 90.0f);
+ if (dist < mindist) {
+ mindist = dist;
+ minidx = i;
+ }
+ }
+
+ mCityIndex = minidx;
+ }
+
+ /**
+ * Animates the earth to be centered at the current city.
+ */
+ private void goToCity() {
+ City city = mCities.get(mCityIndex);
+ float dist = distance(city.getLatitude(), city.getLongitude(),
+ mTiltAngle, mRotAngle - 90.0f);
+
+ mFlyToCity = true;
+ mCityFlyStartTime = System.currentTimeMillis();
+ mCityFlightTime = dist / 5.0f; // 5000 km/sec
+ mRotAngleStart = mRotAngle;
+ mRotAngleDest = city.getLongitude() + 90;
+
+ if (mRotAngleDest - mRotAngleStart > 180.0f) {
+ mRotAngleDest -= 360.0f;
+ } else if (mRotAngleStart - mRotAngleDest > 180.0f) {
+ mRotAngleDest += 360.0f;
+ }
+
+ mTiltAngleStart = mTiltAngle;
+ mTiltAngleDest = city.getLatitude();
+ mRotVelocity = 0.0f;
+ }
+
+ /**
+ * Returns a linearly interpolated value between two values.
+ */
+ private float lerp(float a, float b, float lerp) {
+ return a + (b - a)*lerp;
+ }
+
+ /**
+ * Draws the city lights, using a clip plane to restrict the lights
+ * to the night side of the earth.
+ */
+ private void drawCityLights(GL10 gl, float brightness) {
+ gl.glEnable(GL10.GL_POINT_SMOOTH);
+ gl.glDisable(GL10.GL_DEPTH_TEST);
+ gl.glDisable(GL10.GL_LIGHTING);
+ gl.glDisable(GL10.GL_DITHER);
+ gl.glShadeModel(GL10.GL_FLAT);
+ gl.glEnable(GL10.GL_BLEND);
+ gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
+ gl.glPointSize(1.0f);
+
+ float ls = lerp(0.8f, 0.3f, brightness);
+ gl.glColor4f(ls * 1.0f, ls * 1.0f, ls * 0.8f, 1.0f);
+
+ if (mDisplayWorld) {
+ mClipPlaneEquation[0] = -mLightDir[0];
+ mClipPlaneEquation[1] = -mLightDir[1];
+ mClipPlaneEquation[2] = -mLightDir[2];
+ mClipPlaneEquation[3] = 0.0f;
+ // Assume we have glClipPlanef() from OpenGL ES 1.1
+ ((GL11) gl).glClipPlanef(GL11.GL_CLIP_PLANE0,
+ mClipPlaneEquation, 0);
+ gl.glEnable(GL11.GL_CLIP_PLANE0);
+ }
+ mLights.draw(gl);
+ if (mDisplayWorld) {
+ gl.glDisable(GL11.GL_CLIP_PLANE0);
+ }
+
+ mNumTriangles += mLights.getNumTriangles()*2;
+ }
+
+ /**
+ * Draws the atmosphere.
+ */
+ private void drawAtmosphere(GL10 gl) {
+ gl.glDisable(GL10.GL_LIGHTING);
+ gl.glDisable(GL10.GL_CULL_FACE);
+ gl.glDisable(GL10.GL_DITHER);
+ gl.glDisable(GL10.GL_DEPTH_TEST);
+ gl.glShadeModel(mSmoothShading ? GL10.GL_SMOOTH : GL10.GL_FLAT);
+
+ // Draw the atmospheric layer
+ float tx = mGLView.getTranslateX();
+ float ty = mGLView.getTranslateY();
+ float tz = mGLView.getTranslateZ();
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(tx, ty, tz);
+
+ // Blend in the atmosphere a bit
+ gl.glEnable(GL10.GL_BLEND);
+ gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
+ ATMOSPHERE.draw(gl);
+
+ mNumTriangles += ATMOSPHERE.getNumTriangles();
+ }
+
+ /**
+ * Draws the world in a 2D map view.
+ */
+ private void drawWorldFlat(GL10 gl) {
+ gl.glDisable(GL10.GL_BLEND);
+ gl.glEnable(GL10.GL_DITHER);
+ gl.glShadeModel(mSmoothShading ? GL10.GL_SMOOTH : GL10.GL_FLAT);
+
+ gl.glTranslatef(mWrapX - 2, 0.0f, 0.0f);
+ worldFlat.draw(gl);
+ gl.glTranslatef(2.0f, 0.0f, 0.0f);
+ worldFlat.draw(gl);
+ mNumTriangles += worldFlat.getNumTriangles() * 2;
+
+ mWrapX += mWrapVelocity * mWrapVelocityFactor;
+ while (mWrapX < 0.0f) {
+ mWrapX += 2.0f;
+ }
+ while (mWrapX > 2.0f) {
+ mWrapX -= 2.0f;
+ }
+ }
+
+ /**
+ * Draws the world in a 2D round view.
+ */
+ private void drawWorldRound(GL10 gl) {
+ gl.glDisable(GL10.GL_BLEND);
+ gl.glEnable(GL10.GL_DITHER);
+ gl.glShadeModel(mSmoothShading ? GL10.GL_SMOOTH : GL10.GL_FLAT);
+
+ mWorld.draw(gl);
+ mNumTriangles += mWorld.getNumTriangles();
+ }
+
+ /**
+ * Draws the clock.
+ *
+ * @param canvas the Canvas to draw to
+ * @param now the current time
+ * @param w the width of the screen
+ * @param h the height of the screen
+ * @param lerp controls the animation, between 0.0 and 1.0
+ */
+ private void drawClock(Canvas canvas,
+ long now,
+ int w, int h,
+ float lerp) {
+ float clockAlpha = lerp(0.0f, 0.8f, lerp);
+ mClockShowing = clockAlpha > 0.0f;
+ if (clockAlpha > 0.0f) {
+ City city = mCities.get(mCityIndex);
+ mClock.setCity(city);
+ mClock.setTime(now);
+
+ float cx = w / 2.0f;
+ float cy = h / 2.0f;
+ float smallRadius = 18.0f;
+ float bigRadius = 0.75f * 0.5f * Math.min(w, h);
+ float radius = lerp(smallRadius, bigRadius, lerp);
+
+ // Only display left/right arrows if we are in a name search
+ boolean scrollingByName =
+ (mCityName.length() > 0) && (mCities.size() > 1);
+ mClock.drawClock(canvas, cx, cy, radius,
+ clockAlpha,
+ 1.0f,
+ lerp == 1.0f, lerp == 1.0f,
+ !atEndOfTimeZone(-1),
+ !atEndOfTimeZone(1),
+ scrollingByName,
+ mCityName.length());
+ }
+ }
+
+ /**
+ * Draws the 2D layer.
+ */
+ @Override protected void onDraw(Canvas canvas) {
+ long now = System.currentTimeMillis();
+ if (startTime != -1) {
+ startTime = -1;
+ }
+
+ int w = getWidth();
+ int h = getHeight();
+
+ // Interpolator for clock size, clock alpha, night lights intensity
+ float lerp = Math.min((now - mClockFadeTime)/1000.0f, 1.0f);
+ if (!mDisplayClock) {
+ // Clock is receding
+ lerp = 1.0f - lerp;
+ }
+ lerp = mClockSizeInterpolator.getInterpolation(lerp);
+
+ // we don't need to make sure OpenGL rendering is done because
+ // we're drawing in to a different surface
+
+ drawClock(canvas, now, w, h, lerp);
+
+ mGLView.showMessages(canvas);
+ mGLView.showStatistics(canvas, w);
+ }
+
+ /**
+ * Draws the 3D layer.
+ */
+ protected void drawOpenGLScene() {
+ long now = System.currentTimeMillis();
+ mNumTriangles = 0;
+
+ EGL10 egl = (EGL10)EGLContext.getEGL();
+ GL10 gl = (GL10)mEGLContext.getGL();
+
+ if (!mInitialized) {
+ init(gl);
+ }
+
+ int w = getWidth();
+ int h = getHeight();
+ gl.glViewport(0, 0, w, h);
+
+ gl.glEnable(GL10.GL_LIGHTING);
+ gl.glEnable(GL10.GL_LIGHT0);
+ gl.glEnable(GL10.GL_CULL_FACE);
+ gl.glFrontFace(GL10.GL_CCW);
+
+ float ratio = (float) w / h;
+ mGLView.setAspectRatio(ratio);
+
+ mGLView.setTextureParameters(gl);
+
+ if (PERFORM_DEPTH_TEST) {
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ } else {
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
+ }
+
+ if (mDisplayWorldFlat) {
+ gl.glMatrixMode(GL10.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glFrustumf(-1.0f, 1.0f, -1.0f / ratio, 1.0f / ratio, 1.0f, 2.0f);
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0.0f, 0.0f, -1.0f);
+ } else {
+ mGLView.setProjection(gl);
+ mGLView.setView(gl);
+ }
+
+ if (!mDisplayWorldFlat) {
+ if (mFlyToCity) {
+ float lerp = (now - mCityFlyStartTime)/mCityFlightTime;
+ if (lerp >= 1.0f) {
+ mFlyToCity = false;
+ }
+ lerp = Math.min(lerp, 1.0f);
+ lerp = mFlyToCityInterpolator.getInterpolation(lerp);
+ mRotAngle = lerp(mRotAngleStart, mRotAngleDest, lerp);
+ mTiltAngle = lerp(mTiltAngleStart, mTiltAngleDest, lerp);
+ }
+
+ // Rotate the viewpoint around the earth
+ gl.glMatrixMode(GL10.GL_MODELVIEW);
+ gl.glRotatef(mTiltAngle, 1, 0, 0);
+ gl.glRotatef(mRotAngle, 0, 1, 0);
+
+ // Increment the rotation angle
+ mRotAngle += mRotVelocity;
+ if (mRotAngle < 0.0f) {
+ mRotAngle += 360.0f;
+ }
+ if (mRotAngle > 360.0f) {
+ mRotAngle -= 360.0f;
+ }
+ }
+
+ // Draw the world with lighting
+ gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, mLightDir, 0);
+ mGLView.setLights(gl, GL10.GL_LIGHT0);
+
+ if (mDisplayWorldFlat) {
+ drawWorldFlat(gl);
+ } else if (mDisplayWorld) {
+ drawWorldRound(gl);
+ }
+
+ if (mDisplayLights && !mDisplayWorldFlat) {
+ // Interpolator for clock size, clock alpha, night lights intensity
+ float lerp = Math.min((now - mClockFadeTime)/1000.0f, 1.0f);
+ if (!mDisplayClock) {
+ // Clock is receding
+ lerp = 1.0f - lerp;
+ }
+ lerp = mClockSizeInterpolator.getInterpolation(lerp);
+ drawCityLights(gl, lerp);
+ }
+
+ if (mDisplayAtmosphere && !mDisplayWorldFlat) {
+ drawAtmosphere(gl);
+ }
+ mGLView.setNumTriangles(mNumTriangles);
+ egl.eglSwapBuffers(mEGLDisplay, mEGLSurface);
+
+ if (egl.eglGetError() == EGL11.EGL_CONTEXT_LOST) {
+ // we lost the gpu, quit immediately
+ Context c = getContext();
+ if (c instanceof Activity) {
+ ((Activity)c).finish();
+ }
+ }
+ }
+
+
+ private static final int INVALIDATE = 1;
+ private static final int ONE_MINUTE = 60000;
+
+ /**
+ * Controls the animation using the message queue. Every time we receive
+ * an INVALIDATE message, we redraw and place another message in the queue.
+ */
+ private final Handler mHandler = new Handler() {
+ private long mLastSunPositionTime = 0;
+
+ @Override public void handleMessage(Message msg) {
+ if (msg.what == INVALIDATE) {
+
+ // Use the message's time, it's good enough and
+ // allows us to avoid a system call.
+ if ((msg.getWhen() - mLastSunPositionTime) >= ONE_MINUTE) {
+ // Recompute the sun's position once per minute
+ // Place the light at the Sun's direction
+ computeSunDirection();
+ mLastSunPositionTime = msg.getWhen();
+ }
+
+ // Draw the GL scene
+ drawOpenGLScene();
+
+ // Send an update for the 2D overlay if needed
+ if (mInitialized &&
+ (mClockShowing || mGLView.hasMessages())) {
+ invalidate();
+ }
+
+ // Just send another message immediately. This works because
+ // drawOpenGLScene() does the timing for us -- it will
+ // block until the last frame has been processed.
+ // The invalidate message we're posting here will be
+ // interleaved properly with motion/key events which
+ // guarantee a prompt reaction to the user input.
+ sendEmptyMessage(INVALIDATE);
+ }
+ }
+ };
+}
+
+/**
+ * The main activity class for GlobalTime.
+ */
+public class GlobalTime extends Activity {
+
+ GTView gtView = null;
+
+ @Override protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ gtView = new GTView(this);
+ setContentView(gtView);
+ }
+
+ @Override protected void onResume() {
+ super.onResume();
+ gtView.onResume();
+ Looper.myQueue().addIdleHandler(new Idler());
+ }
+
+ @Override protected void onPause() {
+ super.onPause();
+ gtView.onPause();
+ }
+
+ @Override protected void onStop() {
+ super.onStop();
+ gtView.destroy();
+ gtView = null;
+ }
+
+ // Allow the activity to go idle before its animation starts
+ class Idler implements MessageQueue.IdleHandler {
+ public Idler() {
+ super();
+ }
+
+ public final boolean queueIdle() {
+ if (gtView != null) {
+ gtView.startAnimating();
+ }
+ return false;
+ }
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/LatLongSphere.java b/samples/GlobalTime/src/com/android/globaltime/LatLongSphere.java
new file mode 100644
index 0000000..b455d41
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/LatLongSphere.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+public class LatLongSphere extends Sphere {
+
+ public LatLongSphere(float centerX, float centerY, float centerZ,
+ float radius, int lats, int longs,
+ float minLongitude, float maxLongitude,
+ boolean emitTextureCoordinates,
+ boolean emitNormals,
+ boolean emitColors,
+ boolean flatten) {
+ super(emitTextureCoordinates, emitNormals, emitColors);
+
+ int tris = 2 * (lats - 1) * (longs - 1);
+ int[] vertices = new int[3 * lats * longs];
+ int[] texcoords = new int[2 * lats * longs];
+ int[] colors = new int[4 * lats * longs];
+ int[] normals = new int[3 * lats * longs];
+ short[] indices = new short[3 * tris];
+
+ int vidx = 0;
+ int tidx = 0;
+ int nidx = 0;
+ int cidx = 0;
+ int iidx = 0;
+
+ minLongitude *= DEGREES_TO_RADIANS;
+ maxLongitude *= DEGREES_TO_RADIANS;
+
+ for (int i = 0; i < longs; i++) {
+ float fi = (float) i / (longs - 1);
+ // theta is the longitude
+ float theta =
+ (maxLongitude - minLongitude) * (1.0f - fi) + minLongitude;
+ float sinTheta = (float) Math.sin(theta);
+ float cosTheta = (float) Math.cos(theta);
+
+ for (int j = 0; j < lats; j++) {
+ float fj = (float) j / (lats - 1);
+ // phi is the latitude
+ float phi = PI * fj;
+ float sinPhi = (float) Math.sin(phi);
+ float cosPhi = (float) Math.cos(phi);
+ float x = cosTheta * sinPhi;
+ float y = cosPhi;
+ float z = sinTheta * sinPhi;
+
+ if (flatten) {
+ // Place vertices onto a flat projection
+ vertices[vidx++] = toFixed(2.0f * fi - 1.0f);
+ vertices[vidx++] = toFixed(0.5f - fj);
+ vertices[vidx++] = toFixed(0.0f);
+ } else {
+ // Place vertices onto the surface of a sphere
+ // with the given center and radius
+ vertices[vidx++] = toFixed(x * radius + centerX);
+ vertices[vidx++] = toFixed(y * radius + centerY);
+ vertices[vidx++] = toFixed(z * radius + centerZ);
+ }
+
+ if (emitTextureCoordinates) {
+ texcoords[tidx++] = toFixed(1.0f - (theta / (TWO_PI)));
+ texcoords[tidx++] = toFixed(fj);
+ }
+
+ if (emitNormals) {
+ float norm = 1.0f / Shape.length(x, y, z);
+ normals[nidx++] = toFixed(x * norm);
+ normals[nidx++] = toFixed(y * norm);
+ normals[nidx++] = toFixed(z * norm);
+ }
+
+ // 0 == black, 65536 == white
+ if (emitColors) {
+ colors[cidx++] = (i % 2) * 65536;
+ colors[cidx++] = 0;
+ colors[cidx++] = (j % 2) * 65536;
+ colors[cidx++] = 65536;
+ }
+ }
+ }
+
+ for (int i = 0; i < longs - 1; i++) {
+ for (int j = 0; j < lats - 1; j++) {
+ int base = i * lats + j;
+
+ // Ensure both triangles have the same final vertex
+ // since this vertex carries the color for flat
+ // shading
+ indices[iidx++] = (short) (base);
+ indices[iidx++] = (short) (base + 1);
+ indices[iidx++] = (short) (base + lats + 1);
+
+ indices[iidx++] = (short) (base + lats);
+ indices[iidx++] = (short) (base);
+ indices[iidx++] = (short) (base + lats + 1);
+ }
+ }
+
+ allocateBuffers(vertices, texcoords, normals, colors, indices);
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/PointCloud.java b/samples/GlobalTime/src/com/android/globaltime/PointCloud.java
new file mode 100644
index 0000000..6f4fd55
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/PointCloud.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A class representing a set of GL_POINT objects. GlobalTime uses this class
+ * to draw city lights on the night side of the earth.
+ */
+public class PointCloud extends Shape {
+
+ /**
+ * Constructs a PointCloud with a point at each of the given vertex
+ * (x, y, z) positions.
+ * @param vertices an array of (x, y, z) positions given in fixed-point.
+ */
+ public PointCloud(int[] vertices) {
+ this(vertices, 0, vertices.length);
+ }
+
+ /**
+ * Constructs a PointCloud with a point at each of the given vertex
+ * (x, y, z) positions.
+ * @param vertices an array of (x, y, z) positions given in fixed-point.
+ * @param off the starting offset of the vertices array
+ * @param len the number of elements of the vertices array to use
+ */
+ public PointCloud(int[] vertices, int off, int len) {
+ super(GL10.GL_POINTS, GL10.GL_UNSIGNED_SHORT,
+ false, false, false);
+
+ int numPoints = len / 3;
+ short[] indices = new short[numPoints];
+ for (int i = 0; i < numPoints; i++) {
+ indices[i] = (short)i;
+ }
+
+ allocateBuffers(vertices, null, null, null, indices);
+ this.mNumIndices = mIndexBuffer.capacity();
+ }
+
+ @Override public int getNumTriangles() {
+ return mNumIndices * 2;
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/Shape.java b/samples/GlobalTime/src/com/android/globaltime/Shape.java
new file mode 100644
index 0000000..6c296ce
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/Shape.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * An abstract superclass for various three-dimensional objects to be drawn
+ * using OpenGL ES. Each subclass is responsible for setting up NIO buffers
+ * containing vertices, texture coordinates, colors, normals, and indices.
+ * The {@link #draw(GL10)} method draws the object to the given OpenGL context.
+ */
+public abstract class Shape {
+
+ public static final int INT_BYTES = 4;
+ public static final int SHORT_BYTES = 2;
+
+ public static final float DEGREES_TO_RADIANS = (float) Math.PI / 180.0f;
+ public static final float PI = (float) Math.PI;
+ public static final float TWO_PI = (float) (2.0 * Math.PI);
+ public static final float PI_OVER_TWO = (float) (Math.PI / 2.0);
+
+ protected int mPrimitive;
+ protected int mIndexDatatype;
+
+ protected boolean mEmitTextureCoordinates;
+ protected boolean mEmitNormals;
+ protected boolean mEmitColors;
+
+ protected IntBuffer mVertexBuffer;
+ protected IntBuffer mTexcoordBuffer;
+ protected IntBuffer mColorBuffer;
+ protected IntBuffer mNormalBuffer;
+ protected Buffer mIndexBuffer;
+ protected int mNumIndices = -1;
+
+ /**
+ * Constructs a Shape.
+ *
+ * @param primitive a GL primitive type understood by glDrawElements,
+ * such as GL10.GL_TRIANGLES
+ * @param indexDatatype the GL datatype for the index buffer, such as
+ * GL10.GL_UNSIGNED_SHORT
+ * @param emitTextureCoordinates true to enable use of the texture
+ * coordinate buffer
+ * @param emitNormals true to enable use of the normal buffer
+ * @param emitColors true to enable use of the color buffer
+ */
+ protected Shape(int primitive,
+ int indexDatatype,
+ boolean emitTextureCoordinates,
+ boolean emitNormals,
+ boolean emitColors) {
+ mPrimitive = primitive;
+ mIndexDatatype = indexDatatype;
+ mEmitTextureCoordinates = emitTextureCoordinates;
+ mEmitNormals = emitNormals;
+ mEmitColors = emitColors;
+ }
+
+ /**
+ * Converts the given floating-point value to fixed-point.
+ */
+ public static int toFixed(float x) {
+ return (int) (x * 65536.0);
+ }
+
+ /**
+ * Converts the given fixed-point value to floating-point.
+ */
+ public static float toFloat(int x) {
+ return (float) (x / 65536.0);
+ }
+
+ /**
+ * Computes the cross-product of two vectors p and q and places
+ * the result in out.
+ */
+ public static void cross(float[] p, float[] q, float[] out) {
+ out[0] = p[1] * q[2] - p[2] * q[1];
+ out[1] = p[2] * q[0] - p[0] * q[2];
+ out[2] = p[0] * q[1] - p[1] * q[0];
+ }
+
+ /**
+ * Returns the length of a vector, given as three floats.
+ */
+ public static float length(float vx, float vy, float vz) {
+ return (float) Math.sqrt(vx * vx + vy * vy + vz * vz);
+ }
+
+ /**
+ * Returns the length of a vector, given as an array of three floats.
+ */
+ public static float length(float[] v) {
+ return length(v[0], v[1], v[2]);
+ }
+
+ /**
+ * Normalizes the given vector of three floats to have length == 1.0.
+ * Vectors with length zero are unaffected.
+ */
+ public static void normalize(float[] v) {
+ float length = length(v);
+ if (length != 0.0f) {
+ float norm = 1.0f / length;
+ v[0] *= norm;
+ v[1] *= norm;
+ v[2] *= norm;
+ }
+ }
+
+ /**
+ * Returns the number of triangles associated with this shape.
+ */
+ public int getNumTriangles() {
+ if (mPrimitive == GL10.GL_TRIANGLES) {
+ return mIndexBuffer.capacity() / 3;
+ } else if (mPrimitive == GL10.GL_TRIANGLE_STRIP) {
+ return mIndexBuffer.capacity() - 2;
+ }
+ return 0;
+ }
+
+ /**
+ * Copies the given data into the instance
+ * variables mVertexBuffer, mTexcoordBuffer, mNormalBuffer, mColorBuffer,
+ * and mIndexBuffer.
+ *
+ * @param vertices an array of fixed-point vertex coordinates
+ * @param texcoords an array of fixed-point texture coordinates
+ * @param normals an array of fixed-point normal vector coordinates
+ * @param colors an array of fixed-point color channel values
+ * @param indices an array of short indices
+ */
+ public void allocateBuffers(int[] vertices, int[] texcoords, int[] normals,
+ int[] colors, short[] indices) {
+ allocate(vertices, texcoords, normals, colors);
+
+ ByteBuffer ibb =
+ ByteBuffer.allocateDirect(indices.length * SHORT_BYTES);
+ ibb.order(ByteOrder.nativeOrder());
+ ShortBuffer shortIndexBuffer = ibb.asShortBuffer();
+ shortIndexBuffer.put(indices);
+ shortIndexBuffer.position(0);
+ this.mIndexBuffer = shortIndexBuffer;
+ }
+
+ /**
+ * Copies the given data into the instance
+ * variables mVertexBuffer, mTexcoordBuffer, mNormalBuffer, mColorBuffer,
+ * and mIndexBuffer.
+ *
+ * @param vertices an array of fixed-point vertex coordinates
+ * @param texcoords an array of fixed-point texture coordinates
+ * @param normals an array of fixed-point normal vector coordinates
+ * @param colors an array of fixed-point color channel values
+ * @param indices an array of int indices
+ */
+ public void allocateBuffers(int[] vertices, int[] texcoords, int[] normals,
+ int[] colors, int[] indices) {
+ allocate(vertices, texcoords, normals, colors);
+
+ ByteBuffer ibb =
+ ByteBuffer.allocateDirect(indices.length * INT_BYTES);
+ ibb.order(ByteOrder.nativeOrder());
+ IntBuffer intIndexBuffer = ibb.asIntBuffer();
+ intIndexBuffer.put(indices);
+ intIndexBuffer.position(0);
+ this.mIndexBuffer = intIndexBuffer;
+ }
+
+ /**
+ * Allocate the vertex, texture coordinate, normal, and color buffer.
+ */
+ private void allocate(int[] vertices, int[] texcoords, int[] normals,
+ int[] colors) {
+ ByteBuffer vbb =
+ ByteBuffer.allocateDirect(vertices.length * INT_BYTES);
+ vbb.order(ByteOrder.nativeOrder());
+ mVertexBuffer = vbb.asIntBuffer();
+ mVertexBuffer.put(vertices);
+ mVertexBuffer.position(0);
+
+ if ((texcoords != null) && mEmitTextureCoordinates) {
+ ByteBuffer tbb =
+ ByteBuffer.allocateDirect(texcoords.length * INT_BYTES);
+ tbb.order(ByteOrder.nativeOrder());
+ mTexcoordBuffer = tbb.asIntBuffer();
+ mTexcoordBuffer.put(texcoords);
+ mTexcoordBuffer.position(0);
+ }
+
+ if ((normals != null) && mEmitNormals) {
+ ByteBuffer nbb =
+ ByteBuffer.allocateDirect(normals.length * INT_BYTES);
+ nbb.order(ByteOrder.nativeOrder());
+ mNormalBuffer = nbb.asIntBuffer();
+ mNormalBuffer.put(normals);
+ mNormalBuffer.position(0);
+ }
+
+ if ((colors != null) && mEmitColors) {
+ ByteBuffer cbb =
+ ByteBuffer.allocateDirect(colors.length * INT_BYTES);
+ cbb.order(ByteOrder.nativeOrder());
+ mColorBuffer = cbb.asIntBuffer();
+ mColorBuffer.put(colors);
+ mColorBuffer.position(0);
+ }
+ }
+
+ /**
+ * Draws the shape to the given OpenGL ES 1.0 context. Texture coordinates,
+ * normals, and colors are emitted according the the preferences set for
+ * this shape.
+ */
+ public void draw(GL10 gl) {
+ gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+
+ if (mEmitTextureCoordinates) {
+ gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+ gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mTexcoordBuffer);
+ gl.glEnable(GL10.GL_TEXTURE_2D);
+ } else {
+ gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+ gl.glDisable(GL10.GL_TEXTURE_2D);
+ }
+
+ if (mEmitNormals) {
+ gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
+ gl.glNormalPointer(GL10.GL_FIXED, 0, mNormalBuffer);
+ } else {
+ gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
+ }
+
+ if (mEmitColors) {
+ gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+ gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
+ } else {
+ gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
+ }
+
+ gl.glDrawElements(mPrimitive,
+ mNumIndices > 0 ? mNumIndices : mIndexBuffer.capacity(),
+ mIndexDatatype,
+ mIndexBuffer);
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/Sphere.java b/samples/GlobalTime/src/com/android/globaltime/Sphere.java
new file mode 100644
index 0000000..4dff05d
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/Sphere.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import javax.microedition.khronos.opengles.GL10;
+
+public class Sphere extends Shape {
+
+ public Sphere(boolean emitTextureCoordinates,
+ boolean emitNormals, boolean emitColors) {
+ super(GL10.GL_TRIANGLES, GL10.GL_UNSIGNED_SHORT,
+ emitTextureCoordinates, emitNormals, emitColors);
+ }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/Texture.java b/samples/GlobalTime/src/com/android/globaltime/Texture.java
new file mode 100644
index 0000000..ee3af00
--- /dev/null
+++ b/samples/GlobalTime/src/com/android/globaltime/Texture.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 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.android.globaltime;
+
+import java.nio.ByteBuffer;
+
+public class Texture {
+
+ private ByteBuffer data;
+ private int width, height;
+
+ public Texture(ByteBuffer data, int width, int height) {
+ this.data = data;
+ this.width = width;
+ this.height = height;
+ }
+
+ public ByteBuffer getData() {
+ return data;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+}
diff --git a/samples/HelloActivity/Android.mk b/samples/HelloActivity/Android.mk
new file mode 100644
index 0000000..7f54bdb
--- /dev/null
+++ b/samples/HelloActivity/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := HelloActivity
+
+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/HelloActivity/AndroidManifest.xml b/samples/HelloActivity/AndroidManifest.xml
new file mode 100644
index 0000000..9551e54
--- /dev/null
+++ b/samples/HelloActivity/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.helloactivity">
+ <application android:label="Hello, Activity!">
+ <activity android:name="HelloActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/samples/HelloActivity/res/layout/hello_activity.xml b/samples/HelloActivity/res/layout/hello_activity.xml
new file mode 100644
index 0000000..2a4d2de
--- /dev/null
+++ b/samples/HelloActivity/res/layout/hello_activity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<EditText xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:textSize="18sp"
+ android:autoText="true"
+ android:capitalize="sentences"
+ android:text="@string/hello_activity_text_text" />
+
diff --git a/samples/HelloActivity/res/values/strings.xml b/samples/HelloActivity/res/values/strings.xml
new file mode 100644
index 0000000..7eab42c
--- /dev/null
+++ b/samples/HelloActivity/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="hello_activity_text_text">Hello, World!</string>
+
+</resources>
diff --git a/samples/HelloActivity/src/com/example/android/helloactivity/HelloActivity.java b/samples/HelloActivity/src/com/example/android/helloactivity/HelloActivity.java
new file mode 100644
index 0000000..62bf5ca
--- /dev/null
+++ b/samples/HelloActivity/src/com/example/android/helloactivity/HelloActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 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.helloactivity;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+
+/**
+ * A minimal "Hello, World!" application.
+ */
+public class HelloActivity extends Activity {
+ public HelloActivity() {
+ }
+
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set the layout for this activity. You can find it
+ // in res/layout/hello_activity.xml
+ setContentView(R.layout.hello_activity);
+ }
+}
+
diff --git a/samples/HelloActivity/tests/Android.mk b/samples/HelloActivity/tests/Android.mk
new file mode 100644
index 0000000..abd9a8e
--- /dev/null
+++ b/samples/HelloActivity/tests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := HelloActivityTests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := HelloActivity
+
+include $(BUILD_PACKAGE)
diff --git a/samples/HelloActivity/tests/AndroidManifest.xml b/samples/HelloActivity/tests/AndroidManifest.xml
new file mode 100644
index 0000000..5294d07
--- /dev/null
+++ b/samples/HelloActivity/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.helloactivity.tests">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.helloactivity"
+ android:label="HelloActivity sample tests">
+ </instrumentation>
+
+</manifest>
diff --git a/samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java b/samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
new file mode 100644
index 0000000..6e032da
--- /dev/null
+++ b/samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.helloactivity;
+
+import android.test.ActivityInstrumentationTestCase;
+
+import com.example.android.helloactivity.HelloActivity;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link ActivityTestCase#testActivityTestCaseSetUpProperly}.
+ */
+public class HelloActivityTest extends ActivityInstrumentationTestCase<HelloActivity> {
+
+ public HelloActivityTest() {
+ super("com.example.android.helloactivity", HelloActivity.class);
+ }
+
+}
diff --git a/samples/Home/Android.mk b/samples/Home/Android.mk
new file mode 100644
index 0000000..ddc1851
--- /dev/null
+++ b/samples/Home/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := Home
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/samples/Home/AndroidManifest.xml b/samples/Home/AndroidManifest.xml
new file mode 100644
index 0000000..229171f
--- /dev/null
+++ b/samples/Home/AndroidManifest.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/Home/AndroidManifest.xml
+**
+** Copyright 2006, 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.home">
+ <uses-permission android:name="android.permission.CALL_PHONE"/>
+ <uses-permission android:name="android.permission.GET_TASKS"/>
+ <uses-permission android:name="android.permission.READ_CONTACTS"/>
+ <uses-permission android:name="android.permission.SET_WALLPAPER" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
+
+ <application android:persistent="true"
+ android:label="@string/home_title"
+ android:icon="@drawable/ic_launcher_home">
+
+ <activity android:name="Home"
+ android:theme="@style/Theme"
+ android:launchMode="singleInstance"
+ android:stateNotNeeded="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.HOME"/>
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="Wallpaper"
+ android:label="Wallpaper"
+ android:icon="@drawable/bg_android_icon">
+ <intent-filter>
+ <action android:name="android.intent.action.SET_WALLPAPER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
diff --git a/samples/Home/MODULE_LICENSE_APACHE2 b/samples/Home/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/Home/MODULE_LICENSE_APACHE2
diff --git a/samples/Home/NOTICE b/samples/Home/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/samples/Home/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/samples/Home/res/anim/fade_in.xml b/samples/Home/res/anim/fade_in.xml
new file mode 100644
index 0000000..fe38ab1
--- /dev/null
+++ b/samples/Home/res/anim/fade_in.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="50" />
diff --git a/samples/Home/res/anim/fade_out.xml b/samples/Home/res/anim/fade_out.xml
new file mode 100644
index 0000000..64ac4f9
--- /dev/null
+++ b/samples/Home/res/anim/fade_out.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
diff --git a/samples/Home/res/anim/grid_entry.xml b/samples/Home/res/anim/grid_entry.xml
new file mode 100644
index 0000000..330c07d
--- /dev/null
+++ b/samples/Home/res/anim/grid_entry.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/fade_in.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/decelerate_interpolator">
+ <scale android:fromXScale="0.8" android:toXScale="1.0"
+ android:fromYScale="0.9" android:toYScale="1.0"
+ android:pivotX="100%" android:pivotY="100%" android:duration="200" />
+ <alpha android:fromAlpha="0.5" android:toAlpha="1.0" android:duration="200" />
+</set>
diff --git a/samples/Home/res/anim/grid_exit.xml b/samples/Home/res/anim/grid_exit.xml
new file mode 100644
index 0000000..c9baf2a
--- /dev/null
+++ b/samples/Home/res/anim/grid_exit.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
diff --git a/samples/Home/res/anim/hide_applications.xml b/samples/Home/res/anim/hide_applications.xml
new file mode 100644
index 0000000..93039a8
--- /dev/null
+++ b/samples/Home/res/anim/hide_applications.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:rowDelay="25%"
+ android:directionPriority="column"
+ android:animation="@anim/fade_out" />
diff --git a/samples/Home/res/anim/show_applications.xml b/samples/Home/res/anim/show_applications.xml
new file mode 100644
index 0000000..a97c99c
--- /dev/null
+++ b/samples/Home/res/anim/show_applications.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:rowDelay="25%"
+ android:directionPriority="column"
+ android:direction="right_to_left|bottom_to_top"
+ android:animation="@anim/fade_in" />
diff --git a/samples/Home/res/color/bright_text_dark_focused.xml b/samples/Home/res/color/bright_text_dark_focused.xml
new file mode 100644
index 0000000..3b54573
--- /dev/null
+++ b/samples/Home/res/color/bright_text_dark_focused.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="#000" />
+ <item android:state_focused="true" android:color="#000" />
+ <item android:state_pressed="true" android:color="#000" />
+ <item android:color="#FFF" />
+</selector>
+
diff --git a/samples/Home/res/drawable-land/bg_android.jpg b/samples/Home/res/drawable-land/bg_android.jpg
new file mode 100644
index 0000000..0bd005f
--- /dev/null
+++ b/samples/Home/res/drawable-land/bg_android.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-land/bg_android_icon.jpg b/samples/Home/res/drawable-land/bg_android_icon.jpg
new file mode 100644
index 0000000..2619ef9
--- /dev/null
+++ b/samples/Home/res/drawable-land/bg_android_icon.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-land/bg_sunrise.jpg b/samples/Home/res/drawable-land/bg_sunrise.jpg
new file mode 100644
index 0000000..aa5a7d1
--- /dev/null
+++ b/samples/Home/res/drawable-land/bg_sunrise.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-land/bg_sunrise_icon.jpg b/samples/Home/res/drawable-land/bg_sunrise_icon.jpg
new file mode 100644
index 0000000..4972d8d
--- /dev/null
+++ b/samples/Home/res/drawable-land/bg_sunrise_icon.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-land/bg_sunset.jpg b/samples/Home/res/drawable-land/bg_sunset.jpg
new file mode 100644
index 0000000..0fc885b
--- /dev/null
+++ b/samples/Home/res/drawable-land/bg_sunset.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-land/bg_sunset_icon.jpg b/samples/Home/res/drawable-land/bg_sunset_icon.jpg
new file mode 100644
index 0000000..939edf7
--- /dev/null
+++ b/samples/Home/res/drawable-land/bg_sunset_icon.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-port/bg_android.jpg b/samples/Home/res/drawable-port/bg_android.jpg
new file mode 100644
index 0000000..cbbf3b9
--- /dev/null
+++ b/samples/Home/res/drawable-port/bg_android.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-port/bg_android_icon.jpg b/samples/Home/res/drawable-port/bg_android_icon.jpg
new file mode 100644
index 0000000..d5742b6
--- /dev/null
+++ b/samples/Home/res/drawable-port/bg_android_icon.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-port/bg_sunrise.jpg b/samples/Home/res/drawable-port/bg_sunrise.jpg
new file mode 100644
index 0000000..a69d5da
--- /dev/null
+++ b/samples/Home/res/drawable-port/bg_sunrise.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-port/bg_sunrise_icon.jpg b/samples/Home/res/drawable-port/bg_sunrise_icon.jpg
new file mode 100644
index 0000000..96968bc
--- /dev/null
+++ b/samples/Home/res/drawable-port/bg_sunrise_icon.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-port/bg_sunset.jpg b/samples/Home/res/drawable-port/bg_sunset.jpg
new file mode 100644
index 0000000..7135bd3
--- /dev/null
+++ b/samples/Home/res/drawable-port/bg_sunset.jpg
Binary files differ
diff --git a/samples/Home/res/drawable-port/bg_sunset_icon.jpg b/samples/Home/res/drawable-port/bg_sunset_icon.jpg
new file mode 100644
index 0000000..4ced6a9
--- /dev/null
+++ b/samples/Home/res/drawable-port/bg_sunset_icon.jpg
Binary files differ
diff --git a/samples/Home/res/drawable/all_applications.xml b/samples/Home/res/drawable/all_applications.xml
new file mode 100644
index 0000000..5703c68
--- /dev/null
+++ b/samples/Home/res/drawable/all_applications.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/checkbox.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="false" android:drawable="@drawable/ic_launcher_allshow" />
+ <item android:state_checked="true" android:drawable="@drawable/ic_launcher_allhide" />
+</selector>
+
diff --git a/samples/Home/res/drawable/all_applications_background.xml b/samples/Home/res/drawable/all_applications_background.xml
new file mode 100644
index 0000000..69f5114
--- /dev/null
+++ b/samples/Home/res/drawable/all_applications_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/checkbox_background.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/all_applications_label_background" />
+</selector>
diff --git a/samples/Home/res/drawable/all_applications_button_background.xml b/samples/Home/res/drawable/all_applications_button_background.xml
new file mode 100644
index 0000000..d7bdbd8
--- /dev/null
+++ b/samples/Home/res/drawable/all_applications_button_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/checkbox.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/pressed_application_background_static" />
+ <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pressed_application_background_static" />
+ <item android:state_focused="true" android:drawable="@drawable/focused_application_background_static" />
+ <item android:state_focused="false" android:drawable="@drawable/application_background_static" />
+</selector>
+
diff --git a/samples/Home/res/drawable/all_applications_label_background.9.png b/samples/Home/res/drawable/all_applications_label_background.9.png
new file mode 100644
index 0000000..b1bf466
--- /dev/null
+++ b/samples/Home/res/drawable/all_applications_label_background.9.png
Binary files differ
diff --git a/samples/Home/res/drawable/application_background.9.png b/samples/Home/res/drawable/application_background.9.png
new file mode 100644
index 0000000..29ae09a
--- /dev/null
+++ b/samples/Home/res/drawable/application_background.9.png
Binary files differ
diff --git a/samples/Home/res/drawable/application_background_static.png b/samples/Home/res/drawable/application_background_static.png
new file mode 100644
index 0000000..9af6983
--- /dev/null
+++ b/samples/Home/res/drawable/application_background_static.png
Binary files differ
diff --git a/samples/Home/res/drawable/favorite_background.xml b/samples/Home/res/drawable/favorite_background.xml
new file mode 100644
index 0000000..6d6a69c
--- /dev/null
+++ b/samples/Home/res/drawable/favorite_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/checkbox.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/pressed_application_background_static" />
+ <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pressed_application_background_static" />
+ <item android:state_focused="true" android:drawable="@drawable/focused_application_background_static" />
+ <item android:state_focused="false" android:drawable="@android:color/transparent" />
+</selector>
diff --git a/samples/Home/res/drawable/focused_application_background_static.png b/samples/Home/res/drawable/focused_application_background_static.png
new file mode 100644
index 0000000..3a6d47c
--- /dev/null
+++ b/samples/Home/res/drawable/focused_application_background_static.png
Binary files differ
diff --git a/samples/Home/res/drawable/grid_selector.xml b/samples/Home/res/drawable/grid_selector.xml
new file mode 100644
index 0000000..1116d35
--- /dev/null
+++ b/samples/Home/res/drawable/grid_selector.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:drawable="@drawable/pressed_application_background_static" />
+ <item android:state_window_focused="false" android:drawable="@drawable/focused_application_background_static" />
+ <item android:state_window_focused="true" android:drawable="@drawable/focused_application_background_static" />
+</selector>
diff --git a/samples/Home/res/drawable/hide_all_applications.png b/samples/Home/res/drawable/hide_all_applications.png
new file mode 100644
index 0000000..a67cf78
--- /dev/null
+++ b/samples/Home/res/drawable/hide_all_applications.png
Binary files differ
diff --git a/samples/Home/res/drawable/ic_launcher_allhide.png b/samples/Home/res/drawable/ic_launcher_allhide.png
new file mode 100755
index 0000000..38e125d
--- /dev/null
+++ b/samples/Home/res/drawable/ic_launcher_allhide.png
Binary files differ
diff --git a/samples/Home/res/drawable/ic_launcher_allshow.png b/samples/Home/res/drawable/ic_launcher_allshow.png
new file mode 100755
index 0000000..5803d32
--- /dev/null
+++ b/samples/Home/res/drawable/ic_launcher_allshow.png
Binary files differ
diff --git a/samples/Home/res/drawable/ic_launcher_home.png b/samples/Home/res/drawable/ic_launcher_home.png
new file mode 100755
index 0000000..84af2a2
--- /dev/null
+++ b/samples/Home/res/drawable/ic_launcher_home.png
Binary files differ
diff --git a/samples/Home/res/drawable/pressed_application_background_static.png b/samples/Home/res/drawable/pressed_application_background_static.png
new file mode 100644
index 0000000..b086a3f
--- /dev/null
+++ b/samples/Home/res/drawable/pressed_application_background_static.png
Binary files differ
diff --git a/samples/Home/res/drawable/show_all_applications.png b/samples/Home/res/drawable/show_all_applications.png
new file mode 100644
index 0000000..ed581e1
--- /dev/null
+++ b/samples/Home/res/drawable/show_all_applications.png
Binary files differ
diff --git a/samples/Home/res/layout-land/home.xml b/samples/Home/res/layout-land/home.xml
new file mode 100644
index 0000000..d723c69
--- /dev/null
+++ b/samples/Home/res/layout-land/home.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:home="http://schemas.android.com/apk/res/com.example.android.home"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- All applications on the top side of the screen -->
+ <GridView android:id="@+id/all_apps"
+ android:background="@drawable/application_background"
+ android:persistentDrawingCache="animation|scrolling"
+ android:alwaysDrawnWithCache="true"
+ android:scrollbars="none"
+ android:drawSelectorOnTop="false"
+ android:listSelector="@drawable/grid_selector"
+ android:numColumns="auto_fit"
+ android:columnWidth="78dp"
+ android:stretchMode="spacingWidth"
+ android:layout_weight="1.0"
+ android:layout_height="0dip"
+ android:layout_width="fill_parent"
+ android:stackFromBottom="true"
+ android:visibility="invisible" />
+
+ <!-- Favorites and Recents -->
+ <com.example.android.home.ApplicationsStackLayout android:id="@+id/faves_and_recents"
+ home:stackOrientation="horizontal"
+ home:marginLeft="1dip"
+ home:marginRight="1dip"
+ android:layout_marginTop="0dip"
+ android:layout_width="fill_parent"
+ android:layout_height="65dip"
+ android:background="@drawable/application_background" />
+
+</LinearLayout>
diff --git a/samples/Home/res/layout-port/home.xml b/samples/Home/res/layout-port/home.xml
new file mode 100644
index 0000000..d723c69
--- /dev/null
+++ b/samples/Home/res/layout-port/home.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:home="http://schemas.android.com/apk/res/com.example.android.home"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <!-- All applications on the top side of the screen -->
+ <GridView android:id="@+id/all_apps"
+ android:background="@drawable/application_background"
+ android:persistentDrawingCache="animation|scrolling"
+ android:alwaysDrawnWithCache="true"
+ android:scrollbars="none"
+ android:drawSelectorOnTop="false"
+ android:listSelector="@drawable/grid_selector"
+ android:numColumns="auto_fit"
+ android:columnWidth="78dp"
+ android:stretchMode="spacingWidth"
+ android:layout_weight="1.0"
+ android:layout_height="0dip"
+ android:layout_width="fill_parent"
+ android:stackFromBottom="true"
+ android:visibility="invisible" />
+
+ <!-- Favorites and Recents -->
+ <com.example.android.home.ApplicationsStackLayout android:id="@+id/faves_and_recents"
+ home:stackOrientation="horizontal"
+ home:marginLeft="1dip"
+ home:marginRight="1dip"
+ android:layout_marginTop="0dip"
+ android:layout_width="fill_parent"
+ android:layout_height="65dip"
+ android:background="@drawable/application_background" />
+
+</LinearLayout>
diff --git a/samples/Home/res/layout/all_applications_button.xml b/samples/Home/res/layout/all_applications_button.xml
new file mode 100644
index 0000000..88430b3
--- /dev/null
+++ b/samples/Home/res/layout/all_applications_button.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/show_all_apps"
+ android:layout_width="78dip"
+ android:layout_height="65dip"
+ android:orientation="vertical"
+ android:gravity="center_vertical"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="@drawable/all_applications_button_background">
+
+ <CheckBox
+ android:id="@+id/show_all_apps_check"
+ android:focusable="false"
+ android:clickable="false"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/all_applications_background"
+ android:button="@drawable/all_applications"
+ android:text="@string/show_all_apps"
+ android:textSize="12dip"
+ android:maxLines="1"
+ android:duplicateParentState="true"
+ android:textColor="@color/bright_text_dark_focused"
+ android:gravity="center_horizontal" />
+
+</LinearLayout>
diff --git a/samples/Home/res/layout/application.xml b/samples/Home/res/layout/application.xml
new file mode 100644
index 0000000..4ddc96e
--- /dev/null
+++ b/samples/Home/res/layout/application.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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/label"
+ android:layout_width="78dip"
+ android:layout_height="65dip"
+ android:paddingTop="4dip"
+ android:textSize="12dip"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@color/bright_text_dark_focused"
+ android:gravity="center_horizontal|center_vertical" />
diff --git a/samples/Home/res/layout/favorite.xml b/samples/Home/res/layout/favorite.xml
new file mode 100644
index 0000000..e100a43
--- /dev/null
+++ b/samples/Home/res/layout/favorite.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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:layout_width="78dip"
+ android:layout_height="65dip"
+ android:paddingTop="3dip"
+ android:paddingBottom="3dip"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="@drawable/favorite_background"
+ android:textSize="12dip"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:textColor="@color/bright_text_dark_focused"
+ android:gravity="center_horizontal|bottom" />
diff --git a/samples/Home/res/layout/wallpaper.xml b/samples/Home/res/layout/wallpaper.xml
new file mode 100644
index 0000000..92dc65e
--- /dev/null
+++ b/samples/Home/res/layout/wallpaper.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/samples/SampleCode/res/layout/image_switcher_1.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="5dip"
+ android:background="#70000000"
+ android:text="@string/wallpaper_instructions"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ />
+
+ <Gallery android:id="@+id/gallery"
+ android:background="#70000000"
+ android:layout_width="fill_parent"
+ android:layout_height="60dip"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:gravity="center_vertical"
+ android:spacing="16dp"
+ />
+
+</RelativeLayout>
+
diff --git a/samples/Home/res/values-cs/strings.xml b/samples/Home/res/values-cs/strings.xml
new file mode 100644
index 0000000..2830534
--- /dev/null
+++ b/samples/Home/res/values-cs/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Domů"</string>
+ <string name="show_all_apps">"Vše"</string>
+ <string name="menu_wallpaper">"Tapeta"</string>
+ <string name="menu_search">"Hledat"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Klepnutím na obrázek nastavíte tapetu portrétu"</string>
+</resources>
diff --git a/samples/Home/res/values-de-rDE/strings.xml b/samples/Home/res/values-de-rDE/strings.xml
new file mode 100644
index 0000000..28a1b7c
--- /dev/null
+++ b/samples/Home/res/values-de-rDE/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Startseite"</string>
+ <string name="show_all_apps">"Alle"</string>
+ <string name="menu_wallpaper">"Bildschirmhintergrund"</string>
+ <string name="menu_search">"Suchen"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Tippen Sie auf Bild, um Porträt-Bildschirmhintergrund einzustellen"</string>
+</resources>
diff --git a/samples/Home/res/values-es-rUS/strings.xml b/samples/Home/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..63252cc
--- /dev/null
+++ b/samples/Home/res/values-es-rUS/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Casa"</string>
+ <string name="show_all_apps">"Todo"</string>
+ <string name="menu_wallpaper">"Papel tapiz"</string>
+ <string name="menu_search">"Búsqueda"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Puntee en la imagen para establecer papel tapiz vertical"</string>
+</resources>
diff --git a/samples/Home/res/values-land/strings.xml b/samples/Home/res/values-land/strings.xml
new file mode 100644
index 0000000..a435f41
--- /dev/null
+++ b/samples/Home/res/values-land/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <!-- Wallpaper -->
+ <string name="wallpaper_instructions">Tap image to set landscape wallpaper</string>
+</resources>
+
diff --git a/samples/Home/res/values-nl-rNL/strings.xml b/samples/Home/res/values-nl-rNL/strings.xml
new file mode 100644
index 0000000..4a5ae4f
--- /dev/null
+++ b/samples/Home/res/values-nl-rNL/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="home_title">"Start"</string>
+ <string name="show_all_apps">"Alles"</string>
+ <string name="menu_wallpaper">"Achtergrond"</string>
+ <string name="menu_search">"Zoeken"</string>
+ <!-- no translation found for menu_settings (1769059051084007158) -->
+ <skip />
+ <string name="wallpaper_instructions">"Tik op afbeelding om portretachtergrond in te stellen"</string>
+</resources>
diff --git a/samples/Home/res/values/attrs.xml b/samples/Home/res/values/attrs.xml
new file mode 100644
index 0000000..d14e4fe
--- /dev/null
+++ b/samples/Home/res/values/attrs.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2007, 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>
+ <declare-styleable name="ApplicationsStackLayout">
+ <attr name="stackOrientation">
+ <enum name="horizontal" value="0" />
+ <enum name="vertical" value="1" />
+ </attr>
+ <attr name="marginLeft" format="dimension" />
+ <attr name="marginTop" format="dimension" />
+ <attr name="marginRight" format="dimension" />
+ <attr name="marginBottom" format="dimension" />
+ </declare-styleable>
+</resources>
diff --git a/samples/Home/res/values/strings.xml b/samples/Home/res/values/strings.xml
new file mode 100644
index 0000000..f173434
--- /dev/null
+++ b/samples/Home/res/values/strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <!-- Home -->
+ <string name="home_title">Home Sample</string>
+ <string name="show_all_apps">All</string>
+
+ <!-- Home Menus -->
+ <string name="menu_wallpaper">Wallpaper</string>
+ <string name="menu_search">Search</string>
+ <string name="menu_settings">Settings</string>
+
+ <!-- Wallpaper -->
+ <string name="wallpaper_instructions">Tap picture to set portrait wallpaper</string>
+</resources>
+
diff --git a/samples/Home/res/values/styles.xml b/samples/Home/res/values/styles.xml
new file mode 100644
index 0000000..e87aa58
--- /dev/null
+++ b/samples/Home/res/values/styles.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <style name="Theme" parent="android:Theme">
+ <item name="android:windowNoTitle">true</item>
+ </style>
+</resources>
diff --git a/samples/Home/src/com/example/android/home/ApplicationInfo.java b/samples/Home/src/com/example/android/home/ApplicationInfo.java
new file mode 100644
index 0000000..79f6234
--- /dev/null
+++ b/samples/Home/src/com/example/android/home/ApplicationInfo.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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.home;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+
+/**
+ * Represents a launchable application. An application is made of a name (or title), an intent
+ * and an icon.
+ */
+class ApplicationInfo {
+ /**
+ * The application name.
+ */
+ CharSequence title;
+
+ /**
+ * The intent used to start the application.
+ */
+ Intent intent;
+
+ /**
+ * The application icon.
+ */
+ Drawable icon;
+
+ /**
+ * When set to true, indicates that the icon has been resized.
+ */
+ boolean filtered;
+
+ /**
+ * Creates the application intent based on a component name and various launch flags.
+ *
+ * @param className the class name of the component representing the intent
+ * @param launchFlags the launch flags
+ */
+ final void setActivity(ComponentName className, int launchFlags) {
+ intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setComponent(className);
+ intent.setFlags(launchFlags);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ApplicationInfo)) {
+ return false;
+ }
+
+ ApplicationInfo that = (ApplicationInfo) o;
+ return title.equals(that.title) &&
+ intent.getComponent().getClassName().equals(
+ that.intent.getComponent().getClassName());
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ result = (title != null ? title.hashCode() : 0);
+ final String name = intent.getComponent().getClassName();
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/samples/Home/src/com/example/android/home/ApplicationsStackLayout.java b/samples/Home/src/com/example/android/home/ApplicationsStackLayout.java
new file mode 100644
index 0000000..ccc1f43
--- /dev/null
+++ b/samples/Home/src/com/example/android/home/ApplicationsStackLayout.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2007 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.home;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.TextView;
+import android.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The ApplicationsStackLayout is a specialized layout used for the purpose of the home screen
+ * only. This layout stacks various icons in three distinct areas: the recents, the favorites
+ * (or faves) and the button.
+ *
+ * This layout supports two different orientations: vertical and horizontal. When horizontal,
+ * the areas are laid out this way:
+ *
+ * [RECENTS][FAVES][BUTTON]
+ *
+ * When vertical, the layout is the following:
+ *
+ * [RECENTS]
+ * [FAVES]
+ * [BUTTON]
+ *
+ * The layout operates from the "bottom up" (or from right to left.) This means that the button
+ * area will first be laid out, then the faves area, then the recents. When there are too many
+ * favorites, the recents area is not displayed.
+ *
+ * The following attributes can be set in XML:
+ *
+ * orientation: horizontal or vertical
+ * marginLeft: the left margin of each element in the stack
+ * marginTop: the top margin of each element in the stack
+ * marginRight: the right margin of each element in the stack
+ * marginBottom: the bottom margin of each element in the stack
+ */
+public class ApplicationsStackLayout extends ViewGroup implements View.OnClickListener {
+ public static final int HORIZONTAL = 0;
+ public static final int VERTICAL = 1;
+
+ private View mButton;
+ private LayoutInflater mInflater;
+
+ private int mFavoritesEnd;
+ private int mFavoritesStart;
+
+ private List<ApplicationInfo> mFavorites;
+ private List<ApplicationInfo> mRecents;
+
+ private int mOrientation = VERTICAL;
+
+ private int mMarginLeft;
+ private int mMarginTop;
+ private int mMarginRight;
+ private int mMarginBottom;
+
+ private Rect mDrawRect = new Rect();
+
+ private Drawable mBackground;
+ private int mIconSize;
+
+ public ApplicationsStackLayout(Context context) {
+ super(context);
+ initLayout();
+ }
+
+ public ApplicationsStackLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray a =
+ context.obtainStyledAttributes(attrs, R.styleable.ApplicationsStackLayout);
+
+ mOrientation = a.getInt(R.styleable.ApplicationsStackLayout_stackOrientation, VERTICAL);
+
+ mMarginLeft = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginLeft, 0);
+ mMarginTop = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginTop, 0);
+ mMarginRight = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginRight, 0);
+ mMarginBottom = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginBottom, 0);
+
+ a.recycle();
+
+ mIconSize = 42; //(int) getResources().getDimension(android.R.dimen.app_icon_size);
+
+ initLayout();
+ }
+
+ private void initLayout() {
+ mInflater = LayoutInflater.from(getContext());
+ mButton = mInflater.inflate(R.layout.all_applications_button, this, false);
+ addView(mButton);
+
+ mBackground = getBackground();
+ setBackgroundDrawable(null);
+ setWillNotDraw(false);
+ }
+
+ /**
+ * Return the current orientation, either VERTICAL (default) or HORIZONTAL.
+ *
+ * @return the stack orientation
+ */
+ public int getOrientation() {
+ return mOrientation;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ final Drawable background = mBackground;
+
+ final int right = getWidth();
+ final int bottom = getHeight();
+
+ // Draw behind recents
+ if (mOrientation == VERTICAL) {
+ mDrawRect.set(0, 0, right, mFavoritesStart);
+ } else {
+ mDrawRect.set(0, 0, mFavoritesStart, bottom);
+ }
+ background.setBounds(mDrawRect);
+ background.draw(canvas);
+
+ // Draw behind favorites
+ if (mFavoritesStart > -1) {
+ if (mOrientation == VERTICAL) {
+ mDrawRect.set(0, mFavoritesStart, right, mFavoritesEnd);
+ } else {
+ mDrawRect.set(mFavoritesStart, 0, mFavoritesEnd, bottom);
+ }
+ background.setBounds(mDrawRect);
+ background.draw(canvas);
+ }
+
+ super.onDraw(canvas);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
+ throw new IllegalStateException("ApplicationsStackLayout can only be used with "
+ + "measure spec mode=EXACTLY");
+ }
+
+ setMeasuredDimension(widthSize, heightSize);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ removeAllApplications();
+
+ LayoutParams layoutParams = mButton.getLayoutParams();
+ final int widthSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY);
+ final int heightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
+ mButton.measure(widthSpec, heightSpec);
+
+ if (mOrientation == VERTICAL) {
+ layoutVertical();
+ } else {
+ layoutHorizontal();
+ }
+ }
+
+ private void layoutVertical() {
+ int childLeft = 0;
+ int childTop = getHeight();
+
+ int childWidth = mButton.getMeasuredWidth();
+ int childHeight = mButton.getMeasuredHeight();
+
+ childTop -= childHeight + mMarginBottom;
+ mButton.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
+ childTop -= mMarginTop;
+ mFavoritesEnd = childTop - mMarginBottom;
+
+ int oldChildTop = childTop;
+ childTop = stackApplications(mFavorites, childLeft, childTop);
+ if (childTop != oldChildTop) {
+ mFavoritesStart = childTop + mMarginTop;
+ } else {
+ mFavoritesStart = -1;
+ }
+
+ stackApplications(mRecents, childLeft, childTop);
+ }
+
+ private void layoutHorizontal() {
+ int childLeft = getWidth();
+ int childTop = 0;
+
+ int childWidth = mButton.getMeasuredWidth();
+ int childHeight = mButton.getMeasuredHeight();
+
+ childLeft -= childWidth;
+ mButton.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
+ childLeft -= mMarginLeft;
+ mFavoritesEnd = childLeft - mMarginRight;
+
+ int oldChildLeft = childLeft;
+ childLeft = stackApplications(mFavorites, childLeft, childTop);
+ if (childLeft != oldChildLeft) {
+ mFavoritesStart = childLeft + mMarginLeft;
+ } else {
+ mFavoritesStart = -1;
+ }
+
+ stackApplications(mRecents, childLeft, childTop);
+ }
+
+ private int stackApplications(List<ApplicationInfo> applications, int childLeft, int childTop) {
+ LayoutParams layoutParams;
+ int widthSpec;
+ int heightSpec;
+ int childWidth;
+ int childHeight;
+
+ final boolean isVertical = mOrientation == VERTICAL;
+
+ final int count = applications.size();
+ for (int i = count - 1; i >= 0; i--) {
+ final ApplicationInfo info = applications.get(i);
+ final View view = createApplicationIcon(mInflater, this, info);
+
+ layoutParams = view.getLayoutParams();
+ widthSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY);
+ heightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
+ view.measure(widthSpec, heightSpec);
+
+ childWidth = view.getMeasuredWidth();
+ childHeight = view.getMeasuredHeight();
+
+ if (isVertical) {
+ childTop -= childHeight + mMarginBottom;
+
+ if (childTop < 0) {
+ childTop += childHeight + mMarginBottom;
+ break;
+ }
+ } else {
+ childLeft -= childWidth + mMarginRight;
+
+ if (childLeft < 0) {
+ childLeft += childWidth + mMarginRight;
+ break;
+ }
+ }
+
+ addViewInLayout(view, -1, layoutParams);
+
+ view.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
+
+ if (isVertical) {
+ childTop -= mMarginTop;
+ } else {
+ childLeft -= mMarginLeft;
+ }
+ }
+
+ return isVertical ? childTop : childLeft;
+ }
+
+ private void removeAllApplications() {
+ final int count = getChildCount();
+ for (int i = count - 1; i >= 0; i--) {
+ final View view = getChildAt(i);
+ if (view != mButton) {
+ removeViewAt(i);
+ }
+ }
+ }
+
+ private View createApplicationIcon(LayoutInflater inflater,
+ ViewGroup group, ApplicationInfo info) {
+
+ TextView textView = (TextView) inflater.inflate(R.layout.favorite, group, false);
+
+ info.icon.setBounds(0, 0, mIconSize, mIconSize);
+ textView.setCompoundDrawables(null, info.icon, null, null);
+ textView.setText(info.title);
+
+ textView.setTag(info.intent);
+ textView.setOnClickListener(this);
+
+ return textView;
+ }
+
+ /**
+ * Sets the list of favorites.
+ *
+ * @param applications the applications to put in the favorites area
+ */
+ public void setFavorites(List<ApplicationInfo> applications) {
+ mFavorites = applications;
+ requestLayout();
+ }
+
+ /**
+ * Sets the list of recents.
+ *
+ * @param applications the applications to put in the recents area
+ */
+ public void setRecents(List<ApplicationInfo> applications) {
+ mRecents = applications;
+ requestLayout();
+ }
+
+ public void onClick(View v) {
+ getContext().startActivity((Intent) v.getTag());
+ }
+}
diff --git a/samples/Home/src/com/example/android/home/Home.java b/samples/Home/src/com/example/android/home/Home.java
new file mode 100644
index 0000000..7e94cc3
--- /dev/null
+++ b/samples/Home/src/com/example/android/home/Home.java
@@ -0,0 +1,743 @@
+/*
+ * Copyright (C) 2007 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.home;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.SearchManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.ColorFilter;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.PaintDrawable;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.util.Xml;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.LayoutAnimationController;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.GridView;
+import android.widget.TextView;
+
+import java.io.IOException;
+import java.io.FileReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+public class Home extends Activity {
+ /**
+ * Tag used for logging errors.
+ */
+ private static final String LOG_TAG = "Home";
+
+ /**
+ * Keys during freeze/thaw.
+ */
+ private static final String KEY_SAVE_GRID_OPENED = "grid.opened";
+
+ private static final String DEFAULT_FAVORITES_PATH = "etc/favorites.xml";
+
+ private static final String TAG_FAVORITES = "favorites";
+ private static final String TAG_FAVORITE = "favorite";
+ private static final String TAG_PACKAGE = "package";
+ private static final String TAG_CLASS = "class";
+
+ // Identifiers for option menu items
+ private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1;
+ private static final int MENU_SEARCH = MENU_WALLPAPER_SETTINGS + 1;
+ private static final int MENU_SETTINGS = MENU_SEARCH + 1;
+
+ /**
+ * Maximum number of recent tasks to query.
+ */
+ private static final int MAX_RECENT_TASKS = 20;
+
+ private static boolean mWallpaperChecked;
+ private static ArrayList<ApplicationInfo> mApplications;
+ private static LinkedList<ApplicationInfo> mFavorites;
+
+ private final BroadcastReceiver mWallpaperReceiver = new WallpaperIntentReceiver();
+ private final BroadcastReceiver mApplicationsReceiver = new ApplicationsIntentReceiver();
+
+ private GridView mGrid;
+
+ private LayoutAnimationController mShowLayoutAnimation;
+ private LayoutAnimationController mHideLayoutAnimation;
+
+ private boolean mBlockAnimation;
+
+ private View mShowApplications;
+ private CheckBox mShowApplicationsCheck;
+
+ private ApplicationsStackLayout mApplicationsStack;
+
+ private Animation mGridEntry;
+ private Animation mGridExit;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+
+ setContentView(R.layout.home);
+
+ registerIntentReceivers();
+
+ setDefaultWallpaper();
+
+ loadApplications(true);
+
+ bindApplications();
+ bindFavorites(true);
+ bindRecents();
+ bindButtons();
+
+ mGridEntry = AnimationUtils.loadAnimation(this, R.anim.grid_entry);
+ mGridExit = AnimationUtils.loadAnimation(this, R.anim.grid_exit);
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ // Close the menu
+ if (Intent.ACTION_MAIN.equals(intent.getAction())) {
+ getWindow().closeAllPanels();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ // Remove the callback for the cached drawables or we leak
+ // the previous Home screen on orientation change
+ final int count = mApplications.size();
+ for (int i = 0; i < count; i++) {
+ mApplications.get(i).icon.setCallback(null);
+ }
+
+ unregisterReceiver(mWallpaperReceiver);
+ unregisterReceiver(mApplicationsReceiver);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ bindRecents();
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+ final boolean opened = state.getBoolean(KEY_SAVE_GRID_OPENED, false);
+ if (opened) {
+ showApplications(false);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_SAVE_GRID_OPENED, mGrid.getVisibility() == View.VISIBLE);
+ }
+
+ /**
+ * Registers various intent receivers. The current implementation registers
+ * only a wallpaper intent receiver to let other applications change the
+ * wallpaper.
+ */
+ private void registerIntentReceivers() {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
+ registerReceiver(mWallpaperReceiver, filter);
+
+ filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addDataScheme("package");
+ registerReceiver(mApplicationsReceiver, filter);
+ }
+
+ /**
+ * Creates a new appplications adapter for the grid view and registers it.
+ */
+ private void bindApplications() {
+ if (mGrid == null) {
+ mGrid = (GridView) findViewById(R.id.all_apps);
+ }
+ mGrid.setAdapter(new ApplicationsAdapter(this, mApplications));
+ mGrid.setSelection(0);
+
+ if (mApplicationsStack == null) {
+ mApplicationsStack = (ApplicationsStackLayout) findViewById(R.id.faves_and_recents);
+ }
+ }
+
+ /**
+ * Binds actions to the various buttons.
+ */
+ private void bindButtons() {
+ mShowApplications = findViewById(R.id.show_all_apps);
+ mShowApplications.setOnClickListener(new ShowApplications());
+ mShowApplicationsCheck = (CheckBox) findViewById(R.id.show_all_apps_check);
+
+ mGrid.setOnItemClickListener(new ApplicationLauncher());
+ }
+
+ /**
+ * When no wallpaper was manually set, a default wallpaper is used instead.
+ */
+ private void setDefaultWallpaper() {
+ if (!mWallpaperChecked) {
+ Drawable wallpaper = peekWallpaper();
+ if (wallpaper == null) {
+ try {
+ clearWallpaper();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Failed to clear wallpaper " + e);
+ }
+ } else {
+ getWindow().setBackgroundDrawable(new ClippedDrawable(wallpaper));
+ }
+ mWallpaperChecked = true;
+ }
+ }
+
+ /**
+ * Refreshes the favorite applications stacked over the all apps button.
+ * The number of favorites depends on the user.
+ */
+ private void bindFavorites(boolean isLaunching) {
+ if (!isLaunching || mFavorites == null) {
+
+ FileReader favReader;
+
+ // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
+ final File favFile = new File(Environment.getRootDirectory(), DEFAULT_FAVORITES_PATH);
+ try {
+ favReader = new FileReader(favFile);
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "Couldn't find or open favorites file " + favFile);
+ return;
+ }
+
+ if (mFavorites == null) {
+ mFavorites = new LinkedList<ApplicationInfo>();
+ } else {
+ mFavorites.clear();
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ final PackageManager packageManager = getPackageManager();
+
+ try {
+ final XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(favReader);
+
+ beginDocument(parser, TAG_FAVORITES);
+
+ ApplicationInfo info;
+
+ while (true) {
+ nextElement(parser);
+
+ String name = parser.getName();
+ if (!TAG_FAVORITE.equals(name)) {
+ break;
+ }
+
+ final String favoritePackage = parser.getAttributeValue(null, TAG_PACKAGE);
+ final String favoriteClass = parser.getAttributeValue(null, TAG_CLASS);
+
+ final ComponentName cn = new ComponentName(favoritePackage, favoriteClass);
+ intent.setComponent(cn);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ info = getApplicationInfo(packageManager, intent);
+ if (info != null) {
+ info.intent = intent;
+ mFavorites.addFirst(info);
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(LOG_TAG, "Got exception parsing favorites.", e);
+ } catch (IOException e) {
+ Log.w(LOG_TAG, "Got exception parsing favorites.", e);
+ }
+ }
+
+ mApplicationsStack.setFavorites(mFavorites);
+ }
+
+ private static void beginDocument(XmlPullParser parser, String firstElementName)
+ throws XmlPullParserException, IOException {
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ if (!parser.getName().equals(firstElementName)) {
+ throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
+ ", expected " + firstElementName);
+ }
+ }
+
+ private static void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty
+ }
+ }
+
+ /**
+ * Refreshes the recently launched applications stacked over the favorites. The number
+ * of recents depends on how many favorites are present.
+ */
+ private void bindRecents() {
+ final PackageManager manager = getPackageManager();
+ final ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
+ final List<ActivityManager.RecentTaskInfo> recentTasks = tasksManager.getRecentTasks(
+ MAX_RECENT_TASKS, 0);
+
+ final int count = recentTasks.size();
+ final ArrayList<ApplicationInfo> recents = new ArrayList<ApplicationInfo>();
+
+ for (int i = count - 1; i >= 0; i--) {
+ final Intent intent = recentTasks.get(i).baseIntent;
+
+ if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
+ !intent.hasCategory(Intent.CATEGORY_HOME)) {
+
+ ApplicationInfo info = getApplicationInfo(manager, intent);
+ if (info != null) {
+ info.intent = intent;
+ if (!mFavorites.contains(info)) {
+ recents.add(info);
+ }
+ }
+ }
+ }
+
+ mApplicationsStack.setRecents(recents);
+ }
+
+ private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent) {
+ final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);
+
+ if (resolveInfo == null) {
+ return null;
+ }
+
+ final ApplicationInfo info = new ApplicationInfo();
+ final ActivityInfo activityInfo = resolveInfo.activityInfo;
+ info.icon = activityInfo.loadIcon(manager);
+ if (info.title == null || info.title.length() == 0) {
+ info.title = activityInfo.loadLabel(manager);
+ }
+ if (info.title == null) {
+ info.title = "";
+ }
+ return info;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_BACK:
+ return true;
+ case KeyEvent.KEYCODE_HOME:
+ return true;
+ }
+ }
+
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper)
+ .setIcon(android.R.drawable.ic_menu_gallery)
+ .setAlphabeticShortcut('W');
+ menu.add(0, MENU_SEARCH, 0, R.string.menu_search)
+ .setIcon(android.R.drawable.ic_search_category_default)
+ .setAlphabeticShortcut(SearchManager.MENU_KEY);
+ menu.add(0, MENU_SETTINGS, 0, R.string.menu_settings)
+ .setIcon(android.R.drawable.ic_menu_preferences)
+ .setIntent(new Intent(android.provider.Settings.ACTION_SETTINGS));
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_WALLPAPER_SETTINGS:
+ startWallpaper();
+ return true;
+ case MENU_SEARCH:
+ onSearchRequested();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void startWallpaper() {
+ final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
+ startActivity(Intent.createChooser(pickWallpaper, getString(R.string.menu_wallpaper)));
+ }
+
+ /**
+ * Loads the list of installed applications in mApplications.
+ */
+ private void loadApplications(boolean isLaunching) {
+ if (isLaunching && mApplications != null) {
+ return;
+ }
+
+ PackageManager manager = getPackageManager();
+
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
+ Collections.sort(apps, new ResolveInfo.DisplayNameComparator(manager));
+
+ if (apps != null) {
+ final int count = apps.size();
+
+ if (mApplications == null) {
+ mApplications = new ArrayList<ApplicationInfo>(count);
+ }
+ mApplications.clear();
+
+ for (int i = 0; i < count; i++) {
+ ApplicationInfo application = new ApplicationInfo();
+ ResolveInfo info = apps.get(i);
+
+ application.title = info.loadLabel(manager);
+ application.setActivity(new ComponentName(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name),
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ application.icon = info.activityInfo.loadIcon(manager);
+
+ mApplications.add(application);
+ }
+ }
+ }
+
+ /**
+ * Shows all of the applications by playing an animation on the grid.
+ */
+ private void showApplications(boolean animate) {
+ if (mBlockAnimation) {
+ return;
+ }
+ mBlockAnimation = true;
+
+ mShowApplicationsCheck.toggle();
+
+ if (mShowLayoutAnimation == null) {
+ mShowLayoutAnimation = AnimationUtils.loadLayoutAnimation(
+ this, R.anim.show_applications);
+ }
+
+ // This enables a layout animation; if you uncomment this code, you need to
+ // comment the line mGrid.startAnimation() below
+// mGrid.setLayoutAnimationListener(new ShowGrid());
+// mGrid.setLayoutAnimation(mShowLayoutAnimation);
+// mGrid.startLayoutAnimation();
+
+ if (animate) {
+ mGridEntry.setAnimationListener(new ShowGrid());
+ mGrid.startAnimation(mGridEntry);
+ }
+
+ mGrid.setVisibility(View.VISIBLE);
+
+ if (!animate) {
+ mBlockAnimation = false;
+ }
+
+ // ViewDebug.startHierarchyTracing("Home", mGrid);
+ }
+
+ /**
+ * Hides all of the applications by playing an animation on the grid.
+ */
+ private void hideApplications() {
+ if (mBlockAnimation) {
+ return;
+ }
+ mBlockAnimation = true;
+
+ mShowApplicationsCheck.toggle();
+
+ if (mHideLayoutAnimation == null) {
+ mHideLayoutAnimation = AnimationUtils.loadLayoutAnimation(
+ this, R.anim.hide_applications);
+ }
+
+ mGridExit.setAnimationListener(new HideGrid());
+ mGrid.startAnimation(mGridExit);
+ mGrid.setVisibility(View.INVISIBLE);
+ mShowApplications.requestFocus();
+
+ // This enables a layout animation; if you uncomment this code, you need to
+ // comment the line mGrid.startAnimation() above
+// mGrid.setLayoutAnimationListener(new HideGrid());
+// mGrid.setLayoutAnimation(mHideLayoutAnimation);
+// mGrid.startLayoutAnimation();
+ }
+
+ /**
+ * Receives intents from other applications to change the wallpaper.
+ */
+ private class WallpaperIntentReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ getWindow().setBackgroundDrawable(new ClippedDrawable(getWallpaper()));
+ }
+ }
+
+ /**
+ * Receives notifications when applications are added/removed.
+ */
+ private class ApplicationsIntentReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ loadApplications(false);
+ bindApplications();
+ bindRecents();
+ bindFavorites(false);
+ }
+ }
+
+ /**
+ * GridView adapter to show the list of all installed applications.
+ */
+ private class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> {
+ private Rect mOldBounds = new Rect();
+
+ public ApplicationsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
+ super(context, 0, apps);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final ApplicationInfo info = mApplications.get(position);
+
+ if (convertView == null) {
+ final LayoutInflater inflater = getLayoutInflater();
+ convertView = inflater.inflate(R.layout.application, parent, false);
+ }
+
+ Drawable icon = info.icon;
+
+ if (!info.filtered) {
+ //final Resources resources = getContext().getResources();
+ int width = 42;//(int) resources.getDimension(android.R.dimen.app_icon_size);
+ int height = 42;//(int) resources.getDimension(android.R.dimen.app_icon_size);
+
+ final int iconWidth = icon.getIntrinsicWidth();
+ final int iconHeight = icon.getIntrinsicHeight();
+
+ if (icon instanceof PaintDrawable) {
+ PaintDrawable painter = (PaintDrawable) icon;
+ painter.setIntrinsicWidth(width);
+ painter.setIntrinsicHeight(height);
+ }
+
+ if (width > 0 && height > 0 && (width < iconWidth || height < iconHeight)) {
+ final float ratio = (float) iconWidth / iconHeight;
+
+ if (iconWidth > iconHeight) {
+ height = (int) (width / ratio);
+ } else if (iconHeight > iconWidth) {
+ width = (int) (height * ratio);
+ }
+
+ final Bitmap.Config c =
+ icon.getOpacity() != PixelFormat.OPAQUE ?
+ Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
+ final Bitmap thumb = Bitmap.createBitmap(width, height, c);
+ final Canvas canvas = new Canvas(thumb);
+ canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, 0));
+ // Copy the old bounds to restore them later
+ // If we were to do oldBounds = icon.getBounds(),
+ // the call to setBounds() that follows would
+ // change the same instance and we would lose the
+ // old bounds
+ mOldBounds.set(icon.getBounds());
+ icon.setBounds(0, 0, width, height);
+ icon.draw(canvas);
+ icon.setBounds(mOldBounds);
+ icon = info.icon = new BitmapDrawable(thumb);
+ info.filtered = true;
+ }
+ }
+
+ final TextView textView = (TextView) convertView.findViewById(R.id.label);
+ textView.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null);
+ textView.setText(info.title);
+
+ return convertView;
+ }
+ }
+
+ /**
+ * Shows and hides the applications grid view.
+ */
+ private class ShowApplications implements View.OnClickListener {
+ public void onClick(View v) {
+ if (mGrid.getVisibility() != View.VISIBLE) {
+ showApplications(true);
+ } else {
+ hideApplications();
+ }
+ }
+ }
+
+ /**
+ * Hides the applications grid when the layout animation is over.
+ */
+ private class HideGrid implements Animation.AnimationListener {
+ public void onAnimationStart(Animation animation) {
+ }
+
+ public void onAnimationEnd(Animation animation) {
+ mBlockAnimation = false;
+ }
+
+ public void onAnimationRepeat(Animation animation) {
+ }
+ }
+
+ /**
+ * Shows the applications grid when the layout animation is over.
+ */
+ private class ShowGrid implements Animation.AnimationListener {
+ public void onAnimationStart(Animation animation) {
+ }
+
+ public void onAnimationEnd(Animation animation) {
+ mBlockAnimation = false;
+ // ViewDebug.stopHierarchyTracing();
+ }
+
+ public void onAnimationRepeat(Animation animation) {
+ }
+ }
+
+ /**
+ * Starts the selected activity/application in the grid view.
+ */
+ private class ApplicationLauncher implements AdapterView.OnItemClickListener {
+ public void onItemClick(AdapterView parent, View v, int position, long id) {
+ ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
+ startActivity(app.intent);
+ }
+ }
+
+ /**
+ * When a drawable is attached to a View, the View gives the Drawable its dimensions
+ * by calling Drawable.setBounds(). In this application, the View that draws the
+ * wallpaper has the same size as the screen. However, the wallpaper might be larger
+ * that the screen which means it will be automatically stretched. Because stretching
+ * a bitmap while drawing it is very expensive, we use a ClippedDrawable instead.
+ * This drawable simply draws another wallpaper but makes sure it is not stretched
+ * by always giving it its intrinsic dimensions. If the wallpaper is larger than the
+ * screen, it will simply get clipped but it won't impact performance.
+ */
+ private class ClippedDrawable extends Drawable {
+ private final Drawable mWallpaper;
+
+ public ClippedDrawable(Drawable wallpaper) {
+ mWallpaper = wallpaper;
+ }
+
+ @Override
+ public void setBounds(int left, int top, int right, int bottom) {
+ super.setBounds(left, top, right, bottom);
+ // Ensure the wallpaper is as large as it really is, to avoid stretching it
+ // at drawing time
+ mWallpaper.setBounds(left, top, left + mWallpaper.getIntrinsicWidth(),
+ top + mWallpaper.getIntrinsicHeight());
+ }
+
+ public void draw(Canvas canvas) {
+ mWallpaper.draw(canvas);
+ }
+
+ public void setAlpha(int alpha) {
+ mWallpaper.setAlpha(alpha);
+ }
+
+ public void setColorFilter(ColorFilter cf) {
+ mWallpaper.setColorFilter(cf);
+ }
+
+ public int getOpacity() {
+ return mWallpaper.getOpacity();
+ }
+ }
+}
diff --git a/samples/Home/src/com/example/android/home/Wallpaper.java b/samples/Home/src/com/example/android/home/Wallpaper.java
new file mode 100644
index 0000000..3401c49
--- /dev/null
+++ b/samples/Home/src/com/example/android/home/Wallpaper.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2006 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.home;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.ImageView;
+import android.widget.Gallery.LayoutParams;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Wallpaper picker for the Home application. User can choose from
+ * a gallery of stock photos.
+ */
+public class Wallpaper extends Activity implements
+ AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+
+ private static final String LOG_TAG = "Home";
+
+ private static final Integer[] THUMB_IDS = {
+ R.drawable.bg_android_icon,
+ R.drawable.bg_sunrise_icon,
+ R.drawable.bg_sunset_icon,
+ };
+
+ private static final Integer[] IMAGE_IDS = {
+ R.drawable.bg_android,
+ R.drawable.bg_sunrise,
+ R.drawable.bg_sunset,
+ };
+
+ private Gallery mGallery;
+ private boolean mIsWallpaperSet;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ setContentView(R.layout.wallpaper);
+
+ mGallery = (Gallery) findViewById(R.id.gallery);
+ mGallery.setAdapter(new ImageAdapter(this));
+ mGallery.setOnItemSelectedListener(this);
+ mGallery.setOnItemClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mIsWallpaperSet = false;
+ }
+
+ public void onItemSelected(AdapterView parent, View v, int position, long id) {
+ getWindow().setBackgroundDrawableResource(IMAGE_IDS[position]);
+ }
+
+ public void onItemClick(AdapterView parent, View v, int position, long id) {
+ selectWallpaper(position);
+ }
+
+ /*
+ * When using touch if you tap an image it triggers both the onItemClick and
+ * the onTouchEvent causing the wallpaper to be set twice. Synchronize this
+ * method and ensure we only set the wallpaper once.
+ */
+ private synchronized void selectWallpaper(int position) {
+ if (mIsWallpaperSet) {
+ return;
+ }
+ mIsWallpaperSet = true;
+ try {
+ InputStream stream = getResources().openRawResource(IMAGE_IDS[position]);
+ setWallpaper(stream);
+ setResult(RESULT_OK);
+ finish();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Failed to set wallpaper " + e);
+ }
+ }
+
+ public void onNothingSelected(AdapterView parent) {
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ selectWallpaper(mGallery.getSelectedItemPosition());
+ return true;
+ }
+
+ public class ImageAdapter extends BaseAdapter {
+
+ private Context mContext;
+
+ public ImageAdapter(Context c) {
+ mContext = c;
+ }
+
+ public int getCount() {
+ return THUMB_IDS.length;
+ }
+
+ public Object getItem(int position) {
+ return position;
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ ImageView i = new ImageView(mContext);
+
+ i.setImageResource(THUMB_IDS[position]);
+ i.setAdjustViewBounds(true);
+ i.setLayoutParams(new Gallery.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ i.setBackgroundResource(android.R.drawable.picture_frame);
+ return i;
+ }
+
+ }
+
+}
+
+
diff --git a/samples/LunarLander/Android.mk b/samples/LunarLander/Android.mk
new file mode 100644
index 0000000..8aa11c8
--- /dev/null
+++ b/samples/LunarLander/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := LunarLander
+
+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/LunarLander/AndroidManifest.xml b/samples/LunarLander/AndroidManifest.xml
new file mode 100644
index 0000000..7fdc572
--- /dev/null
+++ b/samples/LunarLander/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.lunarlander">
+ <application android:icon="@drawable/app_lunar_lander" android:label="@string/app_name">
+ <activity android:name="LunarLander">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/samples/LunarLander/_index.html b/samples/LunarLander/_index.html
new file mode 100644
index 0000000..02daeef
--- /dev/null
+++ b/samples/LunarLander/_index.html
@@ -0,0 +1,12 @@
+<p>A sample game. Your objective: to land on the moon.
+It demonstrates...
+<ul>
+<li>loading and drawing resources
+<li>taking keystrokes
+<li>animating by calling invalidate() from draw()
+<li>handling onPause() in an animation
+<li>and many other goodies...
+</ul>
+</p>
+
+<img height="220px" width="320px" alt="Lunar Lander Example" class="gallery" src="sample_lunarlander.png" >
\ No newline at end of file
diff --git a/samples/LunarLander/res/drawable-land/earthrise.png b/samples/LunarLander/res/drawable-land/earthrise.png
new file mode 100644
index 0000000..e2ecdc5
--- /dev/null
+++ b/samples/LunarLander/res/drawable-land/earthrise.png
Binary files differ
diff --git a/samples/LunarLander/res/drawable-port/earthrise.png b/samples/LunarLander/res/drawable-port/earthrise.png
new file mode 100644
index 0000000..a13836c
--- /dev/null
+++ b/samples/LunarLander/res/drawable-port/earthrise.png
Binary files differ
diff --git a/samples/LunarLander/res/drawable/app_lunar_lander.png b/samples/LunarLander/res/drawable/app_lunar_lander.png
new file mode 100644
index 0000000..7557b8c
--- /dev/null
+++ b/samples/LunarLander/res/drawable/app_lunar_lander.png
Binary files differ
diff --git a/samples/LunarLander/res/drawable/lander_crashed.png b/samples/LunarLander/res/drawable/lander_crashed.png
new file mode 100644
index 0000000..a73c015
--- /dev/null
+++ b/samples/LunarLander/res/drawable/lander_crashed.png
Binary files differ
diff --git a/samples/LunarLander/res/drawable/lander_firing.png b/samples/LunarLander/res/drawable/lander_firing.png
new file mode 100644
index 0000000..91378de
--- /dev/null
+++ b/samples/LunarLander/res/drawable/lander_firing.png
Binary files differ
diff --git a/samples/LunarLander/res/drawable/lander_plain.png b/samples/LunarLander/res/drawable/lander_plain.png
new file mode 100644
index 0000000..da448e4
--- /dev/null
+++ b/samples/LunarLander/res/drawable/lander_plain.png
Binary files differ
diff --git a/samples/LunarLander/res/layout/lunar_layout.xml b/samples/LunarLander/res/layout/lunar_layout.xml
new file mode 100644
index 0000000..9ad0536
--- /dev/null
+++ b/samples/LunarLander/res/layout/lunar_layout.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="fill_parent"
+ android:layout_height="fill_parent">
+
+ <com.example.android.lunarlander.LunarView
+ android:id="@+id/lunar"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"/>
+
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+ <TextView
+ android:id="@+id/text"
+ android:text="@string/lunar_layout_text_text"
+ android:visibility="visible"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:gravity="center_horizontal"
+ android:textColor="#88ffffff"
+ android:textSize="24sp"/>
+ </RelativeLayout>
+
+</FrameLayout>
diff --git a/samples/LunarLander/res/values/strings.xml b/samples/LunarLander/res/values/strings.xml
new file mode 100644
index 0000000..ac81847
--- /dev/null
+++ b/samples/LunarLander/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="app_name">Lunar Lander</string>
+
+ <string name="menu_start">Start</string>
+ <string name="menu_stop">Stop</string>
+ <string name="menu_pause">Pause</string>
+ <string name="menu_resume">Resume</string>
+ <string name="menu_easy">Easy</string>
+ <string name="menu_medium">Medium</string>
+ <string name="menu_hard">Hard</string>
+
+ <string name="mode_ready">Lunar Lander\nPress Up To Play</string>
+ <string name="mode_pause">Paused\nPress Up To Resume</string>
+ <string name="mode_lose">Game Over\nPress Up To Play</string>
+ <string name="mode_win_prefix">Success!\n</string>
+ <string name="mode_win_suffix">in a row\nPress Up to Play</string>
+
+ <string name="message_stopped">Stopped</string>
+ <string name="message_off_pad">Off Landing Pad</string>
+ <string name="message_too_fast">Too Fast</string>
+ <string name="message_bad_angle">Bad Angle</string>
+
+ <string name="lunar_layout_text_text"></string>
+</resources>
diff --git a/samples/LunarLander/sample_lunarlander.png b/samples/LunarLander/sample_lunarlander.png
new file mode 100644
index 0000000..ea1ef14
--- /dev/null
+++ b/samples/LunarLander/sample_lunarlander.png
Binary files differ
diff --git a/samples/LunarLander/src/com/example/android/lunarlander/LunarLander.java b/samples/LunarLander/src/com/example/android/lunarlander/LunarLander.java
new file mode 100644
index 0000000..7f54ff6
--- /dev/null
+++ b/samples/LunarLander/src/com/example/android/lunarlander/LunarLander.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2007 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.lunarlander;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Window;
+import android.widget.TextView;
+
+import com.example.android.lunarlander.LunarView.LunarThread;
+
+/**
+ * This is a simple LunarLander activity that houses a single LunarView. It
+ * demonstrates...
+ * <ul>
+ * <li>animating by calling invalidate() from draw()
+ * <li>loading and drawing resources
+ * <li>handling onPause() in an animation
+ * </ul>
+ */
+public class LunarLander extends Activity {
+ private static final int MENU_EASY = 1;
+
+ private static final int MENU_HARD = 2;
+
+ private static final int MENU_MEDIUM = 3;
+
+ private static final int MENU_PAUSE = 4;
+
+ private static final int MENU_RESUME = 5;
+
+ private static final int MENU_START = 6;
+
+ private static final int MENU_STOP = 7;
+
+ /** A handle to the thread that's actually running the animation. */
+ private LunarThread mLunarThread;
+
+ /** A handle to the View in which the game is running. */
+ private LunarView mLunarView;
+
+ /**
+ * Invoked during init to give the Activity a chance to set up its Menu.
+ *
+ * @param menu the Menu to which entries may be added
+ * @return true
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, MENU_START, 0, R.string.menu_start);
+ menu.add(0, MENU_STOP, 0, R.string.menu_stop);
+ menu.add(0, MENU_PAUSE, 0, R.string.menu_pause);
+ menu.add(0, MENU_RESUME, 0, R.string.menu_resume);
+ menu.add(0, MENU_EASY, 0, R.string.menu_easy);
+ menu.add(0, MENU_MEDIUM, 0, R.string.menu_medium);
+ menu.add(0, MENU_HARD, 0, R.string.menu_hard);
+
+ return true;
+ }
+
+ /**
+ * Invoked when the user selects an item from the Menu.
+ *
+ * @param item the Menu entry which was selected
+ * @return true if the Menu item was legit (and we consumed it), false
+ * otherwise
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_START:
+ mLunarThread.doStart();
+ return true;
+ case MENU_STOP:
+ mLunarThread.setState(LunarThread.STATE_LOSE,
+ getText(R.string.message_stopped));
+ return true;
+ case MENU_PAUSE:
+ mLunarThread.pause();
+ return true;
+ case MENU_RESUME:
+ mLunarThread.unpause();
+ return true;
+ case MENU_EASY:
+ mLunarThread.setDifficulty(LunarThread.DIFFICULTY_EASY);
+ return true;
+ case MENU_MEDIUM:
+ mLunarThread.setDifficulty(LunarThread.DIFFICULTY_MEDIUM);
+ return true;
+ case MENU_HARD:
+ mLunarThread.setDifficulty(LunarThread.DIFFICULTY_HARD);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Invoked when the Activity is created.
+ *
+ * @param savedInstanceState a Bundle containing state saved from a previous
+ * execution, or null if this is a new execution
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // turn off the window's title bar
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ // tell system to use the layout defined in our XML file
+ setContentView(R.layout.lunar_layout);
+
+ // get handles to the LunarView from XML, and its LunarThread
+ mLunarView = (LunarView) findViewById(R.id.lunar);
+ mLunarThread = mLunarView.getThread();
+
+ // give the LunarView a handle to the TextView used for messages
+ mLunarView.setTextView((TextView) findViewById(R.id.text));
+
+ if (savedInstanceState == null) {
+ // we were just launched: set up a new game
+ mLunarThread.setState(LunarThread.STATE_READY);
+ Log.w(this.getClass().getName(), "SIS is null");
+ } else {
+ // we are being restored: resume a previous game
+ mLunarThread.restoreState(savedInstanceState);
+ Log.w(this.getClass().getName(), "SIS is nonnull");
+ }
+ }
+
+ /**
+ * Invoked when the Activity loses user focus.
+ */
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mLunarView.getThread().pause(); // pause game when Activity pauses
+ }
+
+ /**
+ * Notification that something is about to happen, to give the Activity a
+ * chance to save state.
+ *
+ * @param outState a Bundle into which this Activity should save its state
+ */
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ // just have the View's thread save its state into our Bundle
+ super.onSaveInstanceState(outState);
+ mLunarThread.saveState(outState);
+ Log.w(this.getClass().getName(), "SIS called");
+ }
+}
diff --git a/samples/LunarLander/src/com/example/android/lunarlander/LunarView.java b/samples/LunarLander/src/com/example/android/lunarlander/LunarView.java
new file mode 100644
index 0000000..c52c7ab
--- /dev/null
+++ b/samples/LunarLander/src/com/example/android/lunarlander/LunarView.java
@@ -0,0 +1,885 @@
+/*
+ * Copyright (C) 2007 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.lunarlander;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.widget.TextView;
+
+
+/**
+ * View that draws, takes keystrokes, etc. for a simple LunarLander game.
+ *
+ * Has a mode which RUNNING, PAUSED, etc. Has a x, y, dx, dy, ... capturing the
+ * current ship physics. All x/y etc. are measured with (0,0) at the lower left.
+ * updatePhysics() advances the physics based on realtime. draw() renders the
+ * ship, and does an invalidate() to prompt another draw() as soon as possible
+ * by the system.
+ */
+class LunarView extends SurfaceView implements SurfaceHolder.Callback {
+ class LunarThread extends Thread {
+ /*
+ * Difficulty setting constants
+ */
+ public static final int DIFFICULTY_EASY = 0;
+ public static final int DIFFICULTY_HARD = 1;
+ public static final int DIFFICULTY_MEDIUM = 2;
+ /*
+ * Physics constants
+ */
+ public static final int PHYS_DOWN_ACCEL_SEC = 35;
+ public static final int PHYS_FIRE_ACCEL_SEC = 80;
+ public static final int PHYS_FUEL_INIT = 60;
+ public static final int PHYS_FUEL_MAX = 100;
+ public static final int PHYS_FUEL_SEC = 10;
+ public static final int PHYS_SLEW_SEC = 120; // degrees/second rotate
+ public static final int PHYS_SPEED_HYPERSPACE = 180;
+ public static final int PHYS_SPEED_INIT = 30;
+ public static final int PHYS_SPEED_MAX = 120;
+ /*
+ * State-tracking constants
+ */
+ public static final int STATE_LOSE = 1;
+ public static final int STATE_PAUSE = 2;
+ public static final int STATE_READY = 3;
+ public static final int STATE_RUNNING = 4;
+ public static final int STATE_WIN = 5;
+
+ /*
+ * Goal condition constants
+ */
+ public static final int TARGET_ANGLE = 18; // > this angle means crash
+ public static final int TARGET_BOTTOM_PADDING = 17; // px below gear
+ public static final int TARGET_PAD_HEIGHT = 8; // how high above ground
+ public static final int TARGET_SPEED = 28; // > this speed means crash
+ public static final double TARGET_WIDTH = 1.6; // width of target
+ /*
+ * UI constants (i.e. the speed & fuel bars)
+ */
+ public static final int UI_BAR = 100; // width of the bar(s)
+ public static final int UI_BAR_HEIGHT = 10; // height of the bar(s)
+ private static final String KEY_DIFFICULTY = "mDifficulty";
+ private static final String KEY_DX = "mDX";
+
+ private static final String KEY_DY = "mDY";
+ private static final String KEY_FUEL = "mFuel";
+ private static final String KEY_GOAL_ANGLE = "mGoalAngle";
+ private static final String KEY_GOAL_SPEED = "mGoalSpeed";
+ private static final String KEY_GOAL_WIDTH = "mGoalWidth";
+
+ private static final String KEY_GOAL_X = "mGoalX";
+ private static final String KEY_HEADING = "mHeading";
+ private static final String KEY_LANDER_HEIGHT = "mLanderHeight";
+ private static final String KEY_LANDER_WIDTH = "mLanderWidth";
+ private static final String KEY_WINS = "mWinsInARow";
+
+ private static final String KEY_X = "mX";
+ private static final String KEY_Y = "mY";
+
+ /*
+ * Member (state) fields
+ */
+ /** The drawable to use as the background of the animation canvas */
+ private Bitmap mBackgroundImage;
+
+ /**
+ * Current height of the surface/canvas.
+ *
+ * @see #setSurfaceSize
+ */
+ private int mCanvasHeight = 1;
+
+ /**
+ * Current width of the surface/canvas.
+ *
+ * @see #setSurfaceSize
+ */
+ private int mCanvasWidth = 1;
+
+ /** What to draw for the Lander when it has crashed */
+ private Drawable mCrashedImage;
+
+ /**
+ * Current difficulty -- amount of fuel, allowed angle, etc. Default is
+ * MEDIUM.
+ */
+ private int mDifficulty;
+
+ /** Velocity dx. */
+ private double mDX;
+
+ /** Velocity dy. */
+ private double mDY;
+
+ /** Is the engine burning? */
+ private boolean mEngineFiring;
+
+ /** What to draw for the Lander when the engine is firing */
+ private Drawable mFiringImage;
+
+ /** Fuel remaining */
+ private double mFuel;
+
+ /** Allowed angle. */
+ private int mGoalAngle;
+
+ /** Allowed speed. */
+ private int mGoalSpeed;
+
+ /** Width of the landing pad. */
+ private int mGoalWidth;
+
+ /** X of the landing pad. */
+ private int mGoalX;
+
+ /** Message handler used by thread to interact with TextView */
+ private Handler mHandler;
+
+ /**
+ * Lander heading in degrees, with 0 up, 90 right. Kept in the range
+ * 0..360.
+ */
+ private double mHeading;
+
+ /** Pixel height of lander image. */
+ private int mLanderHeight;
+
+ /** What to draw for the Lander in its normal state */
+ private Drawable mLanderImage;
+
+ /** Pixel width of lander image. */
+ private int mLanderWidth;
+
+ /** Used to figure out elapsed time between frames */
+ private long mLastTime;
+
+ /** Paint to draw the lines on screen. */
+ private Paint mLinePaint;
+
+ /** "Bad" speed-too-high variant of the line color. */
+ private Paint mLinePaintBad;
+
+ /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */
+ private int mMode;
+
+ /** Currently rotating, -1 left, 0 none, 1 right. */
+ private int mRotating;
+
+ /** Indicate whether the surface has been created & is ready to draw */
+ private boolean mRun = false;
+
+ /** Scratch rect object. */
+ private RectF mScratchRect;
+
+ /** Handle to the surface manager object we interact with */
+ private SurfaceHolder mSurfaceHolder;
+
+ /** Number of wins in a row. */
+ private int mWinsInARow;
+
+ /** X of lander center. */
+ private double mX;
+
+ /** Y of lander center. */
+ private double mY;
+
+ public LunarThread(SurfaceHolder surfaceHolder, Context context,
+ Handler handler) {
+ // get handles to some important objects
+ mSurfaceHolder = surfaceHolder;
+ mHandler = handler;
+ mContext = context;
+
+ Resources res = context.getResources();
+ // cache handles to our key sprites & other drawables
+ mLanderImage = context.getResources().getDrawable(
+ R.drawable.lander_plain);
+ mFiringImage = context.getResources().getDrawable(
+ R.drawable.lander_firing);
+ mCrashedImage = context.getResources().getDrawable(
+ R.drawable.lander_crashed);
+
+ // load background image as a Bitmap instead of a Drawable b/c
+ // we don't need to transform it and it's faster to draw this way
+ mBackgroundImage = BitmapFactory.decodeResource(res,
+ R.drawable.earthrise);
+
+ // Use the regular lander image as the model size for all sprites
+ mLanderWidth = mLanderImage.getIntrinsicWidth();
+ mLanderHeight = mLanderImage.getIntrinsicHeight();
+
+ // Initialize paints for speedometer
+ mLinePaint = new Paint();
+ mLinePaint.setAntiAlias(true);
+ mLinePaint.setARGB(255, 0, 255, 0);
+
+ mLinePaintBad = new Paint();
+ mLinePaintBad.setAntiAlias(true);
+ mLinePaintBad.setARGB(255, 120, 180, 0);
+
+ mScratchRect = new RectF(0, 0, 0, 0);
+
+ mWinsInARow = 0;
+ mDifficulty = DIFFICULTY_MEDIUM;
+
+ // initial show-up of lander (not yet playing)
+ mX = mLanderWidth;
+ mY = mLanderHeight * 2;
+ mFuel = PHYS_FUEL_INIT;
+ mDX = 0;
+ mDY = 0;
+ mHeading = 0;
+ mEngineFiring = true;
+ }
+
+ /**
+ * Starts the game, setting parameters for the current difficulty.
+ */
+ public void doStart() {
+ synchronized (mSurfaceHolder) {
+ // First set the game for Medium difficulty
+ mFuel = PHYS_FUEL_INIT;
+ mEngineFiring = false;
+ mGoalWidth = (int) (mLanderWidth * TARGET_WIDTH);
+ mGoalSpeed = TARGET_SPEED;
+ mGoalAngle = TARGET_ANGLE;
+ int speedInit = PHYS_SPEED_INIT;
+
+ // Adjust difficulty params for EASY/HARD
+ if (mDifficulty == DIFFICULTY_EASY) {
+ mFuel = mFuel * 3 / 2;
+ mGoalWidth = mGoalWidth * 4 / 3;
+ mGoalSpeed = mGoalSpeed * 3 / 2;
+ mGoalAngle = mGoalAngle * 4 / 3;
+ speedInit = speedInit * 3 / 4;
+ } else if (mDifficulty == DIFFICULTY_HARD) {
+ mFuel = mFuel * 7 / 8;
+ mGoalWidth = mGoalWidth * 3 / 4;
+ mGoalSpeed = mGoalSpeed * 7 / 8;
+ speedInit = speedInit * 4 / 3;
+ }
+
+ // pick a convenient initial location for the lander sprite
+ mX = mCanvasWidth / 2;
+ mY = mCanvasHeight - mLanderHeight / 2;
+
+ // start with a little random motion
+ mDY = Math.random() * -speedInit;
+ mDX = Math.random() * 2 * speedInit - speedInit;
+ mHeading = 0;
+
+ // Figure initial spot for landing, not too near center
+ while (true) {
+ mGoalX = (int) (Math.random() * (mCanvasWidth - mGoalWidth));
+ if (Math.abs(mGoalX - (mX - mLanderWidth / 2)) > mCanvasHeight / 6)
+ break;
+ }
+
+ mLastTime = System.currentTimeMillis() + 100;
+ setState(STATE_RUNNING);
+ }
+ }
+
+ /**
+ * Pauses the physics update & animation.
+ */
+ public void pause() {
+ synchronized (mSurfaceHolder) {
+ if (mMode == STATE_RUNNING) setState(STATE_PAUSE);
+ }
+ }
+
+ /**
+ * Restores game state from the indicated Bundle. Typically called when
+ * the Activity is being restored after having been previously
+ * destroyed.
+ *
+ * @param savedState Bundle containing the game state
+ */
+ public synchronized void restoreState(Bundle savedState) {
+ synchronized (mSurfaceHolder) {
+ setState(STATE_PAUSE);
+ mRotating = 0;
+ mEngineFiring = false;
+
+ mDifficulty = savedState.getInt(KEY_DIFFICULTY);
+ mX = savedState.getDouble(KEY_X);
+ mY = savedState.getDouble(KEY_Y);
+ mDX = savedState.getDouble(KEY_DX);
+ mDY = savedState.getDouble(KEY_DY);
+ mHeading = savedState.getDouble(KEY_HEADING);
+
+ mLanderWidth = savedState.getInt(KEY_LANDER_WIDTH);
+ mLanderHeight = savedState.getInt(KEY_LANDER_HEIGHT);
+ mGoalX = savedState.getInt(KEY_GOAL_X);
+ mGoalSpeed = savedState.getInt(KEY_GOAL_SPEED);
+ mGoalAngle = savedState.getInt(KEY_GOAL_ANGLE);
+ mGoalWidth = savedState.getInt(KEY_GOAL_WIDTH);
+ mWinsInARow = savedState.getInt(KEY_WINS);
+ mFuel = savedState.getDouble(KEY_FUEL);
+ }
+ }
+
+ @Override
+ public void run() {
+ while (mRun) {
+ Canvas c = null;
+ try {
+ c = mSurfaceHolder.lockCanvas(null);
+ synchronized (mSurfaceHolder) {
+ if (mMode == STATE_RUNNING) updatePhysics();
+ doDraw(c);
+ }
+ } finally {
+ // do this in a finally so that if an exception is thrown
+ // during the above, we don't leave the Surface in an
+ // inconsistent state
+ if (c != null) {
+ mSurfaceHolder.unlockCanvasAndPost(c);
+ }
+ }
+ }
+ }
+
+ /**
+ * Dump game state to the provided Bundle. Typically called when the
+ * Activity is being suspended.
+ *
+ * @return Bundle with this view's state
+ */
+ public Bundle saveState(Bundle map) {
+ synchronized (mSurfaceHolder) {
+ if (map != null) {
+ map.putInt(KEY_DIFFICULTY, Integer.valueOf(mDifficulty));
+ map.putDouble(KEY_X, Double.valueOf(mX));
+ map.putDouble(KEY_Y, Double.valueOf(mY));
+ map.putDouble(KEY_DX, Double.valueOf(mDX));
+ map.putDouble(KEY_DY, Double.valueOf(mDY));
+ map.putDouble(KEY_HEADING, Double.valueOf(mHeading));
+ map.putInt(KEY_LANDER_WIDTH, Integer.valueOf(mLanderWidth));
+ map.putInt(KEY_LANDER_HEIGHT, Integer
+ .valueOf(mLanderHeight));
+ map.putInt(KEY_GOAL_X, Integer.valueOf(mGoalX));
+ map.putInt(KEY_GOAL_SPEED, Integer.valueOf(mGoalSpeed));
+ map.putInt(KEY_GOAL_ANGLE, Integer.valueOf(mGoalAngle));
+ map.putInt(KEY_GOAL_WIDTH, Integer.valueOf(mGoalWidth));
+ map.putInt(KEY_WINS, Integer.valueOf(mWinsInARow));
+ map.putDouble(KEY_FUEL, Double.valueOf(mFuel));
+ }
+ }
+ return map;
+ }
+
+ /**
+ * Sets the current difficulty.
+ *
+ * @param difficulty
+ */
+ public void setDifficulty(int difficulty) {
+ synchronized (mSurfaceHolder) {
+ mDifficulty = difficulty;
+ }
+ }
+
+ /**
+ * Sets if the engine is currently firing.
+ */
+ public void setFiring(boolean firing) {
+ synchronized (mSurfaceHolder) {
+ mEngineFiring = firing;
+ }
+ }
+
+ /**
+ * Used to signal the thread whether it should be running or not.
+ * Passing true allows the thread to run; passing false will shut it
+ * down if it's already running. Calling start() after this was most
+ * recently called with false will result in an immediate shutdown.
+ *
+ * @param b true to run, false to shut down
+ */
+ public void setRunning(boolean b) {
+ mRun = b;
+ }
+
+ /**
+ * Sets the game mode. That is, whether we are running, paused, in the
+ * failure state, in the victory state, etc.
+ *
+ * @see #setState(int, CharSequence)
+ * @param mode one of the STATE_* constants
+ */
+ public void setState(int mode) {
+ synchronized (mSurfaceHolder) {
+ setState(mode, null);
+ }
+ }
+
+ /**
+ * Sets the game mode. That is, whether we are running, paused, in the
+ * failure state, in the victory state, etc.
+ *
+ * @param mode one of the STATE_* constants
+ * @param message string to add to screen or null
+ */
+ public void setState(int mode, CharSequence message) {
+ /*
+ * This method optionally can cause a text message to be displayed
+ * to the user when the mode changes. Since the View that actually
+ * renders that text is part of the main View hierarchy and not
+ * owned by this thread, we can't touch the state of that View.
+ * Instead we use a Message + Handler to relay commands to the main
+ * thread, which updates the user-text View.
+ */
+ synchronized (mSurfaceHolder) {
+ mMode = mode;
+
+ if (mMode == STATE_RUNNING) {
+ Message msg = mHandler.obtainMessage();
+ Bundle b = new Bundle();
+ b.putString("text", "");
+ b.putInt("viz", View.INVISIBLE);
+ msg.setData(b);
+ mHandler.sendMessage(msg);
+ } else {
+ mRotating = 0;
+ mEngineFiring = false;
+ Resources res = mContext.getResources();
+ CharSequence str = "";
+ if (mMode == STATE_READY)
+ str = res.getText(R.string.mode_ready);
+ else if (mMode == STATE_PAUSE)
+ str = res.getText(R.string.mode_pause);
+ else if (mMode == STATE_LOSE)
+ str = res.getText(R.string.mode_lose);
+ else if (mMode == STATE_WIN)
+ str = res.getString(R.string.mode_win_prefix)
+ + mWinsInARow + " "
+ + res.getString(R.string.mode_win_suffix);
+
+ if (message != null) {
+ str = message + "\n" + str;
+ }
+
+ if (mMode == STATE_LOSE) mWinsInARow = 0;
+
+ Message msg = mHandler.obtainMessage();
+ Bundle b = new Bundle();
+ b.putString("text", str.toString());
+ b.putInt("viz", View.VISIBLE);
+ msg.setData(b);
+ mHandler.sendMessage(msg);
+ }
+ }
+ }
+
+ /* Callback invoked when the surface dimensions change. */
+ public void setSurfaceSize(int width, int height) {
+ // synchronized to make sure these all change atomically
+ synchronized (mSurfaceHolder) {
+ mCanvasWidth = width;
+ mCanvasHeight = height;
+
+ // don't forget to resize the background image
+ mBackgroundImage = mBackgroundImage.createScaledBitmap(
+ mBackgroundImage, width, height, true);
+ }
+ }
+
+ /**
+ * Resumes from a pause.
+ */
+ public void unpause() {
+ // Move the real time clock up to now
+ synchronized (mSurfaceHolder) {
+ mLastTime = System.currentTimeMillis() + 100;
+ }
+ setState(STATE_RUNNING);
+ }
+
+ /**
+ * Handles a key-down event.
+ *
+ * @param keyCode the key that was pressed
+ * @param msg the original event object
+ * @return true
+ */
+ boolean doKeyDown(int keyCode, KeyEvent msg) {
+ synchronized (mSurfaceHolder) {
+ boolean okStart = false;
+ if (keyCode == KeyEvent.KEYCODE_DPAD_UP) okStart = true;
+ if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) okStart = true;
+ if (keyCode == KeyEvent.KEYCODE_S) okStart = true;
+
+ boolean center = (keyCode == KeyEvent.KEYCODE_DPAD_UP);
+
+ if (okStart
+ && (mMode == STATE_READY || mMode == STATE_LOSE || mMode == STATE_WIN)) {
+ // ready-to-start -> start
+ doStart();
+ return true;
+ } else if (mMode == STATE_PAUSE && okStart) {
+ // paused -> running
+ unpause();
+ return true;
+ } else if (mMode == STATE_RUNNING) {
+ // center/space -> fire
+ if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER
+ || keyCode == KeyEvent.KEYCODE_SPACE) {
+ setFiring(true);
+ return true;
+ // left/q -> left
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT
+ || keyCode == KeyEvent.KEYCODE_Q) {
+ mRotating = -1;
+ return true;
+ // right/w -> right
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
+ || keyCode == KeyEvent.KEYCODE_W) {
+ mRotating = 1;
+ return true;
+ // up -> pause
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+ pause();
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Handles a key-up event.
+ *
+ * @param keyCode the key that was pressed
+ * @param msg the original event object
+ * @return true if the key was handled and consumed, or else false
+ */
+ boolean doKeyUp(int keyCode, KeyEvent msg) {
+ boolean handled = false;
+
+ synchronized (mSurfaceHolder) {
+ if (mMode == STATE_RUNNING) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER
+ || keyCode == KeyEvent.KEYCODE_SPACE) {
+ setFiring(false);
+ handled = true;
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT
+ || keyCode == KeyEvent.KEYCODE_Q
+ || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
+ || keyCode == KeyEvent.KEYCODE_W) {
+ mRotating = 0;
+ handled = true;
+ }
+ }
+ }
+
+ return handled;
+ }
+
+ /**
+ * Draws the ship, fuel/speed bars, and background to the provided
+ * Canvas.
+ */
+ private void doDraw(Canvas canvas) {
+ // Draw the background image. Operations on the Canvas accumulate
+ // so this is like clearing the screen.
+ canvas.drawBitmap(mBackgroundImage, 0, 0, null);
+
+ int yTop = mCanvasHeight - ((int) mY + mLanderHeight / 2);
+ int xLeft = (int) mX - mLanderWidth / 2;
+
+ // Draw the fuel gauge
+ int fuelWidth = (int) (UI_BAR * mFuel / PHYS_FUEL_MAX);
+ mScratchRect.set(4, 4, 4 + fuelWidth, 4 + UI_BAR_HEIGHT);
+ canvas.drawRect(mScratchRect, mLinePaint);
+
+ // Draw the speed gauge, with a two-tone effect
+ double speed = Math.sqrt(mDX * mDX + mDY * mDY);
+ int speedWidth = (int) (UI_BAR * speed / PHYS_SPEED_MAX);
+
+ if (speed <= mGoalSpeed) {
+ mScratchRect.set(4 + UI_BAR + 4, 4,
+ 4 + UI_BAR + 4 + speedWidth, 4 + UI_BAR_HEIGHT);
+ canvas.drawRect(mScratchRect, mLinePaint);
+ } else {
+ // Draw the bad color in back, with the good color in front of
+ // it
+ mScratchRect.set(4 + UI_BAR + 4, 4,
+ 4 + UI_BAR + 4 + speedWidth, 4 + UI_BAR_HEIGHT);
+ canvas.drawRect(mScratchRect, mLinePaintBad);
+ int goalWidth = (UI_BAR * mGoalSpeed / PHYS_SPEED_MAX);
+ mScratchRect.set(4 + UI_BAR + 4, 4, 4 + UI_BAR + 4 + goalWidth,
+ 4 + UI_BAR_HEIGHT);
+ canvas.drawRect(mScratchRect, mLinePaint);
+ }
+
+ // Draw the landing pad
+ canvas.drawLine(mGoalX, 1 + mCanvasHeight - TARGET_PAD_HEIGHT,
+ mGoalX + mGoalWidth, 1 + mCanvasHeight - TARGET_PAD_HEIGHT,
+ mLinePaint);
+
+
+ // Draw the ship with its current rotation
+ canvas.save();
+ canvas.rotate((float) mHeading, (float) mX, mCanvasHeight
+ - (float) mY);
+ if (mMode == STATE_LOSE) {
+ mCrashedImage.setBounds(xLeft, yTop, xLeft + mLanderWidth, yTop
+ + mLanderHeight);
+ mCrashedImage.draw(canvas);
+ } else if (mEngineFiring) {
+ mFiringImage.setBounds(xLeft, yTop, xLeft + mLanderWidth, yTop
+ + mLanderHeight);
+ mFiringImage.draw(canvas);
+ } else {
+ mLanderImage.setBounds(xLeft, yTop, xLeft + mLanderWidth, yTop
+ + mLanderHeight);
+ mLanderImage.draw(canvas);
+ }
+ canvas.restore();
+ }
+
+ /**
+ * Figures the lander state (x, y, fuel, ...) based on the passage of
+ * realtime. Does not invalidate(). Called at the start of draw().
+ * Detects the end-of-game and sets the UI to the next state.
+ */
+ private void updatePhysics() {
+ long now = System.currentTimeMillis();
+
+ // Do nothing if mLastTime is in the future.
+ // This allows the game-start to delay the start of the physics
+ // by 100ms or whatever.
+ if (mLastTime > now) return;
+
+ double elapsed = (now - mLastTime) / 1000.0;
+
+ // mRotating -- update heading
+ if (mRotating != 0) {
+ mHeading += mRotating * (PHYS_SLEW_SEC * elapsed);
+
+ // Bring things back into the range 0..360
+ if (mHeading < 0)
+ mHeading += 360;
+ else if (mHeading >= 360) mHeading -= 360;
+ }
+
+ // Base accelerations -- 0 for x, gravity for y
+ double ddx = 0.0;
+ double ddy = -PHYS_DOWN_ACCEL_SEC * elapsed;
+
+ if (mEngineFiring) {
+ // taking 0 as up, 90 as to the right
+ // cos(deg) is ddy component, sin(deg) is ddx component
+ double elapsedFiring = elapsed;
+ double fuelUsed = elapsedFiring * PHYS_FUEL_SEC;
+
+ // tricky case where we run out of fuel partway through the
+ // elapsed
+ if (fuelUsed > mFuel) {
+ elapsedFiring = mFuel / fuelUsed * elapsed;
+ fuelUsed = mFuel;
+
+ // Oddball case where we adjust the "control" from here
+ mEngineFiring = false;
+ }
+
+ mFuel -= fuelUsed;
+
+ // have this much acceleration from the engine
+ double accel = PHYS_FIRE_ACCEL_SEC * elapsedFiring;
+
+ double radians = 2 * Math.PI * mHeading / 360;
+ ddx = Math.sin(radians) * accel;
+ ddy += Math.cos(radians) * accel;
+ }
+
+ double dxOld = mDX;
+ double dyOld = mDY;
+
+ // figure speeds for the end of the period
+ mDX += ddx;
+ mDY += ddy;
+
+ // figure position based on average speed during the period
+ mX += elapsed * (mDX + dxOld) / 2;
+ mY += elapsed * (mDY + dyOld) / 2;
+
+ mLastTime = now;
+
+ // Evaluate if we have landed ... stop the game
+ double yLowerBound = TARGET_PAD_HEIGHT + mLanderHeight / 2
+ - TARGET_BOTTOM_PADDING;
+ if (mY <= yLowerBound) {
+ mY = yLowerBound;
+
+ int result = STATE_LOSE;
+ CharSequence message = "";
+ Resources res = mContext.getResources();
+ double speed = Math.sqrt(mDX * mDX + mDY * mDY);
+ boolean onGoal = (mGoalX <= mX - mLanderWidth / 2 && mX
+ + mLanderWidth / 2 <= mGoalX + mGoalWidth);
+
+ // "Hyperspace" win -- upside down, going fast,
+ // puts you back at the top.
+ if (onGoal && Math.abs(mHeading - 180) < mGoalAngle
+ && speed > PHYS_SPEED_HYPERSPACE) {
+ result = STATE_WIN;
+ mWinsInARow++;
+ doStart();
+
+ return;
+ // Oddball case: this case does a return, all other cases
+ // fall through to setMode() below.
+ } else if (!onGoal) {
+ message = res.getText(R.string.message_off_pad);
+ } else if (!(mHeading <= mGoalAngle || mHeading >= 360 - mGoalAngle)) {
+ message = res.getText(R.string.message_bad_angle);
+ } else if (speed > mGoalSpeed) {
+ message = res.getText(R.string.message_too_fast);
+ } else {
+ result = STATE_WIN;
+ mWinsInARow++;
+ }
+
+ setState(result, message);
+ }
+ }
+ }
+
+ /** Handle to the application context, used to e.g. fetch Drawables. */
+ private Context mContext;
+
+ /** Pointer to the text view to display "Paused.." etc. */
+ private TextView mStatusText;
+
+ /** The thread that actually draws the animation */
+ private LunarThread thread;
+
+ public LunarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ // register our interest in hearing about changes to our surface
+ SurfaceHolder holder = getHolder();
+ holder.addCallback(this);
+
+ // create thread only; it's started in surfaceCreated()
+ thread = new LunarThread(holder, context, new Handler() {
+ @Override
+ public void handleMessage(Message m) {
+ mStatusText.setVisibility(m.getData().getInt("viz"));
+ mStatusText.setText(m.getData().getString("text"));
+ }
+ });
+
+ setFocusable(true); // make sure we get key events
+ }
+
+ /**
+ * Fetches the animation thread corresponding to this LunarView.
+ *
+ * @return the animation thread
+ */
+ public LunarThread getThread() {
+ return thread;
+ }
+
+ /**
+ * Standard override to get key-press events.
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent msg) {
+ return thread.doKeyDown(keyCode, msg);
+ }
+
+ /**
+ * Standard override for key-up. We actually care about these, so we can
+ * turn off the engine or stop rotating.
+ */
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent msg) {
+ return thread.doKeyUp(keyCode, msg);
+ }
+
+ /**
+ * Standard window-focus override. Notice focus lost so we can pause on
+ * focus lost. e.g. user switches to take a call.
+ */
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ if (!hasWindowFocus) thread.pause();
+ }
+
+ /**
+ * Installs a pointer to the text view used for messages.
+ */
+ public void setTextView(TextView textView) {
+ mStatusText = textView;
+ }
+
+ /* Callback invoked when the surface dimensions change. */
+ public void surfaceChanged(SurfaceHolder holder, int format, int width,
+ int height) {
+ thread.setSurfaceSize(width, height);
+ }
+
+ /*
+ * Callback invoked when the Surface has been created and is ready to be
+ * used.
+ */
+ public void surfaceCreated(SurfaceHolder holder) {
+ // start the thread here so that we don't busy-wait in run()
+ // waiting for the surface to be created
+ thread.setRunning(true);
+ thread.start();
+ }
+
+ /*
+ * Callback invoked when the Surface has been destroyed and must no longer
+ * be touched. WARNING: after this method returns, the Surface/Canvas must
+ * never be touched again!
+ */
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // we have to tell thread to shut down & wait for it to finish, or else
+ // it might touch the Surface after we return and explode
+ boolean retry = true;
+ thread.setRunning(false);
+ while (retry) {
+ try {
+ thread.join();
+ retry = false;
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+}
diff --git a/samples/LunarLander/tests/Android.mk b/samples/LunarLander/tests/Android.mk
new file mode 100644
index 0000000..60208cf
--- /dev/null
+++ b/samples/LunarLander/tests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := LunarLanderTests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := LunarLander
+
+include $(BUILD_PACKAGE)
diff --git a/samples/LunarLander/tests/AndroidManifest.xml b/samples/LunarLander/tests/AndroidManifest.xml
new file mode 100644
index 0000000..1bc8364
--- /dev/null
+++ b/samples/LunarLander/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.lunarlander.tests">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.lunarlander"
+ android:label="LunarLander sample tests">
+ </instrumentation>
+
+</manifest>
diff --git a/samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java b/samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
new file mode 100644
index 0000000..fae02da
--- /dev/null
+++ b/samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.lunarlander;
+
+import android.test.ActivityInstrumentationTestCase;
+
+import com.example.android.lunarlander.LunarLander;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link ActivityTestCase#testActivityTestCaseSetUpProperly}.
+ */
+public class LunarLanderTest extends ActivityInstrumentationTestCase<LunarLander> {
+
+ public LunarLanderTest() {
+ super("com.example.android.lunarlander", LunarLander.class);
+ }
+
+}
diff --git a/samples/MailSync/res/values/ids.xml b/samples/MailSync/res/values/ids.xml
new file mode 100644
index 0000000..ee736a6
--- /dev/null
+++ b/samples/MailSync/res/values/ids.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <item type="id" name="from" />
+ <item type="id" name="snippet" />
+ <item type="id" name="subject" />
+</resources>
diff --git a/samples/MySampleRss/Android.mk b/samples/MySampleRss/Android.mk
new file mode 100644
index 0000000..fea9729
--- /dev/null
+++ b/samples/MySampleRss/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := MyRSSReader
+
+LOCAL_SDK_VERSION := current
+
+##include $(BUILD_PACKAGE)
diff --git a/samples/MySampleRss/AndroidManifest.xml b/samples/MySampleRss/AndroidManifest.xml
new file mode 100755
index 0000000..575c81e
--- /dev/null
+++ b/samples/MySampleRss/AndroidManifest.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.codelab.rssexample">
+ <application android:name="MyRssReader" android:label="My Rss Reader">
+ <activity>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="MyRssReader2" android:label="My Rss Reader V2">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="MyRssReader3" android:label="@string/reader_3_label">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="MyRssReader4" android:label="@string/reader_4_label">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="MyRssReader5" android:label="@string/reader_5_label">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="AddRssItem" android:label="@string/add_item_label" android:theme="@android:style/Theme.Dialog"/>
+ <provider android:name="RssContentProvider" android:authorities="my_rss_item" android:multiprocess="true" />
+ <service android:name="RssService" android:process=":myrss"/>
+ </application>
+</manifest>
+
+
diff --git a/samples/MySampleRss/res/drawable/rss_icon.PNG b/samples/MySampleRss/res/drawable/rss_icon.PNG
new file mode 100755
index 0000000..214a38d
--- /dev/null
+++ b/samples/MySampleRss/res/drawable/rss_icon.PNG
Binary files differ
diff --git a/samples/MySampleRss/res/layout/add_item.xml b/samples/MySampleRss/res/layout/add_item.xml
new file mode 100644
index 0000000..8191bf5
--- /dev/null
+++ b/samples/MySampleRss/res/layout/add_item.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="fill_parent"
+ android:layout_width="fill_parent">
+
+ <TextView android:id="@+id/title_label"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:text="@string/add_item_title"/>
+ <EditText android:id="@+id/title_textbox"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_toRightOf="@id/title_label"/>
+ <EditText android:id="@+id/url_textbox"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_below="@id/title_textbox"
+ android:layout_alignLeft="@id/title_textbox"/>
+
+ <!-- Note that we declare url_label *after* url_textbox in this file
+ because it references url_textbox, and a resource file is
+ evaluated sequentially. -->
+ <TextView android:id="@+id/url_label"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_toRightOf="url_textbox"
+ android:layout_alignTop="@id/url_textbox"
+ android:text="@string/add_item_url"/>
+ <Button android:id="@+id/submit"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentBottom="true"
+ android:text="@string/submit"/>
+ <Button android:id="@+id/cancel"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_toLeftOf="@id/submit"
+ android:layout_alignTop="@id/submit"
+ android:text="@string/cancel"/>
+</RelativeLayout>
+
diff --git a/samples/MySampleRss/res/layout/list_element.xml b/samples/MySampleRss/res/layout/list_element.xml
new file mode 100644
index 0000000..4255d86
--- /dev/null
+++ b/samples/MySampleRss/res/layout/list_element.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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/list_item"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
diff --git a/samples/MySampleRss/res/layout/main_screen.xml b/samples/MySampleRss/res/layout/main_screen.xml
new file mode 100755
index 0000000..5292bb2
--- /dev/null
+++ b/samples/MySampleRss/res/layout/main_screen.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="fill_parent"
+ android:layout_width="fill_parent"
+ android:orientation="vertical"
+ android:scrollbars="vertical">
+
+ <ListView android:id="@+id/rssListView"
+ android:layout_height="0px"
+ android:layout_width="fill_parent"
+ android:layout_weight="1"
+ android:background="#00CC00"/>
+
+ <WebView android:id="@+id/rssWebView"
+ android:background="#77CC0000"
+ android:layout_height="0px"
+ android:layout_width="fill_parent"
+ android:layout_weight="1"/>
+
+</LinearLayout>
diff --git a/samples/MySampleRss/res/layout/main_screen2.xml b/samples/MySampleRss/res/layout/main_screen2.xml
new file mode 100644
index 0000000..36b0af4
--- /dev/null
+++ b/samples/MySampleRss/res/layout/main_screen2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="fill_parent"
+ android:layout_width="fill_parent"
+ android:orientation="vertical"
+ android:scrollbars="vertical">
+
+ <ListView android:id="@+id/rssListView"
+ android:layout_height="0px"
+ android:layout_width="fill_parent"
+ android:layout_weight="1"
+ android:background="#9900FF00"/>
+
+ <WebView android:id="@+id/rssWebView"
+ android:layout_height="0px"
+ android:layout_width="fill_parent"
+ android:layout_weight="2"/>
+</LinearLayout>
diff --git a/samples/MySampleRss/res/values/strings.xml b/samples/MySampleRss/res/values/strings.xml
new file mode 100644
index 0000000..8655995
--- /dev/null
+++ b/samples/MySampleRss/res/values/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources>
+ <string name="menu_option_start">Start RSS Service</string>
+ <string name="menu_option_stop">Stop RSS Service</string>
+ <string name="menu_option_add">Add New Feed</string>
+ <string name="menu_option_delete">Delete Feed</string>
+ <string name="menu_option_update">Update All Feeds</string>
+ <string name="add_item_title">Title</string>
+ <string name="add_item_url">URL</string>
+ <string name="submit">Submit</string>
+ <string name="cancel">Cancel</string>
+ <string name="reader_3_label">MyRssReader3</string>
+ <string name="reader_4_label">MyRssReader4</string>
+ <string name="reader_5_label">MyRssReader5</string>
+ <string name="add_item_label">Add a new Feed</string>
+</resources>
\ No newline at end of file
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/AddRssItem.java b/samples/MySampleRss/src/com/example/codelab/rssexample/AddRssItem.java
new file mode 100644
index 0000000..980eec6
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/AddRssItem.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.text.TextUtils;
+import android.os.Bundle;
+
+/*** Form to add a new RSS feed.
+ It is a dialog form,**/
+public class AddRssItem extends Activity {
+
+ // Button handler for Submit/Cancel.
+ // It is a dialog style form because it's declared as such
+ // in the manifest.
+ private OnClickListener mClickListener = new OnClickListener(){
+ public void onClick(View v){
+ if(v.getId() == R.id.submit){
+ String title = ((TextView) findViewById(R.id.title_textbox)).getText().toString();
+ String url = ((TextView) findViewById(R.id.url_textbox)).getText().toString();
+ if(TextUtils.isEmpty(title) || TextUtils.isEmpty(url)){
+ showAlert("Missing Values",
+ "You must specify both a title and a URL value",
+ "OK",
+ null, false, null);
+ return;
+ }
+ Intent res = new Intent("Accepted");
+ res.putExtra(RssContentProvider.TITLE, title);
+ res.putExtra(RssContentProvider.URL, url);
+ res.putExtra(RssContentProvider.LAST_UPDATED, 0);
+ res.putExtra(RssContentProvider.CONTENT, "<html><body><h2>Not updated yet.</h2></body></html>");
+ setResult(RESULT_OK, res);
+ }
+ else
+ setResult(RESULT_CANCELED, (new Intent()).setAction("Canceled" + v.getId()));
+
+ finish();
+
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.add_item);
+ setTitle(getString(R.string.add_item_label));
+
+ Button btn = (Button) findViewById(R.id.cancel);
+ btn.setOnClickListener(mClickListener);
+
+ btn = (Button) findViewById(R.id.submit);
+ btn.setOnClickListener(mClickListener);
+ }
+
+}
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader.java b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader.java
new file mode 100644
index 0000000..d306554
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+//BEGIN_INCLUDE(1_1)
+public class MyRssReader extends Activity {
+ /** Called with the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+
+ // Load screen layout.
+ setContentView(R.layout.main_screen);
+
+//END_INCLUDE(1_1)
+//BEGIN_INCLUDE(1_2)
+ // Load some simple values into the ListView
+ mRssList = (ListView) findViewById(R.id.rssListView);
+ mRssList.setAdapter(
+ new ArrayAdapter<String>(
+ this,
+ R.layout.list_element,
+ new String[] { "Scientific American", "BBC", "The Onion", "Engadget" }));
+//END_INCLUDE(1_2)
+}
+
+ // Store our state before we are potentially bumped from memory.
+ // We'd like to store the current ListView selection.
+ @Override
+ protected void onSaveInstanceState(Bundle outState){
+ int index = mRssList.getSelectedItemIndex();
+ if(index > -1){
+ outState.putInteger("lastIndexItem", index);
+ }
+ }
+
+ // Add our initial menu options. We will tweak this menu when it's loaded swap out
+ // "start service" or "stop service", depending on whether the service is currently running.
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu){
+ // Always call the superclass implementation to
+ // provide standard items.
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, 0, "Start RSS Service", null);
+ menu.add(0, 1, "Stop RSS Service", null);
+ menu.add(0, 2, "Add New Feed", null);
+ menu.add(0, 3, "Delete Feed", null);
+ menu.add(0, 4, "Update All Feeds", null);
+
+ return true;
+ }
+
+ // Toggle out start service/stop service depending on whether the service is running.
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu){
+ return true;
+ }
+
+ // Handle our menu clicks.
+ @Override
+ public boolean onOptionsItemSelected(Menu.Item item){
+ switch (item.getId()) {
+ case 0:
+ showAlert(null, "You clicked 'start'!", "ok", null, false, null);
+ break;
+ case 1:
+ showAlert(null, "You clicked stop!", "ok", null, false, null);
+ break;
+ case 2:
+ showAlert(null, "You clicked 'Add'!", "ok", null, false, null);
+ break;
+ case 3:
+ showAlert(null, "You clicked 'Delete'!", "ok", null, false, null);
+ break;
+ case 4:
+ showAlert(null, "You clicked 'Update'!", "ok", null, false, null);
+ break;
+ default:
+ showAlert(null, "I have no idea what you clicked!", "ok", null, false, null);
+ break;
+ }
+ return true;
+ }
+
+ ListView mRssList;
+}
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader2.java b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader2.java
new file mode 100644
index 0000000..352167a
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader2.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+public class MyRssReader2 extends Activity{
+ private ArrayList<RssItem> mFeeds = null;
+ ListView mRssList = null;
+ private Logger mLogger = Logger.getLogger("com.example.codelab.rssexample");
+
+ @Override
+ public void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+
+ // Load screen layout.
+ setContentView(R.layout.main_screen2);
+
+ // Populate our list
+ mFeeds = initializeList();
+ mLogger.info("MyRssReader.onCreate-1 mFeeds value:" + mFeeds.size());
+// BEGIN_INCLUDE(2_2)
+ // Populate ArrayAdapter and bind it to ListView
+ mRssList = (ListView)findViewById(R.id.rssListView);
+ if(mRssList == null){
+ // Note: Calling showAlert() would fail here because dialogs opened
+ // in onCreate won't be displayed properly, if at all.
+ mLogger.warning("MyRssReader.onCreate-2 -- Couldn't instantiate a ListView!");
+ }
+ RssDataAdapter<RssItem> adap = new RssDataAdapter<RssItem>(this, R.layout.add_item, mFeeds);
+ if(adap == null){
+ mLogger.warning("MyRssReader.onCreate-3 -- Couldn't instantiate RssDataAdapter!");
+ }
+ if(mFeeds == null){
+ mLogger.warning("MyRssReader.onCreate-4 -- Couldn't instantiate a ListView!");
+ }
+ mRssList.setAdapter(adap);
+// END_INCLUDE(2_2)
+
+ mLogger.info("MyRssReader.onCreate-5 -- Loading preferences.");
+ // Set the last selected item.
+ // (icicle is only set if this is being restarted).
+ if(savedInstanceState != null && savedInstanceState.containsKey("lastIndexItem"))
+ {
+ Integer selectedItem = savedInstanceState.getInteger("lastIndexItem");
+ if(selectedItem >= 0 && selectedItem < mRssList.getChildCount()){
+ mRssList.setSelection(savedInstanceState.getInteger("lastIndexItem"));
+ }
+ mLogger.info("MyRssReader.onCreate-6 -- Last selected item:" + selectedItem);
+ }
+ }
+
+ // Store our state before we are potentially bumped from memory.
+ // We'd like to store the current ListView selection.
+ @Override
+ protected void onSaveInstanceState(Bundle outState){
+ int index = mRssList.getSelectedItemIndex();
+ if(index > -1){
+ outState.putInteger("lastIndexItem", index);
+ }
+ }
+
+
+
+ // Add our initial menu options. We will tweak this menu when it's loaded swap out
+ // "start service" or "stop service", depending on whether the service is currently running.
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu){
+ // Always call the superclass implementation to
+ // provide standard items.
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, 0, "Start RSS Service", null);
+ menu.add(0, 1, "Stop RSS Service", null);
+ menu.add(0, 2, "Add New Feed", null);
+ menu.add(0, 3, "Delete Feed", null);
+ menu.add(0, 4, "Update All Feeds", null);
+
+ return true;
+ }
+
+ // Toggle out start service/stop service depending on whether the service is running.
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu){
+ return true;
+ }
+
+ // Handle our menu clicks.
+ @Override
+ public boolean onOptionsItemSelected(Menu.Item item){
+ switch (item.getId()){
+ case 0:
+ showAlert(null, "You clicked 'start'!", "ok", null, false, null);
+ break;
+ case 1:
+ showAlert(null, "You clicked stop!", "ok", null, false, null);
+ break;
+ case 2:
+ showAlert(null, "You clicked 'Add'!", "ok", null, false, null);
+ break;
+ case 3:
+ showAlert(null, "You clicked 'Delete'!", "ok", null, false, null);
+ break;
+ case 4:
+ showAlert(null, "You clicked 'Update'!", "ok", null, false, null);
+ break;
+ default:
+ showAlert(null, "I have no idea what you clicked!", "ok", null, false, null);
+ break;
+ }
+ return true;
+ }
+
+
+ // Our private ArrayAdapter implementation that returns a bold TextView for
+ // RSS items that are unread, or a normal TextView for items that have been read.
+// BEGIN_INCLUDE(2_3)
+ private class RssDataAdapter<T> extends ArrayAdapter<T> {
+ public RssDataAdapter(Context context, int resource, List objects) {
+ super(context, resource, objects);
+ }
+// END_INCLUDE(2_3)
+ // Here's our only important override--returning the list item.
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent){
+ TextView view = null;
+ // Get the item from the underlying array,
+ // Create a TextView wrapper, and change the typeface, if necessary.
+ RssItem item = (RssItem)this.getItem(position);
+ if(item != null)
+ {
+ view = new TextView(parent.getContext());
+ view.setText(item.toString());
+
+ if(! item.hasBeenRead){
+ Typeface type = view.getTypeface();
+ view.setTypeface(Typeface.create(type, Typeface.BOLD_ITALIC));
+ }
+ }
+ return view;
+ }
+ }
+
+//BEGIN_INCLUDE(2_1)
+ // Method to initialize our list of RSS items.
+ private ArrayList<RssItem> initializeList(){
+ ArrayList<RssItem> list = new ArrayList<RssItem>();
+ list.add(new RssItem("http://www.sciam.com/xml/sciam.xml", "Scientific American"));
+ list.add(new RssItem("http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml", "BBC"));
+ list.add(new RssItem("http://www.theonion.com/content/feeds/daily.", "The Onion"));
+ list.add(new RssItem("http://feeds.engadget.com/weblogsinc/engadget", "Engadget"));
+ return list;
+ }
+//END_INCLUDE(2_1)
+}
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader3.java b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader3.java
new file mode 100644
index 0000000..1ffe33e
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader3.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MyRssReader3 extends Activity{
+
+ private ArrayList<RssItem> mFeeds;
+ ListView mRssList;
+ ArrayAdapter mAdap;
+ private static final int ADD_ELEMENT_REQUEST = 1;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+
+ // Load screen layout.
+ setContentView(R.layout.main_screen2);
+
+ // Populate our list
+ mFeeds = initializeList();
+
+ // Populate ArrayAdapter and bind it to ListView
+ mRssList = (ListView)findViewById(R.id.rssListView);
+ mAdap = new RssDataAdapter<RssItem>(this, R.layout.list_element, mFeeds);
+ mRssList.setAdapter(mAdap);
+
+ // Set the last selected item.
+ // (icicle is only set if this is being restarted).
+ if(savedInstanceState != null && savedInstanceState.containsKey("lastIndexItem"))
+ mRssList.setSelection(savedInstanceState.getInteger("lastIndexItem"));
+ }
+
+ // Store our state before we are potentially bumped from memory.
+ // We'd like to store the current ListView selection.
+ @Override
+ protected void onSaveInstanceState(Bundle outState){
+ int index = mRssList.getSelectedItemIndex();
+ if(index > -1){
+ outState.putInteger("lastIndexItem", index);
+ }
+ }
+
+
+ // Add our initial menu options. We will tweak this menu when it's loaded swap out
+ // "start service" or "stop service", depending on whether the service is currently running.
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ // Always call the superclass implementation to
+ // provide standard items.
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, 0, R.string.menu_option_start, null);
+ menu.add(0, 1, R.string.menu_option_stop, null);
+ menu.add(0, 2, R.string.menu_option_add, null);
+ menu.add(0, 3, R.string.menu_option_delete, null);
+ menu.add(0, 4, R.string.menu_option_update, null);
+
+ return true;
+ }
+
+ // Toggle out start service/stop service depending on whether the service is running.
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu){
+ return true;
+ }
+
+ // Handle our menu clicks.
+ @Override
+ public boolean onOptionsItemSelected(Menu.Item item){
+ super.onOptionsItemSelected(item);
+
+ switch (item.getId()){
+ case 0: // Start service
+ showAlert(null, "You clicked 'start'!", "ok", null, false, null);
+ break;
+ case 1: // Stop service
+ showAlert(null, "You clicked stop!", "ok", null, false, null);
+ break;
+ case 2: // Add Item
+ Intent addIntent = new Intent(AddRssItem.class);
+
+ // Use an ID so that if we create a "remove item" form we
+ // can tell which form is returning a value.
+ startActivityForResult(addIntent, ADD_ELEMENT_REQUEST);
+ break;
+ case 3: // Delete item.
+ if(mRssList.hasFocus()){
+ Object selectedItem = mRssList.getSelectedItem();
+ mAdap.removeObject(mRssList.getSelectedItem());
+ }
+ break;
+ case 4: // Update all
+ showAlert(null, "You clicked 'Update'!", "ok", null, false, null);
+ break;
+ default:
+ showAlert(null, "I have no idea what you clicked!", "ok", null, false, null);
+ break;
+ }
+ return true;
+ }
+
+ // Called by the "Add RSS Item" floating screen when it closes.
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data){
+ if(resultCode == RESULT_OK){
+ switch (requestCode){
+ case ADD_ELEMENT_REQUEST:
+ RssItem newIt = new RssItem(
+ data.getStringExtra("url").toString(),
+ data.getStringExtra("title").toString());
+ mAdap.addObject(newIt);
+ mRssList.setSelection(mRssList.getCount() - 1);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Our private ArrayAdapter implementation that returns a bold TextView for
+ // RSS items that are unread, or a normal TextView for items that have been read.
+ private class RssDataAdapter<T> extends ArrayAdapter<T> {
+ public RssDataAdapter(Context context, int resource, List objects) {
+ super(context, resource, objects);
+ }
+
+ // Here's our only important override--returning the list item.
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent){
+
+ // Get the item from the underlying array,
+ // Create a TextView wrapper, and change the typeface, if necessary.
+ RssItem item = (RssItem)this.getItem(position);
+ TextView view = new TextView(parent.getContext());
+ view.setText(item.toString());
+
+ if(! item.hasBeenRead){
+ Typeface type = view.getTypeface();
+ view.setTypeface(Typeface.create(type, Typeface.BOLD_ITALIC));
+ }
+ return view;
+ }
+ }
+
+ // Method to initialize our list of RSS items.
+ private ArrayList<RssItem> initializeList(){
+ ArrayList<RssItem> list = new ArrayList<RssItem>();
+ list.add(new RssItem("http://www.sciam.com/xml/sciam.xml", "Scientific American"));
+ list.add(new RssItem("http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml", "BBC"));
+ list.add(new RssItem("http://feeds.theonion.com/theonion/daily", "The Onion"));
+ list.add(new RssItem("http://feeds.engadget.com/weblogsinc/engadget", "Engadget"));
+ return list;
+ }
+}
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader4.java b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader4.java
new file mode 100644
index 0000000..bc37786
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader4.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.app.Activity;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.view.Menu;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.SimpleCursorAdapter;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+
+public class MyRssReader4 extends Activity {
+
+ ListView mRssList;
+ Cursor mCur;
+ RssCursorAdapter mAdap;
+ private static final int ADD_ELEMENT_REQUEST = 1;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+
+ // Load screen layout.
+ setContentView(R.layout.main_screen2);
+
+ // Populate ArrayAdapter and bind it to ListView
+ mRssList = (ListView)findViewById(R.id.rssListView);
+
+ mCur = managedQuery(RssContentProvider.CONTENT_URI, // Query for all items.
+ null,
+ null,
+ RssContentProvider.DEFAULT_SORT_ORDER);
+// BEGIN_INCLUDE(4_1)
+ mAdap = new RssCursorAdapter(
+ this,
+ R.layout.list_element, // Our layout resource.
+ mCur,
+ new String[]{RssContentProvider.TITLE}, // Columns to retrieve.
+ new int[]{R.id.list_item}); // IDs of widgets to display
+ mRssList.setAdapter(mAdap); // the corresponding column.
+// END_INCLUDE(4_1)
+
+ // Set the last selected item.
+ // (icicle is only set if this is being restarted).
+ if(savedInstanceState != null && savedInstanceState.containsKey("lastIndexItem")){
+ mRssList.setSelection(savedInstanceState.getInteger("lastIndexItem"));
+ }
+ }
+
+ // Store our state before we are potentially bumped from memory.
+ // We'd like to store the current ListView selection.
+ @Override
+ protected void onSaveInstanceState(Bundle outState){
+ int index = mRssList.getSelectedItemIndex();
+ if(index > -1){
+ outState.putInteger("lastIndexItem", index);
+ }
+ }
+
+
+ // Add our initial menu options. We will tweak this menu when it's loaded swap out
+ // "start service" or "stop service", depending on whether the service is currently running.
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu){
+ // Always call the superclass implementation to
+ // provide standard items.
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, 0, R.string.menu_option_start, null);
+ menu.add(0, 1, R.string.menu_option_stop, null);
+ menu.add(0, 2, R.string.menu_option_add, null);
+ menu.add(0, 3, R.string.menu_option_delete, null);
+ menu.add(0, 4, R.string.menu_option_update, null);
+
+ return true;
+ }
+
+ // Toggle out start service/stop service depending on whether the service is running.
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu){
+ return true;
+ }
+
+ // Handle our menu clicks.
+ @Override
+ public boolean onOptionsItemSelected(Menu.Item item){
+ super.onOptionsItemSelected(item);
+
+ switch (item.getId()){
+ case 0: // Start service
+ showAlert(null, "You clicked 'start'!", "ok", null, false, null);
+ break;
+ case 1: // Stop service
+ showAlert(null, "You clicked stop!", "ok", null, false, null);
+ break;
+ case 2: // Add Item
+ Intent addIntent = new Intent(AddRssItem.class);
+
+ // Use an ID so that if we create a "remove item" form we
+ // can tell which form is returning a value.
+ startActivityForResult(addIntent, ADD_ELEMENT_REQUEST);
+ break;
+ case 3: // Delete item.
+ if(mRssList.hasFocus()){
+ int currentSelectionIndex = mRssList.getSelectedItemIndex();
+
+ // Create our content URI by adding the ID of the currently selected item using a
+ // convenience method.
+ Long itemID = mAdap.getItemId(currentSelectionIndex);
+ getContentResolver().delete(RssContentProvider.CONTENT_URI.addId(itemID), null);
+ }
+ break;
+ case 4: // Update all
+ showAlert(null, "You clicked 'Update'!", "ok", null, false, null);
+ break;
+ default:
+ showAlert(null, "I have no idea what you clicked!", "ok", null, false, null);
+ break;
+ }
+ return true;
+ }
+
+ // Called by the "Add RSS Item" floating screen when it closes.
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data){
+ if(resultCode == RESULT_OK){
+ switch (requestCode){
+ case ADD_ELEMENT_REQUEST:
+ ContentValues vals = new ContentValues(4);
+ vals.put(RssContentProvider.TITLE, data.getStringExtra(RssContentProvider.TITLE));
+ vals.put(RssContentProvider.URL, data.getStringExtra(RssContentProvider.URL));
+ vals.put(RssContentProvider.CONTENT, data.getStringExtra(RssContentProvider.CONTENT));
+ vals.put(RssContentProvider.LAST_UPDATED, data.getIntExtra(RssContentProvider.LAST_UPDATED, 0));
+ Uri uri = getContentResolver().insert(
+ RssContentProvider.CONTENT_URI,
+ vals);
+ if(uri != null){
+ mRssList.setSelection(mRssList.getCount() - 1);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Our private ArrayAdapter implementation that returns a bold TextView for
+ // RSS items that are unread, or a normal TextView for items that have been read.
+ private class RssCursorAdapter extends SimpleCursorAdapter {
+ public RssCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to){
+ super(context, layout, c, from, to);
+ }
+
+ // Here's our only important override--returning the list item.
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent){
+ TextView view = (TextView)super.getView(position, convertView, parent);
+
+ if(view != null){
+
+ // Now get the hasBeenRead value to determine the font.
+ int hasBeenReadColumnIndex = getCursor().getColumnIndex(
+ RssContentProvider.HAS_BEEN_READ);
+ boolean hasBeenRead = (getCursor().getInt(hasBeenReadColumnIndex) == 1 ? true : false);
+ if(! hasBeenRead){
+ Typeface type = view.getTypeface();
+ view.setTypeface(Typeface.create(type, Typeface.BOLD_ITALIC));
+ }
+ }
+ return view;
+ }
+ }
+}
+
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader5.java b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader5.java
new file mode 100644
index 0000000..0d59bfd
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/MyRssReader5.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.app.Activity;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.TextView;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+import java.util.logging.Logger;
+
+public class MyRssReader5 extends Activity implements OnItemSelectedListener {
+
+ private ListView mRssList;
+ private Cursor mCur;
+ private RssCursorAdapter mAdap;
+ private WebView mWebView;
+ private static final int ADD_ELEMENT_REQUEST = 1;
+ private Logger mLogger = Logger.getLogger(this.getPackageName());
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ //
+ // Load screen layout.
+ setContentView(R.layout.main_screen2);
+
+ // Populate ArrayAdapter and bind it to ListView
+ mRssList = (ListView)findViewById(R.id.rssListView);
+ mRssList.setOnItemSelectedListener(this);
+
+ mWebView = (WebView)findViewById(R.id.rssWebView);
+
+ mCur = managedQuery(RssContentProvider.CONTENT_URI, // Query for all items.
+ null,
+ null,
+ RssContentProvider.DEFAULT_SORT_ORDER);
+
+ mAdap = new RssCursorAdapter(
+ this,
+ R.layout.list_element, // Our layout resource.
+ mCur,
+ new String[]{RssContentProvider.TITLE}, // Columns to retrieve.
+ new int[]{R.id.list_item}); // IDs of widgets to display
+ mRssList.setAdapter(mAdap); // the corresponding column.
+
+ // Set the last selected item.
+ // (icicle is only set if this is being restarted).
+ if(savedInstanceState != null && savedInstanceState.containsKey("lastIndexItem")){
+ mRssList.setSelection(savedInstanceState.getInteger("lastIndexItem"));
+ }
+ }
+
+//BEGIN_INCLUDE(5_4)
+ // Listener to listen for list selection changes, and send the new text to
+ // the web view.
+ public void onItemSelected(AdapterView parent, View v, int position, long id){
+ // Need to nest this in a try block because we get called sometimes
+ // with the index of a recently deleted item.
+ String content = "";
+ try{
+ content = mCur.getString(mCur.getColumnIndex(RssContentProvider.CONTENT));
+ mLogger.info("MyRssReader5 content string:" + content);
+ }
+ catch (Exception e){
+ // This method is sometimes called after a backing data item
+ // is deleted. In that case, we don't want to throw an error.
+ mLogger.warning("MyRssReader5.onItemSelected() couldn't get the content" +
+ "from the cursor " + e.getMessage());
+ }
+ mWebView.loadData(content, "text/html", "utf-8");
+ }
+//END_INCLUDE(5_4)
+
+ public void onNothingSelected(AdapterView parent){
+ mWebView.loadData("<html><body><p>No selection chosen</p></body></html>", "text/html", "utf-8");
+ }
+
+ // Store our state before we are potentially bumped from memory.
+ // We'd like to store the current ListView selection.
+ @Override
+ protected void onSaveInstanceState(Bundle outState){
+ int index = mRssList.getSelectedItemIndex();
+ if(index > -1){
+ outState.putInteger("lastIndexItem", index);
+ }
+ }
+
+ // Add our initial menu options. We will tweak this menu when it's loaded swap out
+ // "start service" or "stop service", depending on whether the service is currently running.
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu){
+ // Always call the superclass implementation to
+ // provide standard items.
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, 0, R.string.menu_option_start, null);
+ menu.add(0, 1, R.string.menu_option_stop, null);
+ menu.add(0, 2, R.string.menu_option_add, null);
+ menu.add(0, 3, R.string.menu_option_delete, null);
+ menu.add(0, 4, R.string.menu_option_update, null);
+
+ return true;
+ }
+
+ // Toggle out start service/stop service depending on whether the service is running.
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu){
+ return true;
+ }
+
+ // Handle our menu clicks.
+ @Override
+ public boolean onOptionsItemSelected(Menu.Item item){
+ super.onOptionsItemSelected(item);
+
+ switch (item.getId()){
+ case 0: // Start service
+ Intent basicStartIntent = new Intent(RssService.class);
+ startService(basicStartIntent);
+ break;
+ case 1: // Stop service
+ Intent stopIntent = new Intent(RssService.class);
+ stopService(stopIntent);
+ break;
+ case 2: // Add Item
+ Intent addIntent = new Intent(AddRssItem.class);
+ // Use an ID so that if we create a "remove item" form we
+ // can tell which form is returning a value.
+ startActivityForResult(addIntent, ADD_ELEMENT_REQUEST);
+ break;
+ case 3: // Delete item.
+ if(mRssList.hasFocus()){
+ int currentSelectionIndex = mRssList.getSelectedItemIndex();
+ mLogger.info("MyRssReader5.onOptionsItemSelected(): Deleting list member:" +
+ mRssList.getSelectedItemIndex());
+ // Create our content URI by adding the ID of the currently selected item using a
+ // convenience method.
+ Long itemID = mAdap.getItemId(currentSelectionIndex);
+ getContentResolver().delete(RssContentProvider.CONTENT_URI.addId(itemID), null);
+ }
+ break;
+ case 4: // Requery all
+ Bundle startupVals = new Bundle(1);
+ startupVals.putBoolean(RssService.REQUERY_KEY, true);
+ Intent requeryIntent = new Intent(RssService.class);
+ startService(requeryIntent, startupVals);
+ break;
+ default:
+ showAlert(null, "I have no idea what you clicked!", "ok", null, false, null);
+ break;
+ }
+ return true;
+ }
+
+ // Called by the "Add RSS Item" floating screen when it closes.
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data){
+ if(resultCode == RESULT_OK){
+ switch (requestCode){
+ case ADD_ELEMENT_REQUEST:
+ ContentValues vals = new ContentValues(5);
+ vals.put(RssContentProvider.TITLE, data.getStringExtra(RssContentProvider.TITLE));
+ vals.put(RssContentProvider.URL, data.getStringExtra(RssContentProvider.URL));
+ vals.put(RssContentProvider.CONTENT, data.getStringExtra(RssContentProvider.CONTENT));
+ vals.put(RssContentProvider.LAST_UPDATED, data.getIntExtra(RssContentProvider.LAST_UPDATED, 0));
+ Uri uri = getContentResolver().insert(
+ RssContentProvider.CONTENT_URI,
+ vals);
+ if(uri != null){
+ // Tell the service to requery the service, then set
+ // it as the active selection.
+ Bundle startupVals = new Bundle(1);
+ startupVals.putString(RssService.RSS_URL, data.getStringExtra("URL"));
+ Intent startIntent = new Intent(RssService.class);
+ startIntent.putExtras(startupVals);
+ startService(startIntent);
+ mRssList.setSelection(mRssList.getCount() - 1);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Our private ArrayAdapter implementation that returns a bold TextView for
+ // RSS items that are unread, or a normal TextView for items that have been read.
+ private class RssCursorAdapter extends SimpleCursorAdapter {
+ public RssCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
+ super(context, layout, c, from, to);
+ }
+
+ // Here's our only important override--returning the list item.
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent){
+ TextView view = (TextView)super.getView(position, convertView, parent);
+
+ if(view != null){
+
+ // Now get the hasBeenRead value to determine the font.
+ int hasBeenReadColumnIndex = getCursor().getColumnIndex(RssContentProvider.HAS_BEEN_READ);
+ boolean hasBeenRead = (getCursor().getInt(hasBeenReadColumnIndex) == 1 ? true : false);
+ if(! hasBeenRead){
+ Typeface type = view.getTypeface();
+ view.setTypeface(Typeface.create(type, Typeface.BOLD_ITALIC));
+ }
+ }
+ return view;
+ }
+ }
+
+}
+
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/RssContentProvider.java b/samples/MySampleRss/src/com/example/codelab/rssexample/RssContentProvider.java
new file mode 100644
index 0000000..5d523dc
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/RssContentProvider.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.content.ContentProvider;
+import android.content.ContentProviderDatabaseHelper;
+import android.content.UriMatcher;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.content.ContentValues;
+import android.text.TextUtils;
+
+import java.util.logging.Logger;
+
+// Content Provider for RSS feed information. Each row describes a single
+// RSS feed. See the public static constants at the end of this class
+// to learn what each record contains.
+public class RssContentProvider extends ContentProvider {
+ private Logger mLogger = Logger.getLogger("com.example.codelab.rssexample");
+ private SQLiteDatabase mDb;
+ private DatabaseHelper mDbHelper = new DatabaseHelper();
+ private static final String DATABASE_NAME = "rssitems.db";
+ private static final String DATABASE_TABLE_NAME = "rssItems";
+ private static final int DB_VERSION = 1;
+ private static final int ALL_MESSAGES = 1;
+ private static final int SPECIFIC_MESSAGE = 2;
+
+ // Set up our URL matchers to help us determine what an
+ // incoming URI parameter is.
+ private static final UriMatcher URI_MATCHER;
+ static{
+ URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
+ URI_MATCHER.addURI("my_rss_item", "rssitem", ALL_MESSAGES);
+ URI_MATCHER.addURI("my_rss_item", "rssitem/#", SPECIFIC_MESSAGE);
+ }
+
+ // Here's the public URI used to query for RSS items.
+ public static final Uri CONTENT_URI = Uri.parse( "content://my_rss_item/rssitem");
+
+ // Here are our column name constants, used to query for field values.
+ public static final String ID = "_id";
+ public static final String URL = "url";
+ public static final String TITLE = "title";
+ public static final String HAS_BEEN_READ = "hasbeenread";
+ public static final String CONTENT = "rawcontent";
+ public static final String LAST_UPDATED = "lastupdated";
+ public static final String DEFAULT_SORT_ORDER = TITLE + " DESC";
+
+ // Database creation/version management helper.
+ // Create it statically because we don't need to have customized instances.
+ private static class DatabaseHelper extends ContentProviderDatabaseHelper{
+
+ @Override
+ public void onCreate(SQLiteDatabase db){
+ try{
+ String sql = "CREATE TABLE " + DATABASE_TABLE_NAME + "(" +
+ ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ URL + " TEXT," +
+ TITLE + " TEXT," +
+ HAS_BEEN_READ + " BOOLEAN DEFAULT 0," +
+ CONTENT + " TEXT," +
+ LAST_UPDATED + " INTEGER DEFAULT 0);";
+ Logger.getLogger("com.example.codelab.rssexample").info("DatabaseHelper.onCreate(): SQL statement: " + sql);
+ db.execSQL(sql);
+ Logger.getLogger("com.example.codelab.rssexample").info("DatabaseHelper.onCreate(): Created a database");
+ } catch (SQLException e) {
+ Logger.getLogger("com.example.codelab.rssexample").warning("DatabaseHelper.onCreate(): Couldn't create a database!");
+ }
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
+ // Don't have any upgrades yet, so if this gets called for some reason we'll
+ // just drop the existing table, and recreate the database with the
+ // standard method.
+ db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE_NAME + ";");
+
+ }
+ }
+
+ @Override
+ public boolean onCreate() {
+ // First we need to open the database. If this is our first time,
+ // the attempt to retrieve a database will throw
+ // FileNotFoundException, and we will then create the database.
+ final Context con = getContext();
+ try{
+ mDb = mDbHelper.openDatabase(getContext(), DATABASE_NAME, null, DB_VERSION);
+ mLogger.info("RssContentProvider.onCreate(): Opened a database");
+ } catch (Exception ex) {
+ return false;
+ }
+ if(mDb == null){
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ // Convert the URI into a custom MIME type.
+ // Our UriMatcher will parse the URI to decide whether the
+ // URI is for a single item or a list.
+ @Override
+ public String getType(Uri uri) {
+ switch (URI_MATCHER.match(uri)){
+ case ALL_MESSAGES:
+ return "vnd.android.cursor.dir/rssitem"; // List of items.
+ case SPECIFIC_MESSAGE:
+ return "vnd.android.cursor.item/rssitem"; // Specific item.
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String groupBy, String having, String sortOrder) {
+ // We won't bother checking the validity of params here, but you should!
+
+ // SQLiteQueryBuilder is the helper class that creates the
+ // proper SQL syntax for us.
+ SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
+
+ // Set the table we're querying.
+ qBuilder.setTables(DATABASE_TABLE_NAME);
+
+ // If the query ends in a specific record number, we're
+ // being asked for a specific record, so set the
+ // WHERE clause in our query.
+ if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
+ qBuilder.appendWhere("_id=" + uri.getPathLeafId());
+ }
+
+ // Set sort order. If none specified, use default.
+ if(TextUtils.isEmpty(sortOrder)){
+ sortOrder = DEFAULT_SORT_ORDER;
+ }
+
+ // Make the query.
+ Cursor c = qBuilder.query(mDb,
+ projection,
+ selection,
+ selectionArgs,
+ groupBy,
+ having,
+ sortOrder);
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+ return c;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String whereClause) {
+ // NOTE Argument checking code omitted. Check your parameters!
+ int updateCount = mDb.update(DATABASE_TABLE_NAME, values, whereClause);
+
+ // Notify any listeners and return the updated row count.
+ getContext().getContentResolver().notifyUpdate(uri, null);
+ return updateCount;
+ }
+
+ @Override
+ public Uri insert(Uri requestUri, ContentValues initialValues) {
+ // NOTE Argument checking code omitted. Check your parameters! Check that
+ // your row addition request succeeded!
+
+ long rowId = -1;
+ rowId = mDb.insert(DATABASE_TABLE_NAME, "rawcontent", initialValues);
+ Uri newUri = CONTENT_URI.addId(rowId);
+
+ // Notify any listeners and return the URI of the new row.
+ getContext().getContentResolver().notifyInsert(CONTENT_URI, null);
+ return newUri;
+ }
+
+ @Override
+ public int delete(Uri uri, String where) {
+ // NOTE Argument checking code omitted. Check your parameters!
+ int rowCount = mDb.delete(DATABASE_TABLE_NAME, ID + " = " + uri.getPathLeafId());
+
+ // Notify any listeners and return the deleted row count.
+ getContext().getContentResolver().notifyDelete(uri, null);
+ return rowCount;
+ }
+}
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/RssItem.java b/samples/MySampleRss/src/com/example/codelab/rssexample/RssItem.java
new file mode 100644
index 0000000..f13357d
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/RssItem.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import java.util.Date;
+
+// Custom class to hold an RSS item.
+public class RssItem{
+ public String url;
+ public String title;
+ public boolean hasBeenRead = false;
+ public String content;
+ public Date lastUpdated;
+
+ public RssItem(String url, String title){
+ this.url = url;
+ this.title = title;
+ }
+
+ @Override public String toString(){
+ return title;
+ }
+}
diff --git a/samples/MySampleRss/src/com/example/codelab/rssexample/RssService.java b/samples/MySampleRss/src/com/example/codelab/rssexample/RssService.java
new file mode 100644
index 0000000..e84f89d
--- /dev/null
+++ b/samples/MySampleRss/src/com/example/codelab/rssexample/RssService.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2007 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.codelab.rssexample;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Bundle;
+import android.database.Cursor;
+import android.content.ContentResolver;
+import android.os.Handler;
+import android.text.TextUtils;
+import java.io.BufferedReader;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.lang.StringBuilder;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.GregorianCalendar;
+import java.text.SimpleDateFormat;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.text.ParseException;
+
+public class RssService extends Service implements Runnable{
+ private Logger mLogger = Logger.getLogger(this.getPackageName());
+ public static final String REQUERY_KEY = "Requery_All"; // Sent to tell us force a requery.
+ public static final String RSS_URL = "RSS_URL"; // Sent to tell us to requery a specific item.
+ private NotificationManager mNM;
+ private Cursor mCur; // RSS content provider cursor.
+ private GregorianCalendar mLastCheckedTime; // Time we last checked our feeds.
+ private final String LAST_CHECKED_PREFERENCE = "last_checked";
+ static final int UPDATE_FREQUENCY_IN_MINUTES = 60;
+ private Handler mHandler; // Handler to trap our update reminders.
+ private final int NOTIFY_ID = 1; // Identifies our service icon in the icon tray.
+
+ @Override
+ protected void onCreate(){
+ // Display an icon to show that the service is running.
+ mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ Intent clickIntent = new Intent(Intent.ACTION_MAIN);
+ clickIntent.setClassName(MyRssReader5.class.getName());
+ Notification note = new Notification(this, R.drawable.rss_icon, "RSS Service",
+ clickIntent, null);
+ mNM.notify(NOTIFY_ID, note);
+ mHandler = new Handler();
+
+ // Create the intent that will be launched if the user clicks the
+ // icon on the status bar. This will launch our RSS Reader app.
+ Intent intent = new Intent(MyRssReader.class);
+
+ // Get a cursor over the RSS items.
+ ContentResolver rslv = getContentResolver();
+ mCur = rslv.query(RssContentProvider.CONTENT_URI, null, null, null, null);
+
+ // Load last updated value.
+ // We store last updated value in preferences.
+ SharedPreferences pref = getSharedPreferences("", 0);
+ mLastCheckedTime = new GregorianCalendar();
+ mLastCheckedTime.setTimeInMillis(pref.getLong(LAST_CHECKED_PREFERENCE, 0));
+
+//BEGIN_INCLUDE(5_1)
+ // Need to run ourselves on a new thread, because
+ // we will be making resource-intensive HTTP calls.
+ // Our run() method will check whether we need to requery
+ // our sources.
+ Thread thr = new Thread(null, this, "rss_service_thread");
+ thr.start();
+//END_INCLUDE(5_1)
+ mLogger.info("RssService created");
+ }
+
+//BEGIN_INCLUDE(5_3)
+ // A cheap way to pass a message to tell the service to requery.
+ @Override
+ protected void onStart(Intent intent, int startId){
+ super.onStart(startId, arguments);
+ Bundle arguments = intent.getExtras();
+ if(arguments != null) {
+ if(arguments.containsKey(REQUERY_KEY)) {
+ queryRssItems();
+ }
+ if(arguments.containsKey(RSS_URL)) {
+ // Typically called after adding a new RSS feed to the list.
+ queryItem(arguments.getString(RSS_URL));
+ }
+ }
+ }
+//END_INCLUDE(5_3)
+
+ // When the service is destroyed, get rid of our persistent icon.
+ @Override
+ protected void onDestroy(){
+ mNM.cancel(NOTIFY_ID);
+ }
+
+ // Determines whether the next scheduled check time has passed.
+ // Loads this value from a stored preference. If it has (or if no
+ // previous value has been stored), it will requery all RSS feeds;
+ // otherwise, it will post a delayed reminder to check again after
+ // now - next_check_time milliseconds.
+ public void queryIfPeriodicRefreshRequired() {
+ GregorianCalendar nextCheckTime = new GregorianCalendar();
+ nextCheckTime = (GregorianCalendar) mLastCheckedTime.clone();
+ nextCheckTime.add(GregorianCalendar.MINUTE, UPDATE_FREQUENCY_IN_MINUTES);
+ mLogger.info("last checked time:" + mLastCheckedTime.toString() + " Next checked time: " + nextCheckTime.toString());
+
+ if(mLastCheckedTime.before(nextCheckTime)) {
+ queryRssItems();
+ } else {
+ // Post a message to query again when we get to the next check time.
+ long timeTillNextUpdate = mLastCheckedTime.getTimeInMillis() - GregorianCalendar.getInstance().getTimeInMillis();
+ mHandler.postDelayed(this, 1000 * 60 * UPDATE_FREQUENCY_IN_MINUTES);
+ }
+
+ }
+
+ // Query all feeds. If the new feed has a newer pubDate than the previous,
+ // then update it.
+ void queryRssItems(){
+ mLogger.info("Querying Rss feeds...");
+
+ // The cursor might have gone stale. Requery to be sure.
+ // We need to call next() after a requery to get to the
+ // first record.
+ mCur.requery();
+ while (mCur.next()){
+ // Get the URL for the feed from the cursor.
+ int urlColumnIndex = mCur.getColumnIndex(RssContentProvider.URL);
+ String url = mCur.getString(urlColumnIndex);
+ queryItem(url);
+ }
+ // Reset the global "last checked" time
+ mLastCheckedTime.setTimeInMillis(System.currentTimeMillis());
+
+ // Post a message to query again in [update_frequency] minutes
+ mHandler.postDelayed(this, 1000 * 60 * UPDATE_FREQUENCY_IN_MINUTES);
+ }
+
+
+ // Query an individual RSS feed. Returns true if successful, false otherwise.
+ private boolean queryItem(String url) {
+ try {
+ URL wrappedUrl = new URL(url);
+ String rssFeed = readRss(wrappedUrl);
+ mLogger.info("RSS Feed " + url + ":\n " + rssFeed);
+ if(TextUtils.isEmpty(rssFeed)) {
+ return false;
+ }
+
+ // Parse out the feed update date, and compare to the current version.
+ // If feed update time is newer, or zero (if never updated, for new
+ // items), then update the content, date, and hasBeenRead fields.
+ // lastUpdated = <rss><channel><pubDate>value</pubDate></channel></rss>.
+ // If that value doesn't exist, the current date is used.
+ GregorianCalendar feedPubDate = parseRssDocPubDate(rssFeed);
+ GregorianCalendar lastUpdated = new GregorianCalendar();
+ int lastUpdatedColumnIndex = mCur.getColumnIndex(RssContentProvider.LAST_UPDATED);
+ lastUpdated.setTimeInMillis(mCur.getLong(lastUpdatedColumnIndex));
+ if(lastUpdated.getTimeInMillis() == 0 ||
+ lastUpdated.before(feedPubDate) && !TextUtils.isEmpty(rssFeed)) {
+ // Get column indices.
+ int contentColumnIndex = mCur.getColumnIndex(RssContentProvider.CONTENT);
+ int updatedColumnIndex = mCur.getColumnIndex(RssContentProvider.HAS_BEEN_READ);
+
+ // Update values.
+ mCur.updateString(contentColumnIndex, rssFeed);
+ mCur.updateLong(lastUpdatedColumnIndex, feedPubDate.getTimeInMillis());
+ mCur.updateInt(updatedColumnIndex, 0);
+ mCur.commitUpdates();
+ }
+ } catch (MalformedURLException ex) {
+ mLogger.warning("Error in queryItem: Bad url");
+ return false;
+ }
+ return true;
+ }
+
+ // BEGIN_INCLUDE(5_2)
+ // Get the <pubDate> content from a feed and return a
+ // GregorianCalendar version of the date.
+ // If the element doesn't exist or otherwise can't be
+ // found, return a date of 0 to force a refresh.
+ private GregorianCalendar parseRssDocPubDate(String xml){
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTimeInMillis(0);
+ String patt ="<[\\s]*pubDate[\\s]*>(.+?)</pubDate[\\s]*>";
+ Pattern p = Pattern.compile(patt);
+ Matcher m = p.matcher(xml);
+ try {
+ if(m.find()) {
+ mLogger.info("pubDate: " + m.group());
+ SimpleDateFormat pubDate = new SimpleDateFormat();
+ cal.setTime(pubDate.parse(m.group(1)));
+ }
+ } catch(ParseException ex) {
+ mLogger.warning("parseRssDocPubDate couldn't find a <pubDate> tag. Returning default value.");
+ }
+ return cal;
+ }
+
+ // Read the submitted RSS page.
+ String readRss(URL url){
+ String html = "<html><body><h2>No data</h2></body></html>";
+ try {
+ mLogger.info("URL is:" + url.toString());
+ BufferedReader inStream =
+ new BufferedReader(new InputStreamReader(url.openStream()),
+ 1024);
+ String line;
+ StringBuilder rssFeed = new StringBuilder();
+ while ((line = inStream.readLine()) != null){
+ rssFeed.append(line);
+ }
+ html = rssFeed.toString();
+ } catch(IOException ex) {
+ mLogger.warning("Couldn't open an RSS stream");
+ }
+ return html;
+ }
+//END_INCLUDE(5_2)
+
+ // Callback we send to ourself to requery all feeds.
+ public void run() {
+ queryIfPeriodicRefreshRequired();
+ }
+
+ // Required by Service. We won't implement it here, but need to
+ // include this basic code.
+ @Override
+ public IBinder onBind(Intent intent){
+ return mBinder;
+ }
+
+ // This is the object that receives RPC calls from clients.See
+ // RemoteService for a more complete example.
+ private final IBinder mBinder = new Binder() {
+ @Override
+ protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
+ return super.onTransact(code, data, reply, flags);
+ }
+ };
+}
diff --git a/samples/NotePad/Android.mk b/samples/NotePad/Android.mk
new file mode 100644
index 0000000..7939212
--- /dev/null
+++ b/samples/NotePad/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := NotePad
+
+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/NotePad/AndroidManifest.xml b/samples/NotePad/AndroidManifest.xml
new file mode 100644
index 0000000..5c56daf
--- /dev/null
+++ b/samples/NotePad/AndroidManifest.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.notepad"
+>
+ <application android:icon="@drawable/app_notes"
+ android:label="@string/app_name"
+ >
+ <provider android:name="NotePadProvider"
+ android:authorities="com.google.provider.NotePad"
+ />
+
+ <activity android:name="NotesList" android:label="@string/title_notes_list">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <action android:name="android.intent.action.EDIT" />
+ <action android:name="android.intent.action.PICK" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.GET_CONTENT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="NoteEditor"
+ android:theme="@android:style/Theme.Light"
+ android:label="@string/title_note"
+ android:screenOrientation="sensor"
+ android:configChanges="keyboardHidden|orientation"
+ >
+ <!-- This filter says that we can view or edit the data of
+ a single note -->
+ <intent-filter android:label="@string/resolve_edit">
+ <action android:name="android.intent.action.VIEW" />
+ <action android:name="android.intent.action.EDIT" />
+ <action android:name="com.android.notepad.action.EDIT_NOTE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
+ </intent-filter>
+
+ <!-- This filter says that we can create a new note inside
+ of a directory of notes. -->
+ <intent-filter>
+ <action android:name="android.intent.action.INSERT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
+ </intent-filter>
+
+ </activity>
+
+ <activity android:name="TitleEditor" android:label="@string/title_edit_title"
+ android:theme="@android:style/Theme.Dialog"
+ android:windowSoftInputMode="stateVisible">
+ <!-- This activity implements an alternative action that can be
+ performed on notes: editing their title. It can be used as
+ a default operation if the user invokes this action, and is
+ available as an alternative action for any note data. -->
+ <intent-filter android:label="@string/resolve_title">
+ <!-- This is the action we perform. It is a custom action we
+ define for our application, not a generic VIEW or EDIT
+ action since we are not a general note viewer/editor. -->
+ <action android:name="com.android.notepad.action.EDIT_TITLE" />
+ <!-- DEFAULT: execute if being directly invoked. -->
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- ALTERNATIVE: show as an alternative action when the user is
+ working with this type of data. -->
+ <category android:name="android.intent.category.ALTERNATIVE" />
+ <!-- SELECTED_ALTERNATIVE: show as an alternative action the user
+ can perform when selecting this type of data. -->
+ <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
+ <!-- This is the data type we operate on. -->
+ <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
+
diff --git a/samples/NotePad/_index.html b/samples/NotePad/_index.html
new file mode 100644
index 0000000..2a18969
--- /dev/null
+++ b/samples/NotePad/_index.html
@@ -0,0 +1,12 @@
+<p>A simple note pad application.
+It demonstrates...
+<ul>
+<li>using views
+<li>accessing a database
+<li>using an intent to open a new window
+<li>managing activity lifecycle
+<li>and many other goodies...
+</ul>
+</p>
+<img alt="Note Pad Example" class="gallery" src="sample_notepad.png" >
+<img alt="Note Pad Example" class="gallery" src="sample_note.png" >
diff --git a/samples/NotePad/res/drawable/app_notes.png b/samples/NotePad/res/drawable/app_notes.png
new file mode 100644
index 0000000..0479138
--- /dev/null
+++ b/samples/NotePad/res/drawable/app_notes.png
Binary files differ
diff --git a/samples/NotePad/res/layout/note_editor.xml b/samples/NotePad/res/layout/note_editor.xml
new file mode 100644
index 0000000..c54a963
--- /dev/null
+++ b/samples/NotePad/res/layout/note_editor.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.example.android.notepad.NoteEditor$LinedEditText"
+ android:id="@+id/note"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@android:color/transparent"
+ android:padding="5dip"
+ android:scrollbars="vertical"
+ android:fadingEdge="vertical"
+ android:gravity="top"
+ android:textSize="22sp"
+ android:capitalize="sentences"
+/>
diff --git a/samples/NotePad/res/layout/noteslist_item.xml b/samples/NotePad/res/layout/noteslist_item.xml
new file mode 100644
index 0000000..b167734
--- /dev/null
+++ b/samples/NotePad/res/layout/noteslist_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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="@android:id/text1"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:paddingLeft="5dip"
+ android:singleLine="true"
+/>
diff --git a/samples/NotePad/res/layout/title_editor.xml b/samples/NotePad/res/layout/title_editor.xml
new file mode 100644
index 0000000..3593ec6
--- /dev/null
+++ b/samples/NotePad/res/layout/title_editor.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip"
+ android:paddingBottom="3dip">
+
+ <EditText android:id="@+id/title"
+ android:maxLines="1"
+ android:layout_marginTop="2dip"
+ android:layout_width="wrap_content"
+ android:ems="25"
+ android:layout_height="wrap_content"
+ android:autoText="true"
+ android:capitalize="sentences"
+ android:scrollHorizontally="true" />
+
+ <Button android:id="@+id/ok"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:text="@string/button_ok" />
+
+</LinearLayout>
diff --git a/samples/NotePad/res/values/strings.xml b/samples/NotePad/res/values/strings.xml
new file mode 100644
index 0000000..b4bf671
--- /dev/null
+++ b/samples/NotePad/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="menu_delete">Delete</string>
+ <string name="menu_insert">Add note</string>
+ <string name="menu_revert">Revert</string>
+ <string name="menu_discard">Discard</string>
+
+ <string name="resolve_edit">Edit note</string>
+ <string name="resolve_title">Edit title</string>
+
+ <string name="title_create">Create note</string>
+ <string name="title_edit">Edit note</string>
+ <string name="title_notes_list">Note pad</string>
+ <string name="title_note">Note</string>
+ <string name="title_edit_title">Note title:</string>
+
+ <string name="app_name">Note Pad</string>
+
+ <string name="button_ok">OK</string>
+
+ <string name="error_title">Error</string>
+ <string name="error_message">Error loading note</string>
+</resources>
diff --git a/samples/NotePad/sample_note.png b/samples/NotePad/sample_note.png
new file mode 100644
index 0000000..cea1a08
--- /dev/null
+++ b/samples/NotePad/sample_note.png
Binary files differ
diff --git a/samples/NotePad/sample_notepad.png b/samples/NotePad/sample_notepad.png
new file mode 100644
index 0000000..c498847
--- /dev/null
+++ b/samples/NotePad/sample_notepad.png
Binary files differ
diff --git a/samples/NotePad/src/com/example/android/notepad/NoteEditor.java b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
new file mode 100644
index 0000000..e45efd8
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2007 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.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.EditText;
+
+/**
+ * A generic activity for editing a note in a database. This can be used
+ * either to simply view a note {@link Intent#ACTION_VIEW}, view and edit a note
+ * {@link Intent#ACTION_EDIT}, or create a new note {@link Intent#ACTION_INSERT}.
+ */
+public class NoteEditor extends Activity {
+ private static final String TAG = "Notes";
+
+ /**
+ * Standard projection for the interesting columns of a normal note.
+ */
+ private static final String[] PROJECTION = new String[] {
+ Notes._ID, // 0
+ Notes.NOTE, // 1
+ };
+ /** The index of the note column */
+ private static final int COLUMN_INDEX_NOTE = 1;
+
+ // This is our state data that is stored when freezing.
+ private static final String ORIGINAL_CONTENT = "origContent";
+
+ // Identifiers for our menu items.
+ private static final int REVERT_ID = Menu.FIRST;
+ private static final int DISCARD_ID = Menu.FIRST + 1;
+ private static final int DELETE_ID = Menu.FIRST + 2;
+
+ // The different distinct states the activity can be run in.
+ private static final int STATE_EDIT = 0;
+ private static final int STATE_INSERT = 1;
+
+ private int mState;
+ private boolean mNoteOnly = false;
+ private Uri mUri;
+ private Cursor mCursor;
+ private EditText mText;
+ private String mOriginalContent;
+
+ /**
+ * A custom EditText that draws lines between each line of text that is displayed.
+ */
+ public static class LinedEditText extends EditText {
+ private Rect mRect;
+ private Paint mPaint;
+
+ // we need this constructor for LayoutInflater
+ public LinedEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mRect = new Rect();
+ mPaint = new Paint();
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(0x800000FF);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ int count = getLineCount();
+ Rect r = mRect;
+ Paint paint = mPaint;
+
+ for (int i = 0; i < count; i++) {
+ int baseline = getLineBounds(i, r);
+
+ canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
+ }
+
+ super.onDraw(canvas);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Intent intent = getIntent();
+
+ // Do some setup based on the action being performed.
+
+ final String action = intent.getAction();
+ if (Intent.ACTION_EDIT.equals(action)) {
+ // Requested to edit: set that state, and the data being edited.
+ mState = STATE_EDIT;
+ mUri = intent.getData();
+ } else if (Intent.ACTION_INSERT.equals(action)) {
+ // Requested to insert: set that state, and create a new entry
+ // in the container.
+ mState = STATE_INSERT;
+ mUri = getContentResolver().insert(intent.getData(), null);
+
+ // If we were unable to create a new note, then just finish
+ // this activity. A RESULT_CANCELED will be sent back to the
+ // original activity if they requested a result.
+ if (mUri == null) {
+ Log.e(TAG, "Failed to insert new note into " + getIntent().getData());
+ finish();
+ return;
+ }
+
+ // The new entry was created, so assume all will end well and
+ // set the result to be returned.
+ setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
+
+ } else {
+ // Whoops, unknown action! Bail.
+ Log.e(TAG, "Unknown action, exiting");
+ finish();
+ return;
+ }
+
+ // Set the layout for this activity. You can find it in res/layout/note_editor.xml
+ setContentView(R.layout.note_editor);
+
+ // The text view for our note, identified by its ID in the XML file.
+ mText = (EditText) findViewById(R.id.note);
+
+ // Get the note!
+ mCursor = managedQuery(mUri, PROJECTION, null, null, null);
+
+ // If an instance of this activity had previously stopped, we can
+ // get the original text it started with.
+ if (savedInstanceState != null) {
+ mOriginalContent = savedInstanceState.getString(ORIGINAL_CONTENT);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // If we didn't have any trouble retrieving the data, it is now
+ // time to get at the stuff.
+ if (mCursor != null) {
+ // Make sure we are at the one and only row in the cursor.
+ mCursor.moveToFirst();
+
+ // Modify our overall title depending on the mode we are running in.
+ if (mState == STATE_EDIT) {
+ setTitle(getText(R.string.title_edit));
+ } else if (mState == STATE_INSERT) {
+ setTitle(getText(R.string.title_create));
+ }
+
+ // This is a little tricky: we may be resumed after previously being
+ // paused/stopped. We want to put the new text in the text view,
+ // but leave the user where they were (retain the cursor position
+ // etc). This version of setText does that for us.
+ String note = mCursor.getString(COLUMN_INDEX_NOTE);
+ mText.setTextKeepState(note);
+
+ // If we hadn't previously retrieved the original text, do so
+ // now. This allows the user to revert their changes.
+ if (mOriginalContent == null) {
+ mOriginalContent = note;
+ }
+
+ } else {
+ setTitle(getText(R.string.error_title));
+ mText.setText(getText(R.string.error_message));
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ // Save away the original text, so we still have it if the activity
+ // needs to be killed while paused.
+ outState.putString(ORIGINAL_CONTENT, mOriginalContent);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ // The user is going somewhere else, so make sure their current
+ // changes are safely saved away in the provider. We don't need
+ // to do this if only editing.
+ if (mCursor != null) {
+ String text = mText.getText().toString();
+ int length = text.length();
+
+ // If this activity is finished, and there is no text, then we
+ // do something a little special: simply delete the note entry.
+ // Note that we do this both for editing and inserting... it
+ // would be reasonable to only do it when inserting.
+ if (isFinishing() && (length == 0) && !mNoteOnly) {
+ setResult(RESULT_CANCELED);
+ deleteNote();
+
+ // Get out updates into the provider.
+ } else {
+ ContentValues values = new ContentValues();
+
+ // This stuff is only done when working with a full-fledged note.
+ if (!mNoteOnly) {
+ // Bump the modification time to now.
+ values.put(Notes.MODIFIED_DATE, System.currentTimeMillis());
+
+ // If we are creating a new note, then we want to also create
+ // an initial title for it.
+ if (mState == STATE_INSERT) {
+ String title = text.substring(0, Math.min(30, length));
+ if (length > 30) {
+ int lastSpace = title.lastIndexOf(' ');
+ if (lastSpace > 0) {
+ title = title.substring(0, lastSpace);
+ }
+ }
+ values.put(Notes.TITLE, title);
+ }
+ }
+
+ // Write our text back into the provider.
+ values.put(Notes.NOTE, text);
+
+ // Commit all of our changes to persistent storage. When the update completes
+ // the content provider will notify the cursor of the change, which will
+ // cause the UI to be updated.
+ getContentResolver().update(mUri, values, null, null);
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ // Build the menus that are shown when editing.
+ if (mState == STATE_EDIT) {
+ menu.add(0, REVERT_ID, 0, R.string.menu_revert)
+ .setShortcut('0', 'r')
+ .setIcon(android.R.drawable.ic_menu_revert);
+ if (!mNoteOnly) {
+ menu.add(0, DELETE_ID, 0, R.string.menu_delete)
+ .setShortcut('1', 'd')
+ .setIcon(android.R.drawable.ic_menu_delete);
+ }
+
+ // Build the menus that are shown when inserting.
+ } else {
+ menu.add(0, DISCARD_ID, 0, R.string.menu_discard)
+ .setShortcut('0', 'd')
+ .setIcon(android.R.drawable.ic_menu_delete);
+ }
+
+ // If we are working on a full note, then append to the
+ // menu items for any other activities that can do stuff with it
+ // as well. This does a query on the system for any activities that
+ // implement the ALTERNATIVE_ACTION for our data, adding a menu item
+ // for each one that is found.
+ if (!mNoteOnly) {
+ Intent intent = new Intent(null, getIntent().getData());
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
+ new ComponentName(this, NoteEditor.class), null, intent, 0, null);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle all of the possible menu actions.
+ switch (item.getItemId()) {
+ case DELETE_ID:
+ deleteNote();
+ finish();
+ break;
+ case DISCARD_ID:
+ cancelNote();
+ break;
+ case REVERT_ID:
+ cancelNote();
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Take care of canceling work on a note. Deletes the note if we
+ * had created it, otherwise reverts to the original text.
+ */
+ private final void cancelNote() {
+ if (mCursor != null) {
+ if (mState == STATE_EDIT) {
+ // Put the original note text back into the database
+ mCursor.close();
+ mCursor = null;
+ ContentValues values = new ContentValues();
+ values.put(Notes.NOTE, mOriginalContent);
+ getContentResolver().update(mUri, values, null, null);
+ } else if (mState == STATE_INSERT) {
+ // We inserted an empty note, make sure to delete it
+ deleteNote();
+ }
+ }
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+ /**
+ * Take care of deleting a note. Simply deletes the entry.
+ */
+ private final void deleteNote() {
+ if (mCursor != null) {
+ mCursor.close();
+ mCursor = null;
+ getContentResolver().delete(mUri, null, null);
+ mText.setText("");
+ }
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/NotePad.java b/samples/NotePad/src/com/example/android/notepad/NotePad.java
new file mode 100644
index 0000000..25be23e
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NotePad.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007 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.notepad;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Convenience definitions for NotePadProvider
+ */
+public final class NotePad {
+ public static final String AUTHORITY = "com.google.provider.NotePad";
+
+ // This class cannot be instantiated
+ private NotePad() {}
+
+ /**
+ * Notes table
+ */
+ public static final class Notes implements BaseColumns {
+ // This class cannot be instantiated
+ private Notes() {}
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of notes.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} sub-directory of a single note.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "modified DESC";
+
+ /**
+ * The title of the note
+ * <P>Type: TEXT</P>
+ */
+ public static final String TITLE = "title";
+
+ /**
+ * The note itself
+ * <P>Type: TEXT</P>
+ */
+ public static final String NOTE = "note";
+
+ /**
+ * The timestamp for when the note was created
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public static final String CREATED_DATE = "created";
+
+ /**
+ * The timestamp for when the note was last modified
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public static final String MODIFIED_DATE = "modified";
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java b/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java
new file mode 100644
index 0000000..f1d3fdc
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2007 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.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * Provides access to a database of notes. Each note has a title, the note
+ * itself, a creation date and a modified data.
+ */
+public class NotePadProvider extends ContentProvider {
+
+ private static final String TAG = "NotePadProvider";
+
+ private static final String DATABASE_NAME = "note_pad.db";
+ private static final int DATABASE_VERSION = 2;
+ private static final String NOTES_TABLE_NAME = "notes";
+
+ private static HashMap<String, String> sNotesProjectionMap;
+
+ private static final int NOTES = 1;
+ private static final int NOTE_ID = 2;
+
+ private static final UriMatcher sUriMatcher;
+
+ /**
+ * This class helps open, create, and upgrade the database file.
+ */
+ private static class DatabaseHelper extends SQLiteOpenHelper {
+
+ DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " ("
+ + Notes._ID + " INTEGER PRIMARY KEY,"
+ + Notes.TITLE + " TEXT,"
+ + Notes.NOTE + " TEXT,"
+ + Notes.CREATED_DATE + " INTEGER,"
+ + Notes.MODIFIED_DATE + " INTEGER"
+ + ");");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ + newVersion + ", which will destroy all old data");
+ db.execSQL("DROP TABLE IF EXISTS notes");
+ onCreate(db);
+ }
+ }
+
+ private DatabaseHelper mOpenHelper;
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ qb.setTables(NOTES_TABLE_NAME);
+ qb.setProjectionMap(sNotesProjectionMap);
+ break;
+
+ case NOTE_ID:
+ qb.setTables(NOTES_TABLE_NAME);
+ qb.setProjectionMap(sNotesProjectionMap);
+ qb.appendWhere(Notes._ID + "=" + uri.getPathSegments().get(1));
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ // If no sort order is specified use the default
+ String orderBy;
+ if (TextUtils.isEmpty(sortOrder)) {
+ orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;
+ } else {
+ orderBy = sortOrder;
+ }
+
+ // Get the database and run the query
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
+
+ // Tell the cursor what uri to watch, so it knows when its source data changes
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+ return c;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ return Notes.CONTENT_TYPE;
+
+ case NOTE_ID:
+ return Notes.CONTENT_ITEM_TYPE;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ // Validate the requested uri
+ if (sUriMatcher.match(uri) != NOTES) {
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ ContentValues values;
+ if (initialValues != null) {
+ values = new ContentValues(initialValues);
+ } else {
+ values = new ContentValues();
+ }
+
+ Long now = Long.valueOf(System.currentTimeMillis());
+
+ // Make sure that the fields are all set
+ if (values.containsKey(NotePad.Notes.CREATED_DATE) == false) {
+ values.put(NotePad.Notes.CREATED_DATE, now);
+ }
+
+ if (values.containsKey(NotePad.Notes.MODIFIED_DATE) == false) {
+ values.put(NotePad.Notes.MODIFIED_DATE, now);
+ }
+
+ if (values.containsKey(NotePad.Notes.TITLE) == false) {
+ Resources r = Resources.getSystem();
+ values.put(NotePad.Notes.TITLE, r.getString(android.R.string.untitled));
+ }
+
+ if (values.containsKey(NotePad.Notes.NOTE) == false) {
+ values.put(NotePad.Notes.NOTE, "");
+ }
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, values);
+ if (rowId > 0) {
+ Uri noteUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);
+ getContext().getContentResolver().notifyChange(noteUri, null);
+ return noteUri;
+ }
+
+ throw new SQLException("Failed to insert row into " + uri);
+ }
+
+ @Override
+ public int delete(Uri uri, String where, String[] whereArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ count = db.delete(NOTES_TABLE_NAME, where, whereArgs);
+ break;
+
+ case NOTE_ID:
+ String noteId = uri.getPathSegments().get(1);
+ count = db.delete(NOTES_TABLE_NAME, Notes._ID + "=" + noteId
+ + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ count = db.update(NOTES_TABLE_NAME, values, where, whereArgs);
+ break;
+
+ case NOTE_ID:
+ String noteId = uri.getPathSegments().get(1);
+ count = db.update(NOTES_TABLE_NAME, values, Notes._ID + "=" + noteId
+ + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ static {
+ sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);
+ sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);
+
+ sNotesProjectionMap = new HashMap<String, String>();
+ sNotesProjectionMap.put(Notes._ID, Notes._ID);
+ sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE);
+ sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE);
+ sNotesProjectionMap.put(Notes.CREATED_DATE, Notes.CREATED_DATE);
+ sNotesProjectionMap.put(Notes.MODIFIED_DATE, Notes.MODIFIED_DATE);
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/NotesList.java b/samples/NotePad/src/com/example/android/notepad/NotesList.java
new file mode 100644
index 0000000..ceaaa3c
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NotesList.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2007 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.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.app.ListActivity;
+import android.content.ComponentName;
+import android.content.ContentUris;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+
+/**
+ * Displays a list of notes. Will display notes from the {@link Uri}
+ * provided in the intent if there is one, otherwise defaults to displaying the
+ * contents of the {@link NotePadProvider}
+ */
+public class NotesList extends ListActivity {
+ private static final String TAG = "NotesList";
+
+ // Menu item ids
+ public static final int MENU_ITEM_DELETE = Menu.FIRST;
+ public static final int MENU_ITEM_INSERT = Menu.FIRST + 1;
+
+ /**
+ * The columns we are interested in from the database
+ */
+ private static final String[] PROJECTION = new String[] {
+ Notes._ID, // 0
+ Notes.TITLE, // 1
+ };
+
+ /** The index of the title column */
+ private static final int COLUMN_INDEX_TITLE = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
+
+ // If no data was given in the intent (because we were started
+ // as a MAIN activity), then use our default content provider.
+ Intent intent = getIntent();
+ if (intent.getData() == null) {
+ intent.setData(Notes.CONTENT_URI);
+ }
+
+ // Inform the list we provide context menus for items
+ getListView().setOnCreateContextMenuListener(this);
+
+ // Perform a managed query. The Activity will handle closing and requerying the cursor
+ // when needed.
+ Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null,
+ Notes.DEFAULT_SORT_ORDER);
+
+ // Used to map notes entries from the database to views
+ SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor,
+ new String[] { Notes.TITLE }, new int[] { android.R.id.text1 });
+ setListAdapter(adapter);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ // This is our one standard application action -- inserting a
+ // new note into the list.
+ menu.add(0, MENU_ITEM_INSERT, 0, R.string.menu_insert)
+ .setShortcut('3', 'a')
+ .setIcon(android.R.drawable.ic_menu_add);
+
+ // Generate any additional actions that can be performed on the
+ // overall list. In a normal install, there are no additional
+ // actions found here, but this allows other applications to extend
+ // our menu with their own actions.
+ Intent intent = new Intent(null, getIntent().getData());
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
+ new ComponentName(this, NotesList.class), null, intent, 0, null);
+
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ final boolean haveItems = getListAdapter().getCount() > 0;
+
+ // If there are any notes in the list (which implies that one of
+ // them is selected), then we need to generate the actions that
+ // can be performed on the current selection. This will be a combination
+ // of our own specific actions along with any extensions that can be
+ // found.
+ if (haveItems) {
+ // This is the selected item.
+ Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());
+
+ // Build menu... always starts with the EDIT action...
+ Intent[] specifics = new Intent[1];
+ specifics[0] = new Intent(Intent.ACTION_EDIT, uri);
+ MenuItem[] items = new MenuItem[1];
+
+ // ... is followed by whatever other actions are available...
+ Intent intent = new Intent(null, uri);
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,
+ items);
+
+ // Give a shortcut to the edit action.
+ if (items[0] != null) {
+ items[0].setShortcut('1', 'e');
+ }
+ } else {
+ menu.removeGroup(Menu.CATEGORY_ALTERNATIVE);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_ITEM_INSERT:
+ // Launch activity to insert a new item
+ startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
+ AdapterView.AdapterContextMenuInfo info;
+ try {
+ info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ } catch (ClassCastException e) {
+ Log.e(TAG, "bad menuInfo", e);
+ return;
+ }
+
+ Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
+ if (cursor == null) {
+ // For some reason the requested item isn't available, do nothing
+ return;
+ }
+
+ // Setup the menu header
+ menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));
+
+ // Add a menu item to delete the note
+ menu.add(0, MENU_ITEM_DELETE, 0, R.string.menu_delete);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ AdapterView.AdapterContextMenuInfo info;
+ try {
+ info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
+ } catch (ClassCastException e) {
+ Log.e(TAG, "bad menuInfo", e);
+ return false;
+ }
+
+ switch (item.getItemId()) {
+ case MENU_ITEM_DELETE: {
+ // Delete the note that the context menu is for
+ Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
+ getContentResolver().delete(noteUri, null, null);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Uri uri = ContentUris.withAppendedId(getIntent().getData(), id);
+
+ String action = getIntent().getAction();
+ if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) {
+ // The caller is waiting for us to return a note selected by
+ // the user. The have clicked on one, so return it now.
+ setResult(RESULT_OK, new Intent().setData(uri));
+ } else {
+ // Launch activity to view/edit the currently selected item
+ startActivity(new Intent(Intent.ACTION_EDIT, uri));
+ }
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/TitleEditor.java b/samples/NotePad/src/com/example/android/notepad/TitleEditor.java
new file mode 100644
index 0000000..50d38e5
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/TitleEditor.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 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.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.app.Activity;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+/**
+ * An activity that will edit the title of a note. Displays a floating
+ * window with a text field.
+ */
+public class TitleEditor extends Activity implements View.OnClickListener {
+
+ /**
+ * This is a special intent action that means "edit the title of a note".
+ */
+ public static final String EDIT_TITLE_ACTION = "com.android.notepad.action.EDIT_TITLE";
+
+ /**
+ * An array of the columns we are interested in.
+ */
+ private static final String[] PROJECTION = new String[] {
+ NotePad.Notes._ID, // 0
+ NotePad.Notes.TITLE, // 1
+ };
+ /** Index of the title column */
+ private static final int COLUMN_INDEX_TITLE = 1;
+
+ /**
+ * Cursor which will provide access to the note whose title we are editing.
+ */
+ private Cursor mCursor;
+
+ /**
+ * The EditText field from our UI. Keep track of this so we can extract the
+ * text when we are finished.
+ */
+ private EditText mText;
+
+ /**
+ * The content URI to the note that's being edited.
+ */
+ private Uri mUri;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.title_editor);
+
+ // Get the uri of the note whose title we want to edit
+ mUri = getIntent().getData();
+
+ // Get a cursor to access the note
+ mCursor = managedQuery(mUri, PROJECTION, null, null, null);
+
+ // Set up click handlers for the text field and button
+ mText = (EditText) this.findViewById(R.id.title);
+ mText.setOnClickListener(this);
+
+ Button b = (Button) findViewById(R.id.ok);
+ b.setOnClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // Initialize the text with the title column from the cursor
+ if (mCursor != null) {
+ mCursor.moveToFirst();
+ mText.setText(mCursor.getString(COLUMN_INDEX_TITLE));
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ if (mCursor != null) {
+ // Write the title back to the note
+ ContentValues values = new ContentValues();
+ values.put(Notes.TITLE, mText.getText().toString());
+ getContentResolver().update(mUri, values, null, null);
+ }
+ }
+
+ public void onClick(View v) {
+ // When the user clicks, just finish this activity.
+ // onPause will be called, and we save our data there.
+ finish();
+ }
+}
diff --git a/samples/NotePad/src/com/google/provider/NotePad.java b/samples/NotePad/src/com/google/provider/NotePad.java
new file mode 100644
index 0000000..f8de69b
--- /dev/null
+++ b/samples/NotePad/src/com/google/provider/NotePad.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007 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.google.provider;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Convenience definitions for NotePadProvider
+ */
+public final class NotePad {
+ /**
+ * Notes table
+ */
+ public static final class Notes implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI
+ = Uri.parse("content://com.google.provider.NotePad/notes");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "modified DESC";
+
+ /**
+ * The title of the note
+ * <P>Type: TEXT</P>
+ */
+ public static final String TITLE = "title";
+
+ /**
+ * The note itself
+ * <P>Type: TEXT</P>
+ */
+ public static final String NOTE = "note";
+
+ /**
+ * The timestamp for when the note was created
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String CREATED_DATE = "created";
+
+ /**
+ * The timestamp for when the note was last modified
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String MODIFIED_DATE = "modified";
+ }
+}
diff --git a/samples/NotePad/tests/Android.mk b/samples/NotePad/tests/Android.mk
new file mode 100644
index 0000000..43efafc
--- /dev/null
+++ b/samples/NotePad/tests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := NotePadTests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := NotePad
+
+include $(BUILD_PACKAGE)
diff --git a/samples/NotePad/tests/AndroidManifest.xml b/samples/NotePad/tests/AndroidManifest.xml
new file mode 100644
index 0000000..afd502b
--- /dev/null
+++ b/samples/NotePad/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.notepad.tests">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.notepad"
+ android:label="NotePad sample tests">
+ </instrumentation>
+
+</manifest>
diff --git a/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
new file mode 100644
index 0000000..452c599
--- /dev/null
+++ b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.notepad;
+
+import android.test.ActivityInstrumentationTestCase;
+
+import com.example.android.notepad.NotesList;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link ActivityTestCase#testActivityTestCaseSetUpProperly}.
+ */
+public class NotePadTest extends ActivityInstrumentationTestCase<NotesList> {
+
+ public NotePadTest() {
+ super("com.example.android.notepad", NotesList.class);
+ }
+
+}
diff --git a/samples/PlatformLibrary/Android.mk b/samples/PlatformLibrary/Android.mk
new file mode 100644
index 0000000..afb54a2
--- /dev/null
+++ b/samples/PlatformLibrary/Android.mk
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2008 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.
+#
+
+# This makefile shows how to build your own shared library that can be
+# shipped on the system of a phone, and included additional examples of
+# including JNI code with the library and writing client applications against it.
+
+LOCAL_PATH := $(call my-dir)
+
+# the library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_MODULE:= com.example.android.platform_library
+
+# Only compile source java files for the platform library.
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+
+include $(BUILD_JAVA_LIBRARY)
+
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := com.example.android.platform_library.xml
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_MODULE_CLASS := ETC
+
+# This will install the file in /system/etc/permissions
+#
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
+
+# ============================================================
+
+# Also build all of the sub-targets under this one: the library's
+# associated JNI code, and a sample client of the library.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/PlatformLibrary/README.txt b/samples/PlatformLibrary/README.txt
new file mode 100644
index 0000000..5ce9d2f
--- /dev/null
+++ b/samples/PlatformLibrary/README.txt
@@ -0,0 +1,74 @@
+Platform Library Example
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+This directory contains a full example of writing your own Android platform
+shared library, without changing the Android framework. It also shows how to
+write JNI code for incorporating native code into the library, and a client
+application that uses the library.
+
+This example is ONLY for people working with the open source platform to
+create a system image that will be delivered on a device which will include
+a custom library as shown here. It can not be used to create a third party
+shared library, which is not currently supported in Android.
+
+To declare your library to the framework, you must place a file with a .xml
+extension in the /system/etc/permissions directory with the following contents:
+
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+ <library name="com.example.android.platform_library"
+ file="/system/framework/com.example.android.platform_library.jar"/>
+</permissions>
+
+There are three major parts of this example, supplying three distinct
+build targets and corresponding build outputs:
+
+
+com.example.android.platform_library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The top-level Android.mk defines the rules to build the shared library itself,
+whose target is "com.example.android.platform_library". The code for this
+library lives under java/.
+
+Note that the product for this library is a raw .jar file, NOT a .apk, which
+means there is no manifest or resources associated with the library.
+Unfortunately this means that if you need any resources for the library, such
+as drawables or layout files, you will need to add these to the core framework
+resources under frameworks/base/res. Please make sure when doing this that
+you do not make any of these resources public, they should not become part of
+the Android API. In the future we will allow shared libraries to have their
+own resources.
+
+Other than that, the library is very straight-forward, and you can write
+basically whatever code you want. You can also put code in other Java
+namespaces -- the namespace given in the <library> tag above is just the
+public unique name by which clients will link to your library, but once this
+link happens all of the Java namespaces in that library will be available
+to the client.
+
+
+libplatform_library_jni
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This is an optional example of how to write JNI code associated with a
+shared library. This code lives under jni/. The jni/Android.mk file defines
+the rules for building the final .so in which the code lives. This example
+provides everything needed to hook up the native code with the Java library
+and call through to it, plus a very simple JNI call.
+
+
+PlatformLibraryClient
+~~~~~~~~~~~~~~~~~~~~~
+
+This shows an example of how you can write client applications for your new
+shared library. This code lives under client/. Note that the example is
+simply a regular Android .apk, like all of the other .apks created by the
+build system. The only two special things needed to use your library are:
+
+- A LOCAL_JAVA_LIBRARIES line in the Android.mk to have the build system link
+against your shared library.
+
+- A <uses-library> line in the AndroidManifest.xml to have the runtime load
+your library into the application.
diff --git a/samples/PlatformLibrary/client/Android.mk b/samples/PlatformLibrary/client/Android.mk
new file mode 100644
index 0000000..cfd5493
--- /dev/null
+++ b/samples/PlatformLibrary/client/Android.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2008 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.
+#
+
+# This makefile is an example of writing an application that will link against
+# a custom shared library included with an Android system.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_PACKAGE_NAME := PlatformLibraryClient
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Link against the current Android SDK.
+LOCAL_SDK_VERSION := current
+
+# Also link against our own custom library.
+LOCAL_JAVA_LIBRARIES := com.example.android.platform_library
+
+include $(BUILD_PACKAGE)
diff --git a/samples/PlatformLibrary/client/AndroidManifest.xml b/samples/PlatformLibrary/client/AndroidManifest.xml
new file mode 100644
index 0000000..be0d9a1
--- /dev/null
+++ b/samples/PlatformLibrary/client/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This is an example of writing a client application for a custom
+ platform library. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.platform_library.client">
+
+ <application android:label="Platform Lib Client">
+
+ <!-- This tells the system about the custom library used by the
+ application, so that it can be properly loaded and linked
+ to the app when the app is initialized. -->
+ <uses-library android:name="com.example.android.platform_library" />
+
+ <activity android:name="Client">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java b/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java
new file mode 100644
index 0000000..8722c72
--- /dev/null
+++ b/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 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.platform_library.client;
+
+import com.example.android.platform_library.PlatformLibrary;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+/**
+ * Use a custom platform library.
+ */
+public class Client extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Call an API on the library.
+ PlatformLibrary pl = new PlatformLibrary();
+ int res = pl.getInt(false);
+
+ // We'll just make our own view to show the result.
+ TextView tv = new TextView(this);
+ tv.setText("Got from lib: " + res);
+ setContentView(tv);
+ }
+}
+
diff --git a/samples/PlatformLibrary/com.example.android.platform_library.xml b/samples/PlatformLibrary/com.example.android.platform_library.xml
new file mode 100644
index 0000000..b9491d8
--- /dev/null
+++ b/samples/PlatformLibrary/com.example.android.platform_library.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+ <library name="com.example.android.platform_library"
+ file="/system/framework/com.example.android.platform_library.jar"/>
+</permissions>
diff --git a/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java b/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java
new file mode 100644
index 0000000..68154ec
--- /dev/null
+++ b/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 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.platform_library;
+
+import android.util.Config;
+import android.util.Log;
+
+public final class PlatformLibrary {
+ static {
+ /*
+ * Load the library. If it's already loaded, this does nothing.
+ */
+ System.loadLibrary("platform_library_jni");
+ }
+
+ private int mJniInt = -1;
+
+ public PlatformLibrary() {}
+
+ /*
+ * Test native methods.
+ */
+ public int getInt(boolean bad) {
+ /* this alters mJniInt */
+ int result = getJniInt(bad);
+
+ /* reverse a string, for no very good reason */
+ String reverse = reverseString("Android!");
+
+ Log.i("PlatformLibrary", "getInt: " + result + ", '" + reverse + "'");
+
+ return mJniInt;
+ }
+
+ /*
+ * Simple method, called from native code.
+ */
+ private static void yodel(String msg) {
+ Log.d("PlatformLibrary", "yodel: " + msg);
+ }
+
+ /*
+ * Trivial native method call. If "bad" is true, this will throw an
+ * exception.
+ */
+ native private int getJniInt(boolean bad);
+
+ /*
+ * Native method that returns a new string that is the reverse of
+ * the original. This also calls yodel().
+ */
+ native private static String reverseString(String str);
+}
diff --git a/samples/PlatformLibrary/jni/Android.mk b/samples/PlatformLibrary/jni/Android.mk
new file mode 100644
index 0000000..1bdefa1
--- /dev/null
+++ b/samples/PlatformLibrary/jni/Android.mk
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2008 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.
+#
+
+# This makefile supplies the rules for building a library of JNI code for
+# use by our example platform shared library.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_MODULE:= libplatform_library_jni
+
+# All of the source files that we will compile.
+LOCAL_SRC_FILES:= \
+ PlatformLibrary.cpp
+
+# All of the shared libraries we link against.
+LOCAL_SHARED_LIBRARIES := \
+ libandroid_runtime \
+ libnativehelper \
+ libcutils \
+ libutils
+
+# No static libraries.
+LOCAL_STATIC_LIBRARIES :=
+
+# Also need the JNI headers.
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE)
+
+# No specia compiler flags.
+LOCAL_CFLAGS +=
+
+# Don't prelink this library. For more efficient code, you may want
+# to add this library to the prelink map and set this to true.
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/samples/PlatformLibrary/jni/PlatformLibrary.cpp b/samples/PlatformLibrary/jni/PlatformLibrary.cpp
new file mode 100644
index 0000000..ad60002
--- /dev/null
+++ b/samples/PlatformLibrary/jni/PlatformLibrary.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#define LOG_TAG "PlatformLibrary"
+#include "utils/Log.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "jni.h"
+
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Field/method IDs and class object references.
+ *
+ * You should not need to store the JNIEnv pointer in here. It is
+ * thread-specific and will be passed back in on every call.
+ */
+static struct {
+ jclass platformLibraryClass;
+ jfieldID jniInt;
+ jmethodID yodel;
+} gCachedState;
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Helper function to throw an arbitrary exception.
+ *
+ * Takes the exception class name, a format string, and one optional integer
+ * argument (useful for including an error code, perhaps from errno).
+ */
+static void throwException(JNIEnv* env, const char* ex, const char* fmt,
+ int data) {
+
+ if (jclass cls = env->FindClass(ex)) {
+ if (fmt != NULL) {
+ char msg[1000];
+ snprintf(msg, sizeof(msg), fmt, data);
+ env->ThrowNew(cls, msg);
+ } else {
+ env->ThrowNew(cls, NULL);
+ }
+
+ /*
+ * This is usually not necessary -- local references are released
+ * automatically when the native code returns to the VM. It's
+ * required if the code doesn't actually return, e.g. it's sitting
+ * in a native event loop.
+ */
+ env->DeleteLocalRef(cls);
+ }
+}
+
+/*
+ * Trivial sample method.
+ *
+ * If "bad" is true, this throws an exception. Otherwise, this sets the
+ * "mJniInt" field to 42 and returns 24.
+ */
+static jint PlatformLibrary_getJniInt(JNIEnv* env, jobject thiz, jboolean bad) {
+ if (bad) {
+ throwException(env, "java/lang/IllegalStateException",
+ "you are bad", 0);
+ return 0; /* return value will be ignored */
+ }
+ env->SetIntField(thiz, gCachedState.jniInt, 42);
+ return (jint)24;
+}
+
+/*
+ * A more complex sample method.
+ *
+ * This takes a String as an argument, and returns a new String with
+ * characters in reverse order. The new string is passed to another method.
+ * This demonstrates basic String manipulation functions and method
+ * invocation.
+ *
+ * This method is declared "static", so there's no "this" pointer; instead,
+ * we get a pointer to the class object.
+ */
+static jstring PlatformLibrary_reverseString(JNIEnv* env, jclass clazz,
+ jstring str) {
+
+ if (str == NULL) {
+ throwException(env, "java/lang/NullPointerException", NULL, 0);
+ return NULL;
+ }
+
+ /*
+ * Get a pointer to the string's UTF-16 character data. The data
+ * may be a copy or a pointer to the original. Since String data
+ * is immutable, we're not allowed to touch it.
+ */
+ const jchar* strChars = env->GetStringChars(str, NULL);
+ if (strChars == NULL) {
+ /* something went wrong */
+ LOGW("Couldn't get string chars\n");
+ return NULL;
+ }
+ jsize strLength = env->GetStringLength(str);
+
+ /*
+ * Write a progress message to the log. Log messages are UTF-8, so
+ * we want to convert the string to show it.
+ */
+ const char* printable = env->GetStringUTFChars(str, NULL);
+ if (printable != NULL) {
+ LOGD("Reversing string '%s'\n", printable);
+ env->ReleaseStringUTFChars(str, printable);
+ }
+
+ /*
+ * Copy the characters to temporary storage, reversing as we go.
+ */
+ jchar tempChars[strLength];
+ for (int i = 0; i < strLength; i++) {
+ tempChars[i] = strChars[strLength -1 -i];
+ }
+
+ /*
+ * Release the original String. That way, if something fails later on,
+ * we don't have to worry about this leading to a memory leak.
+ */
+ env->ReleaseStringChars(str, strChars);
+ strChars = NULL; /* this pointer no longer valid */
+
+ /*
+ * Create a new String with the chars.
+ */
+ jstring result = env->NewString(tempChars, strLength);
+ if (result == NULL) {
+ LOGE("NewString failed\n");
+ return NULL;
+ }
+
+ /*
+ * Now let's do something with it. We already have the methodID for
+ * "yodel", so we can invoke it directly. It's in our class, so we
+ * can use the Class object reference that was passed in.
+ */
+ env->CallStaticVoidMethod(clazz, gCachedState.yodel, result);
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Array of methods.
+ *
+ * Each entry has three fields: the name of the method, the method
+ * signature, and a pointer to the native implementation.
+ */
+static const JNINativeMethod gMethods[] = {
+ { "getJniInt", "(Z)I",
+ (void*)PlatformLibrary_getJniInt },
+ { "reverseString", "(Ljava/lang/String;)Ljava/lang/String;",
+ (void*)PlatformLibrary_reverseString },
+};
+
+/*
+ * Do some (slow-ish) lookups now and save the results.
+ *
+ * Returns 0 on success.
+ */
+static int cacheIds(JNIEnv* env, jclass clazz) {
+ /*
+ * Save the class in case we want to use it later. Because this is a
+ * reference to the Class object, we need to convert it to a JNI global
+ * reference.
+ */
+ gCachedState.platformLibraryClass = (jclass) env->NewGlobalRef(clazz);
+ if (clazz == NULL) {
+ LOGE("Can't create new global ref\n");
+ return -1;
+ }
+
+ /*
+ * Cache field and method IDs. IDs are not references, which means we
+ * don't need to call NewGlobalRef on them.
+ */
+ gCachedState.jniInt = env->GetFieldID(clazz, "mJniInt", "I");
+ if (gCachedState.jniInt == NULL) {
+ LOGE("Can't find PlatformLibrary.mJniInt\n");
+ return -1;
+ }
+
+ gCachedState.yodel = env->GetStaticMethodID(clazz, "yodel",
+ "(Ljava/lang/String;)V");
+ if (gCachedState.yodel == NULL) {
+ LOGE("Can't find PlatformLibrary.yodel\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Explicitly register all methods for our class.
+ *
+ * While we're at it, cache some class references and method/field IDs.
+ *
+ * Returns 0 on success.
+ */
+static int registerMethods(JNIEnv* env) {
+ static const char* const kClassName =
+ "com/example/android/platform_library/PlatformLibrary";
+ jclass clazz;
+
+ /* look up the class */
+ clazz = env->FindClass(kClassName);
+ if (clazz == NULL) {
+ LOGE("Can't find class %s\n", kClassName);
+ return -1;
+ }
+
+ /* register all the methods */
+ if (env->RegisterNatives(clazz, gMethods,
+ sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
+ {
+ LOGE("Failed registering methods for %s\n", kClassName);
+ return -1;
+ }
+
+ /* fill out the rest of the ID cache */
+ return cacheIds(env, clazz);
+}
+
+// ----------------------------------------------------------------------------
+
+/*
+ * This is called by the VM when the shared library is first loaded.
+ */
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ LOGE("ERROR: GetEnv failed\n");
+ goto bail;
+ }
+ assert(env != NULL);
+
+ if (registerMethods(env) != 0) {
+ LOGE("ERROR: PlatformLibrary native registration failed\n");
+ goto bail;
+ }
+
+ /* success -- return valid version number */
+ result = JNI_VERSION_1_4;
+
+bail:
+ return result;
+}
diff --git a/samples/RSSReader/Android.mk b/samples/RSSReader/Android.mk
new file mode 100644
index 0000000..6f95cb4
--- /dev/null
+++ b/samples/RSSReader/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := RSSReader
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/samples/RSSReader/AndroidManifest.xml b/samples/RSSReader/AndroidManifest.xml
new file mode 100644
index 0000000..c59411d
--- /dev/null
+++ b/samples/RSSReader/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.rssreader">
+ <uses-permission android:name="android.permission.INTERNET" />
+ <application android:label="RSS Reader">
+ <activity android:name="RssReader">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
diff --git a/samples/RSSReader/res/layout/rss_layout.xml b/samples/RSSReader/res/layout/rss_layout.xml
new file mode 100644
index 0000000..842f4f7
--- /dev/null
+++ b/samples/RSSReader/res/layout/rss_layout.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dip"
+ android:orientation="vertical">
+
+ <EditText android:id="@+id/urltext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textSize="12sp"
+ android:autoText="false"
+ android:capitalize="none"
+ android:text="@string/rss_layout_urltext_text" />
+
+ <Button android:id="@+id/download"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/rss_layout_download_text" />
+
+ <TextView android:id="@+id/statustext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:autoText="false"
+ android:capitalize="none"
+ android:textSize="12sp"
+ android:text="@string/rss_layout_statustext_text" />
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:drawSelectorOnTop="false"/>
+
+</LinearLayout>
diff --git a/samples/RSSReader/res/values/strings.xml b/samples/RSSReader/res/values/strings.xml
new file mode 100644
index 0000000..83b7efe
--- /dev/null
+++ b/samples/RSSReader/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="rss_layout_urltext_text">http://rss.slashdot.org/Slashdot/slashdot</string>
+ <string name="rss_layout_statustext_text"></string>
+ <string name="rss_layout_download_text">Download</string>
+
+</resources>
diff --git a/samples/RSSReader/src/com/example/android/rssreader/RssItem.java b/samples/RSSReader/src/com/example/android/rssreader/RssItem.java
new file mode 100644
index 0000000..e1e798a
--- /dev/null
+++ b/samples/RSSReader/src/com/example/android/rssreader/RssItem.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 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.rssreader;
+
+/**
+ * Simple struct class to hold the data for one rss item --
+ * title, link, description.
+ */
+public class RssItem {
+ private CharSequence mTitle;
+ private CharSequence mLink;
+ private CharSequence mDescription;
+
+ public RssItem() {
+ mTitle = "";
+ mLink = "";
+ mDescription = "";
+ }
+
+ public RssItem(CharSequence title, CharSequence link, CharSequence description) {
+ mTitle = title;
+ mLink = link;
+ mDescription = description;
+ }
+
+ public CharSequence getDescription() {
+ return mDescription;
+ }
+
+ public void setDescription(CharSequence description) {
+ mDescription = description;
+ }
+
+ public CharSequence getLink() {
+ return mLink;
+ }
+
+ public void setLink(CharSequence link) {
+ mLink = link;
+ }
+
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ }
+
+// If we made this class Parcelable, the code would look like...
+
+// public void writeToParcel(Parcel parcel) {
+// parcel.writeString(mTitle.toString());
+// parcel.writeString(mLink.toString());
+// parcel.writeString(mDescription.toString());
+// }
+//
+//
+// public static Object createFromParcel(Parcel parcel) {
+// return new RssItem(
+// parcel.readString(),
+// parcel.readString(),
+// parcel.readString());
+// }
+}
+
diff --git a/samples/RSSReader/src/com/example/android/rssreader/RssReader.java b/samples/RSSReader/src/com/example/android/rssreader/RssReader.java
new file mode 100644
index 0000000..2f273c4
--- /dev/null
+++ b/samples/RSSReader/src/com/example/android/rssreader/RssReader.java
@@ -0,0 +1,599 @@
+/*
+ * Copyright (C) 2007 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.rssreader;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.TwoLineListItem;
+import android.util.Xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The RssReader example demonstrates forking off a thread to download
+ * rss data in the background and post the results to a ListView in the UI.
+ * It also shows how to display custom data in a ListView
+ * with a ArrayAdapter subclass.
+ *
+ * <ul>
+ * <li>We own a ListView
+ * <li>The ListView uses our custom RSSListAdapter which
+ * <ul>
+ * <li>The adapter feeds data to the ListView
+ * <li>Override of getView() in the adapter provides the display view
+ * used for selected list items
+ * </ul>
+ * <li>Override of onListItemClick() creates an intent to open the url for that
+ * RssItem in the browser.
+ * <li>Download = fork off a worker thread
+ * <li>The worker thread opens a network connection for the rss data
+ * <li>Uses XmlPullParser to extract the rss item data
+ * <li>Uses mHandler.post() to send new RssItems to the UI
+ * <li>Supports onSaveInstanceState()/onRestoreInstanceState() to save list/selection state on app
+ * pause, so can resume seamlessly
+ * </ul>
+ */
+public class RssReader extends ListActivity {
+ /**
+ * Custom list adapter that fits our rss data into the list.
+ */
+ private RSSListAdapter mAdapter;
+
+ /**
+ * Url edit text field.
+ */
+ private EditText mUrlText;
+
+ /**
+ * Status text field.
+ */
+ private TextView mStatusText;
+
+ /**
+ * Handler used to post runnables to the UI thread.
+ */
+ private Handler mHandler;
+
+ /**
+ * Currently running background network thread.
+ */
+ private RSSWorker mWorker;
+
+ // Take this many chars from the front of the description.
+ public static final int SNIPPET_LENGTH = 90;
+
+
+ // Keys used for data in the onSaveInstanceState() Map.
+ public static final String STRINGS_KEY = "strings";
+
+ public static final String SELECTION_KEY = "selection";
+
+ public static final String URL_KEY = "url";
+
+ public static final String STATUS_KEY = "status";
+
+ /**
+ * Called when the activity starts up. Do activity initialization
+ * here, not in a constructor.
+ *
+ * @see Activity#onCreate
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.rss_layout);
+ // The above layout contains a list id "android:list"
+ // which ListActivity adopts as its list -- we can
+ // access it with getListView().
+
+ // Install our custom RSSListAdapter.
+ List<RssItem> items = new ArrayList<RssItem>();
+ mAdapter = new RSSListAdapter(this, items);
+ getListView().setAdapter(mAdapter);
+
+ // Get pointers to the UI elements in the rss_layout
+ mUrlText = (EditText)findViewById(R.id.urltext);
+ mStatusText = (TextView)findViewById(R.id.statustext);
+
+ Button download = (Button)findViewById(R.id.download);
+ download.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ doRSS(mUrlText.getText());
+ }
+ });
+
+ // Need one of these to post things back to the UI thread.
+ mHandler = new Handler();
+
+ // NOTE: this could use the icicle as done in
+ // onRestoreInstanceState().
+ }
+
+ /**
+ * ArrayAdapter encapsulates a java.util.List of T, for presentation in a
+ * ListView. This subclass specializes it to hold RssItems and display
+ * their title/description data in a TwoLineListItem.
+ */
+ private class RSSListAdapter extends ArrayAdapter<RssItem> {
+ private LayoutInflater mInflater;
+
+ public RSSListAdapter(Context context, List<RssItem> objects) {
+ super(context, 0, objects);
+
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ /**
+ * This is called to render a particular item for the on screen list.
+ * Uses an off-the-shelf TwoLineListItem view, which contains text1 and
+ * text2 TextViews. We pull data from the RssItem and set it into the
+ * view. The convertView is the view from a previous getView(), so
+ * we can re-use it.
+ *
+ * @see ArrayAdapter#getView
+ */
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TwoLineListItem view;
+
+ // Here view may be passed in for re-use, or we make a new one.
+ if (convertView == null) {
+ view = (TwoLineListItem) mInflater.inflate(android.R.layout.simple_list_item_2,
+ null);
+ } else {
+ view = (TwoLineListItem) convertView;
+ }
+
+ RssItem item = this.getItem(position);
+
+ // Set the item title and description into the view.
+ // This example does not render real HTML, so as a hack to make
+ // the description look better, we strip out the
+ // tags and take just the first SNIPPET_LENGTH chars.
+ view.getText1().setText(item.getTitle());
+ String descr = item.getDescription().toString();
+ descr = removeTags(descr);
+ view.getText2().setText(descr.substring(0, Math.min(descr.length(), SNIPPET_LENGTH)));
+ return view;
+ }
+
+ }
+
+ /**
+ * Simple code to strip out <tag>s -- primitive way to sortof display HTML as
+ * plain text.
+ */
+ public String removeTags(String str) {
+ str = str.replaceAll("<.*?>", " ");
+ str = str.replaceAll("\\s+", " ");
+ return str;
+ }
+
+ /**
+ * Called when user clicks an item in the list. Starts an activity to
+ * open the url for that item.
+ */
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ RssItem item = mAdapter.getItem(position);
+
+ // Creates and starts an intent to open the item.link url.
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(item.getLink().toString()));
+ startActivity(intent);
+ }
+
+ /**
+ * Resets the output UI -- list and status text empty.
+ */
+ public void resetUI() {
+ // Reset the list to be empty.
+ List<RssItem> items = new ArrayList<RssItem>();
+ mAdapter = new RSSListAdapter(this, items);
+ getListView().setAdapter(mAdapter);
+
+ mStatusText.setText("");
+ mUrlText.requestFocus();
+ }
+
+ /**
+ * Sets the currently active running worker. Interrupts any earlier worker,
+ * so we only have one at a time.
+ *
+ * @param worker the new worker
+ */
+ public synchronized void setCurrentWorker(RSSWorker worker) {
+ if (mWorker != null) mWorker.interrupt();
+ mWorker = worker;
+ }
+
+ /**
+ * Is the given worker the currently active one.
+ *
+ * @param worker
+ * @return
+ */
+ public synchronized boolean isCurrentWorker(RSSWorker worker) {
+ return (mWorker == worker);
+ }
+
+ /**
+ * Given an rss url string, starts the rss-download-thread going.
+ *
+ * @param rssUrl
+ */
+ private void doRSS(CharSequence rssUrl) {
+ RSSWorker worker = new RSSWorker(rssUrl);
+ setCurrentWorker(worker);
+
+ resetUI();
+ mStatusText.setText("Downloading\u2026");
+
+ worker.start();
+ }
+
+ /**
+ * Runnable that the worker thread uses to post RssItems to the
+ * UI via mHandler.post
+ */
+ private class ItemAdder implements Runnable {
+ RssItem mItem;
+
+ ItemAdder(RssItem item) {
+ mItem = item;
+ }
+
+ public void run() {
+ mAdapter.add(mItem);
+ }
+
+ // NOTE: Performance idea -- would be more efficient to have he option
+ // to add multiple items at once, so you get less "update storm" in the UI
+ // compared to adding things one at a time.
+ }
+
+ /**
+ * Worker thread takes in an rss url string, downloads its data, parses
+ * out the rss items, and communicates them back to the UI as they are read.
+ */
+ private class RSSWorker extends Thread {
+ private CharSequence mUrl;
+
+ public RSSWorker(CharSequence url) {
+ mUrl = url;
+ }
+
+ @Override
+ public void run() {
+ String status = "";
+ try {
+ // Standard code to make an HTTP connection.
+ URL url = new URL(mUrl.toString());
+ URLConnection connection = url.openConnection();
+ connection.setConnectTimeout(10000);
+
+ connection.connect();
+ InputStream in = connection.getInputStream();
+
+ parseRSS(in, mAdapter);
+ status = "done";
+ } catch (Exception e) {
+ status = "failed:" + e.getMessage();
+ }
+
+ // Send status to UI (unless a newer worker has started)
+ // To communicate back to the UI from a worker thread,
+ // pass a Runnable to handler.post().
+ final String temp = status;
+ if (isCurrentWorker(this)) {
+ mHandler.post(new Runnable() {
+ public void run() {
+ mStatusText.setText(temp);
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Populates the menu.
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ menu.add(0, 0, 0, "Slashdot")
+ .setOnMenuItemClickListener(new RSSMenu("http://rss.slashdot.org/Slashdot/slashdot"));
+
+ menu.add(0, 0, 0, "Google News")
+ .setOnMenuItemClickListener(new RSSMenu("http://news.google.com/?output=rss"));
+
+ menu.add(0, 0, 0, "News.com")
+ .setOnMenuItemClickListener(new RSSMenu("http://news.com.com/2547-1_3-0-20.xml"));
+
+ menu.add(0, 0, 0, "Bad Url")
+ .setOnMenuItemClickListener(new RSSMenu("http://nifty.stanford.edu:8080"));
+
+ menu.add(0, 0, 0, "Reset")
+ .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ resetUI();
+ return true;
+ }
+ });
+
+ return true;
+ }
+
+ /**
+ * Puts text in the url text field and gives it focus. Used to make a Runnable
+ * for each menu item. This way, one inner class works for all items vs. an
+ * anonymous inner class for each menu item.
+ */
+ private class RSSMenu implements MenuItem.OnMenuItemClickListener {
+ private CharSequence mUrl;
+
+ RSSMenu(CharSequence url) {
+ mUrl = url;
+ }
+
+ public boolean onMenuItemClick(MenuItem item) {
+ mUrlText.setText(mUrl);
+ mUrlText.requestFocus();
+ return true;
+ }
+ }
+
+
+ /**
+ * Called for us to save out our current state before we are paused,
+ * such a for example if the user switches to another app and memory
+ * gets scarce. The given outState is a Bundle to which we can save
+ * objects, such as Strings, Integers or lists of Strings. In this case, we
+ * save out the list of currently downloaded rss data, (so we don't have to
+ * re-do all the networking just because the user goes back and forth
+ * between aps) which item is currently selected, and the data for the text views.
+ * In onRestoreInstanceState() we look at the map to reconstruct the run-state of the
+ * application, so returning to the activity looks seamlessly correct.
+ * TODO: the Activity javadoc should give more detail about what sort of
+ * data can go in the outState map.
+ *
+ * @see android.app.Activity#onSaveInstanceState
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ // Make a List of all the RssItem data for saving
+ // NOTE: there may be a way to save the RSSItems directly,
+ // rather than their string data.
+ int count = mAdapter.getCount();
+
+ // Save out the items as a flat list of CharSequence objects --
+ // title0, link0, descr0, title1, link1, ...
+ ArrayList<CharSequence> strings = new ArrayList<CharSequence>();
+ for (int i = 0; i < count; i++) {
+ RssItem item = mAdapter.getItem(i);
+ strings.add(item.getTitle());
+ strings.add(item.getLink());
+ strings.add(item.getDescription());
+ }
+ outState.putSerializable(STRINGS_KEY, strings);
+
+ // Save current selection index (if focussed)
+ if (getListView().hasFocus()) {
+ outState.putInt(SELECTION_KEY, Integer.valueOf(getListView().getSelectedItemPosition()));
+ }
+
+ // Save url
+ outState.putString(URL_KEY, mUrlText.getText().toString());
+
+ // Save status
+ outState.putCharSequence(STATUS_KEY, mStatusText.getText());
+ }
+
+ /**
+ * Called to "thaw" re-animate the app from a previous onSaveInstanceState().
+ *
+ * @see android.app.Activity#onRestoreInstanceState
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+
+ // Note: null is a legal value for onRestoreInstanceState.
+ if (state == null) return;
+
+ // Restore items from the big list of CharSequence objects
+ List<CharSequence> strings = (ArrayList<CharSequence>)state.getSerializable(STRINGS_KEY);
+ List<RssItem> items = new ArrayList<RssItem>();
+ for (int i = 0; i < strings.size(); i += 3) {
+ items.add(new RssItem(strings.get(i), strings.get(i + 1), strings.get(i + 2)));
+ }
+
+ // Reset the list view to show this data.
+ mAdapter = new RSSListAdapter(this, items);
+ getListView().setAdapter(mAdapter);
+
+ // Restore selection
+ if (state.containsKey(SELECTION_KEY)) {
+ getListView().requestFocus(View.FOCUS_FORWARD);
+ // todo: is above right? needed it to work
+ getListView().setSelection(state.getInt(SELECTION_KEY));
+ }
+
+ // Restore url
+ mUrlText.setText(state.getCharSequence(URL_KEY));
+
+ // Restore status
+ mStatusText.setText(state.getCharSequence(STATUS_KEY));
+ }
+
+
+
+ /**
+ * Does rudimentary RSS parsing on the given stream and posts rss items to
+ * the UI as they are found. Uses Android's XmlPullParser facility. This is
+ * not a production quality RSS parser -- it just does a basic job of it.
+ *
+ * @param in stream to read
+ * @param adapter adapter for ui events
+ */
+ void parseRSS(InputStream in, RSSListAdapter adapter) throws IOException,
+ XmlPullParserException {
+ // TODO: switch to sax
+
+ XmlPullParser xpp = Xml.newPullParser();
+ xpp.setInput(in, null); // null = parser figures out encoding
+
+ int eventType;
+ String title = "";
+ String link = "";
+ String description = "";
+ eventType = xpp.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tag = xpp.getName();
+ if (tag.equals("item")) {
+ title = link = description = "";
+ } else if (tag.equals("title")) {
+ xpp.next(); // Skip to next element -- assume text is directly inside the tag
+ title = xpp.getText();
+ } else if (tag.equals("link")) {
+ xpp.next();
+ link = xpp.getText();
+ } else if (tag.equals("description")) {
+ xpp.next();
+ description = xpp.getText();
+ }
+ } else if (eventType == XmlPullParser.END_TAG) {
+ // We have a comlete item -- post it back to the UI
+ // using the mHandler (necessary because we are not
+ // running on the UI thread).
+ String tag = xpp.getName();
+ if (tag.equals("item")) {
+ RssItem item = new RssItem(title, link, description);
+ mHandler.post(new ItemAdder(item));
+ }
+ }
+ eventType = xpp.next();
+ }
+ }
+
+ // SAX version of the code to do the parsing.
+ /*
+ private class RSSHandler extends DefaultHandler {
+ RSSListAdapter mAdapter;
+
+ String mTitle;
+ String mLink;
+ String mDescription;
+
+ StringBuilder mBuff;
+
+ boolean mInItem;
+
+ public RSSHandler(RSSListAdapter adapter) {
+ mAdapter = adapter;
+ mInItem = false;
+ mBuff = new StringBuilder();
+ }
+
+ public void startElement(String uri,
+ String localName,
+ String qName,
+ Attributes atts)
+ throws SAXException {
+ String tag = localName;
+ if (tag.equals("")) tag = qName;
+
+ // If inside <item>, clear out buff on each tag start
+ if (mInItem) {
+ mBuff.delete(0, mBuff.length());
+ }
+
+ if (tag.equals("item")) {
+ mTitle = mLink = mDescription = "";
+ mInItem = true;
+ }
+ }
+
+ public void characters(char[] ch,
+ int start,
+ int length)
+ throws SAXException {
+ // Buffer up all the chars when inside <item>
+ if (mInItem) mBuff.append(ch, start, length);
+ }
+
+ public void endElement(String uri,
+ String localName,
+ String qName)
+ throws SAXException {
+ String tag = localName;
+ if (tag.equals("")) tag = qName;
+
+ // For each tag, copy buff chars to right variable
+ if (tag.equals("title")) mTitle = mBuff.toString();
+ else if (tag.equals("link")) mLink = mBuff.toString();
+ if (tag.equals("description")) mDescription = mBuff.toString();
+
+ // Have all the data at this point .... post it to the UI.
+ if (tag.equals("item")) {
+ RssItem item = new RssItem(mTitle, mLink, mDescription);
+ mHandler.post(new ItemAdder(item));
+ mInItem = false;
+ }
+ }
+ }
+ */
+
+ /*
+ public void parseRSS2(InputStream in, RSSListAdapter adapter) throws IOException {
+ SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ DefaultHandler handler = new RSSHandler(adapter);
+
+ parser.parse(in, handler);
+ // TODO: does the parser figure out the encoding right on its own?
+ }
+ */
+}
diff --git a/samples/SimpleJNI/Android.mk b/samples/SimpleJNI/Android.mk
new file mode 100644
index 0000000..a45ada8
--- /dev/null
+++ b/samples/SimpleJNI/Android.mk
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2008 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.
+#
+
+# This makefile shows how to build a shared library and an activity that
+# bundles the shared library and calls it using JNI.
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+LOCAL_PATH:= $(TOP_LOCAL_PATH)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := SimpleJNI
+
+LOCAL_JNI_SHARED_LIBRARIES := libsimplejni
+
+include $(BUILD_PACKAGE)
+
+# ============================================================
+
+# Also build all of the sub-targets under this one: the shared library.
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/samples/SimpleJNI/AndroidManifest.xml b/samples/SimpleJNI/AndroidManifest.xml
new file mode 100644
index 0000000..b163d55
--- /dev/null
+++ b/samples/SimpleJNI/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- This is an example of writing an application that bundles a
+ native code library. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.simplejni">
+ <application android:label="Simple JNI">
+ <activity android:name="SimpleJNI">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/samples/SimpleJNI/jni/Android.mk b/samples/SimpleJNI/jni/Android.mk
new file mode 100644
index 0000000..528196b
--- /dev/null
+++ b/samples/SimpleJNI/jni/Android.mk
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2008 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.
+#
+
+# This makefile supplies the rules for building a library of JNI code for
+# use by our example of how to bundle a shared library with an APK.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_MODULE:= libsimplejni
+
+
+# All of the source files that we will compile.
+LOCAL_SRC_FILES:= \
+ native.cpp
+
+# All of the shared libraries we link against.
+LOCAL_SHARED_LIBRARIES := \
+ libutils
+
+# No static libraries.
+LOCAL_STATIC_LIBRARIES :=
+
+# Also need the JNI headers.
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE)
+
+# No special compiler flags.
+LOCAL_CFLAGS +=
+
+# Don't prelink this library. For more efficient code, you may want
+# to add this library to the prelink map and set this to true. However,
+# it's difficult to do this for applications that are not supplied as
+# part of a system image.
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/samples/SimpleJNI/jni/native.cpp b/samples/SimpleJNI/jni/native.cpp
new file mode 100644
index 0000000..4d2e4e0
--- /dev/null
+++ b/samples/SimpleJNI/jni/native.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#define LOG_TAG "simplejni native.cpp"
+#include <utils/Log.h>
+
+#include <stdio.h>
+
+#include "jni.h"
+
+static jint
+add(JNIEnv *env, jobject thiz, jint a, jint b) {
+int result = a + b;
+ LOGI("%d + %d = %d", a, b, result);
+ return result;
+}
+
+static const char *classPathName = "com/example/android/simplejni/Native";
+
+static JNINativeMethod methods[] = {
+ {"add", "(II)I", (void*)add },
+};
+
+/*
+ * Register several native methods for one class.
+ */
+static int registerNativeMethods(JNIEnv* env, const char* className,
+ JNINativeMethod* gMethods, int numMethods)
+{
+ jclass clazz;
+
+ clazz = env->FindClass(className);
+ if (clazz == NULL) {
+ LOGE("Native registration unable to find class '%s'", className);
+ return JNI_FALSE;
+ }
+ if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
+ LOGE("RegisterNatives failed for '%s'", className);
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+/*
+ * Register native methods for all classes we know about.
+ *
+ * returns JNI_TRUE on success.
+ */
+static int registerNatives(JNIEnv* env)
+{
+ if (!registerNativeMethods(env, classPathName,
+ methods, sizeof(methods) / sizeof(methods[0]))) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+
+// ----------------------------------------------------------------------------
+
+/*
+ * This is called by the VM when the shared library is first loaded.
+ */
+
+typedef union {
+ JNIEnv* env;
+ void* venv;
+} UnionJNIEnvToVoid;
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ UnionJNIEnvToVoid uenv;
+ uenv.venv = NULL;
+ jint result = -1;
+ JNIEnv* env = NULL;
+
+ LOGI("JNI_OnLoad");
+
+ if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
+ LOGE("ERROR: GetEnv failed");
+ goto bail;
+ }
+ env = uenv.env;
+
+ if (registerNatives(env) != JNI_TRUE) {
+ LOGE("ERROR: registerNatives failed");
+ goto bail;
+ }
+
+ result = JNI_VERSION_1_4;
+
+bail:
+ return result;
+}
diff --git a/samples/SimpleJNI/src/com/example/android/simplejni/SimpleJNI.java b/samples/SimpleJNI/src/com/example/android/simplejni/SimpleJNI.java
new file mode 100644
index 0000000..e83cd21
--- /dev/null
+++ b/samples/SimpleJNI/src/com/example/android/simplejni/SimpleJNI.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 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.simplejni;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class SimpleJNI extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView tv = new TextView(this);
+ int sum = Native.add(2, 3);
+ tv.setText("2 + 3 = " + Integer.toString(sum));
+ setContentView(tv);
+ }
+}
+
+class Native {
+ static {
+ // The runtime will add "lib" on the front and ".o" on the end of
+ // the name supplied to loadLibrary.
+ System.loadLibrary("simplejni");
+ }
+
+ static native int add(int a, int b);
+}
diff --git a/samples/SkeletonApp/Android.mk b/samples/SkeletonApp/Android.mk
new file mode 100644
index 0000000..5bada02
--- /dev/null
+++ b/samples/SkeletonApp/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SkeletonApp
+
+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/SkeletonApp/AndroidManifest.xml b/samples/SkeletonApp/AndroidManifest.xml
new file mode 100644
index 0000000..b0b4ef2
--- /dev/null
+++ b/samples/SkeletonApp/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- This file describes the code in the SkeletonApp package, which is
+ used by the system to determine how to start your application and
+ integrate it with the rest of the system. -->
+
+<!-- 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.skeletonapp">
+
+ <!-- This package contains an application... The 'label' is the name
+ to display to the user for the overall application, and provides
+ a default label for all following components. The syntax here is a
+ reference to one of our string resources.-->
+ <application android:label="@string/skeleton_app">
+
+ <!-- An Activity in the application - this is something the user
+ can launch and interact with. The "name" attribute is the
+ name of the class within your package that implements this
+ activity. -->
+ <activity android:name="SkeletonActivity">
+
+ <!-- An IntentFilter tells the system when it should use your
+ activity. This allows the user to get to your activity
+ without someone having to explicitly know to launch your
+ class "com.examplel.android.skeletonapp.SkeletonActivity". -->
+ <intent-filter>
+ <!-- The MAIN action describes a main entry point into an
+ activity, without any associated data. -->
+ <action android:name="android.intent.action.MAIN" />
+
+ <!-- This places this activity into the main app list. -->
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/samples/SkeletonApp/readme.txt b/samples/SkeletonApp/readme.txt
new file mode 100644
index 0000000..1ebddbd
--- /dev/null
+++ b/samples/SkeletonApp/readme.txt
@@ -0,0 +1,65 @@
+Android Skeleton App
+~~~~~~~~~~~~~~~~~~~~
+
+
+This directory contains the full implementation of a basic application for
+the Android platform, demonstrating the basic facilities that applications
+will use. You can run the application either directly from the "test"
+list in the app launcher (it is named Skeleton App) or by selecting it from
+the top list in the Sample Code app.
+
+The files contained here:
+
+
+AndroidManifest.xml
+
+This XML file describes to the Android platform what your application can do.
+It is a required file, and is the mechanism you use to show your application
+to the user (in the app launcher's list), handle data types, etc.
+
+
+src/*
+
+Under this directory is the Java source for for your application.
+
+
+src/com/android/skeletonapp/SkeletonActivity.java
+
+This is the implementation of the "activity" feature described in
+AndroidManifest.xml. The path each class implementation is
+{src/PACKAGE/CLASS.java}, where PACKAGE comes from the name in the <package>
+tag and CLASS comes from the class in the <activity> tag.
+
+
+res/*
+
+Under this directory are the resources for your application.
+
+
+res/layout/skeleton_activity.xml
+
+The res/layout/ directory contains XML files describing user interface
+view hierarchies. The skeleton_activity.xml file here is used by
+SkeletonActivity.java to construct its UI. The base name of each file
+(all text before a '.' character) is taken as the resource name;
+it must be lower-case.
+
+
+res/drawable/violet.png
+
+The res/drawable/ directory contains images and other things that can be
+drawn to the screen. These can be bitmaps (in .png or .jpeg format) or
+special XML files describing more complex drawings. The violet.png file
+here is used as the image to display in one of the views in
+skeleton_activity.xml. Like layout files, the base name is used for the
+resulting resource name.
+
+
+res/values/colors.xml
+res/values/strings.xml
+res/values/styles.xml
+
+These XML files describe additional resources included in the application.
+They all use the same syntax; all of these resources could be defined in one
+file, but we generally split them apart as shown here to keep things organized.
+
diff --git a/samples/SkeletonApp/res/drawable/violet.jpg b/samples/SkeletonApp/res/drawable/violet.jpg
new file mode 100644
index 0000000..d892c40
--- /dev/null
+++ b/samples/SkeletonApp/res/drawable/violet.jpg
Binary files differ
diff --git a/samples/SkeletonApp/res/layout/skeleton_activity.xml b/samples/SkeletonApp/res/layout/skeleton_activity.xml
new file mode 100644
index 0000000..b8dcac7
--- /dev/null
+++ b/samples/SkeletonApp/res/layout/skeleton_activity.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- This file describes the layout of the main SkeletonApp activity
+ user interface.
+ -->
+
+<!-- The top view is a layout manager that places its child views into
+ a row, here set to be vertical (so the first is at the top) -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+
+ <!-- First view is a text editor. We want it to use all available
+ horizontal space, and stretch to fill whatever vertical space
+ is available to it. Note the use of the "id" attribute, which
+ allows us to find this object from the Java code. -->
+ <EditText android:id="@+id/editor"
+ android:layout_width="fill_parent" android:layout_height="0dip"
+ android:autoText="true"
+ android:capitalize="sentences"
+ android:layout_weight="1"
+ android:freezesText="true" >
+ <requestFocus />
+ </EditText>
+
+ <!-- Next view is another linear layout manager, now horizontal. We
+ give it a custom background; see colors.xml for the definition
+ of drawable/semi_black-->
+ <LinearLayout
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" android:gravity="center_horizontal"
+ android:orientation="horizontal"
+ android:background="@drawable/semi_black">
+
+ <!-- On the left: the "back" button. See styles.xml for the
+ definition of style/ActionButton, which we use to hold
+ common attributes that are used for both this and the
+ clear button. See strings.xml for the definition of
+ string/back. -->
+ <Button android:id="@+id/back" style="@style/ActionButton"
+ android:text="@string/back" />
+
+ <!-- In the middle: a custom image, -->
+ <ImageView android:id="@+id/image"
+ android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:paddingLeft="4dip" android_paddingRight="4dip"
+ android:src="@drawable/violet" />
+
+ <!-- On the right: another button, this time with its text color
+ changed to red. Again, see colors.xml for the definition. -->
+ <Button android:id="@+id/clear" style="@style/ActionButton"
+ android:text="@string/clear" android:textColor="@color/red" />
+
+ </LinearLayout>
+
+</LinearLayout>
+
+
diff --git a/samples/SkeletonApp/res/values/colors.xml b/samples/SkeletonApp/res/values/colors.xml
new file mode 100644
index 0000000..1d985bc
--- /dev/null
+++ b/samples/SkeletonApp/res/values/colors.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- This file contains resource definitions for solid colors. In
+ addition to plain color resources (retrieved via Resources.getColor()
+ and friends), we are also using it to define drawables that are
+ a solid color. -->
+
+<resources>
+ <!-- Retrieved via Resources.getColor() and friends. -->
+ <color name="red">#f00</color>
+
+ <!-- Retrieved via Resources.getDrawable() and friends. -->
+ <drawable name="semi_black">#80000000</drawable>
+</resources>
diff --git a/samples/SkeletonApp/res/values/strings.xml b/samples/SkeletonApp/res/values/strings.xml
new file mode 100644
index 0000000..4dc998d
--- /dev/null
+++ b/samples/SkeletonApp/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+ them to be changed based on the locale and options. -->
+
+<resources>
+ <!-- Simple strings. -->
+ <string name="skeleton_app">Skeleton App</string>
+ <string name="back">Back</string>
+ <string name="clear">Clear</string>
+
+ <!-- This is a complex string containing style runs. -->
+ <string name="main_label">Hello <u>th<ignore>e</ignore>re</u>, <i>you</i> <b>Activity</b>!</string>
+</resources>
+
diff --git a/samples/SkeletonApp/res/values/styles.xml b/samples/SkeletonApp/res/values/styles.xml
new file mode 100644
index 0000000..050514f
--- /dev/null
+++ b/samples/SkeletonApp/res/values/styles.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<!-- This file contains resource definitions for style. A style is
+ a collection of named values that can be applied as a group. Here,
+ we are using a style to define a common set of XML attributes that
+ will be used in multiple tags. -->
+
+<resources>
+ <style name="ActionButton">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textAppearance">@style/TextAppearance.ActionButton</item>
+ </style>
+
+ <style name="TextAppearance" parent="android:TextAppearance">
+ </style>
+
+ <style name="TextAppearance.ActionButton">
+ <item name="android:textStyle">italic</item>
+ </style>
+
+</resources>
+
diff --git a/samples/SkeletonApp/src/com/example/android/skeletonapp/SkeletonActivity.java b/samples/SkeletonApp/src/com/example/android/skeletonapp/SkeletonActivity.java
new file mode 100644
index 0000000..7abf3ae
--- /dev/null
+++ b/samples/SkeletonApp/src/com/example/android/skeletonapp/SkeletonActivity.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2007 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.skeletonapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+
+/**
+ * This class provides a basic demonstration of how to write an Android
+ * activity. Inside of its window, it places a single view: an EditText that
+ * displays and edits some internal text.
+ */
+public class SkeletonActivity extends Activity {
+
+ static final private int BACK_ID = Menu.FIRST;
+ static final private int CLEAR_ID = Menu.FIRST + 1;
+
+ private EditText mEditor;
+
+ public SkeletonActivity() {
+ }
+
+ /** Called with the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Inflate our UI from its XML layout description.
+ setContentView(R.layout.skeleton_activity);
+
+ // Find the text editor view inside the layout, because we
+ // want to do various programmatic things with it.
+ mEditor = (EditText) findViewById(R.id.editor);
+
+ // Hook up button presses to the appropriate event handler.
+ ((Button) findViewById(R.id.back)).setOnClickListener(mBackListener);
+ ((Button) findViewById(R.id.clear)).setOnClickListener(mClearListener);
+
+ mEditor.setText(getText(R.string.main_label));
+ }
+
+ /**
+ * Called when the activity is about to start interacting with the user.
+ */
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ /**
+ * Called when your activity's options menu needs to be created.
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ // We are going to create two menus. Note that we assign them
+ // unique integer IDs, labels from our string resources, and
+ // given them shortcuts.
+ menu.add(0, BACK_ID, 0, R.string.back).setShortcut('0', 'b');
+ menu.add(0, CLEAR_ID, 0, R.string.clear).setShortcut('1', 'c');
+
+ return true;
+ }
+
+ /**
+ * Called right before your activity's option menu is displayed.
+ */
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+
+ // Before showing the menu, we need to decide whether the clear
+ // item is enabled depending on whether there is text to clear.
+ menu.findItem(CLEAR_ID).setVisible(mEditor.getText().length() > 0);
+
+ return true;
+ }
+
+ /**
+ * Called when a menu item is selected.
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case BACK_ID:
+ finish();
+ return true;
+ case CLEAR_ID:
+ mEditor.setText("");
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * A call-back for when the user presses the back button.
+ */
+ OnClickListener mBackListener = new OnClickListener() {
+ public void onClick(View v) {
+ finish();
+ }
+ };
+
+ /**
+ * A call-back for when the user presses the clear button.
+ */
+ OnClickListener mClearListener = new OnClickListener() {
+ public void onClick(View v) {
+ mEditor.setText("");
+ }
+ };
+}
diff --git a/samples/SkeletonApp/tests/Android.mk b/samples/SkeletonApp/tests/Android.mk
new file mode 100644
index 0000000..7f26bfa
--- /dev/null
+++ b/samples/SkeletonApp/tests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := SkeletonAppTests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := SkeletonApp
+
+include $(BUILD_PACKAGE)
diff --git a/samples/SkeletonApp/tests/AndroidManifest.xml b/samples/SkeletonApp/tests/AndroidManifest.xml
new file mode 100644
index 0000000..fac1f41
--- /dev/null
+++ b/samples/SkeletonApp/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.skeletonapp.tests">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.skeletonapp"
+ android:label="SkeletonApp sample tests">
+ </instrumentation>
+
+</manifest>
diff --git a/samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java b/samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
new file mode 100644
index 0000000..3123348
--- /dev/null
+++ b/samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 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.skeletonapp;
+
+import android.test.ActivityInstrumentationTestCase;
+
+import com.example.android.skeletonapp.SkeletonActivity;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link ActivityTestCase#testActivityTestCaseSetUpProperly}.
+ */
+public class SkeletonAppTest extends ActivityInstrumentationTestCase<SkeletonActivity> {
+
+ public SkeletonAppTest() {
+ super("com.example.android.skeletonapp", SkeletonActivity.class);
+ }
+}
diff --git a/samples/Snake/Android.mk b/samples/Snake/Android.mk
new file mode 100644
index 0000000..56b642e
--- /dev/null
+++ b/samples/Snake/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := Snake
+
+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/Snake/AndroidManifest.xml b/samples/Snake/AndroidManifest.xml
new file mode 100644
index 0000000..174e8b4
--- /dev/null
+++ b/samples/Snake/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.snake">
+ <application android:label="Snake on a Phone">
+ <activity android:name="Snake"
+ android:screenOrientation="portrait"
+ android:configChanges="keyboardHidden|orientation">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/samples/Snake/MODULE_LICENSE_APACHE2 b/samples/Snake/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/Snake/MODULE_LICENSE_APACHE2
diff --git a/samples/Snake/res/drawable/greenstar.png b/samples/Snake/res/drawable/greenstar.png
new file mode 100644
index 0000000..26be5c8
--- /dev/null
+++ b/samples/Snake/res/drawable/greenstar.png
Binary files differ
diff --git a/samples/Snake/res/drawable/redstar.png b/samples/Snake/res/drawable/redstar.png
new file mode 100644
index 0000000..e9c0947
--- /dev/null
+++ b/samples/Snake/res/drawable/redstar.png
Binary files differ
diff --git a/samples/Snake/res/drawable/yellowstar.png b/samples/Snake/res/drawable/yellowstar.png
new file mode 100644
index 0000000..134b234
--- /dev/null
+++ b/samples/Snake/res/drawable/yellowstar.png
Binary files differ
diff --git a/samples/Snake/res/layout/snake_layout.xml b/samples/Snake/res/layout/snake_layout.xml
new file mode 100644
index 0000000..583c0c4
--- /dev/null
+++ b/samples/Snake/res/layout/snake_layout.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="fill_parent"
+ android:layout_height="fill_parent">
+
+ <com.example.android.snake.SnakeView
+ android:id="@+id/snake"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ tileSize="24"
+ />
+
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+
+ <TextView
+ android:id="@+id/text"
+ android:text="@string/snake_layout_text_text"
+ android:visibility="visible"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:gravity="center_horizontal"
+ android:textColor="#ff8888ff"
+ android:textSize="24sp"/>
+ </RelativeLayout>
+</FrameLayout>
diff --git a/samples/Snake/res/values/attrs.xml b/samples/Snake/res/values/attrs.xml
new file mode 100644
index 0000000..c846864
--- /dev/null
+++ b/samples/Snake/res/values/attrs.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+ <declare-styleable name="TileView">
+ <attr name="tileSize" format="integer" />
+ </declare-styleable>
+</resources>
+
diff --git a/samples/Snake/res/values/strings.xml b/samples/Snake/res/values/strings.xml
new file mode 100644
index 0000000..3c4a89d
--- /dev/null
+++ b/samples/Snake/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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="mode_ready">Snake\nPress Up To Play</string>
+ <string name="mode_pause">Paused\nPress Up To Resume</string>
+ <string name="mode_lose_prefix">Game Over\nScore: </string>
+ <string name="mode_lose_suffix">\nPress Up To Play</string>
+
+ <string name="snake_layout_text_text"></string>
+</resources>
diff --git a/samples/Snake/src/com/example/android/snake/Snake.java b/samples/Snake/src/com/example/android/snake/Snake.java
new file mode 100644
index 0000000..5fdc024
--- /dev/null
+++ b/samples/Snake/src/com/example/android/snake/Snake.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007 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.snake;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Window;
+import android.widget.TextView;
+
+/**
+ * Snake: a simple game that everyone can enjoy.
+ *
+ * This is an implementation of the classic Game "Snake", in which you control a
+ * serpent roaming around the garden looking for apples. Be careful, though,
+ * because when you catch one, not only will you become longer, but you'll move
+ * faster. Running into yourself or the walls will end the game.
+ *
+ */
+public class Snake extends Activity {
+
+ private SnakeView mSnakeView;
+
+ private static String ICICLE_KEY = "snake-view";
+
+ /**
+ * Called when Activity is first created. Turns off the title bar, sets up
+ * the content views, and fires up the SnakeView.
+ *
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // No Title bar
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+ setContentView(R.layout.snake_layout);
+
+ mSnakeView = (SnakeView) findViewById(R.id.snake);
+ mSnakeView.setTextView((TextView) findViewById(R.id.text));
+
+ if (savedInstanceState == null) {
+ // We were just launched -- set up a new game
+ mSnakeView.setMode(SnakeView.READY);
+ } else {
+ // We are being restored
+ Bundle map = savedInstanceState.getBundle(ICICLE_KEY);
+ if (map != null) {
+ mSnakeView.restoreState(map);
+ } else {
+ mSnakeView.setMode(SnakeView.PAUSE);
+ }
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // Pause the game along with the activity
+ mSnakeView.setMode(SnakeView.PAUSE);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ //Store the game state
+ outState.putBundle(ICICLE_KEY, mSnakeView.saveState());
+ }
+
+}
diff --git a/samples/Snake/src/com/example/android/snake/SnakeView.java b/samples/Snake/src/com/example/android/snake/SnakeView.java
new file mode 100644
index 0000000..8dd0232
--- /dev/null
+++ b/samples/Snake/src/com/example/android/snake/SnakeView.java
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2007 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.snake;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * SnakeView: implementation of a simple game of Snake
+ *
+ *
+ */
+public class SnakeView extends TileView {
+
+ private static final String TAG = "SnakeView";
+
+ /**
+ * Current mode of application: READY to run, RUNNING, or you have already
+ * lost. static final ints are used instead of an enum for performance
+ * reasons.
+ */
+ private int mMode = READY;
+ public static final int PAUSE = 0;
+ public static final int READY = 1;
+ public static final int RUNNING = 2;
+ public static final int LOSE = 3;
+
+ /**
+ * Current direction the snake is headed.
+ */
+ private int mDirection = NORTH;
+ private int mNextDirection = NORTH;
+ private static final int NORTH = 1;
+ private static final int SOUTH = 2;
+ private static final int EAST = 3;
+ private static final int WEST = 4;
+
+ /**
+ * Labels for the drawables that will be loaded into the TileView class
+ */
+ private static final int RED_STAR = 1;
+ private static final int YELLOW_STAR = 2;
+ private static final int GREEN_STAR = 3;
+
+ /**
+ * mScore: used to track the number of apples captured mMoveDelay: number of
+ * milliseconds between snake movements. This will decrease as apples are
+ * captured.
+ */
+ private long mScore = 0;
+ private long mMoveDelay = 600;
+ /**
+ * mLastMove: tracks the absolute time when the snake last moved, and is used
+ * to determine if a move should be made based on mMoveDelay.
+ */
+ private long mLastMove;
+
+ /**
+ * mStatusText: text shows to the user in some run states
+ */
+ private TextView mStatusText;
+
+ /**
+ * mSnakeTrail: a list of Coordinates that make up the snake's body
+ * mAppleList: the secret location of the juicy apples the snake craves.
+ */
+ private ArrayList<Coordinate> mSnakeTrail = new ArrayList<Coordinate>();
+ private ArrayList<Coordinate> mAppleList = new ArrayList<Coordinate>();
+
+ /**
+ * Everyone needs a little randomness in their life
+ */
+ private static final Random RNG = new Random();
+
+ /**
+ * Create a simple handler that we can use to cause animation to happen. We
+ * set ourselves as a target and we can use the sleep()
+ * function to cause an update/invalidate to occur at a later date.
+ */
+ private RefreshHandler mRedrawHandler = new RefreshHandler();
+
+ class RefreshHandler extends Handler {
+
+ @Override
+ public void handleMessage(Message msg) {
+ SnakeView.this.update();
+ SnakeView.this.invalidate();
+ }
+
+ public void sleep(long delayMillis) {
+ this.removeMessages(0);
+ sendMessageDelayed(obtainMessage(0), delayMillis);
+ }
+ };
+
+
+ /**
+ * Constructs a SnakeView based on inflation from XML
+ *
+ * @param context
+ * @param attrs
+ */
+ public SnakeView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initSnakeView();
+ }
+
+ public SnakeView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initSnakeView();
+ }
+
+ private void initSnakeView() {
+ setFocusable(true);
+
+ Resources r = this.getContext().getResources();
+
+ resetTiles(4);
+ loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));
+ loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));
+ loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));
+
+ }
+
+
+ private void initNewGame() {
+ mSnakeTrail.clear();
+ mAppleList.clear();
+
+ // For now we're just going to load up a short default eastbound snake
+ // that's just turned north
+
+
+ mSnakeTrail.add(new Coordinate(7, 7));
+ mSnakeTrail.add(new Coordinate(6, 7));
+ mSnakeTrail.add(new Coordinate(5, 7));
+ mSnakeTrail.add(new Coordinate(4, 7));
+ mSnakeTrail.add(new Coordinate(3, 7));
+ mSnakeTrail.add(new Coordinate(2, 7));
+ mNextDirection = NORTH;
+
+ // Two apples to start with
+ addRandomApple();
+ addRandomApple();
+
+ mMoveDelay = 600;
+ mScore = 0;
+ }
+
+
+ /**
+ * Given a ArrayList of coordinates, we need to flatten them into an array of
+ * ints before we can stuff them into a map for flattening and storage.
+ *
+ * @param cvec : a ArrayList of Coordinate objects
+ * @return : a simple array containing the x/y values of the coordinates
+ * as [x1,y1,x2,y2,x3,y3...]
+ */
+ private int[] coordArrayListToArray(ArrayList<Coordinate> cvec) {
+ int count = cvec.size();
+ int[] rawArray = new int[count * 2];
+ for (int index = 0; index < count; index++) {
+ Coordinate c = cvec.get(index);
+ rawArray[2 * index] = c.x;
+ rawArray[2 * index + 1] = c.y;
+ }
+ return rawArray;
+ }
+
+ /**
+ * Save game state so that the user does not lose anything
+ * if the game process is killed while we are in the
+ * background.
+ *
+ * @return a Bundle with this view's state
+ */
+ public Bundle saveState() {
+ Bundle map = new Bundle();
+
+ map.putIntArray("mAppleList", coordArrayListToArray(mAppleList));
+ map.putInt("mDirection", Integer.valueOf(mDirection));
+ map.putInt("mNextDirection", Integer.valueOf(mNextDirection));
+ map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
+ map.putLong("mScore", Long.valueOf(mScore));
+ map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));
+
+ return map;
+ }
+
+ /**
+ * Given a flattened array of ordinate pairs, we reconstitute them into a
+ * ArrayList of Coordinate objects
+ *
+ * @param rawArray : [x1,y1,x2,y2,...]
+ * @return a ArrayList of Coordinates
+ */
+ private ArrayList<Coordinate> coordArrayToArrayList(int[] rawArray) {
+ ArrayList<Coordinate> coordArrayList = new ArrayList<Coordinate>();
+
+ int coordCount = rawArray.length;
+ for (int index = 0; index < coordCount; index += 2) {
+ Coordinate c = new Coordinate(rawArray[index], rawArray[index + 1]);
+ coordArrayList.add(c);
+ }
+ return coordArrayList;
+ }
+
+ /**
+ * Restore game state if our process is being relaunched
+ *
+ * @param icicle a Bundle containing the game state
+ */
+ public void restoreState(Bundle icicle) {
+ setMode(PAUSE);
+
+ mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList"));
+ mDirection = icicle.getInt("mDirection");
+ mNextDirection = icicle.getInt("mNextDirection");
+ mMoveDelay = icicle.getLong("mMoveDelay");
+ mScore = icicle.getLong("mScore");
+ mSnakeTrail = coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
+ }
+
+ /*
+ * handles key events in the game. Update the direction our snake is traveling
+ * based on the DPAD. Ignore events that would cause the snake to immediately
+ * turn back on itself.
+ *
+ * (non-Javadoc)
+ *
+ * @see android.view.View#onKeyDown(int, android.os.KeyEvent)
+ */
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent msg) {
+
+ if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+ if (mMode == READY | mMode == LOSE) {
+ /*
+ * At the beginning of the game, or the end of a previous one,
+ * we should start a new game.
+ */
+ initNewGame();
+ setMode(RUNNING);
+ update();
+ return (true);
+ }
+
+ if (mMode == PAUSE) {
+ /*
+ * If the game is merely paused, we should just continue where
+ * we left off.
+ */
+ setMode(RUNNING);
+ update();
+ return (true);
+ }
+
+ if (mDirection != SOUTH) {
+ mNextDirection = NORTH;
+ }
+ return (true);
+ }
+
+ if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (mDirection != NORTH) {
+ mNextDirection = SOUTH;
+ }
+ return (true);
+ }
+
+ if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
+ if (mDirection != EAST) {
+ mNextDirection = WEST;
+ }
+ return (true);
+ }
+
+ if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
+ if (mDirection != WEST) {
+ mNextDirection = EAST;
+ }
+ return (true);
+ }
+
+ return super.onKeyDown(keyCode, msg);
+ }
+
+ /**
+ * Sets the TextView that will be used to give information (such as "Game
+ * Over" to the user.
+ *
+ * @param newView
+ */
+ public void setTextView(TextView newView) {
+ mStatusText = newView;
+ }
+
+ /**
+ * Updates the current mode of the application (RUNNING or PAUSED or the like)
+ * as well as sets the visibility of textview for notification
+ *
+ * @param newMode
+ */
+ public void setMode(int newMode) {
+ int oldMode = mMode;
+ mMode = newMode;
+
+ if (newMode == RUNNING & oldMode != RUNNING) {
+ mStatusText.setVisibility(View.INVISIBLE);
+ update();
+ return;
+ }
+
+ Resources res = getContext().getResources();
+ CharSequence str = "";
+ if (newMode == PAUSE) {
+ str = res.getText(R.string.mode_pause);
+ }
+ if (newMode == READY) {
+ str = res.getText(R.string.mode_ready);
+ }
+ if (newMode == LOSE) {
+ str = res.getString(R.string.mode_lose_prefix) + mScore
+ + res.getString(R.string.mode_lose_suffix);
+ }
+
+ mStatusText.setText(str);
+ mStatusText.setVisibility(View.VISIBLE);
+ }
+
+ /**
+ * Selects a random location within the garden that is not currently covered
+ * by the snake. Currently _could_ go into an infinite loop if the snake
+ * currently fills the garden, but we'll leave discovery of this prize to a
+ * truly excellent snake-player.
+ *
+ */
+ private void addRandomApple() {
+ Coordinate newCoord = null;
+ boolean found = false;
+ while (!found) {
+ // Choose a new location for our apple
+ int newX = 1 + RNG.nextInt(mXTileCount - 2);
+ int newY = 1 + RNG.nextInt(mYTileCount - 2);
+ newCoord = new Coordinate(newX, newY);
+
+ // Make sure it's not already under the snake
+ boolean collision = false;
+ int snakelength = mSnakeTrail.size();
+ for (int index = 0; index < snakelength; index++) {
+ if (mSnakeTrail.get(index).equals(newCoord)) {
+ collision = true;
+ }
+ }
+ // if we're here and there's been no collision, then we have
+ // a good location for an apple. Otherwise, we'll circle back
+ // and try again
+ found = !collision;
+ }
+ if (newCoord == null) {
+ Log.e(TAG, "Somehow ended up with a null newCoord!");
+ }
+ mAppleList.add(newCoord);
+ }
+
+
+ /**
+ * Handles the basic update loop, checking to see if we are in the running
+ * state, determining if a move should be made, updating the snake's location.
+ */
+ public void update() {
+ if (mMode == RUNNING) {
+ long now = System.currentTimeMillis();
+
+ if (now - mLastMove > mMoveDelay) {
+ clearTiles();
+ updateWalls();
+ updateSnake();
+ updateApples();
+ mLastMove = now;
+ }
+ mRedrawHandler.sleep(mMoveDelay);
+ }
+
+ }
+
+ /**
+ * Draws some walls.
+ *
+ */
+ private void updateWalls() {
+ for (int x = 0; x < mXTileCount; x++) {
+ setTile(GREEN_STAR, x, 0);
+ setTile(GREEN_STAR, x, mYTileCount - 1);
+ }
+ for (int y = 1; y < mYTileCount - 1; y++) {
+ setTile(GREEN_STAR, 0, y);
+ setTile(GREEN_STAR, mXTileCount - 1, y);
+ }
+ }
+
+ /**
+ * Draws some apples.
+ *
+ */
+ private void updateApples() {
+ for (Coordinate c : mAppleList) {
+ setTile(YELLOW_STAR, c.x, c.y);
+ }
+ }
+
+ /**
+ * Figure out which way the snake is going, see if he's run into anything (the
+ * walls, himself, or an apple). If he's not going to die, we then add to the
+ * front and subtract from the rear in order to simulate motion. If we want to
+ * grow him, we don't subtract from the rear.
+ *
+ */
+ private void updateSnake() {
+ boolean growSnake = false;
+
+ // grab the snake by the head
+ Coordinate head = mSnakeTrail.get(0);
+ Coordinate newHead = new Coordinate(1, 1);
+
+ mDirection = mNextDirection;
+
+ switch (mDirection) {
+ case EAST: {
+ newHead = new Coordinate(head.x + 1, head.y);
+ break;
+ }
+ case WEST: {
+ newHead = new Coordinate(head.x - 1, head.y);
+ break;
+ }
+ case NORTH: {
+ newHead = new Coordinate(head.x, head.y - 1);
+ break;
+ }
+ case SOUTH: {
+ newHead = new Coordinate(head.x, head.y + 1);
+ break;
+ }
+ }
+
+ // Collision detection
+ // For now we have a 1-square wall around the entire arena
+ if ((newHead.x < 1) || (newHead.y < 1) || (newHead.x > mXTileCount - 2)
+ || (newHead.y > mYTileCount - 2)) {
+ setMode(LOSE);
+ return;
+
+ }
+
+ // Look for collisions with itself
+ int snakelength = mSnakeTrail.size();
+ for (int snakeindex = 0; snakeindex < snakelength; snakeindex++) {
+ Coordinate c = mSnakeTrail.get(snakeindex);
+ if (c.equals(newHead)) {
+ setMode(LOSE);
+ return;
+ }
+ }
+
+ // Look for apples
+ int applecount = mAppleList.size();
+ for (int appleindex = 0; appleindex < applecount; appleindex++) {
+ Coordinate c = mAppleList.get(appleindex);
+ if (c.equals(newHead)) {
+ mAppleList.remove(c);
+ addRandomApple();
+
+ mScore++;
+ mMoveDelay *= 0.9;
+
+ growSnake = true;
+ }
+ }
+
+ // push a new head onto the ArrayList and pull off the tail
+ mSnakeTrail.add(0, newHead);
+ // except if we want the snake to grow
+ if (!growSnake) {
+ mSnakeTrail.remove(mSnakeTrail.size() - 1);
+ }
+
+ int index = 0;
+ for (Coordinate c : mSnakeTrail) {
+ if (index == 0) {
+ setTile(YELLOW_STAR, c.x, c.y);
+ } else {
+ setTile(RED_STAR, c.x, c.y);
+ }
+ index++;
+ }
+
+ }
+
+ /**
+ * Simple class containing two integer values and a comparison function.
+ * There's probably something I should use instead, but this was quick and
+ * easy to build.
+ *
+ */
+ private class Coordinate {
+ public int x;
+ public int y;
+
+ public Coordinate(int newX, int newY) {
+ x = newX;
+ y = newY;
+ }
+
+ public boolean equals(Coordinate other) {
+ if (x == other.x && y == other.y) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Coordinate: [" + x + "," + y + "]";
+ }
+ }
+
+}
diff --git a/samples/Snake/src/com/example/android/snake/TileView.java b/samples/Snake/src/com/example/android/snake/TileView.java
new file mode 100644
index 0000000..a912c53
--- /dev/null
+++ b/samples/Snake/src/com/example/android/snake/TileView.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2007 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.snake;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+
+/**
+ * TileView: a View-variant designed for handling arrays of "icons" or other
+ * drawables.
+ *
+ */
+public class TileView extends View {
+
+ /**
+ * Parameters controlling the size of the tiles and their range within view.
+ * Width/Height are in pixels, and Drawables will be scaled to fit to these
+ * dimensions. X/Y Tile Counts are the number of tiles that will be drawn.
+ */
+
+ protected static int mTileSize;
+
+ protected static int mXTileCount;
+ protected static int mYTileCount;
+
+ private static int mXOffset;
+ private static int mYOffset;
+
+
+ /**
+ * A hash that maps integer handles specified by the subclasser to the
+ * drawable that will be used for that reference
+ */
+ private Bitmap[] mTileArray;
+
+ /**
+ * A two-dimensional array of integers in which the number represents the
+ * index of the tile that should be drawn at that locations
+ */
+ private int[][] mTileGrid;
+
+ private final Paint mPaint = new Paint();
+
+ public TileView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
+
+ mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
+
+ a.recycle();
+ }
+
+ public TileView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
+
+ mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
+
+ a.recycle();
+ }
+
+
+
+ /**
+ * Rests the internal array of Bitmaps used for drawing tiles, and
+ * sets the maximum index of tiles to be inserted
+ *
+ * @param tilecount
+ */
+
+ public void resetTiles(int tilecount) {
+ mTileArray = new Bitmap[tilecount];
+ }
+
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mXTileCount = (int) Math.floor(w / mTileSize);
+ mYTileCount = (int) Math.floor(h / mTileSize);
+
+ mXOffset = ((w - (mTileSize * mXTileCount)) / 2);
+ mYOffset = ((h - (mTileSize * mYTileCount)) / 2);
+
+ mTileGrid = new int[mXTileCount][mYTileCount];
+ clearTiles();
+ }
+
+ /**
+ * Function to set the specified Drawable as the tile for a particular
+ * integer key.
+ *
+ * @param key
+ * @param tile
+ */
+ public void loadTile(int key, Drawable tile) {
+ Bitmap bitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ tile.setBounds(0, 0, mTileSize, mTileSize);
+ tile.draw(canvas);
+
+ mTileArray[key] = bitmap;
+ }
+
+ /**
+ * Resets all tiles to 0 (empty)
+ *
+ */
+ public void clearTiles() {
+ for (int x = 0; x < mXTileCount; x++) {
+ for (int y = 0; y < mYTileCount; y++) {
+ setTile(0, x, y);
+ }
+ }
+ }
+
+ /**
+ * Used to indicate that a particular tile (set with loadTile and referenced
+ * by an integer) should be drawn at the given x/y coordinates during the
+ * next invalidate/draw cycle.
+ *
+ * @param tileindex
+ * @param x
+ * @param y
+ */
+ public void setTile(int tileindex, int x, int y) {
+ mTileGrid[x][y] = tileindex;
+ }
+
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ for (int x = 0; x < mXTileCount; x += 1) {
+ for (int y = 0; y < mYTileCount; y += 1) {
+ if (mTileGrid[x][y] > 0) {
+ canvas.drawBitmap(mTileArray[mTileGrid[x][y]],
+ mXOffset + x * mTileSize,
+ mYOffset + y * mTileSize,
+ mPaint);
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/samples/Snake/tests/Android.mk b/samples/Snake/tests/Android.mk
new file mode 100644
index 0000000..3d16805
--- /dev/null
+++ b/samples/Snake/tests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := SnakeTests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := Snake
+
+include $(BUILD_PACKAGE)
diff --git a/samples/Snake/tests/AndroidManifest.xml b/samples/Snake/tests/AndroidManifest.xml
new file mode 100644
index 0000000..382506c
--- /dev/null
+++ b/samples/Snake/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.snake.tests">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.snake"
+ android:label="Snake sample tests">
+ </instrumentation>
+
+</manifest>
diff --git a/samples/Snake/tests/src/com/example/android/snake/SnakeTest.java b/samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
new file mode 100644
index 0000000..35d1b12
--- /dev/null
+++ b/samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.snake;
+
+import android.test.ActivityInstrumentationTestCase;
+
+import com.example.android.snake.Snake;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link ActivityTestCase#testActivityTestCaseSetUpProperly}.
+ */
+public class SnakeTest extends ActivityInstrumentationTestCase<Snake> {
+
+ public SnakeTest() {
+ super("com.example.android.snake", Snake.class);
+ }
+
+}
diff --git a/samples/SoftKeyboard/Android.mk b/samples/SoftKeyboard/Android.mk
new file mode 100755
index 0000000..883bf2f
--- /dev/null
+++ b/samples/SoftKeyboard/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := SoftKeyboard
+
+include $(BUILD_PACKAGE)
diff --git a/samples/SoftKeyboard/AndroidManifest.xml b/samples/SoftKeyboard/AndroidManifest.xml
new file mode 100755
index 0000000..61b5131
--- /dev/null
+++ b/samples/SoftKeyboard/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.softkeyboard">
+ <application android:label="@string/ime_name">
+ <service android:name="SoftKeyboard"
+ android:permission="android.permission.BIND_INPUT_METHOD">
+ <intent-filter>
+ <action android:name="android.view.InputMethod" />
+ </intent-filter>
+ <meta-data android:name="android.view.im" android:resource="@xml/method" />
+ </service>
+ </application>
+</manifest>
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png
new file mode 100644
index 0000000..6cee596
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png
new file mode 100755
index 0000000..c0d6d13
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png
new file mode 100644
index 0000000..cbe2b15
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_search.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_search.png
new file mode 100755
index 0000000..127755d
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_search.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png
new file mode 100644
index 0000000..d059628
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png
new file mode 100644
index 0000000..09b94d9
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/layout/input.xml b/samples/SoftKeyboard/res/layout/input.xml
new file mode 100755
index 0000000..1b57468
--- /dev/null
+++ b/samples/SoftKeyboard/res/layout/input.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<com.example.android.softkeyboard.LatinKeyboardView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/keyboard"
+ android:layout_alignParentBottom="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ />
diff --git a/samples/SoftKeyboard/res/values-land/dimens.xml b/samples/SoftKeyboard/res/values-land/dimens.xml
new file mode 100644
index 0000000..b5f3bc1
--- /dev/null
+++ b/samples/SoftKeyboard/res/values-land/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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>
+ <dimen name="key_height">46dip</dimen>
+</resources>
diff --git a/samples/SoftKeyboard/res/values/colors.xml b/samples/SoftKeyboard/res/values/colors.xml
new file mode 100644
index 0000000..74d103a
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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>
+ <color name="candidate_normal">#FF000000</color>
+ <color name="candidate_recommended">#FFE35900</color>
+ <color name="candidate_other">#ff808080</color>
+ <color name="candidate_background">#bbffffff</color>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/dimens.xml b/samples/SoftKeyboard/res/values/dimens.xml
new file mode 100644
index 0000000..caf615c
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/dimens.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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>
+ <dimen name="key_height">50dip</dimen>
+ <dimen name="candidate_font_height">16sp</dimen>
+ <dimen name="candidate_vertical_padding">6sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/strings.xml b/samples/SoftKeyboard/res/values/strings.xml
new file mode 100644
index 0000000..bc645b2
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title for Latin keyboard -->
+ <string name="ime_name">Sample Soft Keyboard</string>
+
+ <!-- Symbols that are commonly considered word separators in this language -->
+ <string name="word_separators">\u0020.,;:!?\n()[]*&@{}/<>_+=|"</string>
+
+ <!-- Labels on soft keys -->
+ <string name="label_go_key">Go</string>
+ <string name="label_next_key">Next</string>
+ <string name="label_send_key">Send</string>
+</resources>
diff --git a/samples/SoftKeyboard/res/xml/method.xml b/samples/SoftKeyboard/res/xml/method.xml
new file mode 100644
index 0000000..d246624
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/method.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2008, 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.
+ */
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Search Manager. -->
+
+<input-method xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/samples/SoftKeyboard/res/xml/qwerty.xml b/samples/SoftKeyboard/res/xml/qwerty.xml
new file mode 100755
index 0000000..e81d9f1
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/qwerty.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+ android:keyWidth="10%p"
+ android:horizontalGap="0px"
+ android:verticalGap="0px"
+ android:keyHeight="@dimen/key_height"
+ >
+
+ <Row>
+ <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
+ <Key android:codes="119" android:keyLabel="w"/>
+ <Key android:codes="101" android:keyLabel="e"/>
+ <Key android:codes="114" android:keyLabel="r"/>
+ <Key android:codes="116" android:keyLabel="t"/>
+ <Key android:codes="121" android:keyLabel="y"/>
+ <Key android:codes="117" android:keyLabel="u"/>
+ <Key android:codes="105" android:keyLabel="i"/>
+ <Key android:codes="111" android:keyLabel="o"/>
+ <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
+ android:keyEdgeFlags="left"/>
+ <Key android:codes="115" android:keyLabel="s"/>
+ <Key android:codes="100" android:keyLabel="d"/>
+ <Key android:codes="102" android:keyLabel="f"/>
+ <Key android:codes="103" android:keyLabel="g"/>
+ <Key android:codes="104" android:keyLabel="h"/>
+ <Key android:codes="106" android:keyLabel="j"/>
+ <Key android:codes="107" android:keyLabel="k"/>
+ <Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+ android:keyWidth="15%p" android:isModifier="true"
+ android:isSticky="true" android:keyEdgeFlags="left"/>
+ <Key android:codes="122" android:keyLabel="z"/>
+ <Key android:codes="120" android:keyLabel="x"/>
+ <Key android:codes="99" android:keyLabel="c"/>
+ <Key android:codes="118" android:keyLabel="v"/>
+ <Key android:codes="98" android:keyLabel="b"/>
+ <Key android:codes="110" android:keyLabel="n"/>
+ <Key android:codes="109" android:keyLabel="m"/>
+ <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+ android:keyWidth="15%p" android:keyEdgeFlags="right"
+ android:isRepeatable="true"/>
+ </Row>
+
+ <Row android:rowEdgeFlags="bottom">
+ <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
+ android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+ <Key android:codes="-2" android:keyLabel="123" android:keyWidth="15%p"/>
+ <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
+ android:keyWidth="30%p" android:isRepeatable="true"/>
+ <Key android:codes="46,44" android:keyLabel=". ,"
+ android:keyWidth="15%p"/>
+ <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+ android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+ </Row>
+</Keyboard>
+
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/xml/symbols.xml b/samples/SoftKeyboard/res/xml/symbols.xml
new file mode 100755
index 0000000..a28d752
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/symbols.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+ android:keyWidth="10%p"
+ android:horizontalGap="0px"
+ android:verticalGap="0px"
+ android:keyHeight="@dimen/key_height"
+ >
+
+ <Row>
+ <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
+ <Key android:codes="50" android:keyLabel="2"/>
+ <Key android:codes="51" android:keyLabel="3"/>
+ <Key android:codes="52" android:keyLabel="4"/>
+ <Key android:codes="53" android:keyLabel="5"/>
+ <Key android:codes="54" android:keyLabel="6"/>
+ <Key android:codes="55" android:keyLabel="7"/>
+ <Key android:codes="56" android:keyLabel="8"/>
+ <Key android:codes="57" android:keyLabel="9"/>
+ <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="64" android:keyLabel="\@" android:keyEdgeFlags="left"/>
+ <Key android:codes="35" android:keyLabel="\#"/>
+ <Key android:codes="36" android:keyLabel="$"/>
+ <Key android:codes="37" android:keyLabel="%"/>
+ <Key android:codes="38" android:keyLabel="&"/>
+ <Key android:codes="42" android:keyLabel="*"/>
+ <Key android:codes="45" android:keyLabel="-"/>
+ <Key android:codes="61" android:keyLabel="="/>
+ <Key android:codes="40" android:keyLabel="("/>
+ <Key android:codes="41" android:keyLabel=")" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+ android:keyWidth="15%p" android:isModifier="true"
+ android:isSticky="true" android:keyEdgeFlags="left"/>
+ <Key android:codes="33" android:keyLabel="!" />
+ <Key android:codes="34" android:keyLabel="""/>
+ <Key android:codes="39" android:keyLabel="\'"/>
+ <Key android:codes="58" android:keyLabel=":"/>
+ <Key android:codes="59" android:keyLabel=";"/>
+ <Key android:codes="47" android:keyLabel="/" />
+ <Key android:codes="63" android:keyLabel="\?"/>
+ <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+ android:keyWidth="15%p" android:keyEdgeFlags="right"
+ android:isRepeatable="true"/>
+ </Row>
+
+ <Row android:rowEdgeFlags="bottom">
+ <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
+ android:keyWidth="20%p" android:keyEdgeFlags="left" />
+ <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
+ <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
+ android:isRepeatable="true"/>
+ <Key android:codes="44" android:keyLabel="," android:keyWidth="15%p" />
+ <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+ android:keyWidth="20%p" android:keyEdgeFlags="right"
+ />
+ </Row>
+</Keyboard>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/xml/symbols_shift.xml b/samples/SoftKeyboard/res/xml/symbols_shift.xml
new file mode 100755
index 0000000..d7139f3
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/symbols_shift.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+ android:keyWidth="10%p"
+ android:horizontalGap="0px"
+ android:verticalGap="0px"
+ android:keyHeight="@dimen/key_height"
+ >
+
+ <Row>
+ <Key android:codes="126" android:keyLabel="~" android:keyEdgeFlags="left"/>
+ <Key android:codes="177" android:keyLabel="±"/>
+ <Key android:codes="215" android:keyLabel="×"/>
+ <Key android:codes="247" android:keyLabel="÷"/>
+ <Key android:codes="8226" android:keyLabel="•"/>
+ <Key android:codes="176" android:keyLabel="°"/>
+ <Key android:codes="96" android:keyLabel="`"/>
+ <Key android:codes="180" android:keyLabel="´"/>
+ <Key android:codes="123" android:keyLabel="{"/>
+ <Key android:codes="125" android:keyLabel="}" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="169" android:keyLabel="©" android:keyEdgeFlags="left"/>
+ <Key android:codes="163" android:keyLabel="£"/>
+ <Key android:codes="8364" android:keyLabel="€"/>
+ <Key android:codes="94" android:keyLabel="^"/>
+ <Key android:codes="174" android:keyLabel="®"/>
+ <Key android:codes="165" android:keyLabel="¥"/>
+ <Key android:codes="95" android:keyLabel="_"/>
+ <Key android:codes="43" android:keyLabel="+"/>
+ <Key android:codes="91" android:keyLabel="["/>
+ <Key android:codes="93" android:keyLabel="]" android:keyEdgeFlags="right"/>
+ </Row>
+
+ <Row>
+ <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+ android:keyWidth="15%p" android:isModifier="true"
+ android:isSticky="true" android:keyEdgeFlags="left"/>
+ <Key android:codes="161" android:keyLabel="¡" />
+ <Key android:codes="60" android:keyLabel="<"/>
+ <Key android:codes="62" android:keyLabel=">"/>
+ <Key android:codes="162" android:keyLabel="¢"/>
+ <Key android:codes="124" android:keyLabel="|"/>
+ <Key android:codes="92" android:keyLabel="\\" />
+ <Key android:codes="191" android:keyLabel="¿"/>
+ <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+ android:keyWidth="15%p" android:keyEdgeFlags="right"
+ android:isRepeatable="true"/>
+ </Row>
+
+ <Row android:rowEdgeFlags="bottom">
+ <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
+ android:keyWidth="20%p" android:keyEdgeFlags="left" />
+ <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
+ <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
+ android:isRepeatable="true"/>
+ <Key android:codes="8230" android:keyLabel="…" android:keyWidth="15%p" />
+ <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+ android:keyWidth="20%p" android:keyEdgeFlags="right" />
+ </Row>
+</Keyboard>
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
new file mode 100755
index 0000000..7cadead
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ *
+ * 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.softkeyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CandidateView extends View {
+
+ private static final int OUT_OF_BOUNDS = -1;
+
+ private SoftKeyboard mService;
+ private List<String> mSuggestions;
+ private int mSelectedIndex;
+ private int mTouchX = OUT_OF_BOUNDS;
+ private Drawable mSelectionHighlight;
+ private boolean mTypedWordValid;
+
+ private Rect mBgPadding;
+
+ private static final int MAX_SUGGESTIONS = 32;
+ private static final int SCROLL_PIXELS = 20;
+
+ private int[] mWordWidth = new int[MAX_SUGGESTIONS];
+ private int[] mWordX = new int[MAX_SUGGESTIONS];
+
+ private static final int X_GAP = 10;
+
+ private static final List<String> EMPTY_LIST = new ArrayList<String>();
+
+ private int mColorNormal;
+ private int mColorRecommended;
+ private int mColorOther;
+ private int mVerticalPadding;
+ private Paint mPaint;
+ private boolean mScrolled;
+ private int mTargetScrollX;
+
+ private int mTotalWidth;
+
+ private GestureDetector mGestureDetector;
+
+ /**
+ * Construct a CandidateView for showing suggested words for completion.
+ * @param context
+ * @param attrs
+ */
+ public CandidateView(Context context) {
+ super(context);
+ mSelectionHighlight = context.getResources().getDrawable(
+ android.R.drawable.list_selector_background);
+ mSelectionHighlight.setState(new int[] {
+ android.R.attr.state_enabled,
+ android.R.attr.state_focused,
+ android.R.attr.state_window_focused,
+ android.R.attr.state_pressed
+ });
+
+ Resources r = context.getResources();
+
+ setBackgroundColor(r.getColor(R.color.candidate_background));
+
+ mColorNormal = r.getColor(R.color.candidate_normal);
+ mColorRecommended = r.getColor(R.color.candidate_recommended);
+ mColorOther = r.getColor(R.color.candidate_other);
+ mVerticalPadding = r.getDimensionPixelSize(R.dimen.candidate_vertical_padding);
+
+ mPaint = new Paint();
+ mPaint.setColor(mColorNormal);
+ mPaint.setAntiAlias(true);
+ mPaint.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_font_height));
+ mPaint.setStrokeWidth(0);
+
+ mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2,
+ float distanceX, float distanceY) {
+ mScrolled = true;
+ int sx = getScrollX();
+ sx += distanceX;
+ if (sx < 0) {
+ sx = 0;
+ }
+ if (sx + getWidth() > mTotalWidth) {
+ sx -= distanceX;
+ }
+ mTargetScrollX = sx;
+ scrollTo(sx, getScrollY());
+ invalidate();
+ return true;
+ }
+ });
+ setHorizontalFadingEdgeEnabled(true);
+ setWillNotDraw(false);
+ setHorizontalScrollBarEnabled(false);
+ setVerticalScrollBarEnabled(false);
+ }
+
+ /**
+ * A connection back to the service to communicate with the text field
+ * @param listener
+ */
+ public void setService(SoftKeyboard listener) {
+ mService = listener;
+ }
+
+ @Override
+ public int computeHorizontalScrollRange() {
+ return mTotalWidth;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int measuredWidth = resolveSize(50, widthMeasureSpec);
+
+ // Get the desired height of the icon menu view (last row of items does
+ // not have a divider below)
+ Rect padding = new Rect();
+ mSelectionHighlight.getPadding(padding);
+ final int desiredHeight = ((int)mPaint.getTextSize()) + mVerticalPadding
+ + padding.top + padding.bottom;
+
+ // Maximum possible width and desired height
+ setMeasuredDimension(measuredWidth,
+ resolveSize(desiredHeight, heightMeasureSpec));
+ }
+
+ /**
+ * If the canvas is null, then only touch calculations are performed to pick the target
+ * candidate.
+ */
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (canvas != null) {
+ super.onDraw(canvas);
+ }
+ mTotalWidth = 0;
+ if (mSuggestions == null) return;
+
+ if (mBgPadding == null) {
+ mBgPadding = new Rect(0, 0, 0, 0);
+ if (getBackground() != null) {
+ getBackground().getPadding(mBgPadding);
+ }
+ }
+ int x = 0;
+ final int count = mSuggestions.size();
+ final int height = getHeight();
+ final Rect bgPadding = mBgPadding;
+ final Paint paint = mPaint;
+ final int touchX = mTouchX;
+ final int scrollX = getScrollX();
+ final boolean scrolled = mScrolled;
+ final boolean typedWordValid = mTypedWordValid;
+ final int y = (int) (((height - mPaint.getTextSize()) / 2) - mPaint.ascent());
+
+ for (int i = 0; i < count; i++) {
+ String suggestion = mSuggestions.get(i);
+ float textWidth = paint.measureText(suggestion);
+ final int wordWidth = (int) textWidth + X_GAP * 2;
+
+ mWordX[i] = x;
+ mWordWidth[i] = wordWidth;
+ paint.setColor(mColorNormal);
+ if (touchX + scrollX >= x && touchX + scrollX < x + wordWidth && !scrolled) {
+ if (canvas != null) {
+ canvas.translate(x, 0);
+ mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height);
+ mSelectionHighlight.draw(canvas);
+ canvas.translate(-x, 0);
+ }
+ mSelectedIndex = i;
+ }
+
+ if (canvas != null) {
+ if ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid)) {
+ paint.setFakeBoldText(true);
+ paint.setColor(mColorRecommended);
+ } else if (i != 0) {
+ paint.setColor(mColorOther);
+ }
+ canvas.drawText(suggestion, x + X_GAP, y, paint);
+ paint.setColor(mColorOther);
+ canvas.drawLine(x + wordWidth + 0.5f, bgPadding.top,
+ x + wordWidth + 0.5f, height + 1, paint);
+ paint.setFakeBoldText(false);
+ }
+ x += wordWidth;
+ }
+ mTotalWidth = x;
+ if (mTargetScrollX != getScrollX()) {
+ scrollToTarget();
+ }
+ }
+
+ private void scrollToTarget() {
+ int sx = getScrollX();
+ if (mTargetScrollX > sx) {
+ sx += SCROLL_PIXELS;
+ if (sx >= mTargetScrollX) {
+ sx = mTargetScrollX;
+ requestLayout();
+ }
+ } else {
+ sx -= SCROLL_PIXELS;
+ if (sx <= mTargetScrollX) {
+ sx = mTargetScrollX;
+ requestLayout();
+ }
+ }
+ scrollTo(sx, getScrollY());
+ invalidate();
+ }
+
+ public void setSuggestions(List<String> suggestions, boolean completions,
+ boolean typedWordValid) {
+ clear();
+ if (suggestions != null) {
+ mSuggestions = new ArrayList<String>(suggestions);
+ }
+ mTypedWordValid = typedWordValid;
+ scrollTo(0, 0);
+ mTargetScrollX = 0;
+ // Compute the total width
+ onDraw(null);
+ invalidate();
+ requestLayout();
+ }
+
+ public void clear() {
+ mSuggestions = EMPTY_LIST;
+ mTouchX = OUT_OF_BOUNDS;
+ mSelectedIndex = -1;
+ invalidate();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent me) {
+
+ if (mGestureDetector.onTouchEvent(me)) {
+ return true;
+ }
+
+ int action = me.getAction();
+ int x = (int) me.getX();
+ int y = (int) me.getY();
+ mTouchX = x;
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mScrolled = false;
+ invalidate();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (y <= 0) {
+ // Fling up!?
+ if (mSelectedIndex >= 0) {
+ mService.pickSuggestionManually(mSelectedIndex);
+ mSelectedIndex = -1;
+ }
+ }
+ invalidate();
+ break;
+ case MotionEvent.ACTION_UP:
+ if (!mScrolled) {
+ if (mSelectedIndex >= 0) {
+ mService.pickSuggestionManually(mSelectedIndex);
+ }
+ }
+ mSelectedIndex = -1;
+ removeHighlight();
+ requestLayout();
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * For flick through from keyboard, call this method with the x coordinate of the flick
+ * gesture.
+ * @param x
+ */
+ public void takeSuggestionAt(float x) {
+ mTouchX = (int) x;
+ // To detect candidate
+ onDraw(null);
+ if (mSelectedIndex >= 0) {
+ mService.pickSuggestionManually(mSelectedIndex);
+ }
+ invalidate();
+ }
+
+ private void removeHighlight() {
+ mTouchX = OUT_OF_BOUNDS;
+ invalidate();
+ }
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
new file mode 100644
index 0000000..1798442
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ *
+ * 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.softkeyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.Keyboard.Key;
+import android.inputmethodservice.Keyboard.Row;
+import android.view.inputmethod.EditorInfo;
+
+public class LatinKeyboard extends Keyboard {
+
+ private Key mEnterKey;
+
+ public LatinKeyboard(Context context, int xmlLayoutResId) {
+ super(context, xmlLayoutResId);
+ }
+
+ public LatinKeyboard(Context context, int layoutTemplateResId,
+ CharSequence characters, int columns, int horizontalPadding) {
+ super(context, layoutTemplateResId, characters, columns, horizontalPadding);
+ }
+
+ @Override
+ protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
+ XmlResourceParser parser) {
+ Key key = new LatinKey(res, parent, x, y, parser);
+ if (key.codes[0] == 10) {
+ mEnterKey = key;
+ }
+ return key;
+ }
+
+ /**
+ * This looks at the ime options given by the current editor, to set the
+ * appropriate label on the keyboard's enter key (if it has one).
+ */
+ void setImeOptions(Resources res, int options) {
+ if (mEnterKey == null) {
+ return;
+ }
+
+ switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
+ case EditorInfo.IME_ACTION_GO:
+ mEnterKey.iconPreview = null;
+ mEnterKey.icon = null;
+ mEnterKey.label = res.getText(R.string.label_go_key);
+ break;
+ case EditorInfo.IME_ACTION_NEXT:
+ mEnterKey.iconPreview = null;
+ mEnterKey.icon = null;
+ mEnterKey.label = res.getText(R.string.label_next_key);
+ break;
+ case EditorInfo.IME_ACTION_SEARCH:
+ mEnterKey.icon = res.getDrawable(
+ R.drawable.sym_keyboard_search);
+ mEnterKey.label = null;
+ break;
+ case EditorInfo.IME_ACTION_SEND:
+ mEnterKey.iconPreview = null;
+ mEnterKey.icon = null;
+ mEnterKey.label = res.getText(R.string.label_send_key);
+ break;
+ default:
+ mEnterKey.icon = res.getDrawable(
+ R.drawable.sym_keyboard_return);
+ mEnterKey.label = null;
+ break;
+ }
+ }
+
+ static class LatinKey extends Keyboard.Key {
+
+ public LatinKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) {
+ super(res, parent, x, y, parser);
+ }
+
+ /**
+ * Overriding this method so that we can reduce the target area for the key that
+ * closes the keyboard.
+ */
+ @Override
+ public boolean isInside(int x, int y) {
+ return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
+ }
+ }
+
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
new file mode 100644
index 0000000..7464607
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ *
+ * 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.softkeyboard;
+
+import android.content.Context;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.inputmethodservice.Keyboard.Key;
+import android.util.AttributeSet;
+
+public class LatinKeyboardView extends KeyboardView {
+
+ static final int KEYCODE_OPTIONS = -100;
+
+ public LatinKeyboardView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected boolean onLongPress(Key key) {
+ if (key.codes[0] == Keyboard.KEYCODE_CANCEL) {
+ getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null);
+ return true;
+ } else {
+ return super.onLongPress(key);
+ }
+ }
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
new file mode 100644
index 0000000..656efdf
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
@@ -0,0 +1,674 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ *
+ * 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.softkeyboard;
+
+import android.inputmethodservice.InputMethodService;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.text.method.MetaKeyKeyListener;
+import android.util.Log;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Example of writing an input method for a soft keyboard. This code is
+ * focused on simplicity over completeness, so it should in no way be considered
+ * to be a complete soft keyboard implementation. Its purpose is to provide
+ * a basic example for how you would get started writing an input method, to
+ * be fleshed out as appropriate.
+ */
+public class SoftKeyboard extends InputMethodService
+ implements KeyboardView.OnKeyboardActionListener {
+ static final boolean DEBUG = false;
+
+ /**
+ * This boolean indicates the optional example code for performing
+ * processing of hard keys in addition to regular text generation
+ * from on-screen interaction. It would be used for input methods that
+ * perform language translations (such as converting text entered on
+ * a QWERTY keyboard to Chinese), but may not be used for input methods
+ * that are primarily intended to be used for on-screen text entry.
+ */
+ static final boolean PROCESS_HARD_KEYS = true;
+
+ private KeyboardView mInputView;
+ private CandidateView mCandidateView;
+ private CompletionInfo[] mCompletions;
+
+ private StringBuilder mComposing = new StringBuilder();
+ private boolean mPredictionOn;
+ private boolean mCompletionOn;
+ private int mLastDisplayWidth;
+ private boolean mCapsLock;
+ private long mLastShiftTime;
+ private long mMetaState;
+
+ private LatinKeyboard mSymbolsKeyboard;
+ private LatinKeyboard mSymbolsShiftedKeyboard;
+ private LatinKeyboard mQwertyKeyboard;
+
+ private LatinKeyboard mCurKeyboard;
+
+ private String mWordSeparators;
+
+ /**
+ * Main initialization of the input method component. Be sure to call
+ * to super class.
+ */
+ @Override public void onCreate() {
+ super.onCreate();
+ mWordSeparators = getResources().getString(R.string.word_separators);
+ }
+
+ /**
+ * This is the point where you can do all of your UI initialization. It
+ * is called after creation and any configuration change.
+ */
+ @Override public void onInitializeInterface() {
+ if (mQwertyKeyboard != null) {
+ // Configuration changes can happen after the keyboard gets recreated,
+ // so we need to be able to re-build the keyboards if the available
+ // space has changed.
+ int displayWidth = getMaxWidth();
+ if (displayWidth == mLastDisplayWidth) return;
+ mLastDisplayWidth = displayWidth;
+ }
+ mQwertyKeyboard = new LatinKeyboard(this, R.xml.qwerty);
+ mSymbolsKeyboard = new LatinKeyboard(this, R.xml.symbols);
+ mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift);
+ }
+
+ /**
+ * Called by the framework when your view for creating input needs to
+ * be generated. This will be called the first time your input method
+ * is displayed, and every time it needs to be re-created such as due to
+ * a configuration change.
+ */
+ @Override public View onCreateInputView() {
+ mInputView = (KeyboardView) getLayoutInflater().inflate(
+ R.layout.input, null);
+ mInputView.setOnKeyboardActionListener(this);
+ mInputView.setKeyboard(mQwertyKeyboard);
+ return mInputView;
+ }
+
+ /**
+ * Called by the framework when your view for showing candidates needs to
+ * be generated, like {@link #onCreateInputView}.
+ */
+ @Override public View onCreateCandidatesView() {
+ mCandidateView = new CandidateView(this);
+ mCandidateView.setService(this);
+ return mCandidateView;
+ }
+
+ /**
+ * This is the main point where we do our initialization of the input method
+ * to begin operating on an application. At this point we have been
+ * bound to the client, and are now receiving all of the detailed information
+ * about the target of our edits.
+ */
+ @Override public void onStartInput(EditorInfo attribute, boolean restarting) {
+ super.onStartInput(attribute, restarting);
+
+ // Reset our state. We want to do this even if restarting, because
+ // the underlying state of the text editor could have changed in any way.
+ mComposing.setLength(0);
+ updateCandidates();
+
+ if (!restarting) {
+ // Clear shift states.
+ mMetaState = 0;
+ }
+
+ mPredictionOn = false;
+ mCompletionOn = false;
+ mCompletions = null;
+
+ // We are now going to initialize our state based on the type of
+ // text being edited.
+ switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) {
+ case EditorInfo.TYPE_CLASS_NUMBER:
+ case EditorInfo.TYPE_CLASS_DATETIME:
+ // Numbers and dates default to the symbols keyboard, with
+ // no extra features.
+ mCurKeyboard = mSymbolsKeyboard;
+ break;
+
+ case EditorInfo.TYPE_CLASS_PHONE:
+ // Phones will also default to the symbols keyboard, though
+ // often you will want to have a dedicated phone keyboard.
+ mCurKeyboard = mSymbolsKeyboard;
+ break;
+
+ case EditorInfo.TYPE_CLASS_TEXT:
+ // This is general text editing. We will default to the
+ // normal alphabetic keyboard, and assume that we should
+ // be doing predictive text (showing candidates as the
+ // user types).
+ mCurKeyboard = mQwertyKeyboard;
+ mPredictionOn = true;
+
+ // We now look for a few special variations of text that will
+ // modify our behavior.
+ int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
+ if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD) {
+ // Do not display predictions / what the user is typing
+ // when they are entering a password.
+ mPredictionOn = false;
+ }
+
+ if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+ || variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
+ // Our predictions are not useful for e-mail addresses
+ // or URIs.
+ mPredictionOn = false;
+ }
+
+ if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
+ // If this is an auto-complete text view, then our predictions
+ // will not be shown and instead we will allow the editor
+ // to supply their own. We only show the editor's
+ // candidates when in fullscreen mode, otherwise relying
+ // own it displaying its own UI.
+ mPredictionOn = false;
+ mCompletionOn = isFullscreenMode();
+ }
+
+ // We also want to look at the current state of the editor
+ // to decide whether our alphabetic keyboard should start out
+ // shifted.
+ updateShiftKeyState(attribute);
+ break;
+
+ default:
+ // For all unknown input types, default to the alphabetic
+ // keyboard with no special features.
+ mCurKeyboard = mQwertyKeyboard;
+ }
+
+ // Update the label on the enter key, depending on what the application
+ // says it will do.
+ mCurKeyboard.setImeOptions(getResources(), attribute.imeOptions);
+ }
+
+ /**
+ * This is called when the user is done editing a field. We can use
+ * this to reset our state.
+ */
+ @Override public void onFinishInput() {
+ super.onFinishInput();
+
+ // Clear current composing text and candidates.
+ mComposing.setLength(0);
+ updateCandidates();
+
+ // We only hide the candidates window when finishing input on
+ // a particular editor, to avoid popping the underlying application
+ // up and down if the user is entering text into the bottom of
+ // its window.
+ setCandidatesViewShown(false);
+
+ mCurKeyboard = mQwertyKeyboard;
+ if (mInputView != null) {
+ mInputView.closing();
+ }
+ }
+
+ @Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
+ super.onStartInputView(attribute, restarting);
+ // Apply the selected keyboard to the input view.
+ mInputView.setKeyboard(mCurKeyboard);
+ mInputView.closing();
+ }
+
+ /**
+ * Deal with the editor reporting movement of its cursor.
+ */
+ @Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
+ int newSelStart, int newSelEnd,
+ int candidatesStart, int candidatesEnd) {
+
+ // If the current selection in the text view changes, we should
+ // clear whatever candidate text we have.
+ if (mComposing.length() > 0 && (newSelStart != candidatesEnd
+ || newSelEnd != candidatesEnd)) {
+ mComposing.setLength(0);
+ updateCandidates();
+ InputConnection ic = getCurrentInputConnection();
+ if (ic != null) {
+ ic.finishComposingText();
+ }
+ }
+ }
+
+ /**
+ * This tells us about completions that the editor has determined based
+ * on the current text in it. We want to use this in fullscreen mode
+ * to show the completions ourself, since the editor can not be seen
+ * in that situation.
+ */
+ @Override public void onDisplayCompletions(CompletionInfo[] completions) {
+ if (mCompletionOn) {
+ mCompletions = completions;
+ if (completions == null) {
+ setSuggestions(null, false, false);
+ return;
+ }
+
+ List<String> stringList = new ArrayList<String>();
+ for (int i=0; i<(completions != null ? completions.length : 0); i++) {
+ CompletionInfo ci = completions[i];
+ if (ci != null) stringList.add(ci.getText().toString());
+ }
+ setSuggestions(stringList, true, true);
+ }
+ }
+
+ /**
+ * This translates incoming hard key events in to edit operations on an
+ * InputConnection. It is only needed when using the
+ * PROCESS_HARD_KEYS option.
+ */
+ private boolean translateKeyDown(int keyCode, KeyEvent event) {
+ mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState,
+ keyCode, event);
+ int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(mMetaState));
+ mMetaState = MetaKeyKeyListener.adjustMetaAfterKeypress(mMetaState);
+ InputConnection ic = getCurrentInputConnection();
+ if (c == 0 || ic == null) {
+ return false;
+ }
+
+ boolean dead = false;
+
+ if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
+ dead = true;
+ c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
+ }
+
+ if (mComposing.length() > 0) {
+ char accent = mComposing.charAt(mComposing.length() -1 );
+ int composed = KeyEvent.getDeadChar(accent, c);
+
+ if (composed != 0) {
+ c = composed;
+ mComposing.setLength(mComposing.length()-1);
+ }
+ }
+
+ onKey(c, null);
+
+ return true;
+ }
+
+ /**
+ * Use this to monitor key events being delivered to the application.
+ * We get first crack at them, and can either resume them or let them
+ * continue to the app.
+ */
+ @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ // The InputMethodService already takes care of the back
+ // key for us, to dismiss the input method if it is shown.
+ // However, our keyboard could be showing a pop-up window
+ // that back should dismiss, so we first allow it to do that.
+ if (event.getRepeatCount() == 0 && mInputView != null) {
+ if (mInputView.handleBack()) {
+ return true;
+ }
+ }
+ break;
+
+ case KeyEvent.KEYCODE_DEL:
+ // Special handling of the delete key: if we currently are
+ // composing text for the user, we want to modify that instead
+ // of let the application to the delete itself.
+ if (mComposing.length() > 0) {
+ onKey(Keyboard.KEYCODE_DELETE, null);
+ return true;
+ }
+ break;
+
+ case KeyEvent.KEYCODE_ENTER:
+ // Let the underlying text editor always handle these.
+ return false;
+
+ default:
+ // For all other keys, if we want to do transformations on
+ // text being entered with a hard keyboard, we need to process
+ // it and do the appropriate action.
+ if (PROCESS_HARD_KEYS) {
+ if (keyCode == KeyEvent.KEYCODE_SPACE
+ && (event.getMetaState()&KeyEvent.META_ALT_ON) != 0) {
+ // A silly example: in our input method, Alt+Space
+ // is a shortcut for 'android' in lower case.
+ InputConnection ic = getCurrentInputConnection();
+ if (ic != null) {
+ // First, tell the editor that it is no longer in the
+ // shift state, since we are consuming this.
+ ic.clearMetaKeyStates(KeyEvent.META_ALT_ON);
+ keyDownUp(KeyEvent.KEYCODE_A);
+ keyDownUp(KeyEvent.KEYCODE_N);
+ keyDownUp(KeyEvent.KEYCODE_D);
+ keyDownUp(KeyEvent.KEYCODE_R);
+ keyDownUp(KeyEvent.KEYCODE_O);
+ keyDownUp(KeyEvent.KEYCODE_I);
+ keyDownUp(KeyEvent.KEYCODE_D);
+ // And we consume this event.
+ return true;
+ }
+ }
+ if (mPredictionOn && translateKeyDown(keyCode, event)) {
+ return true;
+ }
+ }
+ }
+
+ return super.onKeyDown(keyCode, event);
+ }
+
+ /**
+ * Use this to monitor key events being delivered to the application.
+ * We get first crack at them, and can either resume them or let them
+ * continue to the app.
+ */
+ @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
+ // If we want to do transformations on text being entered with a hard
+ // keyboard, we need to process the up events to update the meta key
+ // state we are tracking.
+ if (PROCESS_HARD_KEYS) {
+ if (mPredictionOn) {
+ mMetaState = MetaKeyKeyListener.handleKeyUp(mMetaState,
+ keyCode, event);
+ }
+ }
+
+ return super.onKeyUp(keyCode, event);
+ }
+
+ /**
+ * Helper function to commit any text being composed in to the editor.
+ */
+ private void commitTyped(InputConnection inputConnection) {
+ if (mComposing.length() > 0) {
+ inputConnection.commitText(mComposing, mComposing.length());
+ mComposing.setLength(0);
+ updateCandidates();
+ }
+ }
+
+ /**
+ * Helper to update the shift state of our keyboard based on the initial
+ * editor state.
+ */
+ private void updateShiftKeyState(EditorInfo attr) {
+ if (attr != null
+ && mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
+ int caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
+ mInputView.setShifted(mCapsLock || caps != 0);
+ }
+ }
+
+ /**
+ * Helper to determine if a given character code is alphabetic.
+ */
+ private boolean isAlphabet(int code) {
+ if (Character.isLetter(code)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Helper to send a key down / key up pair to the current editor.
+ */
+ private void keyDownUp(int keyEventCode) {
+ getCurrentInputConnection().sendKeyEvent(
+ new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
+ getCurrentInputConnection().sendKeyEvent(
+ new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
+ }
+
+ /**
+ * Helper to send a character to the editor as raw key events.
+ */
+ private void sendKey(int keyCode) {
+ switch (keyCode) {
+ case '\n':
+ keyDownUp(KeyEvent.KEYCODE_ENTER);
+ break;
+ default:
+ if (keyCode >= '0' && keyCode <= '9') {
+ keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
+ } else {
+ getCurrentInputConnection().commitText(String.valueOf((char) keyCode), 1);
+ }
+ break;
+ }
+ }
+
+ // Implementation of KeyboardViewListener
+
+ public void onKey(int primaryCode, int[] keyCodes) {
+ if (isWordSeparator(primaryCode)) {
+ // Handle separator
+ if (mComposing.length() > 0) {
+ commitTyped(getCurrentInputConnection());
+ }
+ sendKey(primaryCode);
+ updateShiftKeyState(getCurrentInputEditorInfo());
+ } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
+ handleBackspace();
+ } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
+ handleShift();
+ } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
+ handleClose();
+ return;
+ } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
+ // Show a menu or somethin'
+ } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE
+ && mInputView != null) {
+ Keyboard current = mInputView.getKeyboard();
+ if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
+ current = mQwertyKeyboard;
+ } else {
+ current = mSymbolsKeyboard;
+ }
+ mInputView.setKeyboard(current);
+ if (current == mSymbolsKeyboard) {
+ current.setShifted(false);
+ }
+ } else {
+ handleCharacter(primaryCode, keyCodes);
+ }
+ }
+
+ public void onText(CharSequence text) {
+ InputConnection ic = getCurrentInputConnection();
+ if (ic == null) return;
+ ic.beginBatchEdit();
+ if (mComposing.length() > 0) {
+ commitTyped(ic);
+ }
+ ic.commitText(text, 0);
+ ic.endBatchEdit();
+ updateShiftKeyState(getCurrentInputEditorInfo());
+ }
+
+ /**
+ * Update the list of available candidates from the current composing
+ * text. This will need to be filled in by however you are determining
+ * candidates.
+ */
+ private void updateCandidates() {
+ if (!mCompletionOn) {
+ if (mComposing.length() > 0) {
+ ArrayList<String> list = new ArrayList<String>();
+ list.add(mComposing.toString());
+ setSuggestions(list, true, true);
+ } else {
+ setSuggestions(null, false, false);
+ }
+ }
+ }
+
+ public void setSuggestions(List<String> suggestions, boolean completions,
+ boolean typedWordValid) {
+ if (suggestions != null && suggestions.size() > 0) {
+ setCandidatesViewShown(true);
+ } else if (isFullscreenMode()) {
+ setCandidatesViewShown(true);
+ }
+ if (mCandidateView != null) {
+ mCandidateView.setSuggestions(suggestions, completions, typedWordValid);
+ }
+ }
+
+ private void handleBackspace() {
+ final int length = mComposing.length();
+ if (length > 1) {
+ mComposing.delete(length - 1, length);
+ getCurrentInputConnection().setComposingText(mComposing, mComposing.length());
+ updateCandidates();
+ } else if (length > 0) {
+ mComposing.setLength(0);
+ getCurrentInputConnection().commitText("", 0);
+ updateCandidates();
+ } else {
+ keyDownUp(KeyEvent.KEYCODE_DEL);
+ }
+ updateShiftKeyState(getCurrentInputEditorInfo());
+ }
+
+ private void handleShift() {
+ if (mInputView == null) {
+ return;
+ }
+
+ Keyboard currentKeyboard = mInputView.getKeyboard();
+ if (mQwertyKeyboard == currentKeyboard) {
+ // Alphabet keyboard
+ checkToggleCapsLock();
+ mInputView.setShifted(mCapsLock || !mInputView.isShifted());
+ } else if (currentKeyboard == mSymbolsKeyboard) {
+ mSymbolsKeyboard.setShifted(true);
+ mInputView.setKeyboard(mSymbolsShiftedKeyboard);
+ mSymbolsShiftedKeyboard.setShifted(true);
+ } else if (currentKeyboard == mSymbolsShiftedKeyboard) {
+ mSymbolsShiftedKeyboard.setShifted(false);
+ mInputView.setKeyboard(mSymbolsKeyboard);
+ mSymbolsKeyboard.setShifted(false);
+ }
+ }
+
+ private void handleCharacter(int primaryCode, int[] keyCodes) {
+ if (isInputViewShown()) {
+ if (mInputView.isShifted()) {
+ primaryCode = Character.toUpperCase(primaryCode);
+ }
+ }
+ if (isAlphabet(primaryCode) && mPredictionOn) {
+ mComposing.append((char) primaryCode);
+ getCurrentInputConnection().setComposingText(mComposing, mComposing.length());
+ updateShiftKeyState(getCurrentInputEditorInfo());
+ updateCandidates();
+ } else {
+ getCurrentInputConnection().commitText(
+ String.valueOf((char) primaryCode), 1);
+ }
+ }
+
+ private void handleClose() {
+ commitTyped(getCurrentInputConnection());
+ dismissSoftInput(0);
+ mInputView.closing();
+ }
+
+ private void checkToggleCapsLock() {
+ long now = System.currentTimeMillis();
+ if (mLastShiftTime + 800 > now) {
+ mCapsLock = !mCapsLock;
+ mLastShiftTime = 0;
+ } else {
+ mLastShiftTime = now;
+ }
+ }
+
+ private String getWordSeparators() {
+ return mWordSeparators;
+ }
+
+ public boolean isWordSeparator(int code) {
+ String separators = getWordSeparators();
+ return separators.contains(String.valueOf((char)code));
+ }
+
+ public void pickDefaultCandidate() {
+ pickSuggestionManually(0);
+ }
+
+ public void pickSuggestionManually(int index) {
+ if (mCompletionOn && mCompletions != null && index >= 0
+ && index < mCompletions.length) {
+ CompletionInfo ci = mCompletions[index];
+ getCurrentInputConnection().commitCompletion(ci);
+ if (mCandidateView != null) {
+ mCandidateView.clear();
+ }
+ updateShiftKeyState(getCurrentInputEditorInfo());
+ } else if (mComposing.length() > 0) {
+ // If we were generating candidate suggestions for the current
+ // text, we would commit one of them here. But for this sample,
+ // we will just commit the current text.
+ commitTyped(getCurrentInputConnection());
+ }
+ }
+
+ public void swipeRight() {
+ if (mCompletionOn) {
+ pickDefaultCandidate();
+ }
+ }
+
+ public void swipeLeft() {
+ handleBackspace();
+ }
+
+ public void swipeDown() {
+ handleClose();
+ }
+
+ public void swipeUp() {
+ }
+
+ public void onPress(int primaryCode) {
+ }
+
+ public void onRelease(int primaryCode) {
+ }
+}