Merge "Add flag to grant permissions when running tests." into mnc-dev
diff --git a/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java b/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
index 3a0b2a3..505a353 100644
--- a/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
+++ b/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
@@ -32,19 +32,21 @@
*
*/
public class DefaultActivity extends Activity {
-
+
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
+
// Add a persistent setting to allow other apps to know the device has been provisioned.
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
+ Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
+
// Enable the GPS.
// Not needed since this SDK will contain the Settings app.
Settings.Secure.putString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
LocationManager.GPS_PROVIDER);
-
+
// enable install from non market
Settings.Global.putInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS, 1);
diff --git a/build/sdk-windows-x86.atree b/build/sdk-windows-x86.atree
index f8a14b1..e7985bd 100644
--- a/build/sdk-windows-x86.atree
+++ b/build/sdk-windows-x86.atree
@@ -75,7 +75,7 @@
rm build-tools/${PLATFORM_NAME}/bin/dexdump
bin/dexdump.exe strip build-tools/${PLATFORM_NAME}/bin/dexdump.exe
-rm build-tools/${PLATFORM_NAME}/llvm-rs-cc
+rm build-tools/${PLATFORM_NAME}/bin/llvm-rs-cc
bin/llvm-rs-cc.exe strip build-tools/${PLATFORM_NAME}/bin/llvm-rs-cc.exe
rm build-tools/${PLATFORM_NAME}/lib/libLLVM.so
diff --git a/build/sdk.atree b/build/sdk.atree
index b66dbd0..8b40971 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -317,6 +317,13 @@
developers/build/prebuilts/gradle/ScreenCapture samples/${PLATFORM_NAME}/media/ScreenCapture
developers/build/prebuilts/gradle/NfcProvisioning samples/${PLATFORM_NAME}/nfc/NfcProvisioning
developers/build/prebuilts/gradle/DeviceOwner samples/${PLATFORM_NAME}/admin/DeviceOwner
+developers/build/prebuilts/gradle/ConfirmCredential samples/${PLATFORM_NAME}/security/ConfirmCredential
+developers/build/prebuilts/gradle/FingerprintDialog samples/${PLATFORM_NAME}/security/FingerprintDialog
+developers/build/prebuilts/gradle/RuntimePermissions samples/${PLATFORM_NAME}/system/RuntimePermissions
+developers/build/prebuilts/gradle/RuntimePermissionsBasic samples/${PLATFORM_NAME}/system/RuntimePermissionsBasic
+developers/build/prebuilts/gradle/ActiveNotifications samples/${PLATFORM_NAME}/notification/ActiveNotifications
+developers/build/prebuilts/gradle/Camera2Raw samples/${PLATFORM_NAME}/media/Camera2Raw
+developers/build/prebuilts/gradle/AutoBackupForApps samples/${PLATFORM_NAME}/content/AutoBackupForApps
developers/build/prebuilts/androidtv samples/${PLATFORM_NAME}/androidtv
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index e5e2f27..2144d88 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -38,6 +38,7 @@
<uses-permission android:name="android.permission.TRANSMIT_IR" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
<!-- For android.media.audiofx.Visualizer -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
@@ -550,17 +551,7 @@
</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>
+ <service android:name=".app.RemoteService" android:process=":remote" />
<activity android:name=".app.RemoteService$Controller"
android:label="@string/activity_remote_service_controller"
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
index 0c7c108..ea1b681 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
@@ -23,6 +23,7 @@
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
+import android.os.PowerManager;
import android.util.Log;
import android.widget.Toast;
@@ -71,9 +72,7 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
- // We want this service to continue running until it is explicitly
- // stopped, so return sticky.
- return START_STICKY;
+ return START_NOT_STICKY;
}
@Override
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java b/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
index 76458f4..3745def 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java
@@ -32,6 +32,7 @@
import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@@ -80,6 +81,12 @@
}
@Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.i("LocalService", "Received start id " + startId + ": " + intent);
+ return START_NOT_STICKY;
+ }
+
+ @Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel(R.string.remote_service_started);
@@ -232,8 +239,7 @@
// 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"));
+ startService(new Intent(Controller.this, RemoteService.class));
}
};
@@ -242,8 +248,7 @@
// 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"));
+ stopService(new Intent(Controller.this, RemoteService.class));
}
};
}
@@ -361,10 +366,11 @@
// 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);
+ Intent intent = new Intent(Binding.this, RemoteService.class);
+ intent.setAction(IRemoteService.class.getName());
+ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ intent.setAction(ISecondary.class.getName());
+ bindService(intent, mSecondaryConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
mCallbackText.setText("Binding.");
}
@@ -471,6 +477,7 @@
public static class BindingOptions extends Activity {
ServiceConnection mCurConnection;
TextView mCallbackText;
+ Intent mBindIntent;
class MyServiceConnection implements ServiceConnection {
final boolean mUnbindOnDisconnect;
@@ -539,6 +546,9 @@
mCallbackText = (TextView)findViewById(R.id.callback);
mCallbackText.setText("Not attached.");
+
+ mBindIntent = new Intent(this, RemoteService.class);
+ mBindIntent.setAction(IRemoteService.class.getName());
}
private OnClickListener mBindNormalListener = new OnClickListener() {
@@ -548,8 +558,7 @@
mCurConnection = null;
}
ServiceConnection conn = new MyServiceConnection();
- if (bindService(new Intent(IRemoteService.class.getName()),
- conn, Context.BIND_AUTO_CREATE)) {
+ if (bindService(mBindIntent, conn, Context.BIND_AUTO_CREATE)) {
mCurConnection = conn;
}
}
@@ -562,8 +571,8 @@
mCurConnection = null;
}
ServiceConnection conn = new MyServiceConnection();
- if (bindService(new Intent(IRemoteService.class.getName()),
- conn, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND)) {
+ if (bindService(mBindIntent, conn,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND)) {
mCurConnection = conn;
}
}
@@ -590,8 +599,8 @@
mCurConnection = null;
}
ServiceConnection conn = new MyServiceConnection();
- if (bindService(new Intent(IRemoteService.class.getName()),
- conn, Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_OOM_MANAGEMENT)) {
+ if (bindService(mBindIntent, conn,
+ Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_OOM_MANAGEMENT)) {
mCurConnection = conn;
}
}
@@ -604,8 +613,8 @@
mCurConnection = null;
}
ServiceConnection conn = new MyServiceConnection(true);
- if (bindService(new Intent(IRemoteService.class.getName()),
- conn, Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY)) {
+ if (bindService(mBindIntent, conn,
+ Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY)) {
mCurConnection = conn;
}
}
@@ -618,8 +627,8 @@
mCurConnection = null;
}
ServiceConnection conn = new MyServiceConnection();
- if (bindService(new Intent(IRemoteService.class.getName()),
- conn, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT)) {
+ if (bindService(mBindIntent, conn,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT)) {
mCurConnection = conn;
}
}
@@ -632,8 +641,8 @@
mCurConnection = null;
}
ServiceConnection conn = new MyServiceConnection();
- if (bindService(new Intent(IRemoteService.class.getName()),
- conn, Context.BIND_AUTO_CREATE | Context.BIND_ADJUST_WITH_ACTIVITY
+ if (bindService(mBindIntent, conn,
+ Context.BIND_AUTO_CREATE | Context.BIND_ADJUST_WITH_ACTIVITY
| Context.BIND_WAIVE_PRIORITY)) {
mCurConnection = conn;
}
diff --git a/samples/SampleSyncAdapter/samplesyncadapter_server/app.yaml b/samples/SampleSyncAdapter/samplesyncadapter_server/app.yaml
index 8526177..0c4c3b2 100644
--- a/samples/SampleSyncAdapter/samplesyncadapter_server/app.yaml
+++ b/samples/SampleSyncAdapter/samplesyncadapter_server/app.yaml
@@ -12,7 +12,10 @@
# License for the specific language governing permissions and limitations under
# the License.
-application: samplesyncadapter2
+# Note the app name used to be "samplesyncadapter2", but it's now "samplesyncadapterhr" because
+# it's been migrated to HR. But it's still accessible under the old URL,
+# http://samplesyncadapter2.appspot.com/
+application: samplesyncadapterhr
version: 1
runtime: python
api_version: 1
diff --git a/samples/Support7Demos/AndroidManifest.xml b/samples/Support7Demos/AndroidManifest.xml
index 5c5bf14..038fd63 100644
--- a/samples/Support7Demos/AndroidManifest.xml
+++ b/samples/Support7Demos/AndroidManifest.xml
@@ -393,6 +393,15 @@
</intent-filter>
</activity>
+ <activity android:name=".widget.StaggeredGridLayoutManagerActivity"
+ android:label="@string/staggered_grid_layout_manager"
+ android:theme="@style/Theme.AppCompat">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.example.android.supportv7.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
<activity android:name=".view.CardViewActivity"
android:label="@string/card_view"
android:theme="@style/Theme.AppCompat">
diff --git a/samples/Support7Demos/res/values/strings.xml b/samples/Support7Demos/res/values/strings.xml
index 843de1a..820aa0e 100644
--- a/samples/Support7Demos/res/values/strings.xml
+++ b/samples/Support7Demos/res/values/strings.xml
@@ -149,6 +149,7 @@
<string name="animated_recycler_view">RecyclerView/AnimatedRecyclerView</string>
<string name="linear_layout_manager">RecyclerView/Linear Layout Manager</string>
<string name="grid_layout_manager">RecyclerView/Grid Layout Manager</string>
+ <string name="staggered_grid_layout_manager">RecyclerView/Staggered Grid Layout Manager</string>
<string name="checkbox_orientation">Horz.</string>
<string name="checkbox_reverse">Rev.</string>
<string name="checkbox_layout_dir">Layout Dir</string>
@@ -199,4 +200,5 @@
<string name="drag">drag me</string>
<string name="swipe">swipe me</string>
<string name="swiping">swiping</string>
+ <string name="vertical">vertical</string>
</resources>
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/StaggeredGridLayoutManagerActivity.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/StaggeredGridLayoutManagerActivity.java
new file mode 100644
index 0000000..39d8657
--- /dev/null
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/StaggeredGridLayoutManagerActivity.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.supportv7.widget;
+
+import com.example.android.supportv7.R;
+import com.example.android.supportv7.widget.util.ConfigToggle;
+
+import android.support.v7.widget.StaggeredGridLayoutManager;
+
+public class StaggeredGridLayoutManagerActivity
+ extends BaseLayoutManagerActivity<StaggeredGridLayoutManager> {
+
+ private boolean mVertical = true;
+
+ @Override
+ protected StaggeredGridLayoutManager createLayoutManager() {
+ if (mVertical) {
+ return new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
+ } else {
+ return new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL);
+ }
+ }
+
+ @Override
+ ConfigToggle[] createConfigToggles() {
+ return new ConfigToggle[] {
+ new ConfigToggle(this, R.string.vertical) {
+ @Override
+ public boolean isChecked() {
+ return mVertical;
+ }
+
+ @Override
+ public void onChange(boolean newValue) {
+ if (mVertical == newValue) {
+ return;
+ }
+ mVertical = newValue;
+ mRecyclerView.setLayoutManager(createLayoutManager());
+ }
+ }
+ };
+ }
+}
diff --git a/samples/SupportDesignDemos/AndroidManifest.xml b/samples/SupportDesignDemos/AndroidManifest.xml
index e1ecdf3..a837458 100644
--- a/samples/SupportDesignDemos/AndroidManifest.xml
+++ b/samples/SupportDesignDemos/AndroidManifest.xml
@@ -26,7 +26,8 @@
<application android:label="@string/activity_sample_code"
android:supportsRtl="true"
- android:icon="@drawable/app_sample_code">
+ android:icon="@drawable/app_sample_code"
+ android:theme="@style/Theme.FAB">
<activity android:name="SupportDesignDemos">
<intent-filter>
diff --git a/samples/browseable/ActionBarCompat-Basic/_index.jd b/samples/browseable/ActionBarCompat-Basic/_index.jd
index 0d3a2d8..5219ee6 100644
--- a/samples/browseable/ActionBarCompat-Basic/_index.jd
+++ b/samples/browseable/ActionBarCompat-Basic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ActionBarCompat-Basic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-colors.xml b/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-colors.xml
+++ b/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-template-styles.xml b/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ActionBarCompat-Basic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ActionBarCompat-Basic/res/values/base-strings.xml b/samples/browseable/ActionBarCompat-Basic/res/values/base-strings.xml
index 18f71a6..4ec4a82 100644
--- a/samples/browseable/ActionBarCompat-Basic/res/values/base-strings.xml
+++ b/samples/browseable/ActionBarCompat-Basic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ActionBarCompat-Basic</string>
<string name="intro_message">
diff --git a/samples/browseable/ActionBarCompat-ListPopupMenu/_index.jd b/samples/browseable/ActionBarCompat-ListPopupMenu/_index.jd
index 8696da2..d1042de 100644
--- a/samples/browseable/ActionBarCompat-ListPopupMenu/_index.jd
+++ b/samples/browseable/ActionBarCompat-ListPopupMenu/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ActionBarCompat-ListPopupMenu"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-colors.xml b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-colors.xml
+++ b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-template-styles.xml b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/base-strings.xml b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/base-strings.xml
index db43f8c..21359bb 100644
--- a/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/base-strings.xml
+++ b/samples/browseable/ActionBarCompat-ListPopupMenu/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ActionBarCompat-ListPopupMenu</string>
<string name="intro_message">
diff --git a/samples/browseable/ActionBarCompat-ShareActionProvider/_index.jd b/samples/browseable/ActionBarCompat-ShareActionProvider/_index.jd
index 6752a39..d9df536 100644
--- a/samples/browseable/ActionBarCompat-ShareActionProvider/_index.jd
+++ b/samples/browseable/ActionBarCompat-ShareActionProvider/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ActionBarCompat-ShareActionProvider"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-colors.xml b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-colors.xml
+++ b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-template-styles.xml b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/base-strings.xml b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/base-strings.xml
index 2e0aae4..21d17e4 100644
--- a/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/base-strings.xml
+++ b/samples/browseable/ActionBarCompat-ShareActionProvider/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ActionBarCompat-ShareActionProvider</string>
<string name="intro_message">
diff --git a/samples/browseable/ActionBarCompat-Styled/_index.jd b/samples/browseable/ActionBarCompat-Styled/_index.jd
index f2f3b3c..898957a 100644
--- a/samples/browseable/ActionBarCompat-Styled/_index.jd
+++ b/samples/browseable/ActionBarCompat-Styled/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ActionBarCompat-Styled"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-colors.xml b/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-colors.xml
+++ b/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-template-styles.xml b/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ActionBarCompat-Styled/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ActionBarCompat-Styled/res/values/base-strings.xml b/samples/browseable/ActionBarCompat-Styled/res/values/base-strings.xml
index 324726d..7e59404 100644
--- a/samples/browseable/ActionBarCompat-Styled/res/values/base-strings.xml
+++ b/samples/browseable/ActionBarCompat-Styled/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ActionBarCompat-Styled</string>
<string name="intro_message">
diff --git a/samples/browseable/ActiveNotifications/AndroidManifest.xml b/samples/browseable/ActiveNotifications/AndroidManifest.xml
new file mode 100644
index 0000000..3a39282
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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.activenotifications"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@mipmap/ic_launcher"
+ android:theme="@style/AppTheme">
+
+ <activity android:name=".ActiveNotificationActivity"
+ android:label="@string/app_name">
+ <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/browseable/ActiveNotifications/_index.jd b/samples/browseable/ActiveNotifications/_index.jd
new file mode 100644
index 0000000..d8ce4a9
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/_index.jd
@@ -0,0 +1,13 @@
+
+page.tags="ActiveNotification"
+sample.group=Notification
+@jd:body
+
+<p>
+
+The NotificationManager can tell you how many notifications your application is currently showing.
+This sample demonstrates how to use this API that has been introduced with Android M.
+To get started, press the "add a notification" button.
+When a notification is being canceled, the count gets updated via a PendingIntent.
+
+ </p>
diff --git a/samples/browseable/ActiveNotifications/res/drawable-hdpi/tile.9.png b/samples/browseable/ActiveNotifications/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/layout-w720dp/activity_main.xml b/samples/browseable/ActiveNotifications/res/layout-w720dp/activity_main.xml
new file mode 100755
index 0000000..c9a52f6
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,73 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <LinearLayout
+ android:id="@+id/sample_output"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/margin_medium"
+ android:paddingRight="@dimen/margin_medium"
+ android:paddingTop="@dimen/margin_large"
+ android:paddingBottom="@dimen/margin_large"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="0px"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
+
+
diff --git a/samples/browseable/ActiveNotifications/res/layout/activity_main.xml b/samples/browseable/ActiveNotifications/res/layout/activity_main.xml
new file mode 100755
index 0000000..1ae4f98
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/layout/activity_main.xml
@@ -0,0 +1,65 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <ViewAnimator
+ android:id="@+id/sample_output"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <ScrollView
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </ScrollView>
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </ViewAnimator>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:layout_height="0px" />
+
+</LinearLayout>
+
diff --git a/samples/browseable/ActiveNotifications/res/layout/fragment_notification_builder.xml b/samples/browseable/ActiveNotifications/res/layout/fragment_notification_builder.xml
new file mode 100644
index 0000000..379cd5e
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/layout/fragment_notification_builder.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <Button
+ android:id="@+id/add_notification"
+ android:text="@string/add_a_notification"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <TextView
+ style="@android:style/TextAppearance.Material.Large"
+ android:id="@+id/number_of_notifications"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+</LinearLayout>
diff --git a/samples/browseable/ActiveNotifications/res/menu/main.xml b/samples/browseable/ActiveNotifications/res/menu/main.xml
new file mode 100644
index 0000000..b49c2c5
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/menu/main.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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/menu_toggle_log"
+ android:showAsAction="always"
+ android:title="@string/sample_show_log" />
+</menu>
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-hdpi/ic_launcher.png b/samples/browseable/ActiveNotifications/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..b176e69
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-hdpi/ic_notification.png b/samples/browseable/ActiveNotifications/res/mipmap-hdpi/ic_notification.png
new file mode 100644
index 0000000..efb231d
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-hdpi/ic_notification.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-mdpi/ic_launcher.png b/samples/browseable/ActiveNotifications/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..205654f
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-mdpi/ic_notification.png b/samples/browseable/ActiveNotifications/res/mipmap-mdpi/ic_notification.png
new file mode 100644
index 0000000..b5f1bc9
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-mdpi/ic_notification.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-xhdpi/ic_launcher.png b/samples/browseable/ActiveNotifications/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..98262ee
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-xhdpi/ic_notification.png b/samples/browseable/ActiveNotifications/res/mipmap-xhdpi/ic_notification.png
new file mode 100644
index 0000000..3361f2d
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-xhdpi/ic_notification.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-xxhdpi/ic_launcher.png b/samples/browseable/ActiveNotifications/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..325875a
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-xxhdpi/ic_notification.png b/samples/browseable/ActiveNotifications/res/mipmap-xxhdpi/ic_notification.png
new file mode 100644
index 0000000..7d1946a
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-xxhdpi/ic_notification.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-xxxhdpi/ic_launcher.png b/samples/browseable/ActiveNotifications/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..254c775
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/mipmap-xxxhdpi/ic_notification.png b/samples/browseable/ActiveNotifications/res/mipmap-xxxhdpi/ic_notification.png
new file mode 100644
index 0000000..47b12c9
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/mipmap-xxxhdpi/ic_notification.png
Binary files differ
diff --git a/samples/browseable/ActiveNotifications/res/values-sw600dp/template-dimens.xml b/samples/browseable/ActiveNotifications/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values-sw600dp/template-styles.xml b/samples/browseable/ActiveNotifications/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values-v11/template-styles.xml b/samples/browseable/ActiveNotifications/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values-v21/base-colors.xml b/samples/browseable/ActiveNotifications/res/values-v21/base-colors.xml
new file mode 100644
index 0000000..8b6ec3f
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values-v21/base-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values-v21/base-template-styles.xml b/samples/browseable/ActiveNotifications/res/values-v21/base-template-styles.xml
new file mode 100644
index 0000000..c778e4f
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values-v21/base-template-styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light">
+ </style>
+
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values/base-strings.xml b/samples/browseable/ActiveNotifications/res/values/base-strings.xml
new file mode 100644
index 0000000..5fc846c
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values/base-strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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">ActiveNotification</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+The NotificationManager can tell you how many notifications your application is currently showing.
+This sample demonstrates how to use this API that has been introduced with Android M.
+To get started, press the "add a notification" button.
+When a notification is being canceled, the count gets updated via a PendingIntent.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values/fragmentview_strings.xml b/samples/browseable/ActiveNotifications/res/values/fragmentview_strings.xml
new file mode 100755
index 0000000..7b9d9ec
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values/fragmentview_strings.xml
@@ -0,0 +1,19 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="sample_show_log">Show Log</string>
+ <string name="sample_hide_log">Hide Log</string>
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values/strings.xml b/samples/browseable/ActiveNotifications/res/values/strings.xml
new file mode 100644
index 0000000..0f2977d
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="add_a_notification">Add a notification</string>
+ <string name="active_notifications">Active Notifications: %1$s</string>
+ <string name="update_notification_count">Update count</string>
+ <string name="sample_notification_content">This is a sample notification.</string>
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values/template-dimens.xml b/samples/browseable/ActiveNotifications/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/ActiveNotifications/res/values/template-styles.xml b/samples/browseable/ActiveNotifications/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/ActiveNotificationActivity.java b/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/ActiveNotificationActivity.java
new file mode 100644
index 0000000..bdb5421
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/ActiveNotificationActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.activenotifications;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+
+public class ActiveNotificationActivity extends MainActivity {
+
+ private ActiveNotificationFragment mFragment;
+
+ protected static final String ACTION_NOTIFICATION_DELETE
+ = "com.example.android.activenotifications.delete";
+
+ private BroadcastReceiver mDeleteReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mFragment == null) {
+ findFragment();
+ }
+ mFragment.updateNumberOfNotifications();
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
+ super.onCreate(savedInstanceState, persistentState);
+ findFragment();
+ mFragment.updateNumberOfNotifications();
+ }
+
+ private void findFragment() {
+ mFragment = (ActiveNotificationFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.sample_content_fragment);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ registerReceiver(mDeleteReceiver, new IntentFilter(ACTION_NOTIFICATION_DELETE));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ unregisterReceiver(mDeleteReceiver);
+ }
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/ActiveNotificationFragment.java b/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/ActiveNotificationFragment.java
new file mode 100644
index 0000000..3e87849
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/ActiveNotificationFragment.java
@@ -0,0 +1,124 @@
+package com.example.android.activenotifications;
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+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.service.notification.StatusBarNotification;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.example.android.common.logger.Log;
+
+/**
+ * A fragment that enables display of notifications.
+ */
+public class ActiveNotificationFragment extends Fragment {
+
+ private static final String TAG = "ActiveNotificationFragment";
+
+ private NotificationManager mNotificationManager;
+ private TextView mNumberOfNotifications;
+
+ // Every notification needs a unique ID otherwise the previous one would be overwritten.
+ private int mNotificationId = 0;
+ private PendingIntent mDeletePendingIntent;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_notification_builder, container, false);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateNumberOfNotifications();
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ mNotificationManager = (NotificationManager) getActivity().getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ mNumberOfNotifications = (TextView) view.findViewById(R.id.number_of_notifications);
+
+ // Supply actions to the button that is displayed on screen.
+ View.OnClickListener onClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.add_notification: {
+ addNotificationAndReadNumber();
+ break;
+ }
+ }
+ }
+ };
+ view.findViewById(R.id.add_notification).setOnClickListener(onClickListener);
+
+ // [BEGIN create_pending_intent_for_deletion]
+ // Create a PendingIntent to be fired upon deletion of a Notification.
+ Intent deleteIntent = new Intent(ActiveNotificationActivity.ACTION_NOTIFICATION_DELETE);
+ mDeletePendingIntent = PendingIntent.getBroadcast(getActivity(),
+ 2323 /* requestCode */, deleteIntent, 0);
+ // [END create_pending_intent_for_deletion]
+ }
+
+ /**
+ * Add a new {@link Notification} with sample data and send it to the system.
+ * Then read the current number of displayed notifications for this application.
+ */
+ private void addNotificationAndReadNumber() {
+ // [BEGIN create_notification]
+ // Create a Notification and notify the system.
+ final Notification.Builder builder = new Notification.Builder(getActivity())
+ .setSmallIcon(R.mipmap.ic_notification)
+ .setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.sample_notification_content))
+ .setAutoCancel(true)
+ .setDeleteIntent(mDeletePendingIntent);
+
+ final Notification notification = builder.build();
+ mNotificationManager.notify(++mNotificationId, notification);
+ // [END create_notification]
+ Log.i(TAG, "Add a notification");
+ updateNumberOfNotifications();
+ }
+
+ /**
+ * Request the current number of notifications from the {@link NotificationManager} and
+ * display them to the user.
+ */
+ protected void updateNumberOfNotifications() {
+ // [BEGIN get_active_notifications]
+ // Query the currently displayed notifications.
+ final StatusBarNotification[] activeNotifications = mNotificationManager
+ .getActiveNotifications();
+ // [END get_active_notifications]
+ final int numberOfNotifications = activeNotifications.length;
+ mNumberOfNotifications.setText(getString(R.string.active_notifications,
+ numberOfNotifications));
+ Log.i(TAG, getString(R.string.active_notifications, numberOfNotifications));
+ }
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/MainActivity.java b/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/MainActivity.java
new file mode 100644
index 0000000..bf11b8e
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.activenotifications/MainActivity.java
@@ -0,0 +1,110 @@
+/*
+* Copyright 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+package com.example.android.activenotifications;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ViewAnimator;
+
+import com.example.android.common.activities.SampleActivityBase;
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogFragment;
+import com.example.android.common.logger.LogWrapper;
+import com.example.android.common.logger.MessageOnlyLogFilter;
+
+/**
+ * A simple launcher activity containing a summary sample description, sample log and a custom
+ * {@link android.support.v4.app.Fragment} which can display a view.
+ * <p>
+ * For devices with displays with a width of 720dp or greater, the sample log is always visible,
+ * on other devices it's visibility is controlled by an item on the Action Bar.
+ */
+public class MainActivity extends SampleActivityBase {
+
+ public static final String TAG = "MainActivity";
+
+ // Whether the Log Fragment is currently shown
+ private boolean mLogShown;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ if (savedInstanceState == null) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ ActiveNotificationFragment fragment = new ActiveNotificationFragment();
+ transaction.replace(R.id.sample_content_fragment, fragment);
+ transaction.commit();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
+ logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
+ logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.menu_toggle_log:
+ mLogShown = !mLogShown;
+ ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
+ if (mLogShown) {
+ output.setDisplayedChild(1);
+ } else {
+ output.setDisplayedChild(0);
+ }
+ supportInvalidateOptionsMenu();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /** Create a chain of targets that will receive log data */
+ @Override
+ public void initializeLogging() {
+ // Wraps Android's native log framework.
+ LogWrapper logWrapper = new LogWrapper();
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ Log.setLogNode(logWrapper);
+
+ // Filter strips out everything except the message text.
+ MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
+ logWrapper.setNext(msgFilter);
+
+ // On screen logging via a fragment with a TextView.
+ LogFragment logFragment = (LogFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.log_fragment);
+ msgFilter.setNext(logFragment.getLogView());
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/ActiveNotifications/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* Copyright 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/Log.java b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* Copyright 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.common.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogNode.java b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogView.java b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/ActiveNotifications/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/ActivityInstrumentation/_index.jd b/samples/browseable/ActivityInstrumentation/_index.jd
index 77f1e24..c492b1e 100644
--- a/samples/browseable/ActivityInstrumentation/_index.jd
+++ b/samples/browseable/ActivityInstrumentation/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ActivityInstrumentation"
sample.group=Testing
@jd:body
diff --git a/samples/browseable/ActivityInstrumentation/res/values-v21/base-colors.xml b/samples/browseable/ActivityInstrumentation/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ActivityInstrumentation/res/values-v21/base-colors.xml
+++ b/samples/browseable/ActivityInstrumentation/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ActivityInstrumentation/res/values-v21/base-template-styles.xml b/samples/browseable/ActivityInstrumentation/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ActivityInstrumentation/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ActivityInstrumentation/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ActivityInstrumentation/res/values/base-strings.xml b/samples/browseable/ActivityInstrumentation/res/values/base-strings.xml
index 2b3f656..222cf4c 100644
--- a/samples/browseable/ActivityInstrumentation/res/values/base-strings.xml
+++ b/samples/browseable/ActivityInstrumentation/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ActivityInstrumentation</string>
<string name="intro_message">
diff --git a/samples/browseable/ActivitySceneTransitionBasic/_index.jd b/samples/browseable/ActivitySceneTransitionBasic/_index.jd
index fd2e0c7..3fc20c4 100644
--- a/samples/browseable/ActivitySceneTransitionBasic/_index.jd
+++ b/samples/browseable/ActivitySceneTransitionBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ActivitySceneTransitionBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-colors.xml b/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-template-styles.xml b/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ActivitySceneTransitionBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/values/base-strings.xml b/samples/browseable/ActivitySceneTransitionBasic/res/values/base-strings.xml
index 35860cb..ed260a5 100644
--- a/samples/browseable/ActivitySceneTransitionBasic/res/values/base-strings.xml
+++ b/samples/browseable/ActivitySceneTransitionBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ActivitySceneTransitionBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/AdvancedImmersiveMode/_index.jd b/samples/browseable/AdvancedImmersiveMode/_index.jd
index ee91eb7..962d507 100644
--- a/samples/browseable/AdvancedImmersiveMode/_index.jd
+++ b/samples/browseable/AdvancedImmersiveMode/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="AdvancedImmersiveMode"
sample.group=UI
@jd:body
diff --git a/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-colors.xml b/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-colors.xml
+++ b/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-template-styles.xml b/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/AdvancedImmersiveMode/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/AdvancedImmersiveMode/res/values/base-strings.xml b/samples/browseable/AdvancedImmersiveMode/res/values/base-strings.xml
index b1c7f5e..8c99a33 100644
--- a/samples/browseable/AdvancedImmersiveMode/res/values/base-strings.xml
+++ b/samples/browseable/AdvancedImmersiveMode/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">AdvancedImmersiveMode</string>
<string name="intro_message">
diff --git a/samples/browseable/AdvancedImmersiveMode/src/com.example.android.advancedimmersivemode/MainActivity.java b/samples/browseable/AdvancedImmersiveMode/src/com.example.android.advancedimmersivemode/MainActivity.java
index 4fc40af..476c474 100644
--- a/samples/browseable/AdvancedImmersiveMode/src/com.example.android.advancedimmersivemode/MainActivity.java
+++ b/samples/browseable/AdvancedImmersiveMode/src/com.example.android.advancedimmersivemode/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.advancedimmersivemode;
import android.os.Bundle;
diff --git a/samples/browseable/AgendaData/Application/res/values-v21/base-colors.xml b/samples/browseable/AgendaData/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/AgendaData/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/AgendaData/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/AgendaData/Application/res/values-v21/base-template-styles.xml b/samples/browseable/AgendaData/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/AgendaData/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/AgendaData/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/AgendaData/Application/res/values/base-strings.xml b/samples/browseable/AgendaData/Application/res/values/base-strings.xml
index 7f057a0..acc40cf 100644
--- a/samples/browseable/AgendaData/Application/res/values/base-strings.xml
+++ b/samples/browseable/AgendaData/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">AgendaData</string>
<string name="intro_message">
diff --git a/samples/browseable/AgendaData/_index.jd b/samples/browseable/AgendaData/_index.jd
index 7586b50..9ae7d10 100644
--- a/samples/browseable/AgendaData/_index.jd
+++ b/samples/browseable/AgendaData/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="AgendaData"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/AlwaysOn/_index.jd b/samples/browseable/AlwaysOn/_index.jd
index b605782..f68853f 100644
--- a/samples/browseable/AlwaysOn/_index.jd
+++ b/samples/browseable/AlwaysOn/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="AlwaysOn"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/AlwaysOn/src/com.example.android.wearable.wear.alwayson/MainActivity.java b/samples/browseable/AlwaysOn/src/com.example.android.wearable.wear.alwayson/MainActivity.java
index 0eb7f47..3673545 100644
--- a/samples/browseable/AlwaysOn/src/com.example.android.wearable.wear.alwayson/MainActivity.java
+++ b/samples/browseable/AlwaysOn/src/com.example.android.wearable.wear.alwayson/MainActivity.java
@@ -264,7 +264,6 @@
* Otherwise, it is easy for the AlarmManager launch intent to open a new activity
* every time the Alarm is triggered rather than reusing this Activity.
*/
- mAmbientStateAlarmManager.cancel(mAmbientStatePendingIntent);
mAmbientStateAlarmManager.setExact(
AlarmManager.RTC_WAKEUP,
triggerTimeMs,
diff --git a/samples/browseable/AppRestrictionEnforcer/_index.jd b/samples/browseable/AppRestrictionEnforcer/_index.jd
index f25084a..ec7be7c 100644
--- a/samples/browseable/AppRestrictionEnforcer/_index.jd
+++ b/samples/browseable/AppRestrictionEnforcer/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="AppRestrictionEnforcer"
sample.group=Admin
@jd:body
diff --git a/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-colors.xml b/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-colors.xml
+++ b/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-template-styles.xml b/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/AppRestrictionEnforcer/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/AppRestrictionEnforcer/res/values/base-strings.xml b/samples/browseable/AppRestrictionEnforcer/res/values/base-strings.xml
index 1dc6cf9..dbf51bd 100644
--- a/samples/browseable/AppRestrictionEnforcer/res/values/base-strings.xml
+++ b/samples/browseable/AppRestrictionEnforcer/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">AppRestrictionEnforcer</string>
<string name="intro_message">
diff --git a/samples/browseable/AppRestrictionSchema/_index.jd b/samples/browseable/AppRestrictionSchema/_index.jd
index 9378c1a..4b46cc5 100644
--- a/samples/browseable/AppRestrictionSchema/_index.jd
+++ b/samples/browseable/AppRestrictionSchema/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="AppRestrictionSchema"
sample.group=Admin
@jd:body
diff --git a/samples/browseable/AppRestrictionSchema/res/values-v21/base-colors.xml b/samples/browseable/AppRestrictionSchema/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/AppRestrictionSchema/res/values-v21/base-colors.xml
+++ b/samples/browseable/AppRestrictionSchema/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/AppRestrictionSchema/res/values-v21/base-template-styles.xml b/samples/browseable/AppRestrictionSchema/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/AppRestrictionSchema/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/AppRestrictionSchema/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/AppRestrictionSchema/res/values/base-strings.xml b/samples/browseable/AppRestrictionSchema/res/values/base-strings.xml
index 78a3966..f775394 100644
--- a/samples/browseable/AppRestrictionSchema/res/values/base-strings.xml
+++ b/samples/browseable/AppRestrictionSchema/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">AppRestrictionSchema</string>
<string name="intro_message">
diff --git a/samples/browseable/AppRestrictionSchema/src/com.example.android.apprestrictionschema/MainActivity.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.apprestrictionschema/MainActivity.java
index be04a62..2c6269f 100644
--- a/samples/browseable/AppRestrictionSchema/src/com.example.android.apprestrictionschema/MainActivity.java
+++ b/samples/browseable/AppRestrictionSchema/src/com.example.android.apprestrictionschema/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.apprestrictionschema;
import android.os.Bundle;
diff --git a/samples/browseable/AppRestrictions/_index.jd b/samples/browseable/AppRestrictions/_index.jd
index e0c8b2d..0acbfd8 100644
--- a/samples/browseable/AppRestrictions/_index.jd
+++ b/samples/browseable/AppRestrictions/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="AppRestrictions"
sample.group=Content
@jd:body
diff --git a/samples/browseable/AppRestrictions/res/values-v21/base-colors.xml b/samples/browseable/AppRestrictions/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/AppRestrictions/res/values-v21/base-colors.xml
+++ b/samples/browseable/AppRestrictions/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/AppRestrictions/res/values-v21/base-template-styles.xml b/samples/browseable/AppRestrictions/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/AppRestrictions/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/AppRestrictions/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/AppRestrictions/res/values/base-strings.xml b/samples/browseable/AppRestrictions/res/values/base-strings.xml
index d90326c..92cc872 100644
--- a/samples/browseable/AppRestrictions/res/values/base-strings.xml
+++ b/samples/browseable/AppRestrictions/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">AppRestrictions</string>
<string name="intro_message">
diff --git a/samples/browseable/AppUsageStatistics/_index.jd b/samples/browseable/AppUsageStatistics/_index.jd
index ee88115..7a75c60 100644
--- a/samples/browseable/AppUsageStatistics/_index.jd
+++ b/samples/browseable/AppUsageStatistics/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="AppUsageStatistics"
sample.group=System
@jd:body
diff --git a/samples/browseable/AppUsageStatistics/res/values-v21/base-colors.xml b/samples/browseable/AppUsageStatistics/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/AppUsageStatistics/res/values-v21/base-colors.xml
+++ b/samples/browseable/AppUsageStatistics/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/AppUsageStatistics/res/values-v21/base-template-styles.xml b/samples/browseable/AppUsageStatistics/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/AppUsageStatistics/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/AppUsageStatistics/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/AppUsageStatistics/res/values/base-strings.xml b/samples/browseable/AppUsageStatistics/res/values/base-strings.xml
index 9a92da8..762b923 100644
--- a/samples/browseable/AppUsageStatistics/res/values/base-strings.xml
+++ b/samples/browseable/AppUsageStatistics/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">AppUsageStatistics</string>
<string name="intro_message">
diff --git a/samples/browseable/AutoBackupForApps/AndroidManifest.xml b/samples/browseable/AutoBackupForApps/AndroidManifest.xml
new file mode 100644
index 0000000..7dad1e0
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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.autobackupsample" >
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme"
+ android:fullBackupContent="@xml/backup">
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".AddFileActivity" />
+ </application>
+
+</manifest>
diff --git a/samples/browseable/AutoBackupForApps/_index.jd b/samples/browseable/AutoBackupForApps/_index.jd
new file mode 100644
index 0000000..904681a
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/_index.jd
@@ -0,0 +1,16 @@
+
+page.tags="Automatic Backup"
+sample.group=Content
+@jd:body
+
+<p>
+
+This sample demonstrates how to selectively disable Automatic Backups in Android M, either by
+adjusting the location where data files are stored using getNoBackupFilesDir(), or by using a custom
+XML configuration file.
+
+This sample can also be used as a utility to test the behavior of the Automatic Backup feature.
+Executing "adb shell bmgr restore com.example.android.autobackup" from a terminal will cause the
+sample\'s data to be cleared and replaced with a copy from the backup server.
+
+ </p>
diff --git a/samples/browseable/AutoBackupForApps/res/drawable-hdpi/tile.9.png b/samples/browseable/AutoBackupForApps/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/AutoBackupForApps/res/layout/activity_main.xml b/samples/browseable/AutoBackupForApps/res/layout/activity_main.xml
new file mode 100644
index 0000000..4a7879d
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/layout/activity_main.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/fragment"
+ android:name="com.example.android.autobackupsample.MainActivityFragment"
+ tools:layout="@layout/fragment_main" android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/samples/browseable/AutoBackupForApps/res/layout/add_file.xml b/samples/browseable/AutoBackupForApps/res/layout/add_file.xml
new file mode 100644
index 0000000..9249bf4
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/layout/add_file.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal">
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="40dp">
+
+ <!-- File -->
+ <TextView
+ android:id="@+id/file_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="File"
+ android:textAlignment="center"
+ android:textSize="16sp"
+ android:textStyle="bold"
+ android:layout_marginRight="20dp"
+ android:layout_alignBaseline="@+id/file_name"/>
+
+ <EditText
+ android:id="@+id/file_name"
+ android:layout_width="300sp"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/file_label"
+ android:layout_marginBottom="20dp"
+ android:inputType="text"
+ android:text="foo.txt" />
+
+ <!-- Size -->
+ <TextView
+ android:id="@+id/size_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/file_name"
+ android:layout_alignBaseline="@+id/file_size"
+ android:text="Size"
+ android:textSize="16sp"
+ android:textStyle="bold" />
+
+ <EditText
+ android:id="@+id/file_size"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/file_name"
+ android:layout_alignStart="@+id/file_name"
+ android:layout_marginBottom="20dp"
+ android:inputType="numberDecimal"
+ android:text="10" />
+
+ <Spinner
+ android:id="@+id/file_size_spinner"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/file_name"
+ android:layout_toRightOf="@+id/file_size"
+ android:layout_alignEnd="@+id/file_name"
+ android:layout_marginBottom="20dp"
+ />
+
+ <!-- Storage -->
+ <TextView
+ android:id="@+id/storage_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/file_size_spinner"
+ android:layout_alignBaseline="@+id/storage_spinner"
+ android:paddingRight="20dp"
+ android:text="Storage"
+ android:textAlignment="center"
+ android:textSize="16sp"
+ android:textStyle="bold" />
+
+ <Spinner
+ android:id="@+id/storage_spinner"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/file_size_spinner"
+ android:layout_toRightOf="@+id/file_size"
+ android:layout_alignEnd="@+id/file_name"/>
+
+ <Button
+ android:id="@+id/create_file_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/storage_spinner"
+ android:layout_centerInParent="true"
+ android:layout_marginTop="40dp"
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp"
+ android:onClick="onCreateFileButtonClick"
+ android:text="Create" />
+
+ </RelativeLayout>
+</LinearLayout>
diff --git a/samples/browseable/AutoBackupForApps/res/layout/file_list_item.xml b/samples/browseable/AutoBackupForApps/res/layout/file_list_item.xml
new file mode 100644
index 0000000..e2d1866
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/layout/file_list_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:padding="20px"
+ android:orientation="horizontal">
+
+ <TextView android:id="@+id/file_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"/>
+
+ <TextView android:id="@+id/file_size"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/browseable/AutoBackupForApps/res/layout/fragment_main.xml b/samples/browseable/AutoBackupForApps/res/layout/fragment_main.xml
new file mode 100644
index 0000000..35ba962
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/layout/fragment_main.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+ android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:orientation="vertical"
+ tools:context=".MainActivity$PlaceholderFragment">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="20sp"
+ android:background="@android:color/darker_gray">
+
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ android:textStyle="bold"
+ android:text="File name" />
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textStyle="bold"
+ android:text="Size (bytes)" />
+
+ </LinearLayout>
+
+
+ <ListView android:id="@+id/file_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <TextView android:id="@+id/empty_file_list_message"
+ android:text="@string/no_files_click_add_files_menu"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone" />
+
+</LinearLayout>
diff --git a/samples/browseable/AutoBackupForApps/res/menu/menu_main.xml b/samples/browseable/AutoBackupForApps/res/menu/menu_main.xml
new file mode 100644
index 0000000..ebb08b6
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/menu/menu_main.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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"
+ xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
+ <item android:id="@+id/action_add_file" android:title="@string/action_add_file"
+ android:orderInCategory="100" android:showAsAction="ifRoom" />
+ <item android:id="@+id/action_settings" android:title="@string/action_settings"
+ android:orderInCategory="100" android:showAsAction="never" />
+</menu>
diff --git a/samples/browseable/AutoBackupForApps/res/mipmap-hdpi/ic_launcher.png b/samples/browseable/AutoBackupForApps/res/mipmap-hdpi/ic_launcher.png
new file mode 100755
index 0000000..91153b2
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/AutoBackupForApps/res/mipmap-mdpi/ic_launcher.png b/samples/browseable/AutoBackupForApps/res/mipmap-mdpi/ic_launcher.png
new file mode 100755
index 0000000..9a44bc4
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/AutoBackupForApps/res/mipmap-xhdpi/ic_launcher.png b/samples/browseable/AutoBackupForApps/res/mipmap-xhdpi/ic_launcher.png
new file mode 100755
index 0000000..0e1fb39
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/AutoBackupForApps/res/mipmap-xxhdpi/ic_launcher.png b/samples/browseable/AutoBackupForApps/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..e8ae88d
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/AutoBackupForApps/res/mipmap-xxxhdpi/ic_launcher.png b/samples/browseable/AutoBackupForApps/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100755
index 0000000..497fde1
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/AutoBackupForApps/res/values-sw600dp/template-dimens.xml b/samples/browseable/AutoBackupForApps/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values-sw600dp/template-styles.xml b/samples/browseable/AutoBackupForApps/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values-v11/template-styles.xml b/samples/browseable/AutoBackupForApps/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values-v21/base-colors.xml b/samples/browseable/AutoBackupForApps/res/values-v21/base-colors.xml
new file mode 100644
index 0000000..8b6ec3f
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values-v21/base-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values-v21/base-template-styles.xml b/samples/browseable/AutoBackupForApps/res/values-v21/base-template-styles.xml
new file mode 100644
index 0000000..c778e4f
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values-v21/base-template-styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light">
+ </style>
+
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values-w820dp/dimens.xml b/samples/browseable/AutoBackupForApps/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..82d3fbe
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values-w820dp/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values/base-strings.xml b/samples/browseable/AutoBackupForApps/res/values/base-strings.xml
new file mode 100644
index 0000000..a6cef5e
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values/base-strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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">Automatic Backup</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+This sample demonstrates how to selectively disable Automatic Backups in Android M, either by
+adjusting the location where data files are stored using getNoBackupFilesDir(), or by using a custom
+XML configuration file.
+
+This sample can also be used as a utility to test the behavior of the Automatic Backup feature.
+Executing "adb shell bmgr restore com.example.android.autobackup" from a terminal will cause the
+sample\'s data to be cleared and replaced with a copy from the backup server.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values/dimens.xml b/samples/browseable/AutoBackupForApps/res/values/dimens.xml
new file mode 100644
index 0000000..7d5dcce
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values/strings.xml b/samples/browseable/AutoBackupForApps/res/values/strings.xml
new file mode 100644
index 0000000..30512e8
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="action_add_file">Add File</string>
+ <string name="action_settings">Settings</string>
+ <string name="list_of_files">App Data:</string>
+ <string name="file_exists">Please specify a different name. A file with this name exists already.</string>
+ <string name="no_files_click_add_files_menu">Please click on Add File menu in order to create test files.</string>
+ <string name="file_size_is_invalid">Please specify a correct file size.</string>
+ <string name="external_storage_unavailable">The External storage is not available.</string>
+ <string-array name="file_size_array">
+ <item>Bytes</item>
+ <item>Kilobytes</item>
+ <item>Megabytes</item>
+ </string-array>
+ <string-array name="file_storage_array">
+ <item>Internal</item>
+ <item>External</item>
+ <item>Do not Backup</item>
+ </string-array>
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values/template-dimens.xml b/samples/browseable/AutoBackupForApps/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/values/template-styles.xml b/samples/browseable/AutoBackupForApps/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/AutoBackupForApps/res/xml/backup.xml b/samples/browseable/AutoBackupForApps/res/xml/backup.xml
new file mode 100644
index 0000000..334cfa2
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/res/xml/backup.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<full-backup-content xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- This file is referenced from android:fullBackupContent in AndroidManifest.xml, and controls
+ exclusions/inclusions for the default backup policy. -->
+
+ <!-- Shared preferences files can be excluded using the "sharedpref" domain. -->
+ <!-- Be sure to exclude any device-specific identifiers, such as the GCM registration key. -->
+ <!-- You may also wish to exclude directories that contain device-specific session tokens or
+ sensitive user credentials. -->
+ <exclude domain="sharedpref" path="gcm"/>
+ <exclude domain="sharedpref" path="user_credentials"/>
+
+ <!-- Databases can be excluded using the "database" domain. -->
+ <exclude domain="database" path="local_secrets.db"/>
+
+ <!-- Additional domains include "file", "external", "root", and "path". See
+ http://developer.android.com/preview/backup/index.html for more details.
+
+ Additionally, content in the cache directory, external storage, and the no_backup directory
+ (see android.content.Context#getNoBackupFilesDir()) are excluded by default. If you need
+ to backup data in one of these locations, use the <include> directive. -->
+
+</full-backup-content>
\ No newline at end of file
diff --git a/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/AddFileActivity.java b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/AddFileActivity.java
new file mode 100644
index 0000000..00cd1e3
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/AddFileActivity.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.autobackupsample;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import com.example.android.autobackupsample.MainActivityFragment;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+
+/**
+ * The purpose of AddFileActivity activity is to create a data file based on the
+ * file name and size parameters specified as an Intent external parameters or with the
+ * activity UI.
+ * <p/>
+ * The optional intent parameters are
+ * {@link com.example.android.autobackupsample.AddFileActivity#FILE_NAME} and
+ * {@link com.example.android.autobackupsample.AddFileActivity#FILE_SIZE_IN_BYTES}.
+ * {@link com.example.android.autobackupsample.AddFileActivity#FILE_STORAGE}.
+ * <p/>
+ * The activity will return an
+ * {@link com.example.android.autobackupsample.MainActivityFragment#ADD_FILE_RESULT_ERROR}
+ * if intent parameters are specified incorrectly or it will display Toast messages to the user
+ * if those parameters are specified via the activity UI.
+ */
+public class AddFileActivity extends Activity {
+
+ private static final String TAG = "AutoBackupSample";
+
+ /**
+ * The intent parameter that specifies a file name. The file name must be unique for the
+ * application internal directory.
+ */
+ public static final String FILE_NAME = "file_name";
+
+ /**
+ * The intent parameter that specifies a file size in bytes. The size must be a number
+ * larger or equal to 0.
+ */
+ public static final String FILE_SIZE_IN_BYTES = "file_size_in_bytes";
+
+ /**
+ * The file storage is an optional parameter. It should be one of these:
+ * "INTERNAL", "EXTERNAL", "DONOTBACKUP". The default option is "INTERNAL".
+ */
+ public static final String FILE_STORAGE = "file_storage";
+
+ /**
+ * A file size multiplier. It is used to calculate the total number of bytes to be added
+ * to the file.
+ */
+ private int mSizeMultiplier = 1;
+
+ /**
+ * Defines File Storage options.
+ */
+ private static enum FileStorage {
+ INTERNAL,
+ EXTERNAL,
+ DONOTBACKUP;
+ }
+
+ /**
+ * Contains a selected by a user file storage option.
+ */
+ private FileStorage mFileStorage = FileStorage.INTERNAL;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.add_file);
+ initFileSizeSpinner();
+ initFileStorageSpinner();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // If an intent has extra parameters, create the file and finish the activity.
+ if (getIntent().hasExtra(FILE_NAME) && getIntent().hasExtra(FILE_SIZE_IN_BYTES)) {
+ String fileName = getIntent().getStringExtra(FILE_NAME);
+ String sizeInBytesParamValue = getIntent().getStringExtra(FILE_SIZE_IN_BYTES);
+ String fileStorageParamValue = FileStorage.INTERNAL.toString();
+
+ if (getIntent().hasExtra(FILE_STORAGE)) {
+ fileStorageParamValue = getIntent().getStringExtra(FILE_STORAGE);
+ }
+
+ if (TextUtils.isEmpty(fileName) ||
+ isFileExists(fileName) ||
+ !isSizeValid(sizeInBytesParamValue) ||
+ !isFileStorageParamValid(fileStorageParamValue)) {
+ setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
+ finish();
+ return;
+ }
+
+ mFileStorage = FileStorage.valueOf(fileStorageParamValue);
+
+ if (mFileStorage == FileStorage.EXTERNAL && !Utils.isExternalStorageAvailable()) {
+ setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
+ finish();
+ return;
+ }
+
+ createFileWithRandomDataAndFinishActivity(fileName, mFileStorage,
+ sizeInBytesParamValue);
+ }
+ }
+
+ /**
+ * A handler function for a Create File button click event.
+ *
+ * @param view a reference to the Create File button view.
+ */
+ public void onCreateFileButtonClick(View view) {
+ EditText fileNameEditText = (EditText) findViewById(R.id.file_name);
+ EditText fileSizeEditText = (EditText) findViewById(R.id.file_size);
+ String fileName = fileNameEditText.getText().toString();
+ String fileSizeEditTextValue = fileSizeEditText.getText().toString();
+
+ if (TextUtils.isEmpty(fileName) || isFileExists(fileName)) {
+ Toast toast = Toast.makeText(this, getText(R.string.file_exists), Toast.LENGTH_LONG);
+ toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
+ toast.show();
+ return;
+ }
+
+ if (!isSizeValid(fileSizeEditTextValue)) {
+ Toast toast = Toast.makeText(this, getText(R.string.file_size_is_invalid),
+ Toast.LENGTH_LONG);
+ toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
+ toast.show();
+ return;
+ }
+
+ long fileSize = Integer.valueOf(fileSizeEditTextValue) * mSizeMultiplier;
+
+ if (mFileStorage == FileStorage.EXTERNAL && !Utils.isExternalStorageAvailable()) {
+ Toast toast = Toast.makeText(this,
+ getText(R.string.external_storage_unavailable), Toast.LENGTH_LONG);
+ toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
+ toast.show();
+ return;
+ }
+
+ createFileWithRandomDataAndFinishActivity(fileName, mFileStorage, String.valueOf(fileSize));
+ }
+
+ private void initFileSizeSpinner() {
+ Spinner spinner = (Spinner) findViewById(R.id.file_size_spinner);
+ final ArrayAdapter<CharSequence> adapter =
+ ArrayAdapter.createFromResource(this, R.array.file_size_array,
+ android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ String sizeMeasure = adapter.getItem(position).toString();
+ mSizeMultiplier = (int) Math.pow(1024, position);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, String.format("Selected: %s, %d", sizeMeasure,
+ mSizeMultiplier));
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+ });
+ }
+
+ private void initFileStorageSpinner() {
+ Spinner spinner = (Spinner) findViewById(R.id.storage_spinner);
+ final ArrayAdapter<CharSequence> adapter =
+ ArrayAdapter.createFromResource(this, R.array.file_storage_array,
+ android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ mFileStorage = FileStorage.values()[position];
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+ });
+ }
+
+ private void createFileWithRandomDataAndFinishActivity(String fileName, FileStorage storage,
+ String sizeInBytes) {
+ long size = Long.valueOf(sizeInBytes);
+ File file = null;
+ FileOutputStream out = null;
+ BufferedOutputStream bufOut = null;
+ try {
+ switch (storage) {
+ case INTERNAL:
+ file = getInternalFile(fileName);
+ out = openFileOutput(file.getName(), Context.MODE_PRIVATE);
+ break;
+ case EXTERNAL:
+ assert Utils.isExternalStorageAvailable() :
+ "The external storage is not available";
+ File externalAppDir = getExternalFilesDir(null);
+ file = new File(externalAppDir, fileName);
+ out = new FileOutputStream(file);
+ break;
+ case DONOTBACKUP:
+ file = new File(getNoBackupFilesDir(), fileName);
+ out = new FileOutputStream(file);
+ break;
+ }
+
+ if (file == null || out == null) {
+ Log.d(TAG, "Unable to create file output stream");
+ // Returning back to the caller activity.
+ setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
+ finish();
+ return;
+ }
+
+ bufOut = new BufferedOutputStream(out);
+ for (int i = 0; i < size; i++) {
+ byte b = (byte) (255 * Math.random());
+ bufOut.write(b);
+ }
+
+ String message = String.format("File created: %s, size: %s bytes",
+ file.getAbsolutePath(), sizeInBytes);
+
+ Toast toast = Toast.makeText(this, message, Toast.LENGTH_LONG);
+ toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
+ toast.show();
+ Log.d(TAG, message);
+
+ // Returning back to the caller activity.
+ setResult(MainActivityFragment.ADD_FILE_RESULT_SUCCESS);
+ finish();
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage(), e);
+ // Returning back to the caller activity.
+ setResult(MainActivityFragment.ADD_FILE_RESULT_ERROR);
+ finish();
+ } finally {
+ if (bufOut != null) {
+ try {
+ bufOut.close();
+ } catch (Exception e) {
+ // Ignore.
+ }
+ }
+ }
+ }
+
+ private boolean isFileExists(String fileName) {
+ File file = getInternalFile(fileName);
+ if (file.exists()) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "This file exists: " + file.getName());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isSizeValid(String sizeInBytesParamValue) {
+ long sizeInBytes = 0;
+ try {
+ sizeInBytes = Long.valueOf(sizeInBytesParamValue);
+ } catch (NumberFormatException e) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Invalid file size: " + sizeInBytesParamValue);
+ }
+ return false;
+ }
+
+ // Validate file size value. It should be 0 or a positive number.
+ if (sizeInBytes < 0) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Invalid file size: " + sizeInBytes);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isFileStorageParamValid(String fileStorage) {
+ try {
+ mFileStorage = FileStorage.valueOf(fileStorage);
+ } catch (IllegalArgumentException e) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Invalid file storage: " + fileStorage);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private File getInternalFile(String fileName) {
+ File internalAppDir = getFilesDir();
+ return new File(internalAppDir, fileName);
+ }
+
+}
\ No newline at end of file
diff --git a/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/MainActivity.java b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/MainActivity.java
new file mode 100644
index 0000000..b5af289
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/MainActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.autobackupsample;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/MainActivityFragment.java b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/MainActivityFragment.java
new file mode 100644
index 0000000..c07f6b8
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/MainActivityFragment.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.autobackupsample;
+
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.io.File;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+
+
+/**
+ * A placeholder fragment containing a simple view.
+ */
+public class MainActivityFragment extends Fragment {
+
+ private static final String TAG = "AutoBackupSample";
+ public static final int ADD_FILE_REQUEST = 1;
+ public static final int ADD_FILE_RESULT_SUCCESS = 101;
+ public static final int ADD_FILE_RESULT_ERROR = 102;
+
+ private ArrayAdapter<File> mFilesArrayAdapter;
+ private ArrayList<File> mFiles;
+
+ public MainActivityFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ setHasOptionsMenu(true);
+ return inflater.inflate(R.layout.fragment_main, container, false);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == ADD_FILE_REQUEST && resultCode == ADD_FILE_RESULT_SUCCESS) {
+ updateListOfFiles();
+ }
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ inflater.inflate(R.menu.menu_main, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ return true;
+ } else if (id == R.id.action_add_file) {
+ Intent addFileIntent = new Intent(getActivity(), AddFileActivity.class);
+ startActivityForResult(addFileIntent, ADD_FILE_REQUEST);
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mFilesArrayAdapter == null) {
+ mFiles = createListOfFiles();
+ mFilesArrayAdapter = new ArrayAdapter<File>(getActivity(),
+ R.layout.file_list_item, mFiles) {
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ View itemView = inflater.inflate(R.layout.file_list_item, parent, false);
+ TextView fileNameView = (TextView) itemView.findViewById(R.id.file_name);
+ String fileName = getItem(position).getAbsolutePath();
+ fileNameView.setText(fileName);
+ TextView fileSize = (TextView) itemView.findViewById(R.id.file_size);
+ String fileSizeInBytes = NumberFormat.getInstance()
+ .format(getItem(position).length());
+ fileSize.setText(fileSizeInBytes);
+ return itemView;
+ }
+ };
+ updateListOfFiles();
+ ListView filesListView = (ListView) getView().findViewById(R.id.file_list);
+ filesListView.setAdapter(mFilesArrayAdapter);
+ }
+ }
+
+ private ArrayList<File> createListOfFiles() {
+ ArrayList<File> listOfFiles = new ArrayList<File>();
+ addFilesToList(listOfFiles, getActivity().getFilesDir());
+ if (Utils.isExternalStorageAvailable()) {
+ addFilesToList(listOfFiles, getActivity().getExternalFilesDir(null));
+ }
+ addFilesToList(listOfFiles, getActivity().getNoBackupFilesDir());
+ return listOfFiles;
+ }
+
+ private void addFilesToList(ArrayList<File> listOfFiles, File dir) {
+ File[] files = dir.listFiles();
+ for (File file: files) {
+ listOfFiles.add(file);
+ }
+ }
+
+ public void updateListOfFiles() {
+ TextView emptyFileListMessage =
+ (TextView) getView().findViewById(R.id.empty_file_list_message);
+ mFiles = createListOfFiles();
+ if (mFilesArrayAdapter.getCount() > 0) {
+ mFilesArrayAdapter.clear();
+ }
+ for (File file: mFiles) {
+ mFilesArrayAdapter.add(file);
+ }
+ // Display a message instructing to add files if no files found.
+ if (mFiles.size() == 0) {
+ emptyFileListMessage.setVisibility(View.VISIBLE);
+ } else {
+ emptyFileListMessage.setVisibility(View.GONE);
+ }
+ }
+}
+
diff --git a/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/Utils.java b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/Utils.java
new file mode 100644
index 0000000..b9a9833
--- /dev/null
+++ b/samples/browseable/AutoBackupForApps/src/com.example.android.autobackupsample/Utils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.autobackupsample;
+
+import android.os.Environment;
+import android.util.Log;
+
+/**
+ * Utility methods for the app.
+ */
+public class Utils {
+
+ private static final String TAG = "AutoBackupSample";
+
+ public static boolean isExternalStorageAvailable() {
+ String state = Environment.getExternalStorageState();
+ if (!Environment.MEDIA_MOUNTED.equals(state)) {
+ Log.d(TAG, "The external storage is not available.");
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/samples/browseable/BasicAccessibility/_index.jd b/samples/browseable/BasicAccessibility/_index.jd
index 91c34ec..830f17e 100644
--- a/samples/browseable/BasicAccessibility/_index.jd
+++ b/samples/browseable/BasicAccessibility/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicAccessibility"
sample.group=UI
@jd:body
diff --git a/samples/browseable/BasicAccessibility/res/values-v21/base-colors.xml b/samples/browseable/BasicAccessibility/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicAccessibility/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicAccessibility/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicAccessibility/res/values-v21/base-template-styles.xml b/samples/browseable/BasicAccessibility/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicAccessibility/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicAccessibility/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicAccessibility/res/values/base-strings.xml b/samples/browseable/BasicAccessibility/res/values/base-strings.xml
index ac4db70..0e707b2 100644
--- a/samples/browseable/BasicAccessibility/res/values/base-strings.xml
+++ b/samples/browseable/BasicAccessibility/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicAccessibility</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicAndroidKeyStore/_index.jd b/samples/browseable/BasicAndroidKeyStore/_index.jd
index 5eedee8..d82d785 100644
--- a/samples/browseable/BasicAndroidKeyStore/_index.jd
+++ b/samples/browseable/BasicAndroidKeyStore/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicAndroidKeyStore"
sample.group=Security
@jd:body
diff --git a/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-colors.xml b/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-template-styles.xml b/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicAndroidKeyStore/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicAndroidKeyStore/res/values/base-strings.xml b/samples/browseable/BasicAndroidKeyStore/res/values/base-strings.xml
index 7a83818..8b4e370 100644
--- a/samples/browseable/BasicAndroidKeyStore/res/values/base-strings.xml
+++ b/samples/browseable/BasicAndroidKeyStore/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicAndroidKeyStore</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicAndroidKeyStore/src/com.example.android.basicandroidkeystore/MainActivity.java b/samples/browseable/BasicAndroidKeyStore/src/com.example.android.basicandroidkeystore/MainActivity.java
index f322af5..754662b 100644
--- a/samples/browseable/BasicAndroidKeyStore/src/com.example.android.basicandroidkeystore/MainActivity.java
+++ b/samples/browseable/BasicAndroidKeyStore/src/com.example.android.basicandroidkeystore/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.basicandroidkeystore;
import android.graphics.Color;
diff --git a/samples/browseable/BasicContactables/_index.jd b/samples/browseable/BasicContactables/_index.jd
index 8a0a506..0beae6c 100644
--- a/samples/browseable/BasicContactables/_index.jd
+++ b/samples/browseable/BasicContactables/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicContactables"
sample.group=Content
@jd:body
diff --git a/samples/browseable/BasicContactables/res/values-v21/base-colors.xml b/samples/browseable/BasicContactables/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicContactables/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicContactables/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicContactables/res/values-v21/base-template-styles.xml b/samples/browseable/BasicContactables/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicContactables/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicContactables/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicContactables/res/values/base-strings.xml b/samples/browseable/BasicContactables/res/values/base-strings.xml
index acbaaf5..d77a7cb 100644
--- a/samples/browseable/BasicContactables/res/values/base-strings.xml
+++ b/samples/browseable/BasicContactables/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicContactables</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicGestureDetect/_index.jd b/samples/browseable/BasicGestureDetect/_index.jd
index 1e5d0d2..77b02d7 100644
--- a/samples/browseable/BasicGestureDetect/_index.jd
+++ b/samples/browseable/BasicGestureDetect/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicGestureDetect"
sample.group=Input
@jd:body
diff --git a/samples/browseable/BasicGestureDetect/res/values-v21/base-colors.xml b/samples/browseable/BasicGestureDetect/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicGestureDetect/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicGestureDetect/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicGestureDetect/res/values-v21/base-template-styles.xml b/samples/browseable/BasicGestureDetect/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicGestureDetect/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicGestureDetect/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicGestureDetect/res/values/base-strings.xml b/samples/browseable/BasicGestureDetect/res/values/base-strings.xml
index 8b96af7..63e73d1 100644
--- a/samples/browseable/BasicGestureDetect/res/values/base-strings.xml
+++ b/samples/browseable/BasicGestureDetect/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicGestureDetect</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicGestureDetect/res/values/strings.xml b/samples/browseable/BasicGestureDetect/res/values/strings.xml
index 826d90f..004a143 100644
--- a/samples/browseable/BasicGestureDetect/res/values/strings.xml
+++ b/samples/browseable/BasicGestureDetect/res/values/strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="sample_action">Clear Text</string>
</resources>
diff --git a/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java b/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java
index 57d9354..7f540b7 100644
--- a/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java
+++ b/samples/browseable/BasicGestureDetect/src/com.example.android.basicgesturedetect/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.basicgesturedetect;
import android.graphics.Color;
diff --git a/samples/browseable/BasicImmersiveMode/_index.jd b/samples/browseable/BasicImmersiveMode/_index.jd
index 1529847..091adf8 100644
--- a/samples/browseable/BasicImmersiveMode/_index.jd
+++ b/samples/browseable/BasicImmersiveMode/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicImmersiveMode"
sample.group=UI
@jd:body
diff --git a/samples/browseable/BasicImmersiveMode/res/values-v21/base-colors.xml b/samples/browseable/BasicImmersiveMode/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicImmersiveMode/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicImmersiveMode/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicImmersiveMode/res/values-v21/base-template-styles.xml b/samples/browseable/BasicImmersiveMode/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicImmersiveMode/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicImmersiveMode/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicImmersiveMode/res/values/base-strings.xml b/samples/browseable/BasicImmersiveMode/res/values/base-strings.xml
index 46ee0f5..fb776ce 100644
--- a/samples/browseable/BasicImmersiveMode/res/values/base-strings.xml
+++ b/samples/browseable/BasicImmersiveMode/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicImmersiveMode</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicImmersiveMode/res/values/strings.xml b/samples/browseable/BasicImmersiveMode/res/values/strings.xml
index dc12528..d462fc3 100644
--- a/samples/browseable/BasicImmersiveMode/res/values/strings.xml
+++ b/samples/browseable/BasicImmersiveMode/res/values/strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="sample_action">Toggle Immersive Mode!</string>
</resources>
diff --git a/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java b/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java
index 5ffe902..180247e 100644
--- a/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java
+++ b/samples/browseable/BasicImmersiveMode/src/com.example.android.basicimmersivemode/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.basicimmersivemode;
import android.graphics.Color;
diff --git a/samples/browseable/BasicManagedProfile/_index.jd b/samples/browseable/BasicManagedProfile/_index.jd
index 0aa07ea..1522a91 100644
--- a/samples/browseable/BasicManagedProfile/_index.jd
+++ b/samples/browseable/BasicManagedProfile/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicManagedProfile"
sample.group=Admin
@jd:body
diff --git a/samples/browseable/BasicManagedProfile/res/values-v21/base-colors.xml b/samples/browseable/BasicManagedProfile/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicManagedProfile/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicManagedProfile/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicManagedProfile/res/values-v21/base-template-styles.xml b/samples/browseable/BasicManagedProfile/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicManagedProfile/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicManagedProfile/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicManagedProfile/res/values/base-strings.xml b/samples/browseable/BasicManagedProfile/res/values/base-strings.xml
index f66ab5a..97063bc 100644
--- a/samples/browseable/BasicManagedProfile/res/values/base-strings.xml
+++ b/samples/browseable/BasicManagedProfile/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicManagedProfile</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicMediaDecoder/_index.jd b/samples/browseable/BasicMediaDecoder/_index.jd
index 769d8a6..ee3f328 100644
--- a/samples/browseable/BasicMediaDecoder/_index.jd
+++ b/samples/browseable/BasicMediaDecoder/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicMediaDecoder"
sample.group=Media
@jd:body
diff --git a/samples/browseable/BasicMediaDecoder/res/values-v21/base-colors.xml b/samples/browseable/BasicMediaDecoder/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicMediaDecoder/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicMediaDecoder/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicMediaDecoder/res/values-v21/base-template-styles.xml b/samples/browseable/BasicMediaDecoder/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicMediaDecoder/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicMediaDecoder/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicMediaDecoder/res/values/base-strings.xml b/samples/browseable/BasicMediaDecoder/res/values/base-strings.xml
index 7340522..e7a5351 100644
--- a/samples/browseable/BasicMediaDecoder/res/values/base-strings.xml
+++ b/samples/browseable/BasicMediaDecoder/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicMediaDecoder</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicMediaRouter/_index.jd b/samples/browseable/BasicMediaRouter/_index.jd
index 9d2f3f5..ec165f6 100644
--- a/samples/browseable/BasicMediaRouter/_index.jd
+++ b/samples/browseable/BasicMediaRouter/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicMediaRouter"
sample.group=Media
@jd:body
diff --git a/samples/browseable/BasicMediaRouter/res/values-v21/base-colors.xml b/samples/browseable/BasicMediaRouter/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicMediaRouter/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicMediaRouter/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicMediaRouter/res/values-v21/base-template-styles.xml b/samples/browseable/BasicMediaRouter/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicMediaRouter/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicMediaRouter/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicMediaRouter/res/values/base-strings.xml b/samples/browseable/BasicMediaRouter/res/values/base-strings.xml
index 6f16407..8ed08eb 100644
--- a/samples/browseable/BasicMediaRouter/res/values/base-strings.xml
+++ b/samples/browseable/BasicMediaRouter/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicMediaRouter</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicMultitouch/_index.jd b/samples/browseable/BasicMultitouch/_index.jd
index 187017a..10bbcae 100644
--- a/samples/browseable/BasicMultitouch/_index.jd
+++ b/samples/browseable/BasicMultitouch/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicMultitouch"
sample.group=Input
@jd:body
diff --git a/samples/browseable/BasicMultitouch/res/values-v21/base-colors.xml b/samples/browseable/BasicMultitouch/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicMultitouch/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicMultitouch/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicMultitouch/res/values-v21/base-template-styles.xml b/samples/browseable/BasicMultitouch/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicMultitouch/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicMultitouch/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicMultitouch/res/values/base-strings.xml b/samples/browseable/BasicMultitouch/res/values/base-strings.xml
index a5ab6f5..3746a42 100644
--- a/samples/browseable/BasicMultitouch/res/values/base-strings.xml
+++ b/samples/browseable/BasicMultitouch/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicMultitouch</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicNetworking/_index.jd b/samples/browseable/BasicNetworking/_index.jd
index 3d17e0a..1756dc9 100644
--- a/samples/browseable/BasicNetworking/_index.jd
+++ b/samples/browseable/BasicNetworking/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicNetworking"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/BasicNetworking/res/values-v21/base-colors.xml b/samples/browseable/BasicNetworking/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicNetworking/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicNetworking/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicNetworking/res/values-v21/base-template-styles.xml b/samples/browseable/BasicNetworking/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicNetworking/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicNetworking/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicNetworking/res/values/base-strings.xml b/samples/browseable/BasicNetworking/res/values/base-strings.xml
index ddd695f..c8e777d 100644
--- a/samples/browseable/BasicNetworking/res/values/base-strings.xml
+++ b/samples/browseable/BasicNetworking/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicNetworking</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicNotifications/_index.jd b/samples/browseable/BasicNotifications/_index.jd
index d34b8fb..2382567 100644
--- a/samples/browseable/BasicNotifications/_index.jd
+++ b/samples/browseable/BasicNotifications/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicNotifications"
sample.group=Notification
@jd:body
diff --git a/samples/browseable/BasicNotifications/res/values-v21/base-colors.xml b/samples/browseable/BasicNotifications/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicNotifications/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicNotifications/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicNotifications/res/values-v21/base-template-styles.xml b/samples/browseable/BasicNotifications/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicNotifications/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicNotifications/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicNotifications/res/values/base-strings.xml b/samples/browseable/BasicNotifications/res/values/base-strings.xml
index 87f5bf0..bf7e1eb 100644
--- a/samples/browseable/BasicNotifications/res/values/base-strings.xml
+++ b/samples/browseable/BasicNotifications/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicNotifications</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicRenderScript/_index.jd b/samples/browseable/BasicRenderScript/_index.jd
index 3e6c62f..9da15e5 100644
--- a/samples/browseable/BasicRenderScript/_index.jd
+++ b/samples/browseable/BasicRenderScript/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicRenderScript"
sample.group=RenderScript
@jd:body
diff --git a/samples/browseable/BasicRenderScript/res/values-v21/base-colors.xml b/samples/browseable/BasicRenderScript/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicRenderScript/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicRenderScript/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicRenderScript/res/values-v21/base-template-styles.xml b/samples/browseable/BasicRenderScript/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicRenderScript/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicRenderScript/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicRenderScript/res/values/base-strings.xml b/samples/browseable/BasicRenderScript/res/values/base-strings.xml
index 93a7391..64374ea 100644
--- a/samples/browseable/BasicRenderScript/res/values/base-strings.xml
+++ b/samples/browseable/BasicRenderScript/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicRenderScript</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicSyncAdapter/_index.jd b/samples/browseable/BasicSyncAdapter/_index.jd
index a079768..e159447 100644
--- a/samples/browseable/BasicSyncAdapter/_index.jd
+++ b/samples/browseable/BasicSyncAdapter/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicSyncAdapter"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/BasicSyncAdapter/res/values-v21/base-colors.xml b/samples/browseable/BasicSyncAdapter/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicSyncAdapter/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicSyncAdapter/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicSyncAdapter/res/values-v21/base-template-styles.xml b/samples/browseable/BasicSyncAdapter/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicSyncAdapter/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicSyncAdapter/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicSyncAdapter/res/values/base-strings.xml b/samples/browseable/BasicSyncAdapter/res/values/base-strings.xml
index 849d026..6a85060 100644
--- a/samples/browseable/BasicSyncAdapter/res/values/base-strings.xml
+++ b/samples/browseable/BasicSyncAdapter/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicSyncAdapter</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicTransition/_index.jd b/samples/browseable/BasicTransition/_index.jd
index 16415f6..3be179d 100644
--- a/samples/browseable/BasicTransition/_index.jd
+++ b/samples/browseable/BasicTransition/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BasicTransition"
sample.group=UI
@jd:body
diff --git a/samples/browseable/BasicTransition/res/values-v21/base-colors.xml b/samples/browseable/BasicTransition/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BasicTransition/res/values-v21/base-colors.xml
+++ b/samples/browseable/BasicTransition/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BasicTransition/res/values-v21/base-template-styles.xml b/samples/browseable/BasicTransition/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BasicTransition/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BasicTransition/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BasicTransition/res/values/base-strings.xml b/samples/browseable/BasicTransition/res/values/base-strings.xml
index d14eb54..5ace280 100644
--- a/samples/browseable/BasicTransition/res/values/base-strings.xml
+++ b/samples/browseable/BasicTransition/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BasicTransition</string>
<string name="intro_message">
diff --git a/samples/browseable/BasicTransition/src/com.example.android.basictransition/MainActivity.java b/samples/browseable/BasicTransition/src/com.example.android.basictransition/MainActivity.java
index 7eeac2e..7945418 100644
--- a/samples/browseable/BasicTransition/src/com.example.android.basictransition/MainActivity.java
+++ b/samples/browseable/BasicTransition/src/com.example.android.basictransition/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.basictransition;
import android.os.Bundle;
diff --git a/samples/browseable/BatchStepSensor/_index.jd b/samples/browseable/BatchStepSensor/_index.jd
index 9a4f0b0..cd479b4 100644
--- a/samples/browseable/BatchStepSensor/_index.jd
+++ b/samples/browseable/BatchStepSensor/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BatchStepSensor"
sample.group=Sensors
@jd:body
diff --git a/samples/browseable/BatchStepSensor/res/layout/activity_main.xml b/samples/browseable/BatchStepSensor/res/layout/activity_main.xml
index a3c1fa9..811129d 100644
--- a/samples/browseable/BatchStepSensor/res/layout/activity_main.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/activity_main.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<fragment
android:id="@+id/fragment_cardstream"
android:name="com.example.android.batchstepsensor.cardstream.CardStreamFragment"
diff --git a/samples/browseable/BatchStepSensor/res/layout/card.xml b/samples/browseable/BatchStepSensor/res/layout/card.xml
index 6350e6a..a727d8d 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<com.example.android.batchstepsensor.cardstream.CardLayout
android:id="@+id/card_layout"
style="@style/Card"
diff --git a/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml b/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml
index 86d9c2d..8e6f4ad 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card_button_negative.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<com.example.android.batchstepsensor.cardstream.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_button"
style="@style/CardActionNegative"
diff --git a/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml b/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml
index c993df8..1f29ca3 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card_button_neutral.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<com.example.android.batchstepsensor.cardstream.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_button"
style="@style/CardActionNeutral"
diff --git a/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml b/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml
index 7a3baf6..f7400cf 100644
--- a/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/card_button_positive.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<com.example.android.batchstepsensor.cardstream.CardActionButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_button"
style="@style/CardActionPositive"
diff --git a/samples/browseable/BatchStepSensor/res/layout/cardstream.xml b/samples/browseable/BatchStepSensor/res/layout/cardstream.xml
index 889d69c..5d0c8bb 100644
--- a/samples/browseable/BatchStepSensor/res/layout/cardstream.xml
+++ b/samples/browseable/BatchStepSensor/res/layout/cardstream.xml
@@ -14,6 +14,7 @@
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="match_parent"
android:layout_height="match_parent"
diff --git a/samples/browseable/BatchStepSensor/res/values-v21/base-colors.xml b/samples/browseable/BatchStepSensor/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BatchStepSensor/res/values-v21/base-colors.xml
+++ b/samples/browseable/BatchStepSensor/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BatchStepSensor/res/values-v21/base-template-styles.xml b/samples/browseable/BatchStepSensor/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BatchStepSensor/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BatchStepSensor/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BatchStepSensor/res/values/base-strings.xml b/samples/browseable/BatchStepSensor/res/values/base-strings.xml
index 3ff4b3d..2356259 100644
--- a/samples/browseable/BatchStepSensor/res/values/base-strings.xml
+++ b/samples/browseable/BatchStepSensor/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BatchStepSensor</string>
<string name="intro_message">
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java
index 5362693..62b48e7 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/MainActivity.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.example.android.batchstepsensor;
import android.os.Bundle;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/Card.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/Card.java
index 2a342f6..0a5ad54 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/Card.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/Card.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.animation.Animator;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardActionButton.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardActionButton.java
index 054cc72..676f22d 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardActionButton.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardActionButton.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.content.Context;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardLayout.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardLayout.java
index 84ee7b5..efe065f 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardLayout.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardLayout.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.content.Context;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStream.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStream.java
index 6e4e10a..bce52cb 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStream.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStream.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
public interface CardStream {
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamAnimator.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamAnimator.java
index 91a05ae..4bb42f5 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamAnimator.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamAnimator.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.animation.ObjectAnimator;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamFragment.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamFragment.java
index 82ea622..008695f 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamFragment.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamFragment.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.os.Bundle;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamLinearLayout.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamLinearLayout.java
index 9515c00..8fcc13f 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamLinearLayout.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamLinearLayout.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.animation.Animator;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamState.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamState.java
index 59f337c..a6ed607 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamState.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/CardStreamState.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import java.util.HashSet;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/DefaultCardStreamAnimator.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/DefaultCardStreamAnimator.java
index 9f08553..f17a3d7 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/DefaultCardStreamAnimator.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/DefaultCardStreamAnimator.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.animation.ObjectAnimator;
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/OnCardClickListener.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/OnCardClickListener.java
index 31da7cd..0ae3f58 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/OnCardClickListener.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/OnCardClickListener.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
public interface OnCardClickListener {
diff --git a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/StreamRetentionFragment.java b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/StreamRetentionFragment.java
index 71d2a88..6b68978 100644
--- a/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/StreamRetentionFragment.java
+++ b/samples/browseable/BatchStepSensor/src/com.example.android.batchstepsensor/cardstream/StreamRetentionFragment.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.example.android.batchstepsensor.cardstream;
import android.os.Bundle;
diff --git a/samples/browseable/BeamLargeFiles/_index.jd b/samples/browseable/BeamLargeFiles/_index.jd
index d7b3e65..cfb07f4 100644
--- a/samples/browseable/BeamLargeFiles/_index.jd
+++ b/samples/browseable/BeamLargeFiles/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BeamLargeFiles"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/BeamLargeFiles/res/values-v21/base-colors.xml b/samples/browseable/BeamLargeFiles/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BeamLargeFiles/res/values-v21/base-colors.xml
+++ b/samples/browseable/BeamLargeFiles/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BeamLargeFiles/res/values-v21/base-template-styles.xml b/samples/browseable/BeamLargeFiles/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BeamLargeFiles/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BeamLargeFiles/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BeamLargeFiles/res/values/base-strings.xml b/samples/browseable/BeamLargeFiles/res/values/base-strings.xml
index 6b2c69a..dd897b6 100644
--- a/samples/browseable/BeamLargeFiles/res/values/base-strings.xml
+++ b/samples/browseable/BeamLargeFiles/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BeamLargeFiles</string>
<string name="intro_message">
diff --git a/samples/browseable/BeamLargeFiles/src/com.example.android.beamlargefiles/MainActivity.java b/samples/browseable/BeamLargeFiles/src/com.example.android.beamlargefiles/MainActivity.java
index 50d504c..8143678 100644
--- a/samples/browseable/BeamLargeFiles/src/com.example.android.beamlargefiles/MainActivity.java
+++ b/samples/browseable/BeamLargeFiles/src/com.example.android.beamlargefiles/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.beamlargefiles;
import android.graphics.Color;
diff --git a/samples/browseable/BluetoothAdvertisements/_index.jd b/samples/browseable/BluetoothAdvertisements/_index.jd
index 27296b0..6755526 100644
--- a/samples/browseable/BluetoothAdvertisements/_index.jd
+++ b/samples/browseable/BluetoothAdvertisements/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BluetoothAdvertisements"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/BluetoothAdvertisements/res/values-v21/base-colors.xml b/samples/browseable/BluetoothAdvertisements/res/values-v21/base-colors.xml
index d902378..2c744be 100644
--- a/samples/browseable/BluetoothAdvertisements/res/values-v21/base-colors.xml
+++ b/samples/browseable/BluetoothAdvertisements/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<color name="colorPrimary">#434AB3</color>
diff --git a/samples/browseable/BluetoothAdvertisements/res/values-v21/base-template-styles.xml b/samples/browseable/BluetoothAdvertisements/res/values-v21/base-template-styles.xml
index 0234856..0bb9fbf 100644
--- a/samples/browseable/BluetoothAdvertisements/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BluetoothAdvertisements/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BluetoothAdvertisements/res/values/base-strings.xml b/samples/browseable/BluetoothAdvertisements/res/values/base-strings.xml
index 6bfd413..5250c75 100644
--- a/samples/browseable/BluetoothAdvertisements/res/values/base-strings.xml
+++ b/samples/browseable/BluetoothAdvertisements/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BluetoothAdvertisements</string>
<string name="intro_message">
diff --git a/samples/browseable/BluetoothChat/_index.jd b/samples/browseable/BluetoothChat/_index.jd
index 6d1e37a..eec7ccd 100644
--- a/samples/browseable/BluetoothChat/_index.jd
+++ b/samples/browseable/BluetoothChat/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BluetoothChat"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/BluetoothChat/res/values-v21/base-colors.xml b/samples/browseable/BluetoothChat/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BluetoothChat/res/values-v21/base-colors.xml
+++ b/samples/browseable/BluetoothChat/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BluetoothChat/res/values-v21/base-template-styles.xml b/samples/browseable/BluetoothChat/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BluetoothChat/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BluetoothChat/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BluetoothChat/res/values/base-strings.xml b/samples/browseable/BluetoothChat/res/values/base-strings.xml
index fe175fb..2c6877c 100644
--- a/samples/browseable/BluetoothChat/res/values/base-strings.xml
+++ b/samples/browseable/BluetoothChat/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BluetoothChat</string>
<string name="intro_message">
diff --git a/samples/browseable/BluetoothChat/src/com.example.android.bluetoothchat/MainActivity.java b/samples/browseable/BluetoothChat/src/com.example.android.bluetoothchat/MainActivity.java
index cf4ec47..a791fc8 100644
--- a/samples/browseable/BluetoothChat/src/com.example.android.bluetoothchat/MainActivity.java
+++ b/samples/browseable/BluetoothChat/src/com.example.android.bluetoothchat/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.bluetoothchat;
import android.os.Bundle;
diff --git a/samples/browseable/BluetoothLeGatt/_index.jd b/samples/browseable/BluetoothLeGatt/_index.jd
index 13d9cb6..bbd5b3d 100644
--- a/samples/browseable/BluetoothLeGatt/_index.jd
+++ b/samples/browseable/BluetoothLeGatt/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BluetoothLeGatt"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/BluetoothLeGatt/res/values-v21/base-colors.xml b/samples/browseable/BluetoothLeGatt/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BluetoothLeGatt/res/values-v21/base-colors.xml
+++ b/samples/browseable/BluetoothLeGatt/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BluetoothLeGatt/res/values-v21/base-template-styles.xml b/samples/browseable/BluetoothLeGatt/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BluetoothLeGatt/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BluetoothLeGatt/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BluetoothLeGatt/res/values/base-strings.xml b/samples/browseable/BluetoothLeGatt/res/values/base-strings.xml
index f3b546c..8b742b7 100644
--- a/samples/browseable/BluetoothLeGatt/res/values/base-strings.xml
+++ b/samples/browseable/BluetoothLeGatt/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BluetoothLeGatt</string>
<string name="intro_message">
diff --git a/samples/browseable/BorderlessButtons/_index.jd b/samples/browseable/BorderlessButtons/_index.jd
index a940d18..90a59cc 100644
--- a/samples/browseable/BorderlessButtons/_index.jd
+++ b/samples/browseable/BorderlessButtons/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="BorderlessButtons"
sample.group=UI
@jd:body
diff --git a/samples/browseable/BorderlessButtons/res/values-v21/base-colors.xml b/samples/browseable/BorderlessButtons/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/BorderlessButtons/res/values-v21/base-colors.xml
+++ b/samples/browseable/BorderlessButtons/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/BorderlessButtons/res/values-v21/base-template-styles.xml b/samples/browseable/BorderlessButtons/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/BorderlessButtons/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/BorderlessButtons/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/BorderlessButtons/res/values/base-strings.xml b/samples/browseable/BorderlessButtons/res/values/base-strings.xml
index 14f5df2..d00816b 100644
--- a/samples/browseable/BorderlessButtons/res/values/base-strings.xml
+++ b/samples/browseable/BorderlessButtons/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">BorderlessButtons</string>
<string name="intro_message">
diff --git a/samples/browseable/Camera2Basic/_index.jd b/samples/browseable/Camera2Basic/_index.jd
index ba27fff..b945aa8 100644
--- a/samples/browseable/Camera2Basic/_index.jd
+++ b/samples/browseable/Camera2Basic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Camera2Basic"
sample.group=Media
@jd:body
diff --git a/samples/browseable/Camera2Basic/res/values-v21/base-colors.xml b/samples/browseable/Camera2Basic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/Camera2Basic/res/values-v21/base-colors.xml
+++ b/samples/browseable/Camera2Basic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/Camera2Basic/res/values-v21/base-template-styles.xml b/samples/browseable/Camera2Basic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/Camera2Basic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/Camera2Basic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/Camera2Basic/res/values/base-strings.xml b/samples/browseable/Camera2Basic/res/values/base-strings.xml
index 9a7579e..5b1bda4 100644
--- a/samples/browseable/Camera2Basic/res/values/base-strings.xml
+++ b/samples/browseable/Camera2Basic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Camera2Basic</string>
<string name="intro_message">
diff --git a/samples/browseable/Camera2Raw/AndroidManifest.xml b/samples/browseable/Camera2Raw/AndroidManifest.xml
new file mode 100644
index 0000000..f948c6a
--- /dev/null
+++ b/samples/browseable/Camera2Raw/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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.camera2raw"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+ <!-- A camera with RAW capability is required to use this application -->
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.camera.raw" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@style/MaterialTheme">
+
+ <activity android:name="com.example.android.camera2raw.CameraActivity"
+ android:label="@string/app_name">
+ <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/browseable/Camera2Raw/_index.jd b/samples/browseable/Camera2Raw/_index.jd
new file mode 100644
index 0000000..0ef2ae2
--- /dev/null
+++ b/samples/browseable/Camera2Raw/_index.jd
@@ -0,0 +1,11 @@
+
+page.tags="Camera2Raw"
+sample.group=Media
+@jd:body
+
+<p>
+
+ This sample demonstrates how to use the Camera2 API to capture RAW
+ camera buffers and save them as DNG files.
+
+ </p>
diff --git a/samples/browseable/Camera2Raw/res/drawable-hdpi/ic_action_info.png b/samples/browseable/Camera2Raw/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 0000000..32bd1aa
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-hdpi/ic_action_info.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-hdpi/ic_launcher.png b/samples/browseable/Camera2Raw/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..bba1165
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-hdpi/tile.9.png b/samples/browseable/Camera2Raw/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-mdpi/ic_action_info.png b/samples/browseable/Camera2Raw/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 0000000..8efbbf8
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-mdpi/ic_action_info.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-mdpi/ic_launcher.png b/samples/browseable/Camera2Raw/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..4304591
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-xhdpi/ic_action_info.png b/samples/browseable/Camera2Raw/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 0000000..ba143ea
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-xhdpi/ic_action_info.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/Camera2Raw/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..80c5eba
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-xxhdpi/ic_action_info.png b/samples/browseable/Camera2Raw/res/drawable-xxhdpi/ic_action_info.png
new file mode 100644
index 0000000..394eb7e
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-xxhdpi/ic_action_info.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/Camera2Raw/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..9baac9b
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/Camera2Raw/res/layout-land/fragment_camera2_basic.xml b/samples/browseable/Camera2Raw/res/layout-land/fragment_camera2_basic.xml
new file mode 100644
index 0000000..3eb68db
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/layout-land/fragment_camera2_basic.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent">
+
+ <com.example.android.camera2raw.AutoFitTextureView
+ android:id="@+id/texture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true" />
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:layout_below="@id/texture"
+ android:layout_toRightOf="@id/texture"
+ android:background="#4285f4"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/picture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/picture" />
+
+ <ImageButton
+ android:id="@+id/info"
+ style="@android:style/Widget.Material.Light.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:contentDescription="@string/description_info"
+ android:padding="20dp"
+ android:src="@drawable/ic_action_info" />
+
+
+ </FrameLayout>
+
+</RelativeLayout>
diff --git a/samples/browseable/Camera2Raw/res/layout/activity_camera.xml b/samples/browseable/Camera2Raw/res/layout/activity_camera.xml
new file mode 100644
index 0000000..b6db9a1
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/layout/activity_camera.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#000"
+ tools:context="com.example.android.camera2raw.CameraActivity" />
diff --git a/samples/browseable/Camera2Raw/res/layout/fragment_camera2_basic.xml b/samples/browseable/Camera2Raw/res/layout/fragment_camera2_basic.xml
new file mode 100644
index 0000000..e8ed001
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/layout/fragment_camera2_basic.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent">
+
+ <com.example.android.camera2raw.AutoFitTextureView
+ android:id="@+id/texture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true" />
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:layout_below="@id/texture"
+ android:background="#4285f4">
+
+ <Button
+ android:id="@+id/picture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/picture" />
+
+ <ImageButton
+ android:id="@+id/info"
+ android:contentDescription="@string/description_info"
+ style="@android:style/Widget.Material.Light.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|right"
+ android:padding="20dp"
+ android:src="@drawable/ic_action_info" />
+
+ </FrameLayout>
+
+</RelativeLayout>
diff --git a/samples/browseable/Camera2Raw/res/values-sw600dp/template-dimens.xml b/samples/browseable/Camera2Raw/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values-sw600dp/template-styles.xml b/samples/browseable/Camera2Raw/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values-v11/template-styles.xml b/samples/browseable/Camera2Raw/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values-v21/base-colors.xml b/samples/browseable/Camera2Raw/res/values-v21/base-colors.xml
new file mode 100644
index 0000000..8b6ec3f
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values-v21/base-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values-v21/base-template-styles.xml b/samples/browseable/Camera2Raw/res/values-v21/base-template-styles.xml
new file mode 100644
index 0000000..c778e4f
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values-v21/base-template-styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light">
+ </style>
+
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values/base-strings.xml b/samples/browseable/Camera2Raw/res/values/base-strings.xml
new file mode 100644
index 0000000..c3f8c21
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values/base-strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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">Camera2Raw</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ This sample demonstrates how to use the Camera2 API to capture RAW
+ camera buffers and save them as DNG files.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values/strings.xml b/samples/browseable/Camera2Raw/res/values/strings.xml
new file mode 100644
index 0000000..0f56ce9
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="picture">Picture</string>
+ <string name="description_info">Info</string>
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values/styles.xml b/samples/browseable/Camera2Raw/res/values/styles.xml
new file mode 100644
index 0000000..34d16bd
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="MaterialTheme" parent="android:Theme.Material.Light.NoActionBar.Fullscreen" />
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values/template-dimens.xml b/samples/browseable/Camera2Raw/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/Camera2Raw/res/values/template-styles.xml b/samples/browseable/Camera2Raw/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/Camera2Raw/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/AutoFitTextureView.java b/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/AutoFitTextureView.java
new file mode 100644
index 0000000..e02e8b8
--- /dev/null
+++ b/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/AutoFitTextureView.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.camera2raw;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.TextureView;
+
+/**
+ * A {@link TextureView} that can be adjusted to a specified aspect ratio.
+ */
+public class AutoFitTextureView extends TextureView {
+
+ private int mRatioWidth = 0;
+ private int mRatioHeight = 0;
+
+ public AutoFitTextureView(Context context) {
+ this(context, null);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
+ * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
+ * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
+ *
+ * @param width Relative horizontal size
+ * @param height Relative vertical size
+ */
+ public void setAspectRatio(int width, int height) {
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Size cannot be negative.");
+ }
+ if (mRatioWidth == width && mRatioHeight == height) {
+ return;
+ }
+ mRatioWidth = width;
+ mRatioHeight = height;
+ requestLayout();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ if (0 == mRatioWidth || 0 == mRatioHeight) {
+ setMeasuredDimension(width, height);
+ } else {
+ if (width < height * mRatioWidth / mRatioHeight) {
+ setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
+ } else {
+ setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
+ }
+ }
+ }
+
+}
diff --git a/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/Camera2RawFragment.java b/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/Camera2RawFragment.java
new file mode 100644
index 0000000..6460bf3
--- /dev/null
+++ b/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/Camera2RawFragment.java
@@ -0,0 +1,1674 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.camera2raw;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
+import android.hardware.SensorManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.DngCreator;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.Image;
+import android.media.ImageReader;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Size;
+import android.util.SparseIntArray;
+import android.view.LayoutInflater;
+import android.view.OrientationEventListener;
+import android.view.Surface;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A fragment that demonstrates use of the Camera2 API to capture RAW and JPEG photos.
+ *
+ * In this example, the lifecycle of a single request to take a photo is:
+ * <ul>
+ * <li>
+ * The user presses the "Picture" button, resulting in a call to {@link #takePicture()}.
+ * </li>
+ * <li>
+ * {@link #takePicture()} initiates a pre-capture sequence that triggers the camera's built-in
+ * auto-focus, auto-exposure, and auto-white-balance algorithms (aka. "3A") to run.
+ * </li>
+ * <li>
+ * When the pre-capture sequence has finished, a {@link CaptureRequest} with a monotonically
+ * increasing request ID set by calls to {@link CaptureRequest.Builder#setTag(Object)} is sent to
+ * the camera to begin the JPEG and RAW capture sequence, and an
+ * {@link ImageSaver.ImageSaverBuilder} is stored for this request in the
+ * {@link #mJpegResultQueue} and {@link #mRawResultQueue}.
+ * </li>
+ * <li>
+ * As {@link CaptureResult}s and {@link Image}s become available via callbacks in a background
+ * thread, a {@link ImageSaver.ImageSaverBuilder} is looked up by the request ID in
+ * {@link #mJpegResultQueue} and {@link #mRawResultQueue} and updated.
+ * </li>
+ * <li>
+ * When all of the necessary results to save an image are available, the an {@link ImageSaver} is
+ * constructed by the {@link ImageSaver.ImageSaverBuilder} and passed to a separate background
+ * thread to save to a file.
+ * </li>
+ * </ul>
+ */
+public class Camera2RawFragment extends Fragment implements View.OnClickListener {
+ /**
+ * Conversion from screen rotation to JPEG orientation.
+ */
+ private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
+
+ static {
+ ORIENTATIONS.append(Surface.ROTATION_0, 0);
+ ORIENTATIONS.append(Surface.ROTATION_90, 90);
+ ORIENTATIONS.append(Surface.ROTATION_180, 180);
+ ORIENTATIONS.append(Surface.ROTATION_270, 270);
+ }
+
+ /**
+ * Timeout for the pre-capture sequence.
+ */
+ private static final long PRECAPTURE_TIMEOUT_MS = 1000;
+
+ /**
+ * Tolerance when comparing aspect ratios.
+ */
+ private static final double ASPECT_RATIO_TOLERANCE = 0.005;
+
+ /**
+ * Tag for the {@link Log}.
+ */
+ private static final String TAG = "Camera2RawFragment";
+
+ /**
+ * Camera state: Device is closed.
+ */
+ private static final int STATE_CLOSED = 0;
+
+ /**
+ * Camera state: Device is opened, but is not capturing.
+ */
+ private static final int STATE_OPENED = 1;
+
+ /**
+ * Camera state: Showing camera preview.
+ */
+ private static final int STATE_PREVIEW = 2;
+
+ /**
+ * Camera state: Waiting for 3A convergence before capturing a photo.
+ */
+ private static final int STATE_WAITING_FOR_3A_CONVERGENCE = 3;
+
+ /**
+ * An {@link OrientationEventListener} used to determine when device rotation has occurred.
+ * This is mainly necessary for when the device is rotated by 180 degrees, in which case
+ * onCreate or onConfigurationChanged is not called as the view dimensions remain the same,
+ * but the orientation of the has changed, and thus the preview rotation must be updated.
+ */
+ private OrientationEventListener mOrientationListener;
+
+ /**
+ * {@link TextureView.SurfaceTextureListener} handles several lifecycle events of a
+ * {@link TextureView}.
+ */
+ private final TextureView.SurfaceTextureListener mSurfaceTextureListener
+ = new TextureView.SurfaceTextureListener() {
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
+ configureTransform(width, height);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
+ configureTransform(width, height);
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
+ synchronized (mCameraStateLock) {
+ mPreviewSize = null;
+ }
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture texture) {
+ }
+
+ };
+
+ /**
+ * An {@link AutoFitTextureView} for camera preview.
+ */
+ private AutoFitTextureView mTextureView;
+
+ /**
+ * An additional thread for running tasks that shouldn't block the UI. This is used for all
+ * callbacks from the {@link CameraDevice} and {@link CameraCaptureSession}s.
+ */
+ private HandlerThread mBackgroundThread;
+
+ /**
+ * A counter for tracking corresponding {@link CaptureRequest}s and {@link CaptureResult}s
+ * across the {@link CameraCaptureSession} capture callbacks.
+ */
+ private final AtomicInteger mRequestCounter = new AtomicInteger();
+
+ /**
+ * A {@link Semaphore} to prevent the app from exiting before closing the camera.
+ */
+ private final Semaphore mCameraOpenCloseLock = new Semaphore(1);
+
+ /**
+ * A lock protecting camera state.
+ */
+ private final Object mCameraStateLock = new Object();
+
+ // *********************************************************************************************
+ // State protected by mCameraStateLock.
+ //
+ // The following state is used across both the UI and background threads. Methods with "Locked"
+ // in the name expect mCameraStateLock to be held while calling.
+
+ /**
+ * ID of the current {@link CameraDevice}.
+ */
+ private String mCameraId;
+
+ /**
+ * A {@link CameraCaptureSession } for camera preview.
+ */
+ private CameraCaptureSession mCaptureSession;
+
+ /**
+ * A reference to the open {@link CameraDevice}.
+ */
+ private CameraDevice mCameraDevice;
+
+ /**
+ * The {@link Size} of camera preview.
+ */
+ private Size mPreviewSize;
+
+ /**
+ * The {@link CameraCharacteristics} for the currently configured camera device.
+ */
+ private CameraCharacteristics mCharacteristics;
+
+ /**
+ * A {@link Handler} for running tasks in the background.
+ */
+ private Handler mBackgroundHandler;
+
+ /**
+ * A reference counted holder wrapping the {@link ImageReader} that handles JPEG image captures.
+ * This is used to allow us to clean up the {@link ImageReader} when all background tasks using
+ * its {@link Image}s have completed.
+ */
+ private RefCountedAutoCloseable<ImageReader> mJpegImageReader;
+
+ /**
+ * A reference counted holder wrapping the {@link ImageReader} that handles RAW image captures.
+ * This is used to allow us to clean up the {@link ImageReader} when all background tasks using
+ * its {@link Image}s have completed.
+ */
+ private RefCountedAutoCloseable<ImageReader> mRawImageReader;
+
+ /**
+ * Whether or not the currently configured camera device is fixed-focus.
+ */
+ private boolean mNoAFRun = false;
+
+ /**
+ * Number of pending user requests to capture a photo.
+ */
+ private int mPendingUserCaptures = 0;
+
+ /**
+ * Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress JPEG captures.
+ */
+ private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mJpegResultQueue = new TreeMap<>();
+
+ /**
+ * Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress RAW captures.
+ */
+ private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mRawResultQueue = new TreeMap<>();
+
+ /**
+ * {@link CaptureRequest.Builder} for the camera preview
+ */
+ private CaptureRequest.Builder mPreviewRequestBuilder;
+
+ /**
+ * The state of the camera device.
+ *
+ * @see #mPreCaptureCallback
+ */
+ private int mState = STATE_CLOSED;
+
+ /**
+ * Timer to use with pre-capture sequence to ensure a timely capture if 3A convergence is taking
+ * too long.
+ */
+ private long mCaptureTimer;
+
+ //**********************************************************************************************
+
+ /**
+ * {@link CameraDevice.StateCallback} is called when the currently active {@link CameraDevice}
+ * changes its state.
+ */
+ private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
+
+ @Override
+ public void onOpened(CameraDevice cameraDevice) {
+ // This method is called when the camera is opened. We start camera preview here if
+ // the TextureView displaying this has been set up.
+ synchronized (mCameraStateLock) {
+ mState = STATE_OPENED;
+ mCameraOpenCloseLock.release();
+ mCameraDevice = cameraDevice;
+
+ // Start the preview session if the TextureView has been set up already.
+ if (mPreviewSize != null && mTextureView.isAvailable()) {
+ createCameraPreviewSessionLocked();
+ }
+ }
+ }
+
+ @Override
+ public void onDisconnected(CameraDevice cameraDevice) {
+ synchronized (mCameraStateLock) {
+ mState = STATE_CLOSED;
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ }
+ }
+
+ @Override
+ public void onError(CameraDevice cameraDevice, int error) {
+ Log.e(TAG, "Received camera device error: " + error);
+ synchronized(mCameraStateLock) {
+ mState = STATE_CLOSED;
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ }
+ Activity activity = getActivity();
+ if (null != activity) {
+ activity.finish();
+ }
+ }
+
+ };
+
+ /**
+ * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
+ * JPEG image is ready to be saved.
+ */
+ private final ImageReader.OnImageAvailableListener mOnJpegImageAvailableListener
+ = new ImageReader.OnImageAvailableListener() {
+
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ dequeueAndSaveImage(mJpegResultQueue, mJpegImageReader);
+ }
+
+ };
+
+ /**
+ * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
+ * RAW image is ready to be saved.
+ */
+ private final ImageReader.OnImageAvailableListener mOnRawImageAvailableListener
+ = new ImageReader.OnImageAvailableListener() {
+
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ dequeueAndSaveImage(mRawResultQueue, mRawImageReader);
+ }
+
+ };
+
+ /**
+ * A {@link CameraCaptureSession.CaptureCallback} that handles events for the preview and
+ * pre-capture sequence.
+ */
+ private CameraCaptureSession.CaptureCallback mPreCaptureCallback
+ = new CameraCaptureSession.CaptureCallback() {
+
+ private void process(CaptureResult result) {
+ synchronized(mCameraStateLock) {
+ switch (mState) {
+ case STATE_PREVIEW: {
+ // We have nothing to do when the camera preview is running normally.
+ break;
+ }
+ case STATE_WAITING_FOR_3A_CONVERGENCE: {
+ boolean readyToCapture = true;
+ if (!mNoAFRun) {
+ int afState = result.get(CaptureResult.CONTROL_AF_STATE);
+
+ // If auto-focus has reached locked state, we are ready to capture
+ readyToCapture =
+ (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED ||
+ afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED);
+ }
+
+ // If we are running on an non-legacy device, we should also wait until
+ // auto-exposure and auto-white-balance have converged as well before
+ // taking a picture.
+ if (!isLegacyLocked()) {
+ int aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ int awbState = result.get(CaptureResult.CONTROL_AWB_STATE);
+
+ readyToCapture = readyToCapture &&
+ aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED &&
+ awbState == CaptureResult.CONTROL_AWB_STATE_CONVERGED;
+ }
+
+ // If we haven't finished the pre-capture sequence but have hit our maximum
+ // wait timeout, too bad! Begin capture anyway.
+ if (!readyToCapture && hitTimeoutLocked()) {
+ Log.w(TAG, "Timed out waiting for pre-capture sequence to complete.");
+ readyToCapture = true;
+ }
+
+ if (readyToCapture && mPendingUserCaptures > 0) {
+ // Capture once for each user tap of the "Picture" button.
+ while (mPendingUserCaptures > 0) {
+ captureStillPictureLocked();
+ mPendingUserCaptures--;
+ }
+ // After this, the camera will go back to the normal state of preview.
+ mState = STATE_PREVIEW;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
+ CaptureResult partialResult) {
+ process(partialResult);
+ }
+
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+ TotalCaptureResult result) {
+ process(result);
+ }
+
+ };
+
+ /**
+ * A {@link CameraCaptureSession.CaptureCallback} that handles the still JPEG and RAW capture
+ * request.
+ */
+ private final CameraCaptureSession.CaptureCallback mCaptureCallback
+ = new CameraCaptureSession.CaptureCallback() {
+ @Override
+ public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
+ long timestamp, long frameNumber) {
+ String currentDateTime = generateTimestamp();
+ File rawFile = new File(Environment.
+ getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
+ "RAW_" + currentDateTime + ".dng");
+ File jpegFile = new File(Environment.
+ getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
+ "JPEG_" + currentDateTime + ".jpg");
+
+ // Look up the ImageSaverBuilder for this request and update it with the file name
+ // based on the capture start time.
+ ImageSaver.ImageSaverBuilder jpegBuilder;
+ ImageSaver.ImageSaverBuilder rawBuilder;
+ int requestId = (int) request.getTag();
+ synchronized (mCameraStateLock) {
+ jpegBuilder = mJpegResultQueue.get(requestId);
+ rawBuilder = mRawResultQueue.get(requestId);
+ }
+
+ if (jpegBuilder != null) jpegBuilder.setFile(jpegFile);
+ if (rawBuilder != null) rawBuilder.setFile(rawFile);
+ }
+
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+ TotalCaptureResult result) {
+ int requestId = (int) request.getTag();
+ ImageSaver.ImageSaverBuilder jpegBuilder;
+ ImageSaver.ImageSaverBuilder rawBuilder;
+ StringBuilder sb = new StringBuilder();
+
+ // Look up the ImageSaverBuilder for this request and update it with the CaptureResult
+ synchronized (mCameraStateLock) {
+ jpegBuilder = mJpegResultQueue.get(requestId);
+ rawBuilder = mRawResultQueue.get(requestId);
+
+ // If we have all the results necessary, save the image to a file in the background.
+ handleCompletionLocked(requestId, jpegBuilder, mJpegResultQueue);
+ handleCompletionLocked(requestId, rawBuilder, mRawResultQueue);
+
+ if (jpegBuilder != null) {
+ jpegBuilder.setResult(result);
+ sb.append("Saving JPEG as: ");
+ sb.append(jpegBuilder.getSaveLocation());
+ }
+ if (rawBuilder != null) {
+ rawBuilder.setResult(result);
+ if (jpegBuilder != null) sb.append(", ");
+ sb.append("Saving RAW as: ");
+ sb.append(rawBuilder.getSaveLocation());
+ }
+ finishedCaptureLocked();
+ }
+
+ showToast(sb.toString());
+ }
+
+ @Override
+ public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
+ CaptureFailure failure) {
+ int requestId = (int) request.getTag();
+ synchronized (mCameraStateLock) {
+ mJpegResultQueue.remove(requestId);
+ mRawResultQueue.remove(requestId);
+ finishedCaptureLocked();
+ }
+ showToast("Capture failed!");
+ }
+
+ };
+
+ /**
+ * A {@link Handler} for showing {@link Toast}s on the UI thread.
+ */
+ private final Handler mMessageHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ Activity activity = getActivity();
+ if (activity != null) {
+ Toast.makeText(activity, (String) msg.obj, Toast.LENGTH_SHORT).show();
+ }
+ }
+ };
+
+ public static Camera2RawFragment newInstance() {
+ Camera2RawFragment fragment = new Camera2RawFragment();
+ fragment.setRetainInstance(true);
+ return fragment;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_camera2_basic, container, false);
+ }
+
+ @Override
+ public void onViewCreated(final View view, Bundle savedInstanceState) {
+ view.findViewById(R.id.picture).setOnClickListener(this);
+ view.findViewById(R.id.info).setOnClickListener(this);
+ mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
+
+ // Setup a new OrientationEventListener. This is used to handle rotation events like a
+ // 180 degree rotation that do not normally trigger a call to onCreate to do view re-layout
+ // or otherwise cause the preview TextureView's size to change.
+ mOrientationListener = new OrientationEventListener(getActivity(),
+ SensorManager.SENSOR_DELAY_NORMAL) {
+ @Override
+ public void onOrientationChanged(int orientation) {
+ if (mTextureView != null && mTextureView.isAvailable()) {
+ configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
+ }
+ }
+ };
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ startBackgroundThread();
+ openCamera();
+
+ // When the screen is turned off and turned back on, the SurfaceTexture is already
+ // available, and "onSurfaceTextureAvailable" will not be called. In that case, we should
+ // configure the preview bounds here (otherwise, we wait until the surface is ready in
+ // the SurfaceTextureListener).
+ if (mTextureView.isAvailable()) {
+ configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
+ } else {
+ mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+ }
+ if (mOrientationListener != null && mOrientationListener.canDetectOrientation()) {
+ mOrientationListener.enable();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ if (mOrientationListener != null) {
+ mOrientationListener.disable();
+ }
+ closeCamera();
+ stopBackgroundThread();
+ super.onPause();
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.picture: {
+ takePicture();
+ break;
+ }
+ case R.id.info: {
+ Activity activity = getActivity();
+ if (null != activity) {
+ new AlertDialog.Builder(activity)
+ .setMessage(R.string.intro_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .show();
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Sets up state related to camera that is needed before opening a {@link CameraDevice}.
+ */
+ private boolean setUpCameraOutputs() {
+ Activity activity = getActivity();
+ CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ if (manager == null) {
+ ErrorDialog.buildErrorDialog("This device doesn't support Camera2 API.").
+ show(getFragmentManager(), "dialog");
+ return false;
+ }
+ try {
+ // Find a CameraDevice that supports RAW captures, and configure state.
+ for (String cameraId : manager.getCameraIdList()) {
+ CameraCharacteristics characteristics
+ = manager.getCameraCharacteristics(cameraId);
+
+ // We only use a camera that supports RAW in this sample.
+ if (!contains(characteristics.get(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES),
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+ continue;
+ }
+
+ StreamConfigurationMap map = characteristics.get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ // For still image captures, we use the largest available size.
+ Size largestJpeg = Collections.max(
+ Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
+ new CompareSizesByArea());
+
+ Size largestRaw = Collections.max(
+ Arrays.asList(map.getOutputSizes(ImageFormat.RAW_SENSOR)),
+ new CompareSizesByArea());
+
+ synchronized(mCameraStateLock) {
+ // Set up ImageReaders for JPEG and RAW outputs. Place these in a reference
+ // counted wrapper to ensure they are only closed when all background tasks
+ // using them are finished.
+ if (mJpegImageReader == null || mJpegImageReader.getAndRetain() == null) {
+ mJpegImageReader = new RefCountedAutoCloseable<>(
+ ImageReader.newInstance(largestJpeg.getWidth(),
+ largestJpeg.getHeight(), ImageFormat.JPEG, /*maxImages*/5));
+ }
+ mJpegImageReader.get().setOnImageAvailableListener(
+ mOnJpegImageAvailableListener, mBackgroundHandler);
+
+ if (mRawImageReader == null || mRawImageReader.getAndRetain() == null) {
+ mRawImageReader = new RefCountedAutoCloseable<>(
+ ImageReader.newInstance(largestRaw.getWidth(),
+ largestRaw.getHeight(), ImageFormat.RAW_SENSOR, /*maxImages*/ 5));
+ }
+ mRawImageReader.get().setOnImageAvailableListener(
+ mOnRawImageAvailableListener, mBackgroundHandler);
+
+ mCharacteristics = characteristics;
+ mCameraId = cameraId;
+ }
+ return true;
+ }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+
+ // If we found no suitable cameras for capturing RAW, warn the user.
+ ErrorDialog.buildErrorDialog("This device doesn't support capturing RAW photos").
+ show(getFragmentManager(), "dialog");
+ return false;
+ }
+
+ /**
+ * Opens the camera specified by {@link #mCameraId}.
+ */
+ private void openCamera() {
+ if (!setUpCameraOutputs()) {
+ return;
+ }
+
+ Activity activity = getActivity();
+ CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ try {
+ // Wait for any previously running session to finish.
+ if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Time out waiting to lock camera opening.");
+ }
+
+ String cameraId;
+ Handler backgroundHandler;
+ synchronized (mCameraStateLock) {
+ cameraId = mCameraId;
+ backgroundHandler = mBackgroundHandler;
+ }
+
+ // Attempt to open the camera. mStateCallback will be called on the background handler's
+ // thread when this succeeds or fails.
+ manager.openCamera(cameraId, mStateCallback, backgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
+ }
+ }
+
+ /**
+ * Closes the current {@link CameraDevice}.
+ */
+ private void closeCamera() {
+ try {
+ mCameraOpenCloseLock.acquire();
+ synchronized(mCameraStateLock) {
+
+ // Reset state and clean up resources used by the camera.
+ // Note: After calling this, the ImageReaders will be closed after any background
+ // tasks saving Images from these readers have been completed.
+ mPendingUserCaptures = 0;
+ mState = STATE_CLOSED;
+ if (null != mCaptureSession) {
+ mCaptureSession.close();
+ mCaptureSession = null;
+ }
+ if (null != mCameraDevice) {
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ if (null != mJpegImageReader) {
+ mJpegImageReader.close();
+ mJpegImageReader = null;
+ }
+ if (null != mRawImageReader) {
+ mRawImageReader.close();
+ mRawImageReader = null;
+ }
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
+ } finally {
+ mCameraOpenCloseLock.release();
+ }
+ }
+
+ /**
+ * Starts a background thread and its {@link Handler}.
+ */
+ private void startBackgroundThread() {
+ mBackgroundThread = new HandlerThread("CameraBackground");
+ mBackgroundThread.start();
+ synchronized(mCameraStateLock) {
+ mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
+ }
+ }
+
+ /**
+ * Stops the background thread and its {@link Handler}.
+ */
+ private void stopBackgroundThread() {
+ mBackgroundThread.quitSafely();
+ try {
+ mBackgroundThread.join();
+ mBackgroundThread = null;
+ synchronized (mCameraStateLock) {
+ mBackgroundHandler = null;
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates a new {@link CameraCaptureSession} for camera preview.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ */
+ private void createCameraPreviewSessionLocked() {
+ try {
+ SurfaceTexture texture = mTextureView.getSurfaceTexture();
+ // We configure the size of default buffer to be the size of camera preview we want.
+ texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+
+ // This is the output Surface we need to start preview.
+ Surface surface = new Surface(texture);
+
+ // We set up a CaptureRequest.Builder with the output Surface.
+ mPreviewRequestBuilder
+ = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ mPreviewRequestBuilder.addTarget(surface);
+
+ // Here, we create a CameraCaptureSession for camera preview.
+ mCameraDevice.createCaptureSession(Arrays.asList(surface,
+ mJpegImageReader.get().getSurface(),
+ mRawImageReader.get().getSurface()), new CameraCaptureSession.StateCallback() {
+ @Override
+ public void onConfigured(CameraCaptureSession cameraCaptureSession) {
+ synchronized (mCameraStateLock) {
+ // The camera is already closed
+ if (null == mCameraDevice) {
+ return;
+ }
+
+ try {
+ setup3AControlsLocked(mPreviewRequestBuilder);
+ // Finally, we start displaying the camera preview.
+ cameraCaptureSession.setRepeatingRequest(
+ mPreviewRequestBuilder.build(),
+ mPreCaptureCallback, mBackgroundHandler);
+ mState = STATE_PREVIEW;
+ } catch (CameraAccessException|IllegalStateException e) {
+ e.printStackTrace();
+ return;
+ }
+ // When the session is ready, we start displaying the preview.
+ mCaptureSession = cameraCaptureSession;
+ }
+ }
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
+ showToast("Failed to configure camera.");
+ }
+ }, mBackgroundHandler
+ );
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Configure the given {@link CaptureRequest.Builder} to use auto-focus, auto-exposure, and
+ * auto-white-balance controls if available.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ *
+ * @param builder the builder to configure.
+ */
+ private void setup3AControlsLocked(CaptureRequest.Builder builder) {
+ // Enable auto-magical 3A run by camera device
+ builder.set(CaptureRequest.CONTROL_MODE,
+ CaptureRequest.CONTROL_MODE_AUTO);
+
+ Float minFocusDist =
+ mCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+
+ // If MINIMUM_FOCUS_DISTANCE is 0, lens is fixed-focus and we need to skip the AF run.
+ mNoAFRun = (minFocusDist == null || minFocusDist == 0);
+
+ if (!mNoAFRun) {
+ // If there is a "continuous picture" mode available, use it, otherwise default to AUTO.
+ if (contains(mCharacteristics.get(
+ CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES),
+ CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
+ builder.set(CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ } else {
+ builder.set(CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_AUTO);
+ }
+ }
+
+ // If there is an auto-magical flash control mode available, use it, otherwise default to
+ // the "on" mode, which is guaranteed to always be available.
+ if (contains(mCharacteristics.get(
+ CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES),
+ CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)) {
+ builder.set(CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+ } else {
+ builder.set(CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_ON);
+ }
+
+ // If there is an auto-magical white balance control mode available, use it.
+ if (contains(mCharacteristics.get(
+ CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES),
+ CaptureRequest.CONTROL_AWB_MODE_AUTO)) {
+ // Allow AWB to run auto-magically if this device supports this
+ builder.set(CaptureRequest.CONTROL_AWB_MODE,
+ CaptureRequest.CONTROL_AWB_MODE_AUTO);
+ }
+ }
+
+ /**
+ * Configure the necessary {@link android.graphics.Matrix} transformation to `mTextureView`,
+ * and start/restart the preview capture session if necessary.
+ *
+ * This method should be called after the camera state has been initialized in
+ * setUpCameraOutputs.
+ *
+ * @param viewWidth The width of `mTextureView`
+ * @param viewHeight The height of `mTextureView`
+ */
+ private void configureTransform(int viewWidth, int viewHeight) {
+ Activity activity = getActivity();
+ synchronized(mCameraStateLock) {
+ if (null == mTextureView || null == activity) {
+ return;
+ }
+
+ StreamConfigurationMap map = mCharacteristics.get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ // For still image captures, we always use the largest available size.
+ Size largestJpeg = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
+ new CompareSizesByArea());
+
+ // Find the rotation of the device relative to the native device orientation.
+ int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+
+ // Find the rotation of the device relative to the camera sensor's orientation.
+ int totalRotation = sensorToDeviceRotation(mCharacteristics, deviceRotation);
+
+ // Swap the view dimensions for calculation as needed if they are rotated relative to
+ // the sensor.
+ boolean swappedDimensions = totalRotation == 90 || totalRotation == 270;
+ int rotatedViewWidth = viewWidth;
+ int rotatedViewHeight = viewHeight;
+ if (swappedDimensions) {
+ rotatedViewWidth = viewHeight;
+ rotatedViewHeight = viewWidth;
+ }
+
+ // Find the best preview size for these view dimensions and configured JPEG size.
+ Size previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
+ rotatedViewWidth, rotatedViewHeight, largestJpeg);
+
+ if (swappedDimensions) {
+ mTextureView.setAspectRatio(
+ previewSize.getHeight(), previewSize.getWidth());
+ } else {
+ mTextureView.setAspectRatio(
+ previewSize.getWidth(), previewSize.getHeight());
+ }
+
+ // Find rotation of device in degrees (reverse device orientation for front-facing
+ // cameras).
+ int rotation = (mCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
+ CameraCharacteristics.LENS_FACING_FRONT) ?
+ (360 + ORIENTATIONS.get(deviceRotation)) % 360 :
+ (360 - ORIENTATIONS.get(deviceRotation)) % 360;
+
+ Matrix matrix = new Matrix();
+ RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
+ RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
+ float centerX = viewRect.centerX();
+ float centerY = viewRect.centerY();
+
+ // Initially, output stream images from the Camera2 API will be rotated to the native
+ // device orientation from the sensor's orientation, and the TextureView will default to
+ // scaling these buffers to fill it's view bounds. If the aspect ratios and relative
+ // orientations are correct, this is fine.
+ //
+ // However, if the device orientation has been rotated relative to its native
+ // orientation so that the TextureView's dimensions are swapped relative to the
+ // native device orientation, we must do the following to ensure the output stream
+ // images are not incorrectly scaled by the TextureView:
+ // - Undo the scale-to-fill from the output buffer's dimensions (i.e. its dimensions
+ // in the native device orientation) to the TextureView's dimension.
+ // - Apply a scale-to-fill from the output buffer's rotated dimensions
+ // (i.e. its dimensions in the current device orientation) to the TextureView's
+ // dimensions.
+ // - Apply the rotation from the native device orientation to the current device
+ // rotation.
+ if (Surface.ROTATION_90 == deviceRotation || Surface.ROTATION_270 == deviceRotation) {
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
+ matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
+ float scale = Math.max(
+ (float) viewHeight / previewSize.getHeight(),
+ (float) viewWidth / previewSize.getWidth());
+ matrix.postScale(scale, scale, centerX, centerY);
+
+ }
+ matrix.postRotate(rotation, centerX, centerY);
+
+ mTextureView.setTransform(matrix);
+
+ // Start or restart the active capture session if the preview was initialized or
+ // if its aspect ratio changed significantly.
+ if (mPreviewSize == null || !checkAspectsEqual(previewSize, mPreviewSize)) {
+ mPreviewSize = previewSize;
+ if (mState != STATE_CLOSED) {
+ createCameraPreviewSessionLocked();
+ }
+ }
+ }
+ }
+
+ /**
+ * Initiate a still image capture.
+ *
+ * This function sends a capture request that initiates a pre-capture sequence in our state
+ * machine that waits for auto-focus to finish, ending in a "locked" state where the lens is no
+ * longer moving, waits for auto-exposure to choose a good exposure value, and waits for
+ * auto-white-balance to converge.
+ */
+ private void takePicture() {
+ synchronized(mCameraStateLock) {
+ mPendingUserCaptures++;
+
+ // If we already triggered a pre-capture sequence, or are in a state where we cannot
+ // do this, return immediately.
+ if (mState != STATE_PREVIEW) {
+ return;
+ }
+
+ try {
+ // Trigger an auto-focus run if camera is capable. If the camera is already focused,
+ // this should do nothing.
+ if (!mNoAFRun) {
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_START);
+ }
+
+ // If this is not a legacy device, we can also trigger an auto-exposure metering
+ // run.
+ if (!isLegacyLocked()) {
+ // Tell the camera to lock focus.
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
+ }
+
+ // Update state machine to wait for auto-focus, auto-exposure, and
+ // auto-white-balance (aka. "3A") to converge.
+ mState = STATE_WAITING_FOR_3A_CONVERGENCE;
+
+ // Start a timer for the pre-capture sequence.
+ startTimerLocked();
+
+ // Replace the existing repeating request with one with updated 3A triggers.
+ mCaptureSession.capture(mPreviewRequestBuilder.build(), mPreCaptureCallback,
+ mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Send a capture request to the camera device that initiates a capture targeting the JPEG and
+ * RAW outputs.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ */
+ private void captureStillPictureLocked() {
+ try {
+ final Activity activity = getActivity();
+ if (null == activity || null == mCameraDevice) {
+ return;
+ }
+ // This is the CaptureRequest.Builder that we use to take a picture.
+ final CaptureRequest.Builder captureBuilder =
+ mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+
+ captureBuilder.addTarget(mJpegImageReader.get().getSurface());
+ captureBuilder.addTarget(mRawImageReader.get().getSurface());
+
+ // Use the same AE and AF modes as the preview.
+ setup3AControlsLocked(captureBuilder);
+
+ // Set orientation.
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,
+ sensorToDeviceRotation(mCharacteristics, rotation));
+
+ // Set request tag to easily track results in callbacks.
+ captureBuilder.setTag(mRequestCounter.getAndIncrement());
+
+ CaptureRequest request = captureBuilder.build();
+
+ // Create an ImageSaverBuilder in which to collect results, and add it to the queue
+ // of active requests.
+ ImageSaver.ImageSaverBuilder jpegBuilder = new ImageSaver.ImageSaverBuilder(activity)
+ .setCharacteristics(mCharacteristics);
+ ImageSaver.ImageSaverBuilder rawBuilder = new ImageSaver.ImageSaverBuilder(activity)
+ .setCharacteristics(mCharacteristics);
+
+ mJpegResultQueue.put((int) request.getTag(), jpegBuilder);
+ mRawResultQueue.put((int) request.getTag(), rawBuilder);
+
+ mCaptureSession.capture(request, mCaptureCallback, mBackgroundHandler);
+
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Called after a RAW/JPEG capture has completed; resets the AF trigger state for the
+ * pre-capture sequence.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ */
+ private void finishedCaptureLocked() {
+ try {
+ // Reset the auto-focus trigger in case AF didn't run quickly enough.
+ if (!mNoAFRun) {
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
+
+ mCaptureSession.capture(mPreviewRequestBuilder.build(), mPreCaptureCallback,
+ mBackgroundHandler);
+
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
+ }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Retrieve the next {@link Image} from a reference counted {@link ImageReader}, retaining
+ * that {@link ImageReader} until that {@link Image} is no longer in use, and set this
+ * {@link Image} as the result for the next request in the queue of pending requests. If
+ * all necessary information is available, begin saving the image to a file in a background
+ * thread.
+ *
+ * @param pendingQueue the currently active requests.
+ * @param reader a reference counted wrapper containing an {@link ImageReader} from which to
+ * acquire an image.
+ */
+ private void dequeueAndSaveImage(TreeMap<Integer, ImageSaver.ImageSaverBuilder> pendingQueue,
+ RefCountedAutoCloseable<ImageReader> reader) {
+ synchronized (mCameraStateLock) {
+ Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry =
+ pendingQueue.firstEntry();
+ ImageSaver.ImageSaverBuilder builder = entry.getValue();
+
+ // Increment reference count to prevent ImageReader from being closed while we
+ // are saving its Images in a background thread (otherwise their resources may
+ // be freed while we are writing to a file).
+ if (reader == null || reader.getAndRetain() == null) {
+ Log.e(TAG, "Paused the activity before we could save the image," +
+ " ImageReader already closed.");
+ pendingQueue.remove(entry.getKey());
+ return;
+ }
+
+ Image image;
+ try {
+ image = reader.get().acquireNextImage();
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Too many images queued for saving, dropping image for request: " +
+ entry.getKey());
+ pendingQueue.remove(entry.getKey());
+ return;
+ }
+
+ builder.setRefCountedReader(reader).setImage(image);
+
+ handleCompletionLocked(entry.getKey(), builder, pendingQueue);
+ }
+ }
+
+ /**
+ * Runnable that saves an {@link Image} into the specified {@link File}, and updates
+ * {@link android.provider.MediaStore} to include the resulting file.
+ *
+ * This can be constructed through an {@link ImageSaverBuilder} as the necessary image and
+ * result information becomes available.
+ */
+ private static class ImageSaver implements Runnable {
+
+ /**
+ * The image to save.
+ */
+ private final Image mImage;
+ /**
+ * The file we save the image into.
+ */
+ private final File mFile;
+
+ /**
+ * The CaptureResult for this image capture.
+ */
+ private final CaptureResult mCaptureResult;
+
+ /**
+ * The CameraCharacteristics for this camera device.
+ */
+ private final CameraCharacteristics mCharacteristics;
+
+ /**
+ * The Context to use when updating MediaStore with the saved images.
+ */
+ private final Context mContext;
+
+ /**
+ * A reference counted wrapper for the ImageReader that owns the given image.
+ */
+ private final RefCountedAutoCloseable<ImageReader> mReader;
+
+ private ImageSaver(Image image, File file, CaptureResult result,
+ CameraCharacteristics characteristics, Context context,
+ RefCountedAutoCloseable<ImageReader> reader) {
+ mImage = image;
+ mFile = file;
+ mCaptureResult = result;
+ mCharacteristics = characteristics;
+ mContext = context;
+ mReader = reader;
+ }
+
+ @Override
+ public void run() {
+ boolean success = false;
+ int format = mImage.getFormat();
+ switch(format) {
+ case ImageFormat.JPEG: {
+ ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
+ byte[] bytes = new byte[buffer.remaining()];
+ buffer.get(bytes);
+ FileOutputStream output = null;
+ try {
+ output = new FileOutputStream(mFile);
+ output.write(bytes);
+ success = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mImage.close();
+ closeOutput(output);
+ }
+ break;
+ }
+ case ImageFormat.RAW_SENSOR: {
+ DngCreator dngCreator = new DngCreator(mCharacteristics, mCaptureResult);
+ FileOutputStream output = null;
+ try {
+ output = new FileOutputStream(mFile);
+ dngCreator.writeImage(output, mImage);
+ success = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mImage.close();
+ closeOutput(output);
+ }
+ break;
+ }
+ default: {
+ Log.e(TAG, "Cannot save image, unexpected image format:" + format);
+ break;
+ }
+ }
+
+ // Decrement reference count to allow ImageReader to be closed to free up resources.
+ mReader.close();
+
+ // If saving the file succeeded, update MediaStore.
+ if (success) {
+ MediaScannerConnection.scanFile(mContext, new String[] { mFile.getPath()},
+ /*mimeTypes*/null, new MediaScannerConnection.MediaScannerConnectionClient() {
+ @Override
+ public void onMediaScannerConnected() {
+ // Do nothing
+ }
+
+ @Override
+ public void onScanCompleted(String path, Uri uri) {
+ Log.i(TAG, "Scanned " + path + ":");
+ Log.i(TAG, "-> uri=" + uri);
+ }
+ });
+ }
+ }
+
+ /**
+ * Builder class for constructing {@link ImageSaver}s.
+ *
+ * This class is thread safe.
+ */
+ public static class ImageSaverBuilder {
+ private Image mImage;
+ private File mFile;
+ private CaptureResult mCaptureResult;
+ private CameraCharacteristics mCharacteristics;
+ private Context mContext;
+ private RefCountedAutoCloseable<ImageReader> mReader;
+
+ /**
+ * Construct a new ImageSaverBuilder using the given {@link Context}.
+ * @param context a {@link Context} to for accessing the
+ * {@link android.provider.MediaStore}.
+ */
+ public ImageSaverBuilder(final Context context) {
+ mContext = context;
+ }
+
+ public synchronized ImageSaverBuilder setRefCountedReader(
+ RefCountedAutoCloseable<ImageReader> reader) {
+ if (reader == null ) throw new NullPointerException();
+
+ mReader = reader;
+ return this;
+ }
+
+ public synchronized ImageSaverBuilder setImage(final Image image) {
+ if (image == null) throw new NullPointerException();
+ mImage = image;
+ return this;
+ }
+
+ public synchronized ImageSaverBuilder setFile(final File file) {
+ if (file == null) throw new NullPointerException();
+ mFile = file;
+ return this;
+ }
+
+ public synchronized ImageSaverBuilder setResult(final CaptureResult result) {
+ if (result == null) throw new NullPointerException();
+ mCaptureResult = result;
+ return this;
+ }
+
+ public synchronized ImageSaverBuilder setCharacteristics(
+ final CameraCharacteristics characteristics) {
+ if (characteristics == null) throw new NullPointerException();
+ mCharacteristics = characteristics;
+ return this;
+ }
+
+ public synchronized ImageSaver buildIfComplete() {
+ if (!isComplete()) {
+ return null;
+ }
+ return new ImageSaver(mImage, mFile, mCaptureResult, mCharacteristics, mContext,
+ mReader);
+ }
+
+ public synchronized String getSaveLocation() {
+ return (mFile == null) ? "Unknown" : mFile.toString();
+ }
+
+ private boolean isComplete() {
+ return mImage != null && mFile != null && mCaptureResult != null
+ && mCharacteristics != null;
+ }
+ }
+ }
+
+ // Utility classes and methods:
+ // *********************************************************************************************
+
+ /**
+ * Comparator based on area of the given {@link Size} objects.
+ */
+ static class CompareSizesByArea implements Comparator<Size> {
+
+ @Override
+ public int compare(Size lhs, Size rhs) {
+ // We cast here to ensure the multiplications won't overflow
+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
+ (long) rhs.getWidth() * rhs.getHeight());
+ }
+
+ }
+
+ /**
+ * A dialog fragment for displaying non-recoverable errors; this {@ling Activity} will be
+ * finished once the dialog has been acknowledged by the user.
+ */
+ public static class ErrorDialog extends DialogFragment {
+
+ private String mErrorMessage;
+
+ public ErrorDialog() {
+ mErrorMessage = "Unknown error occurred!";
+ }
+
+ // Build a dialog with a custom message (Fragments require default constructor).
+ public static ErrorDialog buildErrorDialog(String errorMessage) {
+ ErrorDialog dialog = new ErrorDialog();
+ dialog.mErrorMessage = errorMessage;
+ return dialog;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Activity activity = getActivity();
+ return new AlertDialog.Builder(activity)
+ .setMessage(mErrorMessage)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ activity.finish();
+ }
+ })
+ .create();
+ }
+ }
+
+ /**
+ * A wrapper for an {@link AutoCloseable} object that implements reference counting to allow
+ * for resource management.
+ */
+ public static class RefCountedAutoCloseable<T extends AutoCloseable> implements AutoCloseable {
+ private T mObject;
+ private long mRefCount = 0;
+
+ /**
+ * Wrap the given object.
+ * @param object an object to wrap.
+ */
+ public RefCountedAutoCloseable(T object) {
+ if (object == null) throw new NullPointerException();
+ mObject = object;
+ }
+
+ /**
+ * Increment the reference count and return the wrapped object.
+ *
+ * @return the wrapped object, or null if the object has been released.
+ */
+ public synchronized T getAndRetain() {
+ if (mRefCount < 0) {
+ return null;
+ }
+ mRefCount++;
+ return mObject;
+ }
+
+ /**
+ * Return the wrapped object.
+ *
+ * @return the wrapped object, or null if the object has been released.
+ */
+ public synchronized T get() {
+ return mObject;
+ }
+
+ /**
+ * Decrement the reference count and release the wrapped object if there are no other
+ * users retaining this object.
+ */
+ @Override
+ public synchronized void close() {
+ if (mRefCount >= 0) {
+ mRefCount--;
+ if (mRefCount < 0) {
+ try {
+ mObject.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ mObject = null;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose
+ * width and height are at least as large as the respective requested values, and whose aspect
+ * ratio matches with the specified value.
+ *
+ * @param choices The list of sizes that the camera supports for the intended output class
+ * @param width The minimum desired width
+ * @param height The minimum desired height
+ * @param aspectRatio The aspect ratio
+ * @return The optimal {@code Size}, or an arbitrary one if none were big enough
+ */
+ private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
+ // Collect the supported resolutions that are at least as big as the preview Surface
+ List<Size> bigEnough = new ArrayList<>();
+ int w = aspectRatio.getWidth();
+ int h = aspectRatio.getHeight();
+ for (Size option : choices) {
+ if (option.getHeight() == option.getWidth() * h / w &&
+ option.getWidth() >= width && option.getHeight() >= height) {
+ bigEnough.add(option);
+ }
+ }
+
+ // Pick the smallest of those, assuming we found any
+ if (bigEnough.size() > 0) {
+ return Collections.min(bigEnough, new CompareSizesByArea());
+ } else {
+ Log.e(TAG, "Couldn't find any suitable preview size");
+ return choices[0];
+ }
+ }
+
+ /**
+ * Generate a string containing a formatted timestamp with the current date and time.
+ *
+ * @return a {@link String} representing a time.
+ */
+ private static String generateTimestamp() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", Locale.US);
+ return sdf.format(new Date());
+ }
+
+ /**
+ * Cleanup the given {@link OutputStream}.
+ *
+ * @param outputStream the stream to close.
+ */
+ private static void closeOutput(OutputStream outputStream) {
+ if (null != outputStream) {
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Return true if the given array contains the given integer.
+ *
+ * @param modes array to check.
+ * @param mode integer to get for.
+ * @return true if the array contains the given integer, otherwise false.
+ */
+ private static boolean contains(int[] modes, int mode) {
+ if (modes == null) {
+ return false;
+ }
+ for (int i : modes) {
+ if (i == mode) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return true if the two given {@link Size}s have the same aspect ratio.
+ *
+ * @param a first {@link Size} to compare.
+ * @param b second {@link Size} to compare.
+ * @return true if the sizes have the same aspect ratio, otherwise false.
+ */
+ private static boolean checkAspectsEqual(Size a, Size b) {
+ double aAspect = a.getWidth() / (double) a.getHeight();
+ double bAspect = b.getWidth() / (double) b.getHeight();
+ return Math.abs(aAspect - bAspect) <= ASPECT_RATIO_TOLERANCE;
+ }
+
+ /**
+ * Rotation need to transform from the camera sensor orientation to the device's current
+ * orientation.
+ * @param c the {@link CameraCharacteristics} to query for the camera sensor orientation.
+ * @param deviceOrientation the current device orientation relative to the native device
+ * orientation.
+ * @return the total rotation from the sensor orientation to the current device orientation.
+ */
+ private static int sensorToDeviceRotation(CameraCharacteristics c, int deviceOrientation) {
+ int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);
+
+ // Get device orientation in degrees
+ deviceOrientation = ORIENTATIONS.get(deviceOrientation);
+
+ // Reverse device orientation for front-facing cameras
+ if (c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
+ deviceOrientation = -deviceOrientation;
+ }
+
+ // Calculate desired JPEG orientation relative to camera orientation to make
+ // the image upright relative to the device orientation
+ return (sensorOrientation + deviceOrientation + 360) % 360;
+ }
+
+ /**
+ * Shows a {@link Toast} on the UI thread.
+ *
+ * @param text The message to show.
+ */
+ private void showToast(String text) {
+ // We show a Toast by sending request message to mMessageHandler. This makes sure that the
+ // Toast is shown on the UI thread.
+ Message message = Message.obtain();
+ message.obj = text;
+ mMessageHandler.sendMessage(message);
+ }
+
+ /**
+ * If the given request has been completed, remove it from the queue of active requests and
+ * send an {@link ImageSaver} with the results from this request to a background thread to
+ * save a file.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ *
+ * @param requestId the ID of the {@link CaptureRequest} to handle.
+ * @param builder the {@link ImageSaver.ImageSaverBuilder} for this request.
+ * @param queue the queue to remove this request from, if completed.
+ */
+ private void handleCompletionLocked(int requestId, ImageSaver.ImageSaverBuilder builder,
+ TreeMap<Integer, ImageSaver.ImageSaverBuilder> queue) {
+ if (builder == null) return;
+ ImageSaver saver = builder.buildIfComplete();
+ if (saver != null) {
+ queue.remove(requestId);
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(saver);
+ }
+ }
+
+ /**
+ * Check if we are using a device that only supports the LEGACY hardware level.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ *
+ * @return true if this is a legacy device.
+ */
+ private boolean isLegacyLocked() {
+ return mCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
+ }
+
+ /**
+ * Start the timer for the pre-capture sequence.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ */
+ private void startTimerLocked() {
+ mCaptureTimer = SystemClock.elapsedRealtime();
+ }
+
+ /**
+ * Check if the timer for the pre-capture sequence has been hit.
+ *
+ * Call this only with {@link #mCameraStateLock} held.
+ *
+ * @return true if the timeout occurred.
+ */
+ private boolean hitTimeoutLocked() {
+ return (SystemClock.elapsedRealtime() - mCaptureTimer) > PRECAPTURE_TIMEOUT_MS;
+ }
+
+ // *********************************************************************************************
+
+}
diff --git a/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/CameraActivity.java b/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/CameraActivity.java
new file mode 100644
index 0000000..e56efab
--- /dev/null
+++ b/samples/browseable/Camera2Raw/src/com.example.android.camera2raw/CameraActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.camera2raw;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Activity displaying a fragment that implements RAW photo captures.
+ */
+public class CameraActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_camera);
+ if (null == savedInstanceState) {
+ getFragmentManager().beginTransaction()
+ .replace(R.id.container, Camera2RawFragment.newInstance())
+ .commit();
+ }
+ }
+
+}
diff --git a/samples/browseable/Camera2Video/_index.jd b/samples/browseable/Camera2Video/_index.jd
index 27ccc11..b15efd3 100644
--- a/samples/browseable/Camera2Video/_index.jd
+++ b/samples/browseable/Camera2Video/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Camera2Video"
sample.group=Media
@jd:body
diff --git a/samples/browseable/Camera2Video/res/values-v21/base-colors.xml b/samples/browseable/Camera2Video/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/Camera2Video/res/values-v21/base-colors.xml
+++ b/samples/browseable/Camera2Video/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/Camera2Video/res/values-v21/base-template-styles.xml b/samples/browseable/Camera2Video/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/Camera2Video/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/Camera2Video/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/Camera2Video/res/values/base-strings.xml b/samples/browseable/Camera2Video/res/values/base-strings.xml
index 08388de..186e60e 100644
--- a/samples/browseable/Camera2Video/res/values/base-strings.xml
+++ b/samples/browseable/Camera2Video/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Camera2Video</string>
<string name="intro_message">
diff --git a/samples/browseable/CardEmulation/_index.jd b/samples/browseable/CardEmulation/_index.jd
index 6a4ce5d..bdeed37 100644
--- a/samples/browseable/CardEmulation/_index.jd
+++ b/samples/browseable/CardEmulation/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="CardEmulation"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/CardEmulation/res/values-v21/base-colors.xml b/samples/browseable/CardEmulation/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/CardEmulation/res/values-v21/base-colors.xml
+++ b/samples/browseable/CardEmulation/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/CardEmulation/res/values-v21/base-template-styles.xml b/samples/browseable/CardEmulation/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/CardEmulation/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/CardEmulation/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/CardEmulation/res/values/base-strings.xml b/samples/browseable/CardEmulation/res/values/base-strings.xml
index 8bd7332..020416a 100644
--- a/samples/browseable/CardEmulation/res/values/base-strings.xml
+++ b/samples/browseable/CardEmulation/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">CardEmulation</string>
<string name="intro_message">
diff --git a/samples/browseable/CardEmulation/src/com.example.android.cardemulation/MainActivity.java b/samples/browseable/CardEmulation/src/com.example.android.cardemulation/MainActivity.java
index af0b9f3..ea641ef 100644
--- a/samples/browseable/CardEmulation/src/com.example.android.cardemulation/MainActivity.java
+++ b/samples/browseable/CardEmulation/src/com.example.android.cardemulation/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.cardemulation;
import android.os.Bundle;
diff --git a/samples/browseable/CardReader/_index.jd b/samples/browseable/CardReader/_index.jd
index 4322b3f..ca18ce0 100644
--- a/samples/browseable/CardReader/_index.jd
+++ b/samples/browseable/CardReader/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="CardReader"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/CardReader/res/values-v21/base-colors.xml b/samples/browseable/CardReader/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/CardReader/res/values-v21/base-colors.xml
+++ b/samples/browseable/CardReader/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/CardReader/res/values-v21/base-template-styles.xml b/samples/browseable/CardReader/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/CardReader/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/CardReader/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/CardReader/res/values/base-strings.xml b/samples/browseable/CardReader/res/values/base-strings.xml
index efede3b..cf12224 100644
--- a/samples/browseable/CardReader/res/values/base-strings.xml
+++ b/samples/browseable/CardReader/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">CardReader</string>
<string name="intro_message">
diff --git a/samples/browseable/CardReader/src/com.example.android.cardreader/MainActivity.java b/samples/browseable/CardReader/src/com.example.android.cardreader/MainActivity.java
index ac6327d..7812329 100644
--- a/samples/browseable/CardReader/src/com.example.android.cardreader/MainActivity.java
+++ b/samples/browseable/CardReader/src/com.example.android.cardreader/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.cardreader;
import android.os.Bundle;
diff --git a/samples/browseable/CardView/_index.jd b/samples/browseable/CardView/_index.jd
index 28cbdc7..3d8c9e0 100644
--- a/samples/browseable/CardView/_index.jd
+++ b/samples/browseable/CardView/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="CardView Sample"
sample.group=UI
@jd:body
diff --git a/samples/browseable/CardView/res/values-v21/base-colors.xml b/samples/browseable/CardView/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/CardView/res/values-v21/base-colors.xml
+++ b/samples/browseable/CardView/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/CardView/res/values-v21/base-template-styles.xml b/samples/browseable/CardView/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/CardView/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/CardView/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/CardView/res/values/base-strings.xml b/samples/browseable/CardView/res/values/base-strings.xml
index d39c396..1286322 100644
--- a/samples/browseable/CardView/res/values/base-strings.xml
+++ b/samples/browseable/CardView/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">CardView Sample</string>
<string name="intro_message">
diff --git a/samples/browseable/ClippingBasic/_index.jd b/samples/browseable/ClippingBasic/_index.jd
index 6db7049..549fa7b 100644
--- a/samples/browseable/ClippingBasic/_index.jd
+++ b/samples/browseable/ClippingBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ClippingBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ClippingBasic/res/values-v21/base-colors.xml b/samples/browseable/ClippingBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ClippingBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/ClippingBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ClippingBasic/res/values-v21/base-template-styles.xml b/samples/browseable/ClippingBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ClippingBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ClippingBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ClippingBasic/res/values/base-strings.xml b/samples/browseable/ClippingBasic/res/values/base-strings.xml
index 622c074..5357999 100644
--- a/samples/browseable/ClippingBasic/res/values/base-strings.xml
+++ b/samples/browseable/ClippingBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ClippingBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/ClippingBasic/src/com.example.android.clippingbasic/MainActivity.java b/samples/browseable/ClippingBasic/src/com.example.android.clippingbasic/MainActivity.java
index fe290f9..91b0eda 100644
--- a/samples/browseable/ClippingBasic/src/com.example.android.clippingbasic/MainActivity.java
+++ b/samples/browseable/ClippingBasic/src/com.example.android.clippingbasic/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.clippingbasic;
import android.os.Bundle;
diff --git a/samples/browseable/ConfirmCredential/AndroidManifest.xml b/samples/browseable/ConfirmCredential/AndroidManifest.xml
new file mode 100644
index 0000000..12f9456
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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.confirmcredential" >
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <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/browseable/ConfirmCredential/_index.jd b/samples/browseable/ConfirmCredential/_index.jd
new file mode 100644
index 0000000..206db44
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/_index.jd
@@ -0,0 +1,11 @@
+
+page.tags="Confirm Credential"
+sample.group=security
+@jd:body
+
+<p>
+
+This sample demonstrates how you can use device credentials (PIN, Pattern, Password) in your app
+to authenticate the user before they are trying to complete some actions.
+
+ </p>
diff --git a/samples/browseable/ConfirmCredential/res/drawable-hdpi/tile.9.png b/samples/browseable/ConfirmCredential/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/ConfirmCredential/res/drawable-nodpi/android_robot.png b/samples/browseable/ConfirmCredential/res/drawable-nodpi/android_robot.png
new file mode 100644
index 0000000..40bf934
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/drawable-nodpi/android_robot.png
Binary files differ
diff --git a/samples/browseable/ConfirmCredential/res/drawable/card.xml b/samples/browseable/ConfirmCredential/res/drawable/card.xml
new file mode 100644
index 0000000..691a4c5
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/drawable/card.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="#fefefe"/>
+
+ <corners
+ android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/samples/browseable/ConfirmCredential/res/layout/activity_main.xml b/samples/browseable/ConfirmCredential/res/layout/activity_main.xml
new file mode 100644
index 0000000..da65a00
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/layout/activity_main.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <ImageView
+ android:layout_width="150dp"
+ android:layout_height="150dp"
+ android:layout_marginTop="32dp"
+ android:layout_marginBottom="32dp"
+ android:layout_gravity="center_horizontal"
+ android:scaleType="fitCenter"
+ android:src="@drawable/android_robot"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:orientation="vertical"
+ android:background="@drawable/card"
+ android:elevation="4dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Headline"
+ android:text="@string/item_title"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:textColor="?android:attr/colorAccent"
+ android:text="@string/item_price"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/item_description"/>
+
+ </LinearLayout>
+ <Button style="@android:style/Widget.Material.Button.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="end"
+ android:textColor="?android:attr/textColorPrimaryInverse"
+ android:text="@string/purchase"
+ android:id="@+id/purchase_button"
+ android:layout_alignParentEnd="true"/>
+
+ <TextView
+ android:id="@+id/confirmation_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:textColor="?android:attr/colorAccent"
+ android:text="@string/purchase_done"
+ android:visibility="gone"/>
+
+ <TextView
+ android:id="@+id/already_has_valid_device_credential_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:textColor="?android:attr/colorAccent"
+ android:text="@string/already_confirmed_device_credentials_within_last_x_seconds"
+ android:visibility="gone"/>
+ </LinearLayout>
+</ScrollView>
diff --git a/samples/browseable/ConfirmCredential/res/mipmap-hdpi/ic_launcher.png b/samples/browseable/ConfirmCredential/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..e9cd9e3
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ConfirmCredential/res/mipmap-mdpi/ic_launcher.png b/samples/browseable/ConfirmCredential/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..b6c3e31
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ConfirmCredential/res/mipmap-xhdpi/ic_launcher.png b/samples/browseable/ConfirmCredential/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..85a14a0
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ConfirmCredential/res/mipmap-xxhdpi/ic_launcher.png b/samples/browseable/ConfirmCredential/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d9d35b0
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ConfirmCredential/res/mipmap-xxxhdpi/ic_launcher.png b/samples/browseable/ConfirmCredential/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..a764233
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/ConfirmCredential/res/values-sw600dp/template-dimens.xml b/samples/browseable/ConfirmCredential/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values-sw600dp/template-styles.xml b/samples/browseable/ConfirmCredential/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values-v11/template-styles.xml b/samples/browseable/ConfirmCredential/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values-v21/base-colors.xml b/samples/browseable/ConfirmCredential/res/values-v21/base-colors.xml
new file mode 100644
index 0000000..8b6ec3f
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values-v21/base-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values-v21/base-template-styles.xml b/samples/browseable/ConfirmCredential/res/values-v21/base-template-styles.xml
new file mode 100644
index 0000000..c778e4f
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values-v21/base-template-styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light">
+ </style>
+
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values/base-strings.xml b/samples/browseable/ConfirmCredential/res/values/base-strings.xml
new file mode 100644
index 0000000..b3dab90
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values/base-strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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">Confirm Credential</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+This sample demonstrates how you can use device credentials (PIN, Pattern, Password) in your app
+to authenticate the user before they are trying to complete some actions.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values/strings.xml b/samples/browseable/ConfirmCredential/res/values/strings.xml
new file mode 100644
index 0000000..b6ff9d3
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="purchase">Purchase</string>
+ <string name="item_title">White Mesh Pluto Backpack</string>
+ <string name="item_price">$62.68</string>
+ <string name="item_description">Mesh backpack in white. Black textile trim throughout.</string>
+ <string name="purchase_done">Device credential confirmed.</string>
+ <string name="already_confirmed_device_credentials_within_last_x_seconds">
+ The device credential has been already confirmed within the last %1$s seconds.</string>
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values/template-dimens.xml b/samples/browseable/ConfirmCredential/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/ConfirmCredential/res/values/template-styles.xml b/samples/browseable/ConfirmCredential/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/ConfirmCredential/src/com.example.android.confirmcredential/MainActivity.java b/samples/browseable/ConfirmCredential/src/com.example.android.confirmcredential/MainActivity.java
new file mode 100644
index 0000000..b8cf6e1
--- /dev/null
+++ b/samples/browseable/ConfirmCredential/src/com.example.android.confirmcredential/MainActivity.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.example.android.confirmcredential;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.UserNotAuthenticatedException;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+
+/**
+ * Main entry point for the sample, showing a backpack and "Purchase" button.
+ */
+public class MainActivity extends Activity {
+
+ /** Alias for our key in the Android Key Store. */
+ private static final String KEY_NAME = "my_key";
+ private static final byte[] SECRET_BYTE_ARRAY = new byte[] {1, 2, 3, 4, 5, 6};
+
+ private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
+
+ /**
+ * If the user has unlocked the device Within the last this number of seconds,
+ * it can be considered as an authenticator.
+ */
+ private static final int AUTHENTICATION_DURATION_SECONDS = 30;
+
+ private KeyguardManager mKeyguardManager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ Button purchaseButton = (Button) findViewById(R.id.purchase_button);
+ if (!mKeyguardManager.isKeyguardSecure()) {
+ // Show a message that the user hasn't set up a lock screen.
+ Toast.makeText(this,
+ "Secure lock screen hasn't set up.\n"
+ + "Go to 'Settings -> Security -> Screenlock' to set up a lock screen",
+ Toast.LENGTH_LONG).show();
+ purchaseButton.setEnabled(false);
+ return;
+ }
+ createKey();
+ findViewById(R.id.purchase_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Test to encrypt something. It might fail if the timeout expired (30s).
+ tryEncrypt();
+ }
+ });
+ }
+
+ /**
+ * Tries to encrypt some data with the generated key in {@link #createKey} which is
+ * only works if the user has just authenticated via device credentials.
+ */
+ private void tryEncrypt() {
+ try {
+ KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_NAME, null);
+ Cipher cipher = Cipher.getInstance(
+ KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/"
+ + KeyProperties.ENCRYPTION_PADDING_PKCS7);
+
+ // Try encrypting something, it will only work if the user authenticated within
+ // the last AUTHENTICATION_DURATION_SECONDS seconds.
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ cipher.doFinal(SECRET_BYTE_ARRAY);
+
+ // If the user has recently authenticated, you will reach here.
+ showAlreadyAuthenticated();
+ } catch (UserNotAuthenticatedException e) {
+ // User is not authenticated, let's authenticate with device credentials.
+ showAuthenticationScreen();
+ } catch (KeyPermanentlyInvalidatedException e) {
+ // This happens if the lock screen has been disabled or reset after the key was
+ // generated after the key was generated.
+ Toast.makeText(this, "Keys are invalidated after created. Retry the purchase\n"
+ + e.getMessage(),
+ Toast.LENGTH_LONG).show();
+ } catch (BadPaddingException | IllegalBlockSizeException | KeyStoreException |
+ CertificateException | UnrecoverableKeyException | IOException
+ | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Creates a symmetric key in the Android Key Store which can only be used after the user has
+ * authenticated with device credentials within the last X seconds.
+ */
+ private void createKey() {
+ // Generate a key to decrypt payment credentials, tokens, etc.
+ // This will most likely be a registration step for the user when they are setting up your app.
+ try {
+ KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(
+ KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
+
+ // Set the alias of the entry in Android KeyStore where the key will appear
+ // and the constrains (purposes) in the constructor of the Builder
+ keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME,
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
+ .setUserAuthenticationRequired(true)
+ // Require that the user has unlocked in the last 30 seconds
+ .setUserAuthenticationValidityDurationSeconds(AUTHENTICATION_DURATION_SECONDS)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+ .build());
+ keyGenerator.generateKey();
+ } catch (NoSuchAlgorithmException | NoSuchProviderException
+ | InvalidAlgorithmParameterException | KeyStoreException
+ | CertificateException | IOException e) {
+ throw new RuntimeException("Failed to create a symmetric key", e);
+ }
+ }
+
+ private void showAuthenticationScreen() {
+ // Create the Confirm Credentials screen. You can customize the title and description. Or
+ // we will provide a generic one for you if you leave it null
+ Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
+ if (intent != null) {
+ startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
+ // Challenge completed, proceed with using cipher
+ if (resultCode == RESULT_OK) {
+ showPurchaseConfirmation();
+ } else {
+ // The user canceled or didn’t complete the lock screen
+ // operation. Go to error/cancellation flow.
+ }
+ }
+ }
+
+ private void showPurchaseConfirmation() {
+ findViewById(R.id.confirmation_message).setVisibility(View.VISIBLE);
+ findViewById(R.id.purchase_button).setEnabled(false);
+ }
+
+ private void showAlreadyAuthenticated() {
+ TextView textView = (TextView) findViewById(
+ R.id.already_has_valid_device_credential_message);
+ textView.setVisibility(View.VISIBLE);
+ textView.setText(getString(
+ R.string.already_confirmed_device_credentials_within_last_x_seconds,
+ AUTHENTICATION_DURATION_SECONDS));
+ findViewById(R.id.purchase_button).setEnabled(false);
+ }
+
+}
diff --git a/samples/browseable/CustomChoiceList/_index.jd b/samples/browseable/CustomChoiceList/_index.jd
index 65ad14f..0abf543 100644
--- a/samples/browseable/CustomChoiceList/_index.jd
+++ b/samples/browseable/CustomChoiceList/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="CustomChoiceList"
sample.group=UI
@jd:body
diff --git a/samples/browseable/CustomChoiceList/res/values-v21/base-colors.xml b/samples/browseable/CustomChoiceList/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/CustomChoiceList/res/values-v21/base-colors.xml
+++ b/samples/browseable/CustomChoiceList/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/CustomChoiceList/res/values-v21/base-template-styles.xml b/samples/browseable/CustomChoiceList/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/CustomChoiceList/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/CustomChoiceList/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/CustomChoiceList/res/values/base-strings.xml b/samples/browseable/CustomChoiceList/res/values/base-strings.xml
index b5fdc00..e14fc26 100644
--- a/samples/browseable/CustomChoiceList/res/values/base-strings.xml
+++ b/samples/browseable/CustomChoiceList/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">CustomChoiceList</string>
<string name="intro_message">
diff --git a/samples/browseable/CustomNotifications/_index.jd b/samples/browseable/CustomNotifications/_index.jd
index 86c829a..148267b 100644
--- a/samples/browseable/CustomNotifications/_index.jd
+++ b/samples/browseable/CustomNotifications/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="CustomNotifications"
sample.group=Notification
@jd:body
diff --git a/samples/browseable/CustomNotifications/res/values-v21/base-colors.xml b/samples/browseable/CustomNotifications/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/CustomNotifications/res/values-v21/base-colors.xml
+++ b/samples/browseable/CustomNotifications/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/CustomNotifications/res/values-v21/base-template-styles.xml b/samples/browseable/CustomNotifications/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/CustomNotifications/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/CustomNotifications/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/CustomNotifications/res/values/base-strings.xml b/samples/browseable/CustomNotifications/res/values/base-strings.xml
index ad3bb89..c78e6e3 100644
--- a/samples/browseable/CustomNotifications/res/values/base-strings.xml
+++ b/samples/browseable/CustomNotifications/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">CustomNotifications</string>
<string name="intro_message">
diff --git a/samples/browseable/CustomTransition/_index.jd b/samples/browseable/CustomTransition/_index.jd
index f5f16fe..2a26e55 100644
--- a/samples/browseable/CustomTransition/_index.jd
+++ b/samples/browseable/CustomTransition/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="CustomTransition"
sample.group=UI
@jd:body
diff --git a/samples/browseable/CustomTransition/res/values-v21/base-colors.xml b/samples/browseable/CustomTransition/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/CustomTransition/res/values-v21/base-colors.xml
+++ b/samples/browseable/CustomTransition/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/CustomTransition/res/values-v21/base-template-styles.xml b/samples/browseable/CustomTransition/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/CustomTransition/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/CustomTransition/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/CustomTransition/res/values/base-strings.xml b/samples/browseable/CustomTransition/res/values/base-strings.xml
index ee1dad4..e396da9 100644
--- a/samples/browseable/CustomTransition/res/values/base-strings.xml
+++ b/samples/browseable/CustomTransition/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">CustomTransition</string>
<string name="intro_message">
diff --git a/samples/browseable/CustomTransition/src/com.example.android.customtransition/MainActivity.java b/samples/browseable/CustomTransition/src/com.example.android.customtransition/MainActivity.java
index bbb6dc0..4df98fc 100644
--- a/samples/browseable/CustomTransition/src/com.example.android.customtransition/MainActivity.java
+++ b/samples/browseable/CustomTransition/src/com.example.android.customtransition/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.customtransition;
import android.os.Bundle;
diff --git a/samples/browseable/DataLayer/Application/res/values-v21/base-colors.xml b/samples/browseable/DataLayer/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DataLayer/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/DataLayer/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DataLayer/Application/res/values-v21/base-template-styles.xml b/samples/browseable/DataLayer/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DataLayer/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DataLayer/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DataLayer/Application/res/values/base-strings.xml b/samples/browseable/DataLayer/Application/res/values/base-strings.xml
index 856ec54..d039ca8 100644
--- a/samples/browseable/DataLayer/Application/res/values/base-strings.xml
+++ b/samples/browseable/DataLayer/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DataLayer</string>
<string name="intro_message">
diff --git a/samples/browseable/DataLayer/_index.jd b/samples/browseable/DataLayer/_index.jd
index 844210f..bc370b9 100644
--- a/samples/browseable/DataLayer/_index.jd
+++ b/samples/browseable/DataLayer/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DataLayer"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-colors.xml b/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-template-styles.xml b/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DelayedConfirmation/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DelayedConfirmation/Application/res/values/base-strings.xml b/samples/browseable/DelayedConfirmation/Application/res/values/base-strings.xml
index b4e1a2e..cd78b39 100644
--- a/samples/browseable/DelayedConfirmation/Application/res/values/base-strings.xml
+++ b/samples/browseable/DelayedConfirmation/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DelayedConfirmation</string>
<string name="intro_message">
diff --git a/samples/browseable/DelayedConfirmation/_index.jd b/samples/browseable/DelayedConfirmation/_index.jd
index 28db25a..603e422 100644
--- a/samples/browseable/DelayedConfirmation/_index.jd
+++ b/samples/browseable/DelayedConfirmation/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DelayedConfirmation"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/DeviceOwner/_index.jd b/samples/browseable/DeviceOwner/_index.jd
index cd9b949..0eb02d8 100644
--- a/samples/browseable/DeviceOwner/_index.jd
+++ b/samples/browseable/DeviceOwner/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DeviceOwner"
sample.group=Admin
@jd:body
diff --git a/samples/browseable/DeviceOwner/res/values-v21/base-colors.xml b/samples/browseable/DeviceOwner/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DeviceOwner/res/values-v21/base-colors.xml
+++ b/samples/browseable/DeviceOwner/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DeviceOwner/res/values-v21/base-template-styles.xml b/samples/browseable/DeviceOwner/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DeviceOwner/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DeviceOwner/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DeviceOwner/res/values/base-strings.xml b/samples/browseable/DeviceOwner/res/values/base-strings.xml
index 71d41f7..89bfe8e 100644
--- a/samples/browseable/DeviceOwner/res/values/base-strings.xml
+++ b/samples/browseable/DeviceOwner/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DeviceOwner</string>
<string name="intro_message">
diff --git a/samples/browseable/DirectorySelection/_index.jd b/samples/browseable/DirectorySelection/_index.jd
index 4b394c2..8a10f9e 100644
--- a/samples/browseable/DirectorySelection/_index.jd
+++ b/samples/browseable/DirectorySelection/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DirectorySelection"
sample.group=Content
@jd:body
diff --git a/samples/browseable/DirectorySelection/res/values-v21/base-colors.xml b/samples/browseable/DirectorySelection/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DirectorySelection/res/values-v21/base-colors.xml
+++ b/samples/browseable/DirectorySelection/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DirectorySelection/res/values-v21/base-template-styles.xml b/samples/browseable/DirectorySelection/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DirectorySelection/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DirectorySelection/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DirectorySelection/res/values/base-strings.xml b/samples/browseable/DirectorySelection/res/values/base-strings.xml
index 782c64a..1ed4f40 100644
--- a/samples/browseable/DirectorySelection/res/values/base-strings.xml
+++ b/samples/browseable/DirectorySelection/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DirectorySelection</string>
<string name="intro_message">
diff --git a/samples/browseable/DisplayingBitmaps/_index.jd b/samples/browseable/DisplayingBitmaps/_index.jd
index e4b4f15..475d632 100644
--- a/samples/browseable/DisplayingBitmaps/_index.jd
+++ b/samples/browseable/DisplayingBitmaps/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DisplayingBitmaps"
sample.group=UI
@jd:body
diff --git a/samples/browseable/DisplayingBitmaps/res/values-v21/base-colors.xml b/samples/browseable/DisplayingBitmaps/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DisplayingBitmaps/res/values-v21/base-colors.xml
+++ b/samples/browseable/DisplayingBitmaps/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DisplayingBitmaps/res/values-v21/base-template-styles.xml b/samples/browseable/DisplayingBitmaps/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DisplayingBitmaps/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DisplayingBitmaps/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DisplayingBitmaps/res/values/base-strings.xml b/samples/browseable/DisplayingBitmaps/res/values/base-strings.xml
index 4401371..8050b15 100644
--- a/samples/browseable/DisplayingBitmaps/res/values/base-strings.xml
+++ b/samples/browseable/DisplayingBitmaps/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DisplayingBitmaps</string>
<string name="intro_message">
diff --git a/samples/browseable/DocumentCentricApps/_index.jd b/samples/browseable/DocumentCentricApps/_index.jd
index 9eb8b2f..8f3e969 100644
--- a/samples/browseable/DocumentCentricApps/_index.jd
+++ b/samples/browseable/DocumentCentricApps/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DocumentCentricRecents"
sample.group=UI
@jd:body
diff --git a/samples/browseable/DocumentCentricApps/res/values-v21/base-colors.xml b/samples/browseable/DocumentCentricApps/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DocumentCentricApps/res/values-v21/base-colors.xml
+++ b/samples/browseable/DocumentCentricApps/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DocumentCentricApps/res/values-v21/base-template-styles.xml b/samples/browseable/DocumentCentricApps/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DocumentCentricApps/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DocumentCentricApps/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DocumentCentricApps/res/values/base-strings.xml b/samples/browseable/DocumentCentricApps/res/values/base-strings.xml
index 0ffbd45..f64e6ef 100644
--- a/samples/browseable/DocumentCentricApps/res/values/base-strings.xml
+++ b/samples/browseable/DocumentCentricApps/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DocumentCentricRecents</string>
<string name="intro_message">
diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/_index.jd b/samples/browseable/DocumentCentricRelinquishIdentity/_index.jd
index 0a489af..5ca5bc8 100644
--- a/samples/browseable/DocumentCentricRelinquishIdentity/_index.jd
+++ b/samples/browseable/DocumentCentricRelinquishIdentity/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DocumentCentricRelinquishIdentity"
sample.group=UI
@jd:body
diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-colors.xml b/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-colors.xml
+++ b/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-template-styles.xml b/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DocumentCentricRelinquishIdentity/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/values/base-strings.xml b/samples/browseable/DocumentCentricRelinquishIdentity/res/values/base-strings.xml
index 6073bba..92850a8 100644
--- a/samples/browseable/DocumentCentricRelinquishIdentity/res/values/base-strings.xml
+++ b/samples/browseable/DocumentCentricRelinquishIdentity/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DocumentCentricRelinquishIdentity</string>
<string name="intro_message">
diff --git a/samples/browseable/DoneBar/_index.jd b/samples/browseable/DoneBar/_index.jd
index b692bb9..8babd0f 100644
--- a/samples/browseable/DoneBar/_index.jd
+++ b/samples/browseable/DoneBar/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DoneBar"
sample.group=UI
@jd:body
diff --git a/samples/browseable/DoneBar/res/values-v21/base-colors.xml b/samples/browseable/DoneBar/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DoneBar/res/values-v21/base-colors.xml
+++ b/samples/browseable/DoneBar/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DoneBar/res/values-v21/base-template-styles.xml b/samples/browseable/DoneBar/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DoneBar/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DoneBar/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DoneBar/res/values/activitycards-strings.xml b/samples/browseable/DoneBar/res/values/activitycards-strings.xml
index 430286c..c0f62c4 100644
--- a/samples/browseable/DoneBar/res/values/activitycards-strings.xml
+++ b/samples/browseable/DoneBar/res/values/activitycards-strings.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
+
<resources>
<string name="donebaractivity_title">Done Bar</string>
<string name="donebaractivity_description">In this presentation, a done bar replaces the action bar entirely, providing
diff --git a/samples/browseable/DoneBar/res/values/base-strings.xml b/samples/browseable/DoneBar/res/values/base-strings.xml
index f7e0540..4b9f137 100644
--- a/samples/browseable/DoneBar/res/values/base-strings.xml
+++ b/samples/browseable/DoneBar/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DoneBar</string>
<string name="intro_message">
diff --git a/samples/browseable/DoneBar/src/com.example.android.donebar/MainActivity.java b/samples/browseable/DoneBar/src/com.example.android.donebar/MainActivity.java
index c51996c..735ac54 100644
--- a/samples/browseable/DoneBar/src/com.example.android.donebar/MainActivity.java
+++ b/samples/browseable/DoneBar/src/com.example.android.donebar/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.donebar;
import android.app.Activity;
diff --git a/samples/browseable/DrawableTinting/_index.jd b/samples/browseable/DrawableTinting/_index.jd
index 1b01114..3536d61 100644
--- a/samples/browseable/DrawableTinting/_index.jd
+++ b/samples/browseable/DrawableTinting/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="DrawableTinting"
sample.group=UI
@jd:body
diff --git a/samples/browseable/DrawableTinting/res/values-v21/base-colors.xml b/samples/browseable/DrawableTinting/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/DrawableTinting/res/values-v21/base-colors.xml
+++ b/samples/browseable/DrawableTinting/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/DrawableTinting/res/values-v21/base-template-styles.xml b/samples/browseable/DrawableTinting/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/DrawableTinting/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/DrawableTinting/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/DrawableTinting/res/values/base-strings.xml b/samples/browseable/DrawableTinting/res/values/base-strings.xml
index 1b3516a..b0db708 100644
--- a/samples/browseable/DrawableTinting/res/values/base-strings.xml
+++ b/samples/browseable/DrawableTinting/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">DrawableTinting</string>
<string name="intro_message">
diff --git a/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/MainActivity.java b/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/MainActivity.java
index d00bc37..deff331 100644
--- a/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/MainActivity.java
+++ b/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.drawabletinting;
import android.os.Bundle;
diff --git a/samples/browseable/ElevationBasic/_index.jd b/samples/browseable/ElevationBasic/_index.jd
index cf473d4..979dc7f 100644
--- a/samples/browseable/ElevationBasic/_index.jd
+++ b/samples/browseable/ElevationBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ElevationBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ElevationBasic/res/values-v21/base-colors.xml b/samples/browseable/ElevationBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ElevationBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/ElevationBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ElevationBasic/res/values-v21/base-template-styles.xml b/samples/browseable/ElevationBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ElevationBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ElevationBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ElevationBasic/res/values/base-strings.xml b/samples/browseable/ElevationBasic/res/values/base-strings.xml
index 9ae4843..a690552 100644
--- a/samples/browseable/ElevationBasic/res/values/base-strings.xml
+++ b/samples/browseable/ElevationBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ElevationBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/MainActivity.java b/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/MainActivity.java
index f4285d2..a7926f9 100644
--- a/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/MainActivity.java
+++ b/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.elevationbasic;
import android.os.Bundle;
diff --git a/samples/browseable/ElevationDrag/_index.jd b/samples/browseable/ElevationDrag/_index.jd
index f484613..ffa96b7 100644
--- a/samples/browseable/ElevationDrag/_index.jd
+++ b/samples/browseable/ElevationDrag/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ElevationDrag"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ElevationDrag/res/values-v21/base-colors.xml b/samples/browseable/ElevationDrag/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ElevationDrag/res/values-v21/base-colors.xml
+++ b/samples/browseable/ElevationDrag/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ElevationDrag/res/values-v21/base-template-styles.xml b/samples/browseable/ElevationDrag/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ElevationDrag/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ElevationDrag/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ElevationDrag/res/values/base-strings.xml b/samples/browseable/ElevationDrag/res/values/base-strings.xml
index 133e1b3..29a37ae 100644
--- a/samples/browseable/ElevationDrag/res/values/base-strings.xml
+++ b/samples/browseable/ElevationDrag/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ElevationDrag</string>
<string name="intro_message">
diff --git a/samples/browseable/ElevationDrag/src/com.example.android.elevationdrag/MainActivity.java b/samples/browseable/ElevationDrag/src/com.example.android.elevationdrag/MainActivity.java
index 98579bf..ace45bf 100644
--- a/samples/browseable/ElevationDrag/src/com.example.android.elevationdrag/MainActivity.java
+++ b/samples/browseable/ElevationDrag/src/com.example.android.elevationdrag/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.elevationdrag;
import android.os.Bundle;
diff --git a/samples/browseable/ElizaChat/_index.jd b/samples/browseable/ElizaChat/_index.jd
index a88371c..14a7cac 100644
--- a/samples/browseable/ElizaChat/_index.jd
+++ b/samples/browseable/ElizaChat/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ElizaChat"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/ElizaChat/res/values-v21/base-colors.xml b/samples/browseable/ElizaChat/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ElizaChat/res/values-v21/base-colors.xml
+++ b/samples/browseable/ElizaChat/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ElizaChat/res/values-v21/base-template-styles.xml b/samples/browseable/ElizaChat/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ElizaChat/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ElizaChat/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ElizaChat/res/values/base-strings.xml b/samples/browseable/ElizaChat/res/values/base-strings.xml
index be29a5b..66da202 100644
--- a/samples/browseable/ElizaChat/res/values/base-strings.xml
+++ b/samples/browseable/ElizaChat/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ElizaChat</string>
<string name="intro_message">
diff --git a/samples/browseable/FindMyPhone/Application/res/values-v21/base-colors.xml b/samples/browseable/FindMyPhone/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/FindMyPhone/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/FindMyPhone/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/FindMyPhone/Application/res/values-v21/base-template-styles.xml b/samples/browseable/FindMyPhone/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/FindMyPhone/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/FindMyPhone/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/FindMyPhone/Application/res/values/base-strings.xml b/samples/browseable/FindMyPhone/Application/res/values/base-strings.xml
index e2e3722..e63b72e 100644
--- a/samples/browseable/FindMyPhone/Application/res/values/base-strings.xml
+++ b/samples/browseable/FindMyPhone/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">FindMyPhone</string>
<string name="intro_message">
diff --git a/samples/browseable/FindMyPhone/_index.jd b/samples/browseable/FindMyPhone/_index.jd
index ed504c9..293a55c 100644
--- a/samples/browseable/FindMyPhone/_index.jd
+++ b/samples/browseable/FindMyPhone/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="FindMyPhone"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/FingerprintDialog/AndroidManifest.xml b/samples/browseable/FingerprintDialog/AndroidManifest.xml
new file mode 100644
index 0000000..5f754ad
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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.fingerprintdialog"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-permission android:name="android.permission.USE_FINGERPRINT"/>
+
+ <application
+ android:name=".InjectedApplication"
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@mipmap/ic_launcher"
+ android:theme="@style/AppTheme">
+
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name">
+ <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/browseable/FingerprintDialog/_index.jd b/samples/browseable/FingerprintDialog/_index.jd
new file mode 100644
index 0000000..2044400
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/_index.jd
@@ -0,0 +1,11 @@
+
+page.tags="Fingerprint Dialog Sample"
+sample.group=security
+@jd:body
+
+<p>
+
+This sample demonstrates how you can use registered fingerprints to authenticate the user
+before proceeding some actions such as purchasing an item.
+
+ </p>
diff --git a/samples/browseable/FingerprintDialog/res/drawable-hdpi/ic_fp_40px.png b/samples/browseable/FingerprintDialog/res/drawable-hdpi/ic_fp_40px.png
new file mode 100644
index 0000000..48ebd8a
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable-hdpi/ic_fp_40px.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/drawable-hdpi/tile.9.png b/samples/browseable/FingerprintDialog/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/drawable-mdpi/ic_fp_40px.png b/samples/browseable/FingerprintDialog/res/drawable-mdpi/ic_fp_40px.png
new file mode 100644
index 0000000..122f442
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable-mdpi/ic_fp_40px.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/drawable-nodpi/android_robot.png b/samples/browseable/FingerprintDialog/res/drawable-nodpi/android_robot.png
new file mode 100644
index 0000000..40bf934
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable-nodpi/android_robot.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/drawable-xhdpi/ic_fp_40px.png b/samples/browseable/FingerprintDialog/res/drawable-xhdpi/ic_fp_40px.png
new file mode 100644
index 0000000..e1c9590
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable-xhdpi/ic_fp_40px.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/drawable-xxhdpi/ic_fp_40px.png b/samples/browseable/FingerprintDialog/res/drawable-xxhdpi/ic_fp_40px.png
new file mode 100644
index 0000000..f7e8724
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable-xxhdpi/ic_fp_40px.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/drawable-xxxhdpi/ic_fp_40px.png b/samples/browseable/FingerprintDialog/res/drawable-xxxhdpi/ic_fp_40px.png
new file mode 100644
index 0000000..0fb8545
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable-xxxhdpi/ic_fp_40px.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/drawable/card.xml b/samples/browseable/FingerprintDialog/res/drawable/card.xml
new file mode 100644
index 0000000..691a4c5
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable/card.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="#fefefe"/>
+
+ <corners
+ android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/samples/browseable/FingerprintDialog/res/drawable/ic_fingerprint_error.xml b/samples/browseable/FingerprintDialog/res/drawable/ic_fingerprint_error.xml
new file mode 100644
index 0000000..be46116
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable/ic_fingerprint_error.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="40.0dp"
+ android:height="40.0dp"
+ android:viewportWidth="40.0"
+ android:viewportHeight="40.0">
+ <path
+ android:pathData="M20.0,0.0C8.96,0.0 0.0,8.95 0.0,20.0s8.96,20.0 20.0,20.0c11.04,0.0 20.0,-8.95 20.0,-20.0S31.04,0.0 20.0,0.0z"
+ android:fillColor="#F4511E"/>
+ <path
+ android:pathData="M21.33,29.33l-2.67,0.0l0.0,-2.67l2.67,0.0L21.33,29.33zM21.33,22.67l-2.67,0.0l0.0,-12.0l2.67,0.0L21.33,22.67z"
+ android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/samples/browseable/FingerprintDialog/res/drawable/ic_fingerprint_success.xml b/samples/browseable/FingerprintDialog/res/drawable/ic_fingerprint_success.xml
new file mode 100644
index 0000000..261f3e7
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/drawable/ic_fingerprint_success.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="40.0dp"
+ android:height="40.0dp"
+ android:viewportWidth="40.0"
+ android:viewportHeight="40.0">
+ <path
+ android:pathData="M20.0,20.0m-20.0,0.0a20.0,20.0 0.0,1.0 1.0,40.0 0.0a20.0,20.0 0.0,1.0 1.0,-40.0 0.0"
+ android:fillColor="#009688"/>
+ <path
+ android:pathData="M11.2,21.41l1.63,-1.619999 4.17,4.169998 10.59,-10.589999 1.619999,1.63 -12.209999,12.209999z"
+ android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/samples/browseable/FingerprintDialog/res/layout/activity_main.xml b/samples/browseable/FingerprintDialog/res/layout/activity_main.xml
new file mode 100644
index 0000000..8f30557
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/layout/activity_main.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <ImageView
+ android:layout_width="150dp"
+ android:layout_height="150dp"
+ android:layout_marginTop="32dp"
+ android:layout_marginBottom="32dp"
+ android:layout_gravity="center_horizontal"
+ android:scaleType="fitCenter"
+ android:src="@drawable/android_robot"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:orientation="vertical"
+ android:background="@drawable/card"
+ android:elevation="4dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Headline"
+ android:text="@string/item_title"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:textColor="?android:attr/colorAccent"
+ android:text="@string/item_price"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/item_description"/>
+
+ </LinearLayout>
+ <Button style="@android:style/Widget.Material.Button.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="end"
+ android:textColor="?android:attr/textColorPrimaryInverse"
+ android:text="@string/purchase"
+ android:id="@+id/purchase_button"
+ android:layout_alignParentEnd="true"/>
+
+ <TextView
+ android:id="@+id/confirmation_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:textColor="?android:attr/colorAccent"
+ android:text="@string/purchase_done"
+ android:visibility="gone"/>
+
+ <TextView
+ android:id="@+id/encrypted_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Body2"
+ android:textColor="?android:attr/colorAccent"
+ android:text="@string/purchase_done"
+ android:visibility="gone"/>
+ </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_backup.xml b/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_backup.xml
new file mode 100644
index 0000000..0b88e33
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_backup.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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:id="@+id/backup_container"
+ android:layout_width="match_parent" android:layout_height="match_parent"
+ android:paddingTop="16dp"
+ android:paddingBottom="8dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:text="@string/password_description"
+ android:id="@+id/description"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginStart="24dp"
+ android:layout_marginEnd="24dp"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="textPassword"
+ android:ems="10"
+ android:hint="@string/password"
+ android:imeOptions="actionGo"
+ android:id="@+id/password"
+ android:layout_below="@+id/description"
+ android:layout_marginTop="16dp"
+ android:layout_marginStart="20dp"
+ android:layout_marginEnd="20dp"
+ android:layout_alignParentStart="true" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_container.xml b/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_container.xml
new file mode 100644
index 0000000..08bb1bb
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_container.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <include layout="@layout/fingerprint_dialog_content" />
+
+ <include
+ layout="@layout/fingerprint_dialog_backup"
+ android:visibility="gone" />
+
+ </FrameLayout>
+
+ <LinearLayout
+ android:id="@+id/buttonPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp"
+ android:gravity="bottom"
+ style="?android:attr/buttonBarStyle">
+
+ <Space
+ android:id="@+id/spacer"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+ <Button
+ android:id="@+id/cancel_button"
+ style="?android:attr/buttonBarNegativeButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <Button
+ android:id="@+id/second_dialog_button"
+ style="?android:attr/buttonBarPositiveButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_content.xml b/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_content.xml
new file mode 100644
index 0000000..b56ccbb
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/layout/fingerprint_dialog_content.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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:id="@+id/fingerprint_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="8dp"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp"
+ android:paddingTop="16dp">
+
+ <TextView
+ android:id="@+id/fingerprint_description"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:text="@string/fingerprint_description"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+
+ <ImageView
+ android:id="@+id/fingerprint_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_below="@+id/fingerprint_description"
+ android:layout_marginTop="20dp"
+ android:src="@drawable/ic_fp_40px" />
+
+ <TextView
+ android:id="@+id/fingerprint_status"
+ style="@android:style/TextAppearance.Material.Body1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/fingerprint_icon"
+ android:layout_alignTop="@+id/fingerprint_icon"
+ android:layout_marginLeft="16dp"
+ android:layout_toEndOf="@+id/fingerprint_icon"
+ android:gravity="center_vertical"
+ android:text="@string/fingerprint_hint"
+ android:textColor="@color/hint_color" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/samples/browseable/FingerprintDialog/res/mipmap-hdpi/ic_launcher.png b/samples/browseable/FingerprintDialog/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..68c473a
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/mipmap-mdpi/ic_launcher.png b/samples/browseable/FingerprintDialog/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..fd7e5f6
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/mipmap-xhdpi/ic_launcher.png b/samples/browseable/FingerprintDialog/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..106c0d3
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/mipmap-xxhdpi/ic_launcher.png b/samples/browseable/FingerprintDialog/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b319beb
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/mipmap-xxxhdpi/ic_launcher.png b/samples/browseable/FingerprintDialog/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4dc0ddf
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/FingerprintDialog/res/values-sw600dp/template-dimens.xml b/samples/browseable/FingerprintDialog/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values-sw600dp/template-styles.xml b/samples/browseable/FingerprintDialog/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values-v11/template-styles.xml b/samples/browseable/FingerprintDialog/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values-v21/base-colors.xml b/samples/browseable/FingerprintDialog/res/values-v21/base-colors.xml
new file mode 100644
index 0000000..8b6ec3f
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values-v21/base-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values-v21/base-template-styles.xml b/samples/browseable/FingerprintDialog/res/values-v21/base-template-styles.xml
new file mode 100644
index 0000000..c778e4f
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values-v21/base-template-styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light">
+ </style>
+
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values/base-strings.xml b/samples/browseable/FingerprintDialog/res/values/base-strings.xml
new file mode 100644
index 0000000..f3545f5
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values/base-strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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">Fingerprint Dialog Sample</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+This sample demonstrates how you can use registered fingerprints to authenticate the user
+before proceeding some actions such as purchasing an item.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values/colors.xml b/samples/browseable/FingerprintDialog/res/values/colors.xml
new file mode 100644
index 0000000..a24f3c8
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values/colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="warning_color">#f4511e</color>
+ <color name="hint_color">#42000000</color>
+ <color name="success_color">#009688</color>
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values/strings.xml b/samples/browseable/FingerprintDialog/res/values/strings.xml
new file mode 100644
index 0000000..8a6ecde
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="action_settings">Settings</string>
+ <string name="cancel">Cancel</string>
+ <string name="use_password">Use password</string>
+ <string name="sign_in">Sign in</string>
+ <string name="ok">Ok</string>
+ <string name="password">Password</string>
+ <string name="fingerprint_description">Confirm fingerprint to continue</string>
+ <string name="fingerprint_hint">Touch sensor</string>
+ <string name="password_description">Enter your store password to continue</string>
+ <string name="purchase">Purchase</string>
+ <string name="fingerprint_not_recognized">Fingerprint not recognized. Try again</string>
+ <string name="fingerprint_success">Fingerprint recognized</string>
+ <string name="item_title">White Mesh Pluto Backpack</string>
+ <string name="item_price">$62.68</string>
+ <string name="item_description">Mesh backpack in white. Black textile trim throughout.</string>
+ <string name="purchase_done">Purchase successful</string>
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values/template-dimens.xml b/samples/browseable/FingerprintDialog/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/FingerprintDialog/res/values/template-styles.xml b/samples/browseable/FingerprintDialog/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintAuthenticationDialogFragment.java b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintAuthenticationDialogFragment.java
new file mode 100644
index 0000000..57c00de
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintAuthenticationDialogFragment.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.example.android.fingerprintdialog;
+
+import android.app.DialogFragment;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import javax.inject.Inject;
+
+/**
+ * A dialog which uses fingerprint APIs to authenticate the user, and falls back to password
+ * authentication if fingerprint is not available.
+ */
+public class FingerprintAuthenticationDialogFragment extends DialogFragment
+ implements TextView.OnEditorActionListener, FingerprintUiHelper.Callback {
+
+ private Button mCancelButton;
+ private Button mSecondDialogButton;
+ private View mFingerprintContent;
+ private View mBackupContent;
+ private EditText mPassword;
+
+ private Stage mStage = Stage.FINGERPRINT;
+
+ private FingerprintManager.CryptoObject mCryptoObject;
+ private FingerprintUiHelper mFingerprintUiHelper;
+
+ @Inject FingerprintUiHelper.FingerprintUiHelperBuilder mFingerprintUiHelperBuilder;
+ @Inject InputMethodManager mInputMethodManager;
+
+ @Inject
+ public FingerprintAuthenticationDialogFragment() {}
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Do not create a new Fragment when the Activity is re-created such as orientation changes.
+ setRetainInstance(true);
+ setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ getDialog().setTitle(getString(R.string.sign_in));
+ View v = inflater.inflate(R.layout.fingerprint_dialog_container, container, false);
+ mCancelButton = (Button) v.findViewById(R.id.cancel_button);
+ mCancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ dismiss();
+ }
+ });
+
+ mSecondDialogButton = (Button) v.findViewById(R.id.second_dialog_button);
+ mSecondDialogButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mStage == Stage.FINGERPRINT) {
+ goToBackup();
+ } else {
+ verifyPassword();
+ }
+ }
+ });
+ mFingerprintContent = v.findViewById(R.id.fingerprint_container);
+ mBackupContent = v.findViewById(R.id.backup_container);
+ mPassword = (EditText) v.findViewById(R.id.password);
+ mPassword.setOnEditorActionListener(this);
+ mFingerprintUiHelper = mFingerprintUiHelperBuilder.build(
+ (ImageView) v.findViewById(R.id.fingerprint_icon),
+ (TextView) v.findViewById(R.id.fingerprint_status), this);
+ updateStage();
+
+ // If fingerprint authentication is not available, switch immediately to the backup
+ // (password) screen.
+ if (!mFingerprintUiHelper.isFingerprintAuthAvailable()) {
+ goToBackup();
+ }
+ return v;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mStage == Stage.FINGERPRINT) {
+ mFingerprintUiHelper.startListening(mCryptoObject);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mFingerprintUiHelper.stopListening();
+ }
+
+ /**
+ * Sets the crypto object to be passed in when authenticating with fingerprint.
+ */
+ public void setCryptoObject(FingerprintManager.CryptoObject cryptoObject) {
+ mCryptoObject = cryptoObject;
+ }
+
+ /**
+ * Switches to backup (password) screen. This either can happen when fingerprint is not
+ * available or the user chooses to use the password authentication method by pressing the
+ * button. This can also happen when the user had too many fingerprint attempts.
+ */
+ private void goToBackup() {
+ mStage = Stage.PASSWORD;
+ updateStage();
+ mPassword.requestFocus();
+
+ // Show the keyboard.
+ mPassword.postDelayed(mShowKeyboardRunnable, 500);
+
+ // Fingerprint is not used anymore. Stop listening for it.
+ mFingerprintUiHelper.stopListening();
+ }
+
+ /**
+ * Checks whether the current entered password is correct, and dismisses the the dialog and
+ * let's the activity know about the result.
+ */
+ private void verifyPassword() {
+ if (checkPassword(mPassword.getText().toString())) {
+ ((MainActivity) getActivity()).onPurchased(false /* without Fingerprint */);
+ dismiss();
+ } else {
+ // assume the password is always correct.
+ }
+ }
+
+ /**
+ * @return true if {@code password} is correct, false otherwise
+ */
+ private boolean checkPassword(String password) {
+ // Assume the password is always correct.
+ // In the real world situation, the password needs to be verified in the server side.
+ return password.length() > 0;
+ }
+
+ private final Runnable mShowKeyboardRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mInputMethodManager.showSoftInput(mPassword, 0);
+ }
+ };
+
+ private void updateStage() {
+ switch (mStage) {
+ case FINGERPRINT:
+ mCancelButton.setText(R.string.cancel);
+ mSecondDialogButton.setText(R.string.use_password);
+ mFingerprintContent.setVisibility(View.VISIBLE);
+ mBackupContent.setVisibility(View.GONE);
+ break;
+ case PASSWORD:
+ mCancelButton.setText(R.string.cancel);
+ mSecondDialogButton.setText(R.string.ok);
+ mFingerprintContent.setVisibility(View.GONE);
+ mBackupContent.setVisibility(View.VISIBLE);
+ break;
+ }
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_GO) {
+ verifyPassword();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onAuthenticated() {
+ // Callback from FingerprintUiHelper. Let the activity know that authentication was
+ // successful.
+ ((MainActivity) getActivity()).onPurchased(true /* withFingerprint */);
+ dismiss();
+ }
+
+ @Override
+ public void onError() {
+ goToBackup();
+ }
+
+ /**
+ * Enumeration to indicate which authentication method the user is trying to authenticate with.
+ */
+ private enum Stage {
+ FINGERPRINT,
+ PASSWORD
+ }
+}
diff --git a/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintModule.java b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintModule.java
new file mode 100644
index 0000000..16d5067
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintModule.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.example.android.fingerprintdialog;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+import android.view.inputmethod.InputMethodManager;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger module for Fingerprint APIs.
+ */
+@Module(
+ library = true,
+ injects = {MainActivity.class}
+)
+public class FingerprintModule {
+
+ private final Context mContext;
+
+ public FingerprintModule(Context context) {
+ mContext = context;
+ }
+
+ @Provides
+ public Context providesContext() {
+ return mContext;
+ }
+
+ @Provides
+ public FingerprintManager providesFingerprintManager(Context context) {
+ return context.getSystemService(FingerprintManager.class);
+ }
+
+ @Provides
+ public KeyguardManager providesKeyguardManager(Context context) {
+ return context.getSystemService(KeyguardManager.class);
+ }
+
+ @Provides
+ public KeyStore providesKeystore() {
+ try {
+ return KeyStore.getInstance("AndroidKeyStore");
+ } catch (KeyStoreException e) {
+ throw new RuntimeException("Failed to get an instance of KeyStore", e);
+ }
+ }
+
+ @Provides
+ public KeyGenerator providesKeyGenerator() {
+ try {
+ return KeyGenerator.getInstance("AES", "AndroidKeyStore");
+ } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+ throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
+ }
+ }
+
+ @Provides
+ public Cipher providesCipher(KeyStore keyStore) {
+ try {
+ return Cipher.getInstance("AES/CBC/PKCS7Padding");
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new RuntimeException("Failed to get an instance of Cipher", e);
+ }
+ }
+
+ @Provides
+ public InputMethodManager providesInputMethodManager(Context context) {
+ return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ }
+}
diff --git a/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintUiHelper.java b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintUiHelper.java
new file mode 100644
index 0000000..ab7570c
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/FingerprintUiHelper.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.example.android.fingerprintdialog;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.CancellationSignal;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import javax.inject.Inject;
+
+/**
+ * Small helper class to manage text/icon around fingerprint authentication UI.
+ */
+public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
+
+ @VisibleForTesting static final long ERROR_TIMEOUT_MILLIS = 1600;
+ @VisibleForTesting static final long SUCCESS_DELAY_MILLIS = 1300;
+
+ private final FingerprintManager mFingerprintManager;
+ private final ImageView mIcon;
+ private final TextView mErrorTextView;
+ private final Callback mCallback;
+ private CancellationSignal mCancellationSignal;
+
+ @VisibleForTesting boolean mSelfCancelled;
+
+ /**
+ * Builder class for {@link FingerprintUiHelper} in which injected fields from Dagger
+ * holds its fields and takes other arguments in the {@link #build} method.
+ */
+ public static class FingerprintUiHelperBuilder {
+ private final FingerprintManager mFingerPrintManager;
+
+ @Inject
+ public FingerprintUiHelperBuilder(FingerprintManager fingerprintManager) {
+ mFingerPrintManager = fingerprintManager;
+ }
+
+ public FingerprintUiHelper build(ImageView icon, TextView errorTextView, Callback callback) {
+ return new FingerprintUiHelper(mFingerPrintManager, icon, errorTextView,
+ callback);
+ }
+ }
+
+ /**
+ * Constructor for {@link FingerprintUiHelper}. This method is expected to be called from
+ * only the {@link FingerprintUiHelperBuilder} class.
+ */
+ private FingerprintUiHelper(FingerprintManager fingerprintManager,
+ ImageView icon, TextView errorTextView, Callback callback) {
+ mFingerprintManager = fingerprintManager;
+ mIcon = icon;
+ mErrorTextView = errorTextView;
+ mCallback = callback;
+ }
+
+ public boolean isFingerprintAuthAvailable() {
+ return mFingerprintManager.isHardwareDetected()
+ && mFingerprintManager.hasEnrolledFingerprints();
+ }
+
+ public void startListening(FingerprintManager.CryptoObject cryptoObject) {
+ if (!isFingerprintAuthAvailable()) {
+ return;
+ }
+ mCancellationSignal = new CancellationSignal();
+ mSelfCancelled = false;
+ mFingerprintManager.authenticate(cryptoObject, mCancellationSignal, this, 0 /* flags */);
+ mIcon.setImageResource(R.drawable.ic_fp_40px);
+ }
+
+ public void stopListening() {
+ if (mCancellationSignal != null) {
+ mSelfCancelled = true;
+ mCancellationSignal.cancel();
+ mCancellationSignal = null;
+ }
+ }
+
+ @Override
+ public void onAuthenticationError(int errMsgId, CharSequence errString) {
+ if (!mSelfCancelled) {
+ showError(errString);
+ mIcon.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onError();
+ }
+ }, ERROR_TIMEOUT_MILLIS);
+ }
+ }
+
+ @Override
+ public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+ showError(helpString);
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+ showError(mIcon.getResources().getString(
+ R.string.fingerprint_not_recognized));
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
+ mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
+ mIcon.setImageResource(R.drawable.ic_fingerprint_success);
+ mErrorTextView.setTextColor(
+ mErrorTextView.getResources().getColor(R.color.success_color, null));
+ mErrorTextView.setText(
+ mErrorTextView.getResources().getString(R.string.fingerprint_success));
+ mIcon.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onAuthenticated();
+ }
+ }, SUCCESS_DELAY_MILLIS);
+ }
+
+ private void showError(CharSequence error) {
+ mIcon.setImageResource(R.drawable.ic_fingerprint_error);
+ mErrorTextView.setText(error);
+ mErrorTextView.setTextColor(
+ mErrorTextView.getResources().getColor(R.color.warning_color, null));
+ mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
+ mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
+ }
+
+ @VisibleForTesting
+ Runnable mResetErrorTextRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mErrorTextView.setTextColor(
+ mErrorTextView.getResources().getColor(R.color.hint_color, null));
+ mErrorTextView.setText(
+ mErrorTextView.getResources().getString(R.string.fingerprint_hint));
+ mIcon.setImageResource(R.drawable.ic_fp_40px);
+ }
+ };
+
+ public interface Callback {
+
+ void onAuthenticated();
+
+ void onError();
+ }
+}
diff --git a/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/InjectedApplication.java b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/InjectedApplication.java
new file mode 100644
index 0000000..b7075a9
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/InjectedApplication.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.example.android.fingerprintdialog;
+
+import android.app.Application;
+import android.util.Log;
+
+import dagger.ObjectGraph;
+
+/**
+ * The Application class of the sample which holds the ObjectGraph in Dagger and enables
+ * dependency injection.
+ */
+public class InjectedApplication extends Application {
+
+ private static final String TAG = InjectedApplication.class.getSimpleName();
+
+ private ObjectGraph mObjectGraph;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ initObjectGraph(new FingerprintModule(this));
+ }
+
+ /**
+ * Initialize the Dagger module. Passing null or mock modules can be used for testing.
+ *
+ * @param module for Dagger
+ */
+ public void initObjectGraph(Object module) {
+ mObjectGraph = module != null ? ObjectGraph.create(module) : null;
+ }
+
+ public void inject(Object object) {
+ if (mObjectGraph == null) {
+ // This usually happens during tests.
+ Log.i(TAG, "Object graph is not initialized.");
+ return;
+ }
+ mObjectGraph.inject(object);
+ }
+
+}
diff --git a/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/MainActivity.java b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/MainActivity.java
new file mode 100644
index 0000000..9d09765
--- /dev/null
+++ b/samples/browseable/FingerprintDialog/src/com.example.android.fingerprintdialog/MainActivity.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.example.android.fingerprintdialog;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore.KeyProperties;
+import android.util.Base64;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.inject.Inject;
+
+/**
+ * Main entry point for the sample, showing a backpack and "Purchase" button.
+ */
+public class MainActivity extends Activity {
+
+ private static final String TAG = MainActivity.class.getSimpleName();
+
+ private static final String DIALOG_FRAGMENT_TAG = "myFragment";
+ private static final String SECRET_MESSAGE = "Very secret message";
+ /** Alias for our key in the Android Key Store */
+ private static final String KEY_NAME = "my_key";
+
+ @Inject KeyguardManager mKeyguardManager;
+ @Inject FingerprintAuthenticationDialogFragment mFragment;
+ @Inject KeyStore mKeyStore;
+ @Inject KeyGenerator mKeyGenerator;
+ @Inject Cipher mCipher;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ((InjectedApplication) getApplication()).inject(this);
+
+ requestPermissions(new String[]{Manifest.permission.USE_FINGERPRINT}, 0);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] state) {
+ if (requestCode == 0 && state[0] == PackageManager.PERMISSION_GRANTED) {
+ setContentView(R.layout.activity_main);
+ Button purchaseButton = (Button) findViewById(R.id.purchase_button);
+ if (!mKeyguardManager.isKeyguardSecure()) {
+ // Show a message that the user hasn't set up a fingerprint or lock screen.
+ Toast.makeText(this,
+ "Secure lock screen hasn't set up.\n"
+ + "Go to 'Settings -> Security -> Fingerprint' to set up a fingerprint",
+ Toast.LENGTH_LONG).show();
+ purchaseButton.setEnabled(false);
+ return;
+ }
+ createKey();
+ purchaseButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ // Show the fingerprint dialog. The user has the option to use the fingerprint with
+ // crypto, or you can fall back to using a server-side verified password.
+ mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
+ mFragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
+ }
+ });
+
+ // Set up the crypto object for later. The object will be authenticated by use
+ // of the fingerprint.
+ initCipher();
+ }
+ }
+
+ private void initCipher() {
+ try {
+ mKeyStore.load(null);
+ SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null);
+ mCipher.init(Cipher.ENCRYPT_MODE, key);
+ } catch (KeyPermanentlyInvalidatedException e) {
+ // This happens if the lock screen has been disabled or reset after the key was
+ // generated, or if a fingerprint got enrolled after the key was generated.
+ Toast.makeText(this, "Keys are invalidated after created. Retry the purchase\n"
+ + e.getMessage(),
+ Toast.LENGTH_LONG).show();
+ } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
+ | NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new RuntimeException("Failed to init Cipher", e);
+ }
+ }
+
+ public void onPurchased(boolean withFingerprint) {
+ findViewById(R.id.purchase_button).setVisibility(View.GONE);
+ if (withFingerprint) {
+ // If the user has authenticated with fingerprint, verify that using cryptography and
+ // then show the confirmation message.
+ tryEncrypt();
+ } else {
+ // Authentication happened with backup password. Just show the confirmation message.
+ showConfirmation(null);
+ }
+ }
+
+ // Show confirmation, if fingerprint was used show crypto information.
+ private void showConfirmation(byte[] encrypted) {
+ findViewById(R.id.confirmation_message).setVisibility(View.VISIBLE);
+ if (encrypted != null) {
+ TextView v = (TextView) findViewById(R.id.encrypted_message);
+ v.setVisibility(View.VISIBLE);
+ v.setText(Base64.encodeToString(encrypted, 0 /* flags */));
+ }
+ }
+
+ /**
+ * Tries to encrypt some data with the generated key in {@link #createKey} which is
+ * only works if the user has just authenticated via fingerprint.
+ */
+ private void tryEncrypt() {
+ try {
+ byte[] encrypted = mCipher.doFinal(SECRET_MESSAGE.getBytes());
+ showConfirmation(encrypted);
+ } catch (BadPaddingException | IllegalBlockSizeException e) {
+ Toast.makeText(this, "Failed to encrypt the data with the generated key. "
+ + "Retry the purchase", Toast.LENGTH_LONG).show();
+ Log.e(TAG, "Failed to encrypt the data with the generated key." + e.getMessage());
+ }
+ }
+
+ /**
+ * Creates a symmetric key in the Android Key Store which can only be used after the user has
+ * authenticated with fingerprint.
+ */
+ private void createKey() {
+ // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
+ // for your flow. Use of keys is necessary if you need to know if the set of
+ // enrolled fingerprints has changed.
+ try {
+ mKeyStore.load(null);
+ // Set the alias of the entry in Android KeyStore where the key will appear
+ // and the constrains (purposes) in the constructor of the Builder
+ mKeyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME,
+ KeyProperties.PURPOSE_ENCRYPT |
+ KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
+ // Require the user to authenticate with a fingerprint to authorize every use
+ // of the key
+ .setUserAuthenticationRequired(true)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+ .build());
+ mKeyGenerator.generateKey();
+ } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
+ | CertificateException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/samples/browseable/Flashlight/_index.jd b/samples/browseable/Flashlight/_index.jd
index d691b73..1858b3e 100644
--- a/samples/browseable/Flashlight/_index.jd
+++ b/samples/browseable/Flashlight/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Flashlight"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/FloatingActionButtonBasic/_index.jd b/samples/browseable/FloatingActionButtonBasic/_index.jd
index 48a11c2..edb323a 100644
--- a/samples/browseable/FloatingActionButtonBasic/_index.jd
+++ b/samples/browseable/FloatingActionButtonBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="FloatingActionButtonBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-colors.xml b/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-template-styles.xml b/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/FloatingActionButtonBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/FloatingActionButtonBasic/res/values/base-strings.xml b/samples/browseable/FloatingActionButtonBasic/res/values/base-strings.xml
index 2eea10e..fea5b74 100644
--- a/samples/browseable/FloatingActionButtonBasic/res/values/base-strings.xml
+++ b/samples/browseable/FloatingActionButtonBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">FloatingActionButtonBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/MainActivity.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/MainActivity.java
index b88fc7a..8cd9fd7 100644
--- a/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/MainActivity.java
+++ b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.floatingactionbuttonbasic;
import android.os.Bundle;
diff --git a/samples/browseable/Geofencing/Application/res/values-v21/base-colors.xml b/samples/browseable/Geofencing/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/Geofencing/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/Geofencing/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/Geofencing/Application/res/values-v21/base-template-styles.xml b/samples/browseable/Geofencing/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/Geofencing/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/Geofencing/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/Geofencing/Application/res/values/base-strings.xml b/samples/browseable/Geofencing/Application/res/values/base-strings.xml
index 5a66931..7f7abad 100644
--- a/samples/browseable/Geofencing/Application/res/values/base-strings.xml
+++ b/samples/browseable/Geofencing/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Geofencing</string>
<string name="intro_message">
diff --git a/samples/browseable/Geofencing/_index.jd b/samples/browseable/Geofencing/_index.jd
index 497a5b1..e6c9835 100644
--- a/samples/browseable/Geofencing/_index.jd
+++ b/samples/browseable/Geofencing/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Geofencing"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/GridViewPager/_index.jd b/samples/browseable/GridViewPager/_index.jd
index 0abe754..95f54d3 100644
--- a/samples/browseable/GridViewPager/_index.jd
+++ b/samples/browseable/GridViewPager/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="GridViewPager"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/HdrViewfinder/_index.jd b/samples/browseable/HdrViewfinder/_index.jd
index 3348a3f..482eb86 100644
--- a/samples/browseable/HdrViewfinder/_index.jd
+++ b/samples/browseable/HdrViewfinder/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="HdrViewfinder"
sample.group=Media
@jd:body
diff --git a/samples/browseable/HdrViewfinder/res/values-v21/base-colors.xml b/samples/browseable/HdrViewfinder/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/HdrViewfinder/res/values-v21/base-colors.xml
+++ b/samples/browseable/HdrViewfinder/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/HdrViewfinder/res/values-v21/base-template-styles.xml b/samples/browseable/HdrViewfinder/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/HdrViewfinder/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/HdrViewfinder/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/HdrViewfinder/res/values/base-strings.xml b/samples/browseable/HdrViewfinder/res/values/base-strings.xml
index 64c518c..effcf64 100644
--- a/samples/browseable/HdrViewfinder/res/values/base-strings.xml
+++ b/samples/browseable/HdrViewfinder/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">HdrViewfinder</string>
<string name="intro_message">
diff --git a/samples/browseable/HorizontalPaging/_index.jd b/samples/browseable/HorizontalPaging/_index.jd
index 4e4ba00..6acb149 100644
--- a/samples/browseable/HorizontalPaging/_index.jd
+++ b/samples/browseable/HorizontalPaging/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="HorizontalPaging"
sample.group=UI
@jd:body
diff --git a/samples/browseable/HorizontalPaging/res/values-v21/base-colors.xml b/samples/browseable/HorizontalPaging/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/HorizontalPaging/res/values-v21/base-colors.xml
+++ b/samples/browseable/HorizontalPaging/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/HorizontalPaging/res/values-v21/base-template-styles.xml b/samples/browseable/HorizontalPaging/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/HorizontalPaging/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/HorizontalPaging/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/HorizontalPaging/res/values/base-strings.xml b/samples/browseable/HorizontalPaging/res/values/base-strings.xml
index 3f5d5a9..eb02d46 100644
--- a/samples/browseable/HorizontalPaging/res/values/base-strings.xml
+++ b/samples/browseable/HorizontalPaging/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">HorizontalPaging</string>
<string name="intro_message">
diff --git a/samples/browseable/ImmersiveMode/_index.jd b/samples/browseable/ImmersiveMode/_index.jd
index 38c7fbd..2c560aa 100644
--- a/samples/browseable/ImmersiveMode/_index.jd
+++ b/samples/browseable/ImmersiveMode/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ImmersiveMode"
sample.group=UI
@jd:body
diff --git a/samples/browseable/ImmersiveMode/res/values-v21/base-colors.xml b/samples/browseable/ImmersiveMode/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ImmersiveMode/res/values-v21/base-colors.xml
+++ b/samples/browseable/ImmersiveMode/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ImmersiveMode/res/values-v21/base-template-styles.xml b/samples/browseable/ImmersiveMode/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ImmersiveMode/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ImmersiveMode/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ImmersiveMode/res/values/base-strings.xml b/samples/browseable/ImmersiveMode/res/values/base-strings.xml
index a247c6b..3021d4c 100644
--- a/samples/browseable/ImmersiveMode/res/values/base-strings.xml
+++ b/samples/browseable/ImmersiveMode/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ImmersiveMode</string>
<string name="intro_message">
diff --git a/samples/browseable/ImmersiveMode/res/values/strings.xml b/samples/browseable/ImmersiveMode/res/values/strings.xml
index 65ee47d..ad7e485 100644
--- a/samples/browseable/ImmersiveMode/res/values/strings.xml
+++ b/samples/browseable/ImmersiveMode/res/values/strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="sample_action">Toggle immersive mode!</string>
</resources>
diff --git a/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java b/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java
index 645e92f..e94149f 100644
--- a/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java
+++ b/samples/browseable/ImmersiveMode/src/com.example.android.immersivemode/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.immersivemode;
import android.graphics.Color;
diff --git a/samples/browseable/Interpolator/_index.jd b/samples/browseable/Interpolator/_index.jd
index 30aa7a8..16ead22 100644
--- a/samples/browseable/Interpolator/_index.jd
+++ b/samples/browseable/Interpolator/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Interpolator"
sample.group=UI
@jd:body
diff --git a/samples/browseable/Interpolator/res/values-v21/base-colors.xml b/samples/browseable/Interpolator/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/Interpolator/res/values-v21/base-colors.xml
+++ b/samples/browseable/Interpolator/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/Interpolator/res/values-v21/base-template-styles.xml b/samples/browseable/Interpolator/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/Interpolator/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/Interpolator/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/Interpolator/res/values/base-strings.xml b/samples/browseable/Interpolator/res/values/base-strings.xml
index 4997667..a22c0dc 100644
--- a/samples/browseable/Interpolator/res/values/base-strings.xml
+++ b/samples/browseable/Interpolator/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Interpolator</string>
<string name="intro_message">
diff --git a/samples/browseable/Interpolator/src/com.example.android.interpolator/MainActivity.java b/samples/browseable/Interpolator/src/com.example.android.interpolator/MainActivity.java
index f71fd05..925aec7 100644
--- a/samples/browseable/Interpolator/src/com.example.android.interpolator/MainActivity.java
+++ b/samples/browseable/Interpolator/src/com.example.android.interpolator/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.interpolator;
import android.os.Bundle;
diff --git a/samples/browseable/JobScheduler/_index.jd b/samples/browseable/JobScheduler/_index.jd
index 7f438ea..658127f 100644
--- a/samples/browseable/JobScheduler/_index.jd
+++ b/samples/browseable/JobScheduler/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="JobScheduler"
sample.group=Background
@jd:body
diff --git a/samples/browseable/JobScheduler/res/values-v21/base-colors.xml b/samples/browseable/JobScheduler/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/JobScheduler/res/values-v21/base-colors.xml
+++ b/samples/browseable/JobScheduler/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/JobScheduler/res/values-v21/base-template-styles.xml b/samples/browseable/JobScheduler/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/JobScheduler/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/JobScheduler/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/JobScheduler/res/values/base-strings.xml b/samples/browseable/JobScheduler/res/values/base-strings.xml
index 90ee18a..cd86344 100644
--- a/samples/browseable/JobScheduler/res/values/base-strings.xml
+++ b/samples/browseable/JobScheduler/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">JobScheduler</string>
<string name="intro_message">
diff --git a/samples/browseable/JumpingJack/_index.jd b/samples/browseable/JumpingJack/_index.jd
index d742e9e..3b55050 100644
--- a/samples/browseable/JumpingJack/_index.jd
+++ b/samples/browseable/JumpingJack/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="JumpingJack"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/LNotifications/_index.jd b/samples/browseable/LNotifications/_index.jd
index d156267..06bb609 100644
--- a/samples/browseable/LNotifications/_index.jd
+++ b/samples/browseable/LNotifications/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="LNotifications Sample"
sample.group=Notification
@jd:body
diff --git a/samples/browseable/LNotifications/res/values-v21/base-colors.xml b/samples/browseable/LNotifications/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/LNotifications/res/values-v21/base-colors.xml
+++ b/samples/browseable/LNotifications/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/LNotifications/res/values-v21/base-template-styles.xml b/samples/browseable/LNotifications/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/LNotifications/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/LNotifications/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/LNotifications/res/values/base-strings.xml b/samples/browseable/LNotifications/res/values/base-strings.xml
index 417452d..aec51eb 100644
--- a/samples/browseable/LNotifications/res/values/base-strings.xml
+++ b/samples/browseable/LNotifications/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">LNotifications Sample</string>
<string name="intro_message">
diff --git a/samples/browseable/MediaBrowserService/_index.jd b/samples/browseable/MediaBrowserService/_index.jd
index f7454ec..6e2af25 100644
--- a/samples/browseable/MediaBrowserService/_index.jd
+++ b/samples/browseable/MediaBrowserService/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="MediaBrowserService"
sample.group=Media
@jd:body
diff --git a/samples/browseable/MediaEffects/_index.jd b/samples/browseable/MediaEffects/_index.jd
index 76448c3..b43a483 100644
--- a/samples/browseable/MediaEffects/_index.jd
+++ b/samples/browseable/MediaEffects/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="MediaEffects"
sample.group=Media
@jd:body
diff --git a/samples/browseable/MediaEffects/res/values-v21/base-colors.xml b/samples/browseable/MediaEffects/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/MediaEffects/res/values-v21/base-colors.xml
+++ b/samples/browseable/MediaEffects/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/MediaEffects/res/values-v21/base-template-styles.xml b/samples/browseable/MediaEffects/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/MediaEffects/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/MediaEffects/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/MediaEffects/res/values/base-strings.xml b/samples/browseable/MediaEffects/res/values/base-strings.xml
index 1acde21..05f445c 100644
--- a/samples/browseable/MediaEffects/res/values/base-strings.xml
+++ b/samples/browseable/MediaEffects/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">MediaEffects</string>
<string name="intro_message">
diff --git a/samples/browseable/MediaEffects/src/com.example.android.mediaeffects/MainActivity.java b/samples/browseable/MediaEffects/src/com.example.android.mediaeffects/MainActivity.java
index be62243..57e2b50 100644
--- a/samples/browseable/MediaEffects/src/com.example.android.mediaeffects/MainActivity.java
+++ b/samples/browseable/MediaEffects/src/com.example.android.mediaeffects/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.mediaeffects;
import android.os.Bundle;
diff --git a/samples/browseable/MediaRecorder/_index.jd b/samples/browseable/MediaRecorder/_index.jd
index 54b37c8..f1ab587 100644
--- a/samples/browseable/MediaRecorder/_index.jd
+++ b/samples/browseable/MediaRecorder/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="MediaRecorder"
sample.group=Media
@jd:body
diff --git a/samples/browseable/MediaRecorder/res/values-v21/base-colors.xml b/samples/browseable/MediaRecorder/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/MediaRecorder/res/values-v21/base-colors.xml
+++ b/samples/browseable/MediaRecorder/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/MediaRecorder/res/values-v21/base-template-styles.xml b/samples/browseable/MediaRecorder/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/MediaRecorder/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/MediaRecorder/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/MediaRecorder/res/values/base-strings.xml b/samples/browseable/MediaRecorder/res/values/base-strings.xml
index 91a0b44..7a500d0 100644
--- a/samples/browseable/MediaRecorder/res/values/base-strings.xml
+++ b/samples/browseable/MediaRecorder/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">MediaRecorder</string>
<string name="intro_message">
diff --git a/samples/browseable/MediaRouter/_index.jd b/samples/browseable/MediaRouter/_index.jd
index 66ac113..30679d8 100644
--- a/samples/browseable/MediaRouter/_index.jd
+++ b/samples/browseable/MediaRouter/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="MediaRouter"
sample.group=Media
@jd:body
diff --git a/samples/browseable/MediaRouter/res/values-v21/base-colors.xml b/samples/browseable/MediaRouter/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/MediaRouter/res/values-v21/base-colors.xml
+++ b/samples/browseable/MediaRouter/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/MediaRouter/res/values-v21/base-template-styles.xml b/samples/browseable/MediaRouter/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/MediaRouter/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/MediaRouter/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/MediaRouter/res/values/base-strings.xml b/samples/browseable/MediaRouter/res/values/base-strings.xml
index 667c735..129562d 100644
--- a/samples/browseable/MediaRouter/res/values/base-strings.xml
+++ b/samples/browseable/MediaRouter/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">MediaRouter</string>
<string name="intro_message">
diff --git a/samples/browseable/MessagingService/_index.jd b/samples/browseable/MessagingService/_index.jd
index ceaba34..ce82da8 100644
--- a/samples/browseable/MessagingService/_index.jd
+++ b/samples/browseable/MessagingService/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="MessagingService"
sample.group=Notification
@jd:body
diff --git a/samples/browseable/NavigationDrawer/_index.jd b/samples/browseable/NavigationDrawer/_index.jd
index 7238cf1..904ac92 100644
--- a/samples/browseable/NavigationDrawer/_index.jd
+++ b/samples/browseable/NavigationDrawer/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Navigation Drawer"
sample.group=UI
@jd:body
diff --git a/samples/browseable/NavigationDrawer/res/values-v21/base-colors.xml b/samples/browseable/NavigationDrawer/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/NavigationDrawer/res/values-v21/base-colors.xml
+++ b/samples/browseable/NavigationDrawer/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/NavigationDrawer/res/values-v21/base-template-styles.xml b/samples/browseable/NavigationDrawer/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/NavigationDrawer/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/NavigationDrawer/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/NavigationDrawer/res/values/activitycards-strings.xml b/samples/browseable/NavigationDrawer/res/values/activitycards-strings.xml
index 885a1ec..3803f18 100644
--- a/samples/browseable/NavigationDrawer/res/values/activitycards-strings.xml
+++ b/samples/browseable/NavigationDrawer/res/values/activitycards-strings.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
+
<resources>
<string name="navigationdraweractivity_title">Navigation Drawer Example</string>
<string name="navigationdraweractivity_description">This example illustrates a common usage of the DrawerLayout widget in the Android
diff --git a/samples/browseable/NavigationDrawer/res/values/base-strings.xml b/samples/browseable/NavigationDrawer/res/values/base-strings.xml
index 62e8426..b5905d2 100644
--- a/samples/browseable/NavigationDrawer/res/values/base-strings.xml
+++ b/samples/browseable/NavigationDrawer/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Navigation Drawer</string>
<string name="intro_message">
diff --git a/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/MainActivity.java b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/MainActivity.java
index 665edf3..834d4f2 100644
--- a/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/MainActivity.java
+++ b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.navigationdrawer;
import android.app.Activity;
diff --git a/samples/browseable/NetworkConnect/_index.jd b/samples/browseable/NetworkConnect/_index.jd
index 7d67dd3..7be3ce2 100644
--- a/samples/browseable/NetworkConnect/_index.jd
+++ b/samples/browseable/NetworkConnect/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="NetworkConnect"
sample.group=Connectivity
@jd:body
diff --git a/samples/browseable/NetworkConnect/res/values-v21/base-colors.xml b/samples/browseable/NetworkConnect/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/NetworkConnect/res/values-v21/base-colors.xml
+++ b/samples/browseable/NetworkConnect/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/NetworkConnect/res/values-v21/base-template-styles.xml b/samples/browseable/NetworkConnect/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/NetworkConnect/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/NetworkConnect/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/NetworkConnect/res/values/base-strings.xml b/samples/browseable/NetworkConnect/res/values/base-strings.xml
index 75b3a8c..ae4485e 100644
--- a/samples/browseable/NetworkConnect/res/values/base-strings.xml
+++ b/samples/browseable/NetworkConnect/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">NetworkConnect</string>
<string name="intro_message">
diff --git a/samples/browseable/NfcProvisioning/_index.jd b/samples/browseable/NfcProvisioning/_index.jd
index fa42757..3738518 100644
--- a/samples/browseable/NfcProvisioning/_index.jd
+++ b/samples/browseable/NfcProvisioning/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="NfcProvisioning"
sample.group=Admin
@jd:body
diff --git a/samples/browseable/NfcProvisioning/res/values-v21/base-colors.xml b/samples/browseable/NfcProvisioning/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/NfcProvisioning/res/values-v21/base-colors.xml
+++ b/samples/browseable/NfcProvisioning/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/NfcProvisioning/res/values-v21/base-template-styles.xml b/samples/browseable/NfcProvisioning/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/NfcProvisioning/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/NfcProvisioning/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/NfcProvisioning/res/values/base-strings.xml b/samples/browseable/NfcProvisioning/res/values/base-strings.xml
index 0114f3e..33a8bfb 100644
--- a/samples/browseable/NfcProvisioning/res/values/base-strings.xml
+++ b/samples/browseable/NfcProvisioning/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">NfcProvisioning</string>
<string name="intro_message">
diff --git a/samples/browseable/NfcProvisioning/src/com.example.android.nfcprovisioning/MainActivity.java b/samples/browseable/NfcProvisioning/src/com.example.android.nfcprovisioning/MainActivity.java
index 768e1c8..2d78ac8 100644
--- a/samples/browseable/NfcProvisioning/src/com.example.android.nfcprovisioning/MainActivity.java
+++ b/samples/browseable/NfcProvisioning/src/com.example.android.nfcprovisioning/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.nfcprovisioning;
import android.os.Bundle;
diff --git a/samples/browseable/Notifications/Application/res/values-v21/base-colors.xml b/samples/browseable/Notifications/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/Notifications/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/Notifications/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/Notifications/Application/res/values-v21/base-template-styles.xml b/samples/browseable/Notifications/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/Notifications/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/Notifications/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/Notifications/Application/res/values/base-strings.xml b/samples/browseable/Notifications/Application/res/values/base-strings.xml
index 55d83b0..9ab282f 100644
--- a/samples/browseable/Notifications/Application/res/values/base-strings.xml
+++ b/samples/browseable/Notifications/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Wearable Notifications</string>
<string name="intro_message">
diff --git a/samples/browseable/Notifications/_index.jd b/samples/browseable/Notifications/_index.jd
index ba28233..e2bfa36 100644
--- a/samples/browseable/Notifications/_index.jd
+++ b/samples/browseable/Notifications/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Wearable Notifications"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/PdfRendererBasic/_index.jd b/samples/browseable/PdfRendererBasic/_index.jd
index 59c5a53..728dcb1 100644
--- a/samples/browseable/PdfRendererBasic/_index.jd
+++ b/samples/browseable/PdfRendererBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="PdfRendererBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/PdfRendererBasic/res/values-v21/base-colors.xml b/samples/browseable/PdfRendererBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/PdfRendererBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/PdfRendererBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/PdfRendererBasic/res/values-v21/base-template-styles.xml b/samples/browseable/PdfRendererBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/PdfRendererBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/PdfRendererBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/PdfRendererBasic/res/values/base-strings.xml b/samples/browseable/PdfRendererBasic/res/values/base-strings.xml
index d97b3c6..51b7dd2 100644
--- a/samples/browseable/PdfRendererBasic/res/values/base-strings.xml
+++ b/samples/browseable/PdfRendererBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">PdfRendererBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/PermissionRequest/_index.jd b/samples/browseable/PermissionRequest/_index.jd
index d0f6785..a10dec1 100644
--- a/samples/browseable/PermissionRequest/_index.jd
+++ b/samples/browseable/PermissionRequest/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="PermissionRequest"
sample.group=Content
@jd:body
diff --git a/samples/browseable/PermissionRequest/res/values-v21/base-colors.xml b/samples/browseable/PermissionRequest/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/PermissionRequest/res/values-v21/base-colors.xml
+++ b/samples/browseable/PermissionRequest/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/PermissionRequest/res/values-v21/base-template-styles.xml b/samples/browseable/PermissionRequest/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/PermissionRequest/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/PermissionRequest/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/PermissionRequest/res/values/base-strings.xml b/samples/browseable/PermissionRequest/res/values/base-strings.xml
index c66a246..6a7a5f6 100644
--- a/samples/browseable/PermissionRequest/res/values/base-strings.xml
+++ b/samples/browseable/PermissionRequest/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">PermissionRequest</string>
<string name="intro_message">
diff --git a/samples/browseable/PermissionRequest/src/com.example.android.permissionrequest/MainActivity.java b/samples/browseable/PermissionRequest/src/com.example.android.permissionrequest/MainActivity.java
index a11849f..8bdd42d 100644
--- a/samples/browseable/PermissionRequest/src/com.example.android.permissionrequest/MainActivity.java
+++ b/samples/browseable/PermissionRequest/src/com.example.android.permissionrequest/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.permissionrequest;
import android.os.Bundle;
diff --git a/samples/browseable/Quiz/Application/res/values-v21/base-colors.xml b/samples/browseable/Quiz/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/Quiz/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/Quiz/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/Quiz/Application/res/values-v21/base-template-styles.xml b/samples/browseable/Quiz/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/Quiz/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/Quiz/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/Quiz/Application/res/values/base-strings.xml b/samples/browseable/Quiz/Application/res/values/base-strings.xml
index 527d038..156bb92 100644
--- a/samples/browseable/Quiz/Application/res/values/base-strings.xml
+++ b/samples/browseable/Quiz/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Quiz</string>
<string name="intro_message">
diff --git a/samples/browseable/Quiz/_index.jd b/samples/browseable/Quiz/_index.jd
index 3c1a1da..06c152b 100644
--- a/samples/browseable/Quiz/_index.jd
+++ b/samples/browseable/Quiz/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Quiz"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/RecipeAssistant/Application/res/values-v21/base-colors.xml b/samples/browseable/RecipeAssistant/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/RecipeAssistant/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/RecipeAssistant/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/RecipeAssistant/Application/res/values-v21/base-template-styles.xml b/samples/browseable/RecipeAssistant/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/RecipeAssistant/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/RecipeAssistant/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/RecipeAssistant/Application/res/values/base-strings.xml b/samples/browseable/RecipeAssistant/Application/res/values/base-strings.xml
index e536fbd..6caf812 100644
--- a/samples/browseable/RecipeAssistant/Application/res/values/base-strings.xml
+++ b/samples/browseable/RecipeAssistant/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">RecipeAssistant</string>
<string name="intro_message">
diff --git a/samples/browseable/RecipeAssistant/_index.jd b/samples/browseable/RecipeAssistant/_index.jd
index 0860bce..0d2f7da 100644
--- a/samples/browseable/RecipeAssistant/_index.jd
+++ b/samples/browseable/RecipeAssistant/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="RecipeAssistant"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/RecyclerView/_index.jd b/samples/browseable/RecyclerView/_index.jd
index 31b0fac..18005f1 100644
--- a/samples/browseable/RecyclerView/_index.jd
+++ b/samples/browseable/RecyclerView/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="RecyclerView"
sample.group=UI
@jd:body
diff --git a/samples/browseable/RecyclerView/res/values-v21/base-colors.xml b/samples/browseable/RecyclerView/res/values-v21/base-colors.xml
index 16853b1..58f08a3 100644
--- a/samples/browseable/RecyclerView/res/values-v21/base-colors.xml
+++ b/samples/browseable/RecyclerView/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<color name="colorPrimary">#00BCD4</color>
diff --git a/samples/browseable/RecyclerView/res/values-v21/base-template-styles.xml b/samples/browseable/RecyclerView/res/values-v21/base-template-styles.xml
index c2b4c8e..0995e4d 100644
--- a/samples/browseable/RecyclerView/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/RecyclerView/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/RecyclerView/res/values/base-strings.xml b/samples/browseable/RecyclerView/res/values/base-strings.xml
index 7580f12..3ccf660 100644
--- a/samples/browseable/RecyclerView/res/values/base-strings.xml
+++ b/samples/browseable/RecyclerView/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">RecyclerView</string>
<string name="intro_message">
diff --git a/samples/browseable/RecyclerView/src/com.example.android.recyclerview/MainActivity.java b/samples/browseable/RecyclerView/src/com.example.android.recyclerview/MainActivity.java
index 7556067..e428e39 100644
--- a/samples/browseable/RecyclerView/src/com.example.android.recyclerview/MainActivity.java
+++ b/samples/browseable/RecyclerView/src/com.example.android.recyclerview/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.recyclerview;
import android.os.Bundle;
diff --git a/samples/browseable/RenderScriptIntrinsic/_index.jd b/samples/browseable/RenderScriptIntrinsic/_index.jd
index f5d5e4e..3684d24 100644
--- a/samples/browseable/RenderScriptIntrinsic/_index.jd
+++ b/samples/browseable/RenderScriptIntrinsic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="RenderScriptIntrinsic"
sample.group=RenderScript
@jd:body
diff --git a/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-colors.xml b/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-colors.xml
+++ b/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-template-styles.xml b/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/RenderScriptIntrinsic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/RenderScriptIntrinsic/res/values/base-strings.xml b/samples/browseable/RenderScriptIntrinsic/res/values/base-strings.xml
index e32a259..eefbf6c 100644
--- a/samples/browseable/RenderScriptIntrinsic/res/values/base-strings.xml
+++ b/samples/browseable/RenderScriptIntrinsic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">RenderScriptIntrinsic</string>
<string name="intro_message">
diff --git a/samples/browseable/RepeatingAlarm/_index.jd b/samples/browseable/RepeatingAlarm/_index.jd
index 1735034..60ae8e3 100644
--- a/samples/browseable/RepeatingAlarm/_index.jd
+++ b/samples/browseable/RepeatingAlarm/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="RepeatingAlarm"
sample.group=Background
@jd:body
diff --git a/samples/browseable/RepeatingAlarm/res/values-v21/base-colors.xml b/samples/browseable/RepeatingAlarm/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/RepeatingAlarm/res/values-v21/base-colors.xml
+++ b/samples/browseable/RepeatingAlarm/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/RepeatingAlarm/res/values-v21/base-template-styles.xml b/samples/browseable/RepeatingAlarm/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/RepeatingAlarm/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/RepeatingAlarm/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/RepeatingAlarm/res/values/base-strings.xml b/samples/browseable/RepeatingAlarm/res/values/base-strings.xml
index e6170d2..5aa04c6 100644
--- a/samples/browseable/RepeatingAlarm/res/values/base-strings.xml
+++ b/samples/browseable/RepeatingAlarm/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">RepeatingAlarm</string>
<string name="intro_message">
diff --git a/samples/browseable/RepeatingAlarm/res/values/strings.xml b/samples/browseable/RepeatingAlarm/res/values/strings.xml
index 59a8ff2..6aabc67 100644
--- a/samples/browseable/RepeatingAlarm/res/values/strings.xml
+++ b/samples/browseable/RepeatingAlarm/res/values/strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="sample_action">Set Alarm</string>
</resources>
diff --git a/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java b/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java
index b7527d5..2f4a539 100644
--- a/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java
+++ b/samples/browseable/RepeatingAlarm/src/com.example.android.repeatingalarm/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.repeatingalarm;
import android.graphics.Color;
diff --git a/samples/browseable/RevealEffectBasic/_index.jd b/samples/browseable/RevealEffectBasic/_index.jd
index c48c617..f1e9268 100644
--- a/samples/browseable/RevealEffectBasic/_index.jd
+++ b/samples/browseable/RevealEffectBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="RevealEffectBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/RevealEffectBasic/res/values-v21/base-colors.xml b/samples/browseable/RevealEffectBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/RevealEffectBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/RevealEffectBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/RevealEffectBasic/res/values-v21/base-template-styles.xml b/samples/browseable/RevealEffectBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/RevealEffectBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/RevealEffectBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/RevealEffectBasic/res/values/base-strings.xml b/samples/browseable/RevealEffectBasic/res/values/base-strings.xml
index b4aa183..11b9839 100644
--- a/samples/browseable/RevealEffectBasic/res/values/base-strings.xml
+++ b/samples/browseable/RevealEffectBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">RevealEffectBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/MainActivity.java b/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/MainActivity.java
index e9b27d9..6d7188e 100644
--- a/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/MainActivity.java
+++ b/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.revealeffectbasic;
import android.os.Bundle;
diff --git a/samples/browseable/RuntimePermissions/AndroidManifest.xml b/samples/browseable/RuntimePermissions/AndroidManifest.xml
new file mode 100644
index 0000000..050b051
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/AndroidManifest.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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.system.runtimepermissions" >
+
+ <!-- BEGIN_INCLUDE(manifest) -->
+
+ <!-- Note that all required permissions are declared here in the Android manifest.
+ On Android M and above, use of these permissions is only requested at run time. -->
+ <uses-permission android:name="android.permission.CAMERA"/>
+
+ <!-- The following permissions are only requested if the device is on M or above.
+ On older platforms these permissions are not requested and will not be available. -->
+ <uses-permission-sdk-m android:name="android.permission.READ_CONTACTS" />
+ <uses-permission-sdk-m android:name="android.permission.WRITE_CONTACTS" />
+
+ <!-- END_INCLUDE(manifest) -->
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <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/browseable/RuntimePermissions/_index.jd b/samples/browseable/RuntimePermissions/_index.jd
new file mode 100644
index 0000000..75c6fee
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/_index.jd
@@ -0,0 +1,12 @@
+
+page.tags="RuntimePermissions"
+sample.group=System
+@jd:body
+
+<p>
+
+ This sample shows runtime permissions available in the Android M and above.
+ Display the log to follow the execution.
+ If executed on an Android M device, an additional option to access contacts is shown.
+
+ </p>
diff --git a/samples/browseable/RuntimePermissions/res/drawable-hdpi/tile.9.png b/samples/browseable/RuntimePermissions/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissions/res/layout-w720dp/activity_main.xml b/samples/browseable/RuntimePermissions/res/layout-w720dp/activity_main.xml
new file mode 100644
index 0000000..c9a52f6
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/layout-w720dp/activity_main.xml
@@ -0,0 +1,73 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <LinearLayout
+ android:id="@+id/sample_output"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <FrameLayout
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/margin_medium"
+ android:paddingRight="@dimen/margin_medium"
+ android:paddingTop="@dimen/margin_large"
+ android:paddingBottom="@dimen/margin_large"
+ android:text="@string/intro_message" />
+ </FrameLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="0px"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
+
+
diff --git a/samples/browseable/RuntimePermissions/res/layout/activity_main.xml b/samples/browseable/RuntimePermissions/res/layout/activity_main.xml
new file mode 100644
index 0000000..64e8322
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/layout/activity_main.xml
@@ -0,0 +1,65 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/sample_main_layout">
+
+ <ViewAnimator
+ android:id="@+id/sample_output"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <ScrollView
+ style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </ScrollView>
+
+ <fragment
+ android:name="com.example.android.common.logger.LogFragment"
+ android:id="@+id/log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </ViewAnimator>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@android:color/darker_gray" />
+
+ <FrameLayout
+ android:id="@+id/sample_content_fragment"
+ android:layout_weight="2"
+ android:layout_width="match_parent"
+ android:layout_height="0px" />
+
+</LinearLayout>
+
diff --git a/samples/browseable/RuntimePermissions/res/layout/fragment_camera.xml b/samples/browseable/RuntimePermissions/res/layout/fragment_camera.xml
new file mode 100644
index 0000000..ecdc54a
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/layout/fragment_camera.xml
@@ -0,0 +1,33 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent">
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/back"
+ android:onClick="onBackClick"
+ android:layout_gravity="center_horizontal"/>
+
+ <FrameLayout
+ android:id="@+id/camera_preview"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ />
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/browseable/RuntimePermissions/res/layout/fragment_camera_unavailable.xml b/samples/browseable/RuntimePermissions/res/layout/fragment_camera_unavailable.xml
new file mode 100644
index 0000000..200ebbc
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/layout/fragment_camera_unavailable.xml
@@ -0,0 +1,43 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/back"
+ android:onClick="onBackClick"
+ android:layout_gravity="center_horizontal"/>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:text="@string/camera_unavailable"/>
+
+ </ScrollView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/browseable/RuntimePermissions/res/layout/fragment_contacts.xml b/samples/browseable/RuntimePermissions/res/layout/fragment_contacts.xml
new file mode 100644
index 0000000..8a70fe2
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/layout/fragment_contacts.xml
@@ -0,0 +1,54 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/back"
+ android:onClick="onBackClick"
+ android:layout_gravity="center_horizontal"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/contacts_intro"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/contact_message"/>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/add_contact"
+ android:id="@+id/contact_add"/>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/show_contact"
+ android:id="@+id/contact_load"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/browseable/RuntimePermissions/res/layout/fragment_main.xml b/samples/browseable/RuntimePermissions/res/layout/fragment_main.xml
new file mode 100644
index 0000000..f9bfd5f
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/layout/fragment_main.xml
@@ -0,0 +1,48 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:orientation="vertical"
+ tools:context=".MainActivityFragment">
+
+ <TextView
+ android:text="@string/main_introduction"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/show_camera"
+ android:id="@+id/button_camera"
+ android:onClick="showCamera"/>
+
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/show_contacts"
+ android:id="@+id/button_contacts"
+ android:onClick="showContacts"/>
+
+</LinearLayout>
diff --git a/samples/browseable/RuntimePermissions/res/menu/main.xml b/samples/browseable/RuntimePermissions/res/menu/main.xml
new file mode 100644
index 0000000..b49c2c5
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/menu/main.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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/menu_toggle_log"
+ android:showAsAction="always"
+ android:title="@string/sample_show_log" />
+</menu>
diff --git a/samples/browseable/RuntimePermissions/res/mipmap-hdpi/ic_launcher.png b/samples/browseable/RuntimePermissions/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..3279054
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissions/res/mipmap-mdpi/ic_launcher.png b/samples/browseable/RuntimePermissions/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..225fe42
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissions/res/mipmap-xhdpi/ic_launcher.png b/samples/browseable/RuntimePermissions/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..c129dbb
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissions/res/mipmap-xxhdpi/ic_launcher.png b/samples/browseable/RuntimePermissions/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b4ab118
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissions/res/mipmap-xxxhdpi/ic_launcher.png b/samples/browseable/RuntimePermissions/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..99649fb
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissions/res/values-sw600dp/template-dimens.xml b/samples/browseable/RuntimePermissions/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values-sw600dp/template-styles.xml b/samples/browseable/RuntimePermissions/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values-v11/template-styles.xml b/samples/browseable/RuntimePermissions/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values-v21/base-colors.xml b/samples/browseable/RuntimePermissions/res/values-v21/base-colors.xml
new file mode 100644
index 0000000..8b6ec3f
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values-v21/base-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values-v21/base-template-styles.xml b/samples/browseable/RuntimePermissions/res/values-v21/base-template-styles.xml
new file mode 100644
index 0000000..c778e4f
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values-v21/base-template-styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light">
+ </style>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values/base-strings.xml b/samples/browseable/RuntimePermissions/res/values/base-strings.xml
new file mode 100644
index 0000000..58d75f9
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values/base-strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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">RuntimePermissions</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ This sample shows runtime permissions available in the Android M and above.
+ Display the log to follow the execution.
+ If executed on an Android M device, an additional option to access contacts is shown.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values/fragmentview_strings.xml b/samples/browseable/RuntimePermissions/res/values/fragmentview_strings.xml
new file mode 100644
index 0000000..7b9d9ec
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values/fragmentview_strings.xml
@@ -0,0 +1,19 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="sample_show_log">Show Log</string>
+ <string name="sample_hide_log">Hide Log</string>
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values/strings.xml b/samples/browseable/RuntimePermissions/res/values/strings.xml
new file mode 100644
index 0000000..941f059
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="contacts_string">Total number of contacts: %1$,d\nFirst contact:<b>%2$s</b></string>
+ <string name="contacts_none">No contacts stored on device.</string>
+ <string name="contacts_empty">Contacts not loaded.</string>
+ <string name="add_contact">Add a contact</string>
+ <string name="show_contact">Show first contact</string>
+ <string name="contacts_intro">This fragment demonstrates access to the contact database on the device.\n
+ Clicking \"Add a contact\" adds a new contact named "__DUMMY ENTRY" directly into the database.\n
+ Clicking \"Show first contact\" accesses the contact database to display the name of the first contact.</string>
+ <string name="camera_unavailable"><b>Camera could not be opened.</b>\nThis occurs when the camera is not available (for example it is already in use) or if the system has denied access (for example when camera access has been disabled).</string>
+ <string name="back">Back</string>
+ <string name="show_camera">Show camera preview</string>
+ <string name="show_contacts">Show and add contacts</string>
+ <string name="main_introduction">Click the buttons below to show a camera preview or access the contacts database.\nNote that the contacts option is only available on Android M to illustrate the use of optional, M-only permissions that are not requested on lower SDK platforms.</string>
+ <string name="permision_available_camera">Camera Permission has been granted. Preview can now be opened.</string>
+ <string name="permision_available_contacts">Contacts Permissions have been granted. Contacts screen can now be opened.</string>
+ <string name="permissions_not_granted">Permissions were not granted.</string>
+</resources>
\ No newline at end of file
diff --git a/samples/browseable/RuntimePermissions/res/values/template-dimens.xml b/samples/browseable/RuntimePermissions/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissions/res/values/template-styles.xml b/samples/browseable/RuntimePermissions/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/RuntimePermissions/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* Copyright 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/Log.java b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* Copyright 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.common.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogNode.java b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogView.java b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/MainActivity.java b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/MainActivity.java
new file mode 100644
index 0000000..43436aa
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/MainActivity.java
@@ -0,0 +1,279 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.system.runtimepermissions;
+
+import com.example.android.common.activities.SampleActivityBase;
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogFragment;
+import com.example.android.common.logger.LogWrapper;
+import com.example.android.common.logger.MessageOnlyLogFilter;
+import com.example.android.system.runtimepermissions.camera.CameraPreviewFragment;
+import com.example.android.system.runtimepermissions.contacts.ContactsFragment;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Toast;
+import android.widget.ViewAnimator;
+
+/**
+ * Launcher Activity that demonstrates the use of runtime permissions for Android M.
+ * It contains a summary sample description, sample log and a Fragment that calls callbacks on this
+ * Activity to illustrate parts of the runtime permissions API.
+ * <p>
+ * This Activity requests permissions to access the camera ({@link android.Manifest.permission#CAMERA})
+ * when the 'Show Camera' button is clicked to display the camera preview.
+ * Contacts permissions (({@link android.Manifest.permission#READ_CONTACTS} and ({@link
+ * android.Manifest.permission#WRITE_CONTACTS})) are requested when the 'Show and Add Contacts'
+ * button is
+ * clicked to display the first contact in the contacts database and to add a dummy contact
+ * directly
+ * to it. First, permissions are checked if they have already been granted through {@link
+ * android.app.Activity#checkSelfPermission(String)} (wrapped in {@link
+ * PermissionUtil#hasSelfPermission(Activity, String)} and {@link PermissionUtil#hasSelfPermission(Activity,
+ * String[])} for compatibility). If permissions have not been granted, they are requested through
+ * {@link Activity#requestPermissions(String[], int)} and the return value checked in {@link
+ * Activity#onRequestPermissionsResult(int, String[], int[])}.
+ * <p>
+ * If this sample is executed on a device running a platform version below M, all permissions
+ * declared
+ * in the Android manifest file are always granted at install time and cannot be requested at run
+ * time.
+ * <p>
+ * This sample targets the M platform and must therefore request permissions at runtime. Change the
+ * targetSdk in the file 'Application/build.gradle' to 22 to run the application in compatibility
+ * mode.
+ * Now, if a permission has been disable by the system through the application settings, disabled
+ * APIs provide compatibility data.
+ * For example the camera cannot be opened or an empty list of contacts is returned. No special
+ * action is required in this case.
+ * <p>
+ * (This class is based on the MainActivity used in the SimpleFragment sample template.)
+ */
+public class MainActivity extends SampleActivityBase {
+
+ public static final String TAG = "MainActivity";
+
+ /**
+ * Id to identify a camera permission request.
+ */
+ private static final int REQUEST_CAMERA = 0;
+
+ /**
+ * Id to identify a contacts permission request.
+ */
+ private static final int REQUEST_CONTACTS = 1;
+
+ /**
+ * Permissions required to read and write contacts. Used by the {@link ContactsFragment}.
+ */
+ private static String[] PERMISSIONS_CONTACT = {Manifest.permission.READ_CONTACTS,
+ Manifest.permission.WRITE_CONTACTS};
+
+ // Whether the Log Fragment is currently shown.
+ private boolean mLogShown;
+
+
+ /**
+ * Called when the 'show camera' button is clicked.
+ * Callback is defined in resource layout definition.
+ */
+ public void showCamera(View view) {
+ Log.i(TAG, "Show camera button pressed. Checking permission.");
+ // BEGIN_INCLUDE(camera_permission)
+ // Check if the Camera permission is already available.
+ if (PermissionUtil.hasSelfPermission(this, Manifest.permission.CAMERA)) {
+ Log.i(TAG,
+ "CAMERA permission has already been granted. Displaying camera preview.");
+ // Camera permissions is already available, show the camera preview.
+ showCameraPreview();
+ } else {
+ Log.i(TAG, "CAMERA permission has NOT been granted. Requesting permission.");
+ // Camera permission has not been granted. Request it.
+ requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA);
+ }
+ // END_INCLUDE(camera_permission)
+
+ }
+
+ /**
+ * Called when the 'show camera' button is clicked.
+ * Callback is defined in resource layout definition.
+ */
+ public void showContacts(View v) {
+ Log.i(TAG, "Show contacts button pressed. Checking permissions.");
+ // Verify that all required contact permissions have been granted.
+ if (PermissionUtil.hasSelfPermission(this, PERMISSIONS_CONTACT)) {
+ Log.i(TAG,
+ "Contact permissions have already been granted. Displaying contact details.");
+ // Contact permissions have been granted. Show the contacts fragment.
+ showContactDetails();
+ } else {
+ Log.i(TAG, "Contact permissions has NOT been granted. Requesting permission.");
+ // contact permissions has not been granted (read and write contacts). Request them.
+ requestPermissions(PERMISSIONS_CONTACT, REQUEST_CONTACTS);
+ }
+ }
+
+ /**
+ * Display the {@link CameraPreviewFragment} in the content area if the required Camera
+ * permission has been granted.
+ */
+ private void showCameraPreview() {
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
+ .addToBackStack("contacts")
+ .commit();
+ }
+
+ /**
+ * Display the {@link ContactsFragment} in the content area if the required contacts
+ * permissions
+ * have been granted.
+ */
+ private void showContactDetails() {
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.sample_content_fragment, ContactsFragment.newInstance())
+ .addToBackStack("contacts")
+ .commit();
+ }
+
+
+ /**
+ * Callback received when a permissions request has been completed.
+ */
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+
+ if (requestCode == REQUEST_CAMERA) {
+ // BEGIN_INCLUDE(permission_result)
+ // Received permission result for camera permission.
+ Log.i(TAG, "Received response for Camera permission request.");
+
+ // Check if the only required permission has been granted
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ // Camera permission has been granted, preview can be displayed
+ Log.i(TAG, "CAMERA permission has now been granted. Showing preview.");
+ Toast.makeText(this, R.string.permision_available_camera, Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ Log.i(TAG, "CAMERA permission was NOT granted.");
+ Toast.makeText(this, R.string.permissions_not_granted, Toast.LENGTH_SHORT).show();
+
+ }
+ // END_INCLUDE(permission_result)
+
+ } else if (requestCode == REQUEST_CONTACTS) {
+ Log.i(TAG, "Received response for contact permissions request.");
+
+ // We have requested multiple permissions for contacts, so all of them need to be
+ // checked.
+ if (PermissionUtil.verifyPermissions(grantResults)) {
+ // All required permissions have been granted, display contacts fragment.
+ Toast.makeText(this, R.string.permision_available_contacts, Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ Log.i(TAG, "Contacts permissions were NOT granted.");
+ Toast.makeText(this, R.string.permissions_not_granted, Toast.LENGTH_SHORT).show();
+ }
+
+ } else {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+ }
+
+ /* Note: Methods and definitions below are only used to provide the UI for this sample and are
+ not relevant for the execution of the runtime permissions API. */
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
+ logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
+ logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_toggle_log:
+ mLogShown = !mLogShown;
+ ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
+ if (mLogShown) {
+ output.setDisplayedChild(1);
+ } else {
+ output.setDisplayedChild(0);
+ }
+ supportInvalidateOptionsMenu();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /** Create a chain of targets that will receive log data */
+ @Override
+ public void initializeLogging() {
+ // Wraps Android's native log framework.
+ LogWrapper logWrapper = new LogWrapper();
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ Log.setLogNode(logWrapper);
+
+ // Filter strips out everything except the message text.
+ MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
+ logWrapper.setNext(msgFilter);
+
+ // On screen logging via a fragment with a TextView.
+ LogFragment logFragment = (LogFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.log_fragment);
+ msgFilter.setNext(logFragment.getLogView());
+ }
+
+ public void onBackClick(View view) {
+ getSupportFragmentManager().popBackStack();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ if (savedInstanceState == null) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ RuntimePermissionsFragment fragment = new RuntimePermissionsFragment();
+ transaction.replace(R.id.sample_content_fragment, fragment);
+ transaction.commit();
+ }
+
+ // This method sets up our custom logger, which will print all log messages to the device
+ // screen, as well as to adb logcat.
+ initializeLogging();
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/PermissionUtil.java b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/PermissionUtil.java
new file mode 100644
index 0000000..ba2370f
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/PermissionUtil.java
@@ -0,0 +1,90 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.system.runtimepermissions;
+
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.os.Build;
+
+/**
+ * Utility class that wraps access to the runtime permissions API in M and provides basic helper
+ * methods.
+ */
+public abstract class PermissionUtil {
+
+ /**
+ * Check that all given permissions have been granted by verifying that each entry in the
+ * given array is of the value {@link PackageManager#PERMISSION_GRANTED}.
+ *
+ * @see Activity#onRequestPermissionsResult(int, String[], int[])
+ */
+ public static boolean verifyPermissions(int[] grantResults) {
+ // Verify that each required permission has been granted, otherwise return false.
+ for (int result : grantResults) {
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the Activity has access to all given permissions.
+ * Always returns true on platforms below M.
+ *
+ * @see Activity#checkSelfPermission(String)
+ */
+ public static boolean hasSelfPermission(Activity activity, String[] permissions) {
+ // Below Android M all permissions are granted at install time and are already available.
+ if (!isMNC()) {
+ return true;
+ }
+
+ // Verify that all required permissions have been granted
+ for (String permission : permissions) {
+ if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the Activity has access to a given permission.
+ * Always returns true on platforms below M.
+ *
+ * @see Activity#checkSelfPermission(String)
+ */
+ public static boolean hasSelfPermission(Activity activity, String permission) {
+ // Below Android M all permissions are granted at install time and are already available.
+ if (!isMNC()) {
+ return true;
+ }
+
+ return activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
+ }
+
+ public static boolean isMNC() {
+ /*
+ TODO: In the Android M Preview release, checking if the platform is M is done through
+ the codename, not the version code. Once the API has been finalised, the following check
+ should be used: */
+ // return Build.VERSION.SDK_INT == Build.VERSION_CODES.MNC
+
+ return "MNC".equals(Build.VERSION.CODENAME);
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/RuntimePermissionsFragment.java b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/RuntimePermissionsFragment.java
new file mode 100644
index 0000000..b35bfeb
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/RuntimePermissionsFragment.java
@@ -0,0 +1,50 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.system.runtimepermissions;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class RuntimePermissionsFragment extends Fragment {
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.fragment_main, null);
+
+ // BEGIN_INCLUDE(m_only_permission)
+ if (!PermissionUtil.isMNC()) {
+ /*
+ The contacts permissions have been declared in the AndroidManifest for Android M only.
+ They are not available on older platforms, so we are hiding the button to access the
+ contacts database.
+ This shows how new runtime-only permissions can be added, that do not apply to older
+ platform versions. This can be useful for automated updates where additional
+ permissions might prompt the user on upgrade.
+ */
+ root.findViewById(R.id.button_camera).setVisibility(View.GONE);
+ }
+ // END_INCLUDE(m_only_permission)
+
+ return root;
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/camera/CameraPreview.java b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/camera/CameraPreview.java
new file mode 100644
index 0000000..1d25b51
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/camera/CameraPreview.java
@@ -0,0 +1,142 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.system.runtimepermissions.camera;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import java.io.IOException;
+
+/**
+ * Camera preview that displays a {@link Camera}.
+ *
+ * Handles basic lifecycle methods to display and stop the preview.
+ * <p>
+ * Implementation is based directly on the documentation at
+ * http://developer.android.com/guide/topics/media/camera.html
+ */
+public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
+
+ private static final String TAG = "CameraPreview";
+ private SurfaceHolder mHolder;
+ private Camera mCamera;
+ private Camera.CameraInfo mCameraInfo;
+ private int mDisplayOrientation;
+
+ public CameraPreview(Context context, Camera camera, Camera.CameraInfo cameraInfo,
+ int displayOrientation) {
+ super(context);
+
+ // Do not initialise if no camera has been set
+ if (camera == null || cameraInfo == null) {
+ return;
+ }
+ mCamera = camera;
+ mCameraInfo = cameraInfo;
+ mDisplayOrientation = displayOrientation;
+
+ // Install a SurfaceHolder.Callback so we get notified when the
+ // underlying surface is created and destroyed.
+ mHolder = getHolder();
+ mHolder.addCallback(this);
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ // The Surface has been created, now tell the camera where to draw the preview.
+ try {
+ mCamera.setPreviewDisplay(holder);
+ mCamera.startPreview();
+ Log.d(TAG, "Camera preview started.");
+ } catch (IOException e) {
+ Log.d(TAG, "Error setting camera preview: " + e.getMessage());
+ }
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // empty. Take care of releasing the Camera preview in your activity.
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ // If your preview can change or rotate, take care of those events here.
+ // Make sure to stop the preview before resizing or reformatting it.
+
+ if (mHolder.getSurface() == null) {
+ // preview surface does not exist
+ Log.d(TAG, "Preview surface does not exist");
+ return;
+ }
+
+ // stop preview before making changes
+ try {
+ mCamera.stopPreview();
+ Log.d(TAG, "Preview stopped.");
+ } catch (Exception e) {
+ // ignore: tried to stop a non-existent preview
+ Log.d(TAG, "Error starting camera preview: " + e.getMessage());
+ }
+
+ int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation);
+ mCamera.setDisplayOrientation(orientation);
+
+ try {
+ mCamera.setPreviewDisplay(mHolder);
+ mCamera.startPreview();
+ Log.d(TAG, "Camera preview started.");
+ } catch (Exception e) {
+ Log.d(TAG, "Error starting camera preview: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Calculate the correct orientation for a {@link Camera} preview that is displayed on screen.
+ *
+ * Implementation is based on the sample code provided in
+ * {@link Camera#setDisplayOrientation(int)}.
+ */
+ public static int calculatePreviewOrientation(Camera.CameraInfo info, int rotation) {
+ int degrees = 0;
+
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ degrees = 0;
+ break;
+ case Surface.ROTATION_90:
+ degrees = 90;
+ break;
+ case Surface.ROTATION_180:
+ degrees = 180;
+ break;
+ case Surface.ROTATION_270:
+ degrees = 270;
+ break;
+ }
+
+ int result;
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+ result = (info.orientation + degrees) % 360;
+ result = (360 - result) % 360; // compensate the mirror
+ } else { // back-facing
+ result = (info.orientation - degrees + 360) % 360;
+ }
+
+ return result;
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/camera/CameraPreviewFragment.java b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/camera/CameraPreviewFragment.java
new file mode 100644
index 0000000..d0938f6
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/camera/CameraPreviewFragment.java
@@ -0,0 +1,112 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.system.runtimepermissions.camera;
+
+import com.example.android.common.logger.Log;
+import com.example.android.system.runtimepermissions.R;
+
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.Toast;
+
+/**
+ * Displays a {@link CameraPreview} of the first {@link Camera}.
+ * An error message is displayed if the Camera is not available.
+ * <p>
+ * This Fragment is only used to illustrate that access to the Camera API has been granted (or
+ * denied) as part of the runtime permissions model. It is not relevant for the use of the
+ * permissions API.
+ * <p>
+ * Implementation is based directly on the documentation at
+ * http://developer.android.com/guide/topics/media/camera.html
+ */
+public class CameraPreviewFragment extends Fragment {
+
+ private static final String TAG = "CameraPreview";
+
+ /**
+ * Id of the camera to access. 0 is the first camera.
+ */
+ private static final int CAMERA_ID = 0;
+
+ private CameraPreview mPreview;
+ private Camera mCamera;
+
+ public static CameraPreviewFragment newInstance() {
+ return new CameraPreviewFragment();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ // Open an instance of the first camera and retrieve its info.
+ mCamera = getCameraInstance(CAMERA_ID);
+ Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
+ Camera.getCameraInfo(CAMERA_ID, cameraInfo);
+
+ if (mCamera == null || cameraInfo == null) {
+ // Camera is not available, display error message
+ Toast.makeText(getActivity(), "Camera is not available.", Toast.LENGTH_SHORT).show();
+ return inflater.inflate(R.layout.fragment_camera_unavailable, null);
+ }
+
+ View root = inflater.inflate(R.layout.fragment_camera, null);
+
+ // Get the rotation of the screen to adjust the preview image accordingly.
+ final int displayRotation = getActivity().getWindowManager().getDefaultDisplay()
+ .getRotation();
+
+ // Create the Preview view and set it as the content of this Activity.
+ mPreview = new CameraPreview(getActivity(), mCamera, cameraInfo, displayRotation);
+ FrameLayout preview = (FrameLayout) root.findViewById(R.id.camera_preview);
+ preview.addView(mPreview);
+
+ return root;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Stop camera access
+ releaseCamera();
+ }
+
+ /** A safe way to get an instance of the Camera object. */
+ public static Camera getCameraInstance(int cameraId) {
+ Camera c = null;
+ try {
+ c = Camera.open(cameraId); // attempt to get a Camera instance
+ } catch (Exception e) {
+ // Camera is not available (in use or does not exist)
+ Log.d(TAG, "Camera " + cameraId + " is not available: " + e.getMessage());
+ }
+ return c; // returns null if camera is unavailable
+ }
+
+ private void releaseCamera() {
+ if (mCamera != null) {
+ mCamera.release(); // release the camera for other applications
+ mCamera = null;
+ }
+ }
+}
diff --git a/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/contacts/ContactsFragment.java b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/contacts/ContactsFragment.java
new file mode 100644
index 0000000..19f54fb
--- /dev/null
+++ b/samples/browseable/RuntimePermissions/src/com.example.android.system.runtimepermissions/contacts/ContactsFragment.java
@@ -0,0 +1,189 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.system.runtimepermissions.contacts;
+
+import com.example.android.common.logger.Log;
+import com.example.android.system.runtimepermissions.R;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.OperationApplicationException;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+/**
+ * Displays the first contact stored on the device and contains an option to add a dummy contact.
+ * <p>
+ * This Fragment is only used to illustrate that access to the Contacts ContentProvider API has
+ * been granted (or denied) as part of the runtime permissions model. It is not relevant for the
+ * use
+ * of the permissions API.
+ * <p>
+ * This fragments demonstrates a basic use case for accessing the Contacts Provider. The
+ * implementation is based on the training guide available here:
+ * https://developer.android.com/training/contacts-provider/retrieve-names.html
+ */
+public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
+
+ private static final String TAG = "Contacts";
+ private TextView mMessageText = null;
+
+ private static String DUMMY_CONTACT_NAME = "__DUMMY CONTACT from runtime permissions sample";
+
+ /**
+ * Projection for the content provider query includes the id and primary name of a contact.
+ */
+ private static final String[] PROJECTION = {ContactsContract.Contacts._ID,
+ ContactsContract.Contacts.DISPLAY_NAME_PRIMARY};
+ /**
+ * Sort order for the query. Sorted by primary name in ascending order.
+ */
+ private static final String ORDER = ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " ASC";
+
+
+ /**
+ * Creates a new instance of a ContactsFragment.
+ */
+ public static ContactsFragment newInstance() {
+ return new ContactsFragment();
+ }
+
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_contacts, container, false);
+
+ mMessageText = (TextView) rootView.findViewById(R.id.contact_message);
+
+ // Register a listener to add a dummy contact when a button is clicked.
+ Button button = (Button) rootView.findViewById(R.id.contact_add);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ insertDummyContact();
+ }
+ });
+
+ // Register a listener to display the first contact when a button is clicked.
+ button = (Button) rootView.findViewById(R.id.contact_load);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ loadContact();
+ }
+ });
+ return rootView;
+ }
+
+ /**
+ * Restart the Loader to query the Contacts content provider to display the first contact.
+ */
+ private void loadContact() {
+ getLoaderManager().restartLoader(0, null, this);
+ }
+
+ /**
+ * Initialises a new {@link CursorLoader} that queries the {@link ContactsContract}.
+ */
+ @Override
+ public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
+ return new CursorLoader(getActivity(), ContactsContract.Contacts.CONTENT_URI, PROJECTION,
+ null, null, ORDER);
+ }
+
+
+ /**
+ * Dislays either the name of the first contact or a message.
+ */
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+
+ if (cursor != null) {
+ final int totalCount = cursor.getCount();
+ if (totalCount > 0) {
+ cursor.moveToFirst();
+ String name = cursor
+ .getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
+ mMessageText.setText(
+ getResources().getString(R.string.contacts_string, totalCount, name));
+ Log.d(TAG, "First contact loaded: " + name);
+ Log.d(TAG, "Total number of contacts: " + totalCount);
+ Log.d(TAG, "Total number of contacts: " + totalCount);
+ } else {
+ Log.d(TAG, "List of contacts is empty.");
+ mMessageText.setText(R.string.contacts_empty);
+ }
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ mMessageText.setText(R.string.contacts_empty);
+ }
+
+ /**
+ * Accesses the Contacts content provider directly to insert a new contact.
+ * <p>
+ * The contact is called "__DUMMY ENTRY" and only contains a name.
+ */
+ private void insertDummyContact() {
+ // Two operations are needed to insert a new contact.
+ ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(2);
+
+ // First, set up a new raw contact.
+ ContentProviderOperation.Builder op =
+ ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);
+ operations.add(op.build());
+
+ // Next, set the name for the contact.
+ op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE,
+ ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
+ DUMMY_CONTACT_NAME);
+ operations.add(op.build());
+
+ // Apply the operations.
+ ContentResolver resolver = getActivity().getContentResolver();
+ try {
+ resolver.applyBatch(ContactsContract.AUTHORITY, operations);
+ } catch (RemoteException e) {
+ Log.d(TAG, "Could not add a new contact: " + e.getMessage());
+ } catch (OperationApplicationException e) {
+ Log.d(TAG, "Could not add a new contact: " + e.getMessage());
+ }
+ }
+}
diff --git a/samples/browseable/RuntimePermissionsBasic/AndroidManifest.xml b/samples/browseable/RuntimePermissionsBasic/AndroidManifest.xml
new file mode 100644
index 0000000..1f7ea6a
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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.basicpermissions">
+
+ <!-- BEGIN_INCLUDE(manifest) -->
+
+ <!-- Note that all required permissions are declared here in the Android manifest.
+ On Android M and above, use of these permissions is only requested at run time. -->
+ <uses-permission android:name="android.permission.CAMERA"/>
+ <!-- END_INCLUDE(manifest) -->
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme">
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+
+ <!-- Activity that only displays the camera preview. -->
+ <activity
+ android:name=".camera.CameraPreviewActivity"
+ android:exported="false"/>
+
+ </application>
+
+</manifest>
diff --git a/samples/browseable/RuntimePermissionsBasic/_index.jd b/samples/browseable/RuntimePermissionsBasic/_index.jd
new file mode 100644
index 0000000..c4b5d4c
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/_index.jd
@@ -0,0 +1,12 @@
+
+page.tags="RuntimePermissionsBasic"
+sample.group=System
+@jd:body
+
+<p>
+
+ This sample shows runtime permissions available in the Android M and above.
+ This sample shows a basic implementation for requesting permissions at runtime. Click the button to request the Camera permission and open a full-screen camera preview.
+Note: The "RuntimePermissions" sample provides a more complete overview over the runtime permission features available.
+
+ </p>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/drawable-hdpi/tile.9.png b/samples/browseable/RuntimePermissionsBasic/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissionsBasic/res/layout/activity_camera.xml b/samples/browseable/RuntimePermissionsBasic/res/layout/activity_camera.xml
new file mode 100644
index 0000000..b12eee1
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/layout/activity_camera.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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/camera_preview"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ />
diff --git a/samples/browseable/RuntimePermissionsBasic/res/layout/activity_camera_unavailable.xml b/samples/browseable/RuntimePermissionsBasic/res/layout/activity_camera_unavailable.xml
new file mode 100644
index 0000000..af0efe5
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/layout/activity_camera_unavailable.xml
@@ -0,0 +1,37 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/camera_unavailable"/>
+
+ </ScrollView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/browseable/RuntimePermissionsBasic/res/layout/activity_main.xml b/samples/browseable/RuntimePermissionsBasic/res/layout/activity_main.xml
new file mode 100644
index 0000000..c3bf99c
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/layout/activity_main.xml
@@ -0,0 +1,40 @@
+<!--
+ Copyright 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/horizontal_page_margin"
+ android:paddingRight="@dimen/horizontal_page_margin"
+ android:paddingTop="@dimen/vertical_page_margin"
+ android:paddingBottom="@dimen/vertical_page_margin"
+ android:orientation="vertical"
+ tools:context=".MainActivity">
+
+ <TextView
+ android:text="@string/intro"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/horizontal_page_margin"/>
+
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Open Camera Preview"
+ android:id="@+id/button_open_camera"/>
+</LinearLayout>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/mipmap-hdpi/ic_launcher.png b/samples/browseable/RuntimePermissionsBasic/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a7cee76
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissionsBasic/res/mipmap-mdpi/ic_launcher.png b/samples/browseable/RuntimePermissionsBasic/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..378d029
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissionsBasic/res/mipmap-xhdpi/ic_launcher.png b/samples/browseable/RuntimePermissionsBasic/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..c898742
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissionsBasic/res/mipmap-xxhdpi/ic_launcher.png b/samples/browseable/RuntimePermissionsBasic/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..ad4f1df
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissionsBasic/res/mipmap-xxxhdpi/ic_launcher.png b/samples/browseable/RuntimePermissionsBasic/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..484f298
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values-sw600dp/template-dimens.xml b/samples/browseable/RuntimePermissionsBasic/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values-sw600dp/template-styles.xml b/samples/browseable/RuntimePermissionsBasic/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values-v11/template-styles.xml b/samples/browseable/RuntimePermissionsBasic/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values-v21/base-colors.xml b/samples/browseable/RuntimePermissionsBasic/res/values-v21/base-colors.xml
new file mode 100644
index 0000000..8b6ec3f
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values-v21/base-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values-v21/base-template-styles.xml b/samples/browseable/RuntimePermissionsBasic/res/values-v21/base-template-styles.xml
new file mode 100644
index 0000000..c778e4f
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values-v21/base-template-styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light">
+ </style>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values/base-strings.xml b/samples/browseable/RuntimePermissionsBasic/res/values/base-strings.xml
new file mode 100644
index 0000000..1a6b6be
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values/base-strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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">RuntimePermissionsBasic</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ This sample shows runtime permissions available in the Android M and above.
+ This sample shows a basic implementation for requesting permissions at runtime. Click the button to request the Camera permission and open a full-screen camera preview.
+Note: The "RuntimePermissions" sample provides a more complete overview over the runtime permission features available.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values/strings.xml b/samples/browseable/RuntimePermissionsBasic/res/values/strings.xml
new file mode 100644
index 0000000..eb0b7c4
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values/strings.xml
@@ -0,0 +1,6 @@
+<resources>
+ <string name="show_camera">Show camera preview</string>
+ <string name="camera_unavailable"><b>Camera could not be opened.</b>\nThis occurs when the camera is not available (for example it is already in use) or if the system has denied access (for example when camera access has been disabled).</string>
+ <string name="intro">This sample shows a basic implementation for requesting permissions at runtime.\nClick the button below to request the Camera permission and open a full-screen camera preview.</string>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values/template-dimens.xml b/samples/browseable/RuntimePermissionsBasic/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/res/values/template-styles.xml b/samples/browseable/RuntimePermissionsBasic/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/MainActivity.java b/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/MainActivity.java
new file mode 100644
index 0000000..9de3b01
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/MainActivity.java
@@ -0,0 +1,135 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.basicpermissions;
+
+import com.example.android.basicpermissions.camera.CameraPreviewActivity;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+/**
+ * Launcher Activity that demonstrates the use of runtime permissions for Android M.
+ * This Activity requests permissions to access the camera
+ * ({@link android.Manifest.permission#CAMERA})
+ * when the 'Show Camera Preview' button is clicked to start {@link CameraPreviewActivity} once
+ * the permission has been granted.
+ * <p>
+ * First, the status of the Camera permission is checked using {@link
+ * Activity#checkSelfPermission(String)}.
+ * If it has not been granted ({@link PackageManager#PERMISSION_GRANTED}), it is requested by
+ * calling
+ * {@link Activity#requestPermissions(String[], int)}. The result of the request is returned in
+ * {@link Activity#onRequestPermissionsResult(int, String[], int[])}, which starts {@link
+ * CameraPreviewActivity}
+ * if the permission has been granted.
+ */
+public class MainActivity extends Activity {
+
+ private static final int PERMISSION_REQUEST_CAMERA = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ // Register a listener for the 'Show Camera Preview' button.
+ Button b = (Button) findViewById(R.id.button_open_camera);
+ b.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showCameraPreview();
+ }
+ });
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ // BEGIN_INCLUDE(onRequestPermissionsResult)
+ if (requestCode == PERMISSION_REQUEST_CAMERA) {
+ // Request for camera permission.
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ // Permission has been granted. Start camera preview Activity.
+ Toast.makeText(this, "Camera permission was granted. Starting preview.",
+ Toast.LENGTH_SHORT)
+ .show();
+ startCamera();
+ } else {
+ // Permission request was denied.
+ Toast.makeText(this, "Camera permission request was denied.", Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+ // END_INCLUDE(onRequestPermissionsResult)
+ }
+
+ private void showCameraPreview() {
+ // BEGIN_INCLUDE(startCamera)
+ if (isMNC()) {
+ // On Android M and above, need to check if permission has been granted at runtime.
+ if (checkSelfPermission(Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_GRANTED) {
+ // Permission is available, start camera preview
+ startCamera();
+ Toast.makeText(this,
+ "Camera permission has already been granted. Starting preview.",
+ Toast.LENGTH_SHORT).show();
+ } else {
+ // Permission has not been granted and must be requested.
+ Toast.makeText(this,
+ "Permission is not available. Requesting camera permission.",
+ Toast.LENGTH_SHORT).show();
+ requestPermissions(new String[]{Manifest.permission.CAMERA},
+ PERMISSION_REQUEST_CAMERA);
+ }
+ } else {
+ /*
+ Below Android M all permissions have already been grated at install time and do not
+ need to verified or requested.
+ If a permission has been disabled in the system settings, the API will return
+ unavailable or empty data instead. */
+ Toast.makeText(this,
+ "Requested permissions are granted at install time below M and are always "
+ + "available at runtime.",
+ Toast.LENGTH_SHORT).show();
+ startCamera();
+ }
+ // END_INCLUDE(startCamera)
+ }
+
+ private void startCamera() {
+ Intent intent = new Intent(this, CameraPreviewActivity.class);
+ startActivity(intent);
+ }
+
+ public static boolean isMNC() {
+ /*
+ TODO: In the Android M Preview release, checking if the platform is M is done through
+ the codename, not the version code. Once the API has been finalised, the following check
+ should be used: */
+ // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.MNC
+
+ return "MNC".equals(Build.VERSION.CODENAME);
+ }
+}
diff --git a/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/camera/CameraPreview.java b/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/camera/CameraPreview.java
new file mode 100644
index 0000000..7abf2d8
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/camera/CameraPreview.java
@@ -0,0 +1,142 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.basicpermissions.camera;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import java.io.IOException;
+
+/**
+ * Camera preview that displays a {@link Camera}.
+ *
+ * Handles basic lifecycle methods to display and stop the preview.
+ * <p>
+ * Implementation is based directly on the documentation at
+ * http://developer.android.com/guide/topics/media/camera.html
+ */
+public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
+
+ private static final String TAG = "CameraPreview";
+ private SurfaceHolder mHolder;
+ private Camera mCamera;
+ private Camera.CameraInfo mCameraInfo;
+ private int mDisplayOrientation;
+
+ public CameraPreview(Context context, Camera camera, Camera.CameraInfo cameraInfo,
+ int displayOrientation) {
+ super(context);
+
+ // Do not initialise if no camera has been set
+ if (camera == null || cameraInfo == null) {
+ return;
+ }
+ mCamera = camera;
+ mCameraInfo = cameraInfo;
+ mDisplayOrientation = displayOrientation;
+
+ // Install a SurfaceHolder.Callback so we get notified when the
+ // underlying surface is created and destroyed.
+ mHolder = getHolder();
+ mHolder.addCallback(this);
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ // The Surface has been created, now tell the camera where to draw the preview.
+ try {
+ mCamera.setPreviewDisplay(holder);
+ mCamera.startPreview();
+ Log.d(TAG, "Camera preview started.");
+ } catch (IOException e) {
+ Log.d(TAG, "Error setting camera preview: " + e.getMessage());
+ }
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // empty. Take care of releasing the Camera preview in your activity.
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ // If your preview can change or rotate, take care of those events here.
+ // Make sure to stop the preview before resizing or reformatting it.
+
+ if (mHolder.getSurface() == null) {
+ // preview surface does not exist
+ Log.d(TAG, "Preview surface does not exist");
+ return;
+ }
+
+ // stop preview before making changes
+ try {
+ mCamera.stopPreview();
+ Log.d(TAG, "Preview stopped.");
+ } catch (Exception e) {
+ // ignore: tried to stop a non-existent preview
+ Log.d(TAG, "Error starting camera preview: " + e.getMessage());
+ }
+
+ int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation);
+ mCamera.setDisplayOrientation(orientation);
+
+ try {
+ mCamera.setPreviewDisplay(mHolder);
+ mCamera.startPreview();
+ Log.d(TAG, "Camera preview started.");
+ } catch (Exception e) {
+ Log.d(TAG, "Error starting camera preview: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Calculate the correct orientation for a {@link Camera} preview that is displayed on screen.
+ *
+ * Implementation is based on the sample code provided in
+ * {@link Camera#setDisplayOrientation(int)}.
+ */
+ public static int calculatePreviewOrientation(Camera.CameraInfo info, int rotation) {
+ int degrees = 0;
+
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ degrees = 0;
+ break;
+ case Surface.ROTATION_90:
+ degrees = 90;
+ break;
+ case Surface.ROTATION_180:
+ degrees = 180;
+ break;
+ case Surface.ROTATION_270:
+ degrees = 270;
+ break;
+ }
+
+ int result;
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+ result = (info.orientation + degrees) % 360;
+ result = (360 - result) % 360; // compensate the mirror
+ } else { // back-facing
+ result = (info.orientation - degrees + 360) % 360;
+ }
+
+ return result;
+ }
+}
diff --git a/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/camera/CameraPreviewActivity.java b/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/camera/CameraPreviewActivity.java
new file mode 100644
index 0000000..ee589d9
--- /dev/null
+++ b/samples/browseable/RuntimePermissionsBasic/src/com.example.android.basicpermissions/camera/CameraPreviewActivity.java
@@ -0,0 +1,104 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.example.android.basicpermissions.camera;
+
+import com.example.android.basicpermissions.R;
+
+import android.app.Activity;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.widget.FrameLayout;
+import android.widget.Toast;
+
+/**
+ * Displays a {@link CameraPreview} of the first {@link Camera}.
+ * An error message is displayed if the Camera is not available.
+ * <p>
+ * This Activity is only used to illustrate that access to the Camera API has been granted (or
+ * denied) as part of the runtime permissions model. It is not relevant for the use of the
+ * permissions API.
+ * <p>
+ * Implementation is based directly on the documentation at
+ * http://developer.android.com/guide/topics/media/camera.html
+ */
+public class CameraPreviewActivity extends Activity {
+
+ private static final String TAG = "CameraPreview";
+
+ /**
+ * Id of the camera to access. 0 is the first camera.
+ */
+ private static final int CAMERA_ID = 0;
+
+ private CameraPreview mPreview;
+ private Camera mCamera;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Open an instance of the first camera and retrieve its info.
+ mCamera = getCameraInstance(CAMERA_ID);
+ Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
+ Camera.getCameraInfo(CAMERA_ID, cameraInfo);
+
+ if (mCamera == null || cameraInfo == null) {
+ // Camera is not available, display error message
+ Toast.makeText(this, "Camera is not available.", Toast.LENGTH_SHORT).show();
+ setContentView(R.layout.activity_camera_unavailable);
+ } else {
+
+ setContentView(R.layout.activity_camera);
+
+ // Get the rotation of the screen to adjust the preview image accordingly.
+ final int displayRotation = getWindowManager().getDefaultDisplay()
+ .getRotation();
+
+ // Create the Preview view and set it as the content of this Activity.
+ mPreview = new CameraPreview(this, mCamera, cameraInfo, displayRotation);
+ FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
+ preview.addView(mPreview);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Stop camera access
+ releaseCamera();
+ }
+
+ /** A safe way to get an instance of the Camera object. */
+ private Camera getCameraInstance(int cameraId) {
+ Camera c = null;
+ try {
+ c = Camera.open(cameraId); // attempt to get a Camera instance
+ } catch (Exception e) {
+ // Camera is not available (in use or does not exist)
+ Toast.makeText(this, "Camera " + cameraId + " is not available: " + e.getMessage(),
+ Toast.LENGTH_SHORT).show();
+ }
+ return c; // returns null if camera is unavailable
+ }
+
+ private void releaseCamera() {
+ if (mCamera != null) {
+ mCamera.release(); // release the camera for other applications
+ mCamera = null;
+ }
+ }
+}
diff --git a/samples/browseable/ScreenCapture/_index.jd b/samples/browseable/ScreenCapture/_index.jd
index ee22e4b..2b14ede 100644
--- a/samples/browseable/ScreenCapture/_index.jd
+++ b/samples/browseable/ScreenCapture/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="ScreenCapture"
sample.group=Media
@jd:body
diff --git a/samples/browseable/ScreenCapture/res/values-v21/base-colors.xml b/samples/browseable/ScreenCapture/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/ScreenCapture/res/values-v21/base-colors.xml
+++ b/samples/browseable/ScreenCapture/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/ScreenCapture/res/values-v21/base-template-styles.xml b/samples/browseable/ScreenCapture/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/ScreenCapture/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/ScreenCapture/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/ScreenCapture/res/values/base-strings.xml b/samples/browseable/ScreenCapture/res/values/base-strings.xml
index 79880f0..3118f3e 100644
--- a/samples/browseable/ScreenCapture/res/values/base-strings.xml
+++ b/samples/browseable/ScreenCapture/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">ScreenCapture</string>
<string name="intro_message">
diff --git a/samples/browseable/ScreenCapture/src/com.example.android.screencapture/MainActivity.java b/samples/browseable/ScreenCapture/src/com.example.android.screencapture/MainActivity.java
index 67ae9e8..d26e78f 100644
--- a/samples/browseable/ScreenCapture/src/com.example.android.screencapture/MainActivity.java
+++ b/samples/browseable/ScreenCapture/src/com.example.android.screencapture/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.screencapture;
import android.os.Bundle;
diff --git a/samples/browseable/SkeletonWearableApp/_index.jd b/samples/browseable/SkeletonWearableApp/_index.jd
index f3ab425..8ec4d4a 100644
--- a/samples/browseable/SkeletonWearableApp/_index.jd
+++ b/samples/browseable/SkeletonWearableApp/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="SkeletonWearableApp"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/SlidingTabsBasic/_index.jd b/samples/browseable/SlidingTabsBasic/_index.jd
index ec30b9f..bbe9233 100644
--- a/samples/browseable/SlidingTabsBasic/_index.jd
+++ b/samples/browseable/SlidingTabsBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="SlidingTabsBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/SlidingTabsBasic/res/values-v21/base-colors.xml b/samples/browseable/SlidingTabsBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/SlidingTabsBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/SlidingTabsBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/SlidingTabsBasic/res/values-v21/base-template-styles.xml b/samples/browseable/SlidingTabsBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/SlidingTabsBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/SlidingTabsBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/SlidingTabsBasic/res/values/base-strings.xml b/samples/browseable/SlidingTabsBasic/res/values/base-strings.xml
index ea90429..55eb4ce 100644
--- a/samples/browseable/SlidingTabsBasic/res/values/base-strings.xml
+++ b/samples/browseable/SlidingTabsBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">SlidingTabsBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/SlidingTabsBasic/src/com.example.android.slidingtabsbasic/MainActivity.java b/samples/browseable/SlidingTabsBasic/src/com.example.android.slidingtabsbasic/MainActivity.java
index d7d2ff5..2bdc1e5 100644
--- a/samples/browseable/SlidingTabsBasic/src/com.example.android.slidingtabsbasic/MainActivity.java
+++ b/samples/browseable/SlidingTabsBasic/src/com.example.android.slidingtabsbasic/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.slidingtabsbasic;
import android.os.Bundle;
diff --git a/samples/browseable/SlidingTabsColors/_index.jd b/samples/browseable/SlidingTabsColors/_index.jd
index 5fc023e..08c8842 100644
--- a/samples/browseable/SlidingTabsColors/_index.jd
+++ b/samples/browseable/SlidingTabsColors/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="SlidingTabsColors"
sample.group=UI
@jd:body
diff --git a/samples/browseable/SlidingTabsColors/res/values-v21/base-colors.xml b/samples/browseable/SlidingTabsColors/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/SlidingTabsColors/res/values-v21/base-colors.xml
+++ b/samples/browseable/SlidingTabsColors/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/SlidingTabsColors/res/values-v21/base-template-styles.xml b/samples/browseable/SlidingTabsColors/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/SlidingTabsColors/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/SlidingTabsColors/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/SlidingTabsColors/res/values/base-strings.xml b/samples/browseable/SlidingTabsColors/res/values/base-strings.xml
index 66070a4..e77d261 100644
--- a/samples/browseable/SlidingTabsColors/res/values/base-strings.xml
+++ b/samples/browseable/SlidingTabsColors/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">SlidingTabsColors</string>
<string name="intro_message">
diff --git a/samples/browseable/SlidingTabsColors/src/com.example.android.slidingtabscolors/MainActivity.java b/samples/browseable/SlidingTabsColors/src/com.example.android.slidingtabscolors/MainActivity.java
index dc1205b..df55e05 100644
--- a/samples/browseable/SlidingTabsColors/src/com.example.android.slidingtabscolors/MainActivity.java
+++ b/samples/browseable/SlidingTabsColors/src/com.example.android.slidingtabscolors/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.slidingtabscolors;
import android.os.Bundle;
diff --git a/samples/browseable/SpeedTracker/Application/res/values-v21/base-colors.xml b/samples/browseable/SpeedTracker/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/SpeedTracker/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/SpeedTracker/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/SpeedTracker/Application/res/values-v21/base-template-styles.xml b/samples/browseable/SpeedTracker/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/SpeedTracker/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/SpeedTracker/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/SpeedTracker/Application/res/values/base-strings.xml b/samples/browseable/SpeedTracker/Application/res/values/base-strings.xml
index 0d22a87..61f103c 100644
--- a/samples/browseable/SpeedTracker/Application/res/values/base-strings.xml
+++ b/samples/browseable/SpeedTracker/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">Speed Tracker</string>
<string name="intro_message">
diff --git a/samples/browseable/SpeedTracker/_index.jd b/samples/browseable/SpeedTracker/_index.jd
index 298926f..e870952 100644
--- a/samples/browseable/SpeedTracker/_index.jd
+++ b/samples/browseable/SpeedTracker/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Speed Tracker"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/StorageClient/_index.jd b/samples/browseable/StorageClient/_index.jd
index d1444f5..06bf16c 100644
--- a/samples/browseable/StorageClient/_index.jd
+++ b/samples/browseable/StorageClient/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="StorageClient"
sample.group=Content
@jd:body
diff --git a/samples/browseable/StorageClient/res/values-v21/base-colors.xml b/samples/browseable/StorageClient/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/StorageClient/res/values-v21/base-colors.xml
+++ b/samples/browseable/StorageClient/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/StorageClient/res/values-v21/base-template-styles.xml b/samples/browseable/StorageClient/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/StorageClient/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/StorageClient/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/StorageClient/res/values/base-strings.xml b/samples/browseable/StorageClient/res/values/base-strings.xml
index 0e3659d..5b0ccba 100644
--- a/samples/browseable/StorageClient/res/values/base-strings.xml
+++ b/samples/browseable/StorageClient/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">StorageClient</string>
<string name="intro_message">
diff --git a/samples/browseable/StorageClient/res/values/strings.xml b/samples/browseable/StorageClient/res/values/strings.xml
index c571bb5..1f29efc 100644
--- a/samples/browseable/StorageClient/res/values/strings.xml
+++ b/samples/browseable/StorageClient/res/values/strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="sample_action">Show Me The Image</string>
</resources>
diff --git a/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java b/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java
index 2925d01..be9c160 100644
--- a/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java
+++ b/samples/browseable/StorageClient/src/com.example.android.storageclient/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.storageclient;
import android.graphics.Color;
diff --git a/samples/browseable/StorageProvider/_index.jd b/samples/browseable/StorageProvider/_index.jd
index 02e8c66..600fc61 100644
--- a/samples/browseable/StorageProvider/_index.jd
+++ b/samples/browseable/StorageProvider/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="MyCloud"
sample.group=Content
@jd:body
diff --git a/samples/browseable/StorageProvider/res/values-v21/base-colors.xml b/samples/browseable/StorageProvider/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/StorageProvider/res/values-v21/base-colors.xml
+++ b/samples/browseable/StorageProvider/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/StorageProvider/res/values-v21/base-template-styles.xml b/samples/browseable/StorageProvider/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/StorageProvider/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/StorageProvider/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/StorageProvider/res/values/base-strings.xml b/samples/browseable/StorageProvider/res/values/base-strings.xml
index 3453e88..1712bef 100644
--- a/samples/browseable/StorageProvider/res/values/base-strings.xml
+++ b/samples/browseable/StorageProvider/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">MyCloud</string>
<string name="intro_message">
diff --git a/samples/browseable/StorageProvider/res/values/strings.xml b/samples/browseable/StorageProvider/res/values/strings.xml
index cde5fb5..e72be8d 100644
--- a/samples/browseable/StorageProvider/res/values/strings.xml
+++ b/samples/browseable/StorageProvider/res/values/strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="sample_action">Log in</string>
</resources>
diff --git a/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java b/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java
index e46a55a..4d41ff4 100644
--- a/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java
+++ b/samples/browseable/StorageProvider/src/com.example.android.storageprovider/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.storageprovider;
import android.graphics.Color;
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/_index.jd b/samples/browseable/SwipeRefreshLayoutBasic/_index.jd
index ca15805..9d06020 100644
--- a/samples/browseable/SwipeRefreshLayoutBasic/_index.jd
+++ b/samples/browseable/SwipeRefreshLayoutBasic/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="SwipeRefreshLayoutBasic"
sample.group=UI
@jd:body
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-colors.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-colors.xml
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-template-styles.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/res/values/base-strings.xml b/samples/browseable/SwipeRefreshLayoutBasic/res/values/base-strings.xml
index a9f797f..a9421d4 100644
--- a/samples/browseable/SwipeRefreshLayoutBasic/res/values/base-strings.xml
+++ b/samples/browseable/SwipeRefreshLayoutBasic/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">SwipeRefreshLayoutBasic</string>
<string name="intro_message">
diff --git a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/MainActivity.java b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/MainActivity.java
index 61e70fc..bf969e3 100644
--- a/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/MainActivity.java
+++ b/samples/browseable/SwipeRefreshLayoutBasic/src/com.example.android.swiperefreshlayoutbasic/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.swiperefreshlayoutbasic;
import android.os.Bundle;
diff --git a/samples/browseable/SwipeRefreshListFragment/_index.jd b/samples/browseable/SwipeRefreshListFragment/_index.jd
index bbbedf7..c424ab4 100644
--- a/samples/browseable/SwipeRefreshListFragment/_index.jd
+++ b/samples/browseable/SwipeRefreshListFragment/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="SwipeRefreshListFragment"
sample.group=UI
@jd:body
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-colors.xml b/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-colors.xml
+++ b/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-template-styles.xml b/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/SwipeRefreshListFragment/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/SwipeRefreshListFragment/res/values/base-strings.xml b/samples/browseable/SwipeRefreshListFragment/res/values/base-strings.xml
index 4a327dd..13d46eb 100644
--- a/samples/browseable/SwipeRefreshListFragment/res/values/base-strings.xml
+++ b/samples/browseable/SwipeRefreshListFragment/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">SwipeRefreshListFragment</string>
<string name="intro_message">
diff --git a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/MainActivity.java b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/MainActivity.java
index ca3a5bf..cbec157 100644
--- a/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/MainActivity.java
+++ b/samples/browseable/SwipeRefreshListFragment/src/com.example.android.swiperefreshlistfragment/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.swiperefreshlistfragment;
import android.os.Bundle;
diff --git a/samples/browseable/SwipeRefreshMultipleViews/_index.jd b/samples/browseable/SwipeRefreshMultipleViews/_index.jd
index 0cc246b..b65f72c 100644
--- a/samples/browseable/SwipeRefreshMultipleViews/_index.jd
+++ b/samples/browseable/SwipeRefreshMultipleViews/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="SwipeRefreshMultipleViews"
sample.group=UI
@jd:body
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-colors.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-colors.xml
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-template-styles.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/SwipeRefreshMultipleViews/res/values/base-strings.xml b/samples/browseable/SwipeRefreshMultipleViews/res/values/base-strings.xml
index f7d4341..5d44bbe 100644
--- a/samples/browseable/SwipeRefreshMultipleViews/res/values/base-strings.xml
+++ b/samples/browseable/SwipeRefreshMultipleViews/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">SwipeRefreshMultipleViews</string>
<string name="intro_message">
diff --git a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MainActivity.java b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MainActivity.java
index a8bbf4d..7af9990 100644
--- a/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MainActivity.java
+++ b/samples/browseable/SwipeRefreshMultipleViews/src/com.example.android.swiperefreshmultipleviews/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.swiperefreshmultipleviews;
import android.os.Bundle;
diff --git a/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-colors.xml b/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-template-styles.xml b/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/SynchronizedNotifications/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/SynchronizedNotifications/Application/res/values/base-strings.xml b/samples/browseable/SynchronizedNotifications/Application/res/values/base-strings.xml
index 8b6d8ff..d787b17 100644
--- a/samples/browseable/SynchronizedNotifications/Application/res/values/base-strings.xml
+++ b/samples/browseable/SynchronizedNotifications/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">SynchronizedNotifications</string>
<string name="intro_message">
diff --git a/samples/browseable/SynchronizedNotifications/Application/src/com.example.android.wearable.synchronizednotifications/MainActivity.java b/samples/browseable/SynchronizedNotifications/Application/src/com.example.android.wearable.synchronizednotifications/MainActivity.java
index ad1b372..016f20f 100644
--- a/samples/browseable/SynchronizedNotifications/Application/src/com.example.android.wearable.synchronizednotifications/MainActivity.java
+++ b/samples/browseable/SynchronizedNotifications/Application/src/com.example.android.wearable.synchronizednotifications/MainActivity.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+
package com.example.android.wearable.synchronizednotifications;
import android.graphics.Color;
diff --git a/samples/browseable/SynchronizedNotifications/_index.jd b/samples/browseable/SynchronizedNotifications/_index.jd
index fe882ad..d2e28d0 100644
--- a/samples/browseable/SynchronizedNotifications/_index.jd
+++ b/samples/browseable/SynchronizedNotifications/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="SynchronizedNotifications"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/TextLinkify/_index.jd b/samples/browseable/TextLinkify/_index.jd
index 5b4c000..efd8f9e 100644
--- a/samples/browseable/TextLinkify/_index.jd
+++ b/samples/browseable/TextLinkify/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="TextLinkify"
sample.group=Views
@jd:body
diff --git a/samples/browseable/TextLinkify/res/values-v21/base-colors.xml b/samples/browseable/TextLinkify/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/TextLinkify/res/values-v21/base-colors.xml
+++ b/samples/browseable/TextLinkify/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/TextLinkify/res/values-v21/base-template-styles.xml b/samples/browseable/TextLinkify/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/TextLinkify/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/TextLinkify/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/TextLinkify/res/values/base-strings.xml b/samples/browseable/TextLinkify/res/values/base-strings.xml
index 831f4b2..c44ca09 100644
--- a/samples/browseable/TextLinkify/res/values/base-strings.xml
+++ b/samples/browseable/TextLinkify/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">TextLinkify</string>
<string name="intro_message">
diff --git a/samples/browseable/TextSwitcher/_index.jd b/samples/browseable/TextSwitcher/_index.jd
index ddcc042..fccca3a 100644
--- a/samples/browseable/TextSwitcher/_index.jd
+++ b/samples/browseable/TextSwitcher/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="TextSwitcher"
sample.group=UI
@jd:body
diff --git a/samples/browseable/TextSwitcher/res/values-v21/base-colors.xml b/samples/browseable/TextSwitcher/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/TextSwitcher/res/values-v21/base-colors.xml
+++ b/samples/browseable/TextSwitcher/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/TextSwitcher/res/values-v21/base-template-styles.xml b/samples/browseable/TextSwitcher/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/TextSwitcher/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/TextSwitcher/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/TextSwitcher/res/values/base-strings.xml b/samples/browseable/TextSwitcher/res/values/base-strings.xml
index 223f068..9e6ab5e 100644
--- a/samples/browseable/TextSwitcher/res/values/base-strings.xml
+++ b/samples/browseable/TextSwitcher/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">TextSwitcher</string>
<string name="intro_message">
diff --git a/samples/browseable/Timer/_index.jd b/samples/browseable/Timer/_index.jd
index 68941ef..5b285e8 100644
--- a/samples/browseable/Timer/_index.jd
+++ b/samples/browseable/Timer/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="Timer"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/WatchFace/Application/res/values-v21/base-colors.xml b/samples/browseable/WatchFace/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/WatchFace/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/WatchFace/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/WatchFace/Application/res/values-v21/base-template-styles.xml b/samples/browseable/WatchFace/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/WatchFace/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/WatchFace/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/WatchFace/Application/res/values/base-strings.xml b/samples/browseable/WatchFace/Application/res/values/base-strings.xml
index 5108f61..ef8f1d3 100644
--- a/samples/browseable/WatchFace/Application/res/values/base-strings.xml
+++ b/samples/browseable/WatchFace/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">WatchFace</string>
<string name="intro_message">
diff --git a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/AnalogWatchFaceService.java b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/AnalogWatchFaceService.java
index f0fb4f5..15c550f 100644
--- a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/AnalogWatchFaceService.java
+++ b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/AnalogWatchFaceService.java
@@ -33,10 +33,10 @@
import android.support.wearable.watchface.CanvasWatchFaceService;
import android.support.wearable.watchface.WatchFaceService;
import android.support.wearable.watchface.WatchFaceStyle;
-import android.text.format.Time;
import android.util.Log;
import android.view.SurfaceHolder;
+import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
@@ -64,12 +64,14 @@
private class Engine extends CanvasWatchFaceService.Engine {
static final int MSG_UPDATE_TIME = 0;
+ static final float TWO_PI = (float) Math.PI * 2f;
+
Paint mHourPaint;
Paint mMinutePaint;
Paint mSecondPaint;
Paint mTickPaint;
boolean mMute;
- Time mTime;
+ Calendar mCalendar;
/** Handler to update the time once a second in interactive mode. */
final Handler mUpdateTimeHandler = new Handler() {
@@ -95,8 +97,8 @@
final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mTime.clear(intent.getStringExtra("time-zone"));
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
+ invalidate();
}
};
boolean mRegisteredTimeZoneReceiver = false;
@@ -124,7 +126,7 @@
.build());
Resources resources = AnalogWatchFaceService.this.getResources();
- Drawable backgroundDrawable = resources.getDrawable(R.drawable.bg);
+ Drawable backgroundDrawable = resources.getDrawable(R.drawable.bg, null /* theme */);
mBackgroundBitmap = ((BitmapDrawable) backgroundDrawable).getBitmap();
mHourPaint = new Paint();
@@ -150,7 +152,7 @@
mTickPaint.setStrokeWidth(2.f);
mTickPaint.setAntiAlias(true);
- mTime = new Time();
+ mCalendar = Calendar.getInstance();
}
@Override
@@ -212,7 +214,7 @@
@Override
public void onDraw(Canvas canvas, Rect bounds) {
- mTime.setToNow();
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
int width = bounds.width();
int height = bounds.height();
@@ -236,7 +238,7 @@
float innerTickRadius = centerX - 10;
float outerTickRadius = centerX;
for (int tickIndex = 0; tickIndex < 12; tickIndex++) {
- float tickRot = (float) (tickIndex * Math.PI * 2 / 12);
+ float tickRot = tickIndex * TWO_PI / 12;
float innerX = (float) Math.sin(tickRot) * innerTickRadius;
float innerY = (float) -Math.cos(tickRot) * innerTickRadius;
float outerX = (float) Math.sin(tickRot) * outerTickRadius;
@@ -245,10 +247,13 @@
centerX + outerX, centerY + outerY, mTickPaint);
}
- float secRot = mTime.second / 30f * (float) Math.PI;
- int minutes = mTime.minute;
- float minRot = minutes / 30f * (float) Math.PI;
- float hrRot = ((mTime.hour + (minutes / 60f)) / 6f ) * (float) Math.PI;
+ float seconds =
+ mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f;
+ float secRot = seconds / 60f * TWO_PI;
+ float minutes = mCalendar.get(Calendar.MINUTE) + seconds / 60f;
+ float minRot = minutes / 60f * TWO_PI;
+ float hours = mCalendar.get(Calendar.HOUR) + minutes / 60f;
+ float hrRot = hours / 12f * TWO_PI;
float secLength = centerX - 20;
float minLength = centerX - 40;
@@ -280,8 +285,7 @@
registerReceiver();
// Update time zone in case it changed while we weren't visible.
- mTime.clear(TimeZone.getDefault().getID());
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
} else {
unregisterReceiver();
}
diff --git a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/DigitalWatchFaceService.java b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/DigitalWatchFaceService.java
index b8b1314..0bc420d 100644
--- a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/DigitalWatchFaceService.java
+++ b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/DigitalWatchFaceService.java
@@ -31,7 +31,7 @@
import android.support.wearable.watchface.CanvasWatchFaceService;
import android.support.wearable.watchface.WatchFaceService;
import android.support.wearable.watchface.WatchFaceStyle;
-import android.text.format.Time;
+import android.text.format.DateFormat;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.WindowInsets;
@@ -46,6 +46,7 @@
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.Wearable;
+import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
@@ -125,8 +126,8 @@
final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mTime.clear(intent.getStringExtra("time-zone"));
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
+ invalidate();
}
};
boolean mRegisteredTimeZoneReceiver = false;
@@ -139,7 +140,7 @@
Paint mColonPaint;
float mColonWidth;
boolean mMute;
- Time mTime;
+ Calendar mCalendar;
boolean mShouldDrawColons;
float mXOffset;
float mYOffset;
@@ -185,7 +186,7 @@
mAmPmPaint = createTextPaint(resources.getColor(R.color.digital_am_pm));
mColonPaint = createTextPaint(resources.getColor(R.color.digital_colons));
- mTime = new Time();
+ mCalendar = Calendar.getInstance();
}
@Override
@@ -219,8 +220,7 @@
registerReceiver();
// Update time zone in case it changed while we weren't visible.
- mTime.clear(TimeZone.getDefault().getID());
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
} else {
unregisterReceiver();
@@ -403,18 +403,14 @@
return String.format("%02d", hour);
}
- private int convertTo12Hour(int hour) {
- int result = hour % 12;
- return (result == 0) ? 12 : result;
- }
-
- private String getAmPmString(int hour) {
- return (hour < 12) ? mAmString : mPmString;
+ private String getAmPmString(int amPm) {
+ return amPm == Calendar.AM ? mAmString : mPmString;
}
@Override
public void onDraw(Canvas canvas, Rect bounds) {
- mTime.setToNow();
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
+ boolean is24Hour = DateFormat.is24HourFormat(DigitalWatchFaceService.this);
// Show colons for the first half of each second so the colons blink on when the time
// updates.
@@ -425,7 +421,19 @@
// Draw the hours.
float x = mXOffset;
- String hourString = String.valueOf(convertTo12Hour(mTime.hour));
+ String hourString;
+ if (is24Hour) {
+ hourString = formatTwoDigitNumber(mCalendar.get(Calendar.HOUR_OF_DAY));
+ } else {
+ int hour = mCalendar.get(Calendar.HOUR);
+ if (hour == 0) {
+ hour = 12;
+ }
+ hourString = String.valueOf(hour);
+ if (hour < 10) {
+ x += mHourPaint.measureText("0");
+ }
+ }
canvas.drawText(hourString, x, mYOffset, mHourPaint);
x += mHourPaint.measureText(hourString);
@@ -437,22 +445,23 @@
x += mColonWidth;
// Draw the minutes.
- String minuteString = formatTwoDigitNumber(mTime.minute);
+ String minuteString = formatTwoDigitNumber(mCalendar.get(Calendar.MINUTE));
canvas.drawText(minuteString, x, mYOffset, mMinutePaint);
x += mMinutePaint.measureText(minuteString);
- // In ambient and mute modes, draw AM/PM. Otherwise, draw a second blinking
- // colon followed by the seconds.
- if (isInAmbientMode() || mMute) {
- x += mColonWidth;
- canvas.drawText(getAmPmString(mTime.hour), x, mYOffset, mAmPmPaint);
- } else {
+ // In unmuted interactive mode, draw a second blinking colon followed by the seconds.
+ // Otherwise, if we're in 12-hour mode, draw AM/PM
+ if (!isInAmbientMode() && !mMute) {
if (mShouldDrawColons) {
canvas.drawText(COLON_STRING, x, mYOffset, mColonPaint);
}
x += mColonWidth;
- canvas.drawText(formatTwoDigitNumber(mTime.second), x, mYOffset,
- mSecondPaint);
+ canvas.drawText(formatTwoDigitNumber(
+ mCalendar.get(Calendar.SECOND)), x, mYOffset, mSecondPaint);
+ } else if (!is24Hour) {
+ x += mColonWidth;
+ canvas.drawText(getAmPmString(
+ mCalendar.get(Calendar.AM_PM)), x, mYOffset, mAmPmPaint);
}
}
diff --git a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/SweepWatchFaceService.java b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/SweepWatchFaceService.java
index 44e9569..193f29a 100644
--- a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/SweepWatchFaceService.java
+++ b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/SweepWatchFaceService.java
@@ -31,10 +31,10 @@
import android.support.wearable.watchface.CanvasWatchFaceService;
import android.support.wearable.watchface.WatchFaceService;
import android.support.wearable.watchface.WatchFaceStyle;
-import android.text.format.Time;
import android.util.Log;
import android.view.SurfaceHolder;
+import java.util.Calendar;
import java.util.TimeZone;
/**
@@ -53,18 +53,20 @@
}
private class Engine extends CanvasWatchFaceService.Engine {
+ static final float TWO_PI = (float) Math.PI * 2f;
+
Paint mHourPaint;
Paint mMinutePaint;
Paint mSecondPaint;
Paint mTickPaint;
boolean mMute;
- Time mTime;
+ Calendar mCalendar;
final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mTime.clear(intent.getStringExtra("time-zone"));
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
+ invalidate();
}
};
boolean mRegisteredTimeZoneReceiver = false;
@@ -92,7 +94,7 @@
.build());
Resources resources = SweepWatchFaceService.this.getResources();
- Drawable backgroundDrawable = resources.getDrawable(R.drawable.bg);
+ Drawable backgroundDrawable = resources.getDrawable(R.drawable.bg, null /* theme */);
mBackgroundBitmap = ((BitmapDrawable) backgroundDrawable).getBitmap();
mHourPaint = new Paint();
@@ -118,7 +120,7 @@
mTickPaint.setStrokeWidth(2.f);
mTickPaint.setAntiAlias(true);
- mTime = new Time();
+ mCalendar = Calendar.getInstance();
}
@Override
@@ -174,8 +176,7 @@
Log.v(TAG, "onDraw");
}
long now = System.currentTimeMillis();
- mTime.set(now);
- int milliseconds = (int) (now % 1000);
+ mCalendar.setTimeInMillis(now);
int width = bounds.width();
int height = bounds.height();
@@ -208,11 +209,13 @@
centerX + outerX, centerY + outerY, mTickPaint);
}
- float seconds = mTime.second + milliseconds / 1000f;
- float secRot = seconds / 30f * (float) Math.PI;
- int minutes = mTime.minute;
- float minRot = minutes / 30f * (float) Math.PI;
- float hrRot = ((mTime.hour + (minutes / 60f)) / 6f ) * (float) Math.PI;
+ float seconds =
+ mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f;
+ float secRot = seconds / 60f * TWO_PI;
+ float minutes = mCalendar.get(Calendar.MINUTE) + seconds / 60f;
+ float minRot = minutes / 60f * TWO_PI;
+ float hours = mCalendar.get(Calendar.HOUR) + minutes / 60f;
+ float hrRot = hours / 12f * TWO_PI;
float secLength = centerX - 20;
float minLength = centerX - 40;
@@ -246,8 +249,7 @@
registerReceiver();
// Update time zone in case it changed while we weren't visible.
- mTime.clear(TimeZone.getDefault().getID());
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
invalidate();
} else {
diff --git a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/TiltWatchFaceService.java b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/TiltWatchFaceService.java
index 6dd01b0..ffb0b6c 100644
--- a/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/TiltWatchFaceService.java
+++ b/samples/browseable/WatchFace/Wearable/src/com.example.android.wearable.watchface/TiltWatchFaceService.java
@@ -24,11 +24,11 @@
import android.opengl.Matrix;
import android.support.wearable.watchface.Gles2WatchFaceService;
import android.support.wearable.watchface.WatchFaceStyle;
-import android.text.format.Time;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
+import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
@@ -44,6 +44,9 @@
/** Expected frame rate in interactive mode. */
private static final long FPS = 60;
+ /** Z distance from the camera to the watchface. */
+ private static final float EYE_Z = 2.3f;
+
/** How long each frame is displayed at expected frame rate. */
private static final long FRAME_PERIOD_MS = TimeUnit.SECONDS.toMillis(1) / FPS;
@@ -107,7 +110,7 @@
/** Triangle for the hour hand. */
private Gles2ColoredTriangleList mHourHandTriangle;
- private Time mTime = new Time();
+ private Calendar mCalendar = Calendar.getInstance();
/** Whether we've registered {@link #mTimeZoneReceiver}. */
private boolean mRegisteredTimeZoneReceiver;
@@ -115,8 +118,8 @@
private final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mTime.clear(intent.getStringExtra("time-zone"));
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
+ invalidate();
}
};
@@ -170,7 +173,7 @@
mMinuteHandTriangle = createHand(
triangleProgram,
0.06f /* width */,
- 0.8f /* height */,
+ 1f /* height */,
new float[]{
0.7f /* red */,
0.7f /* green */,
@@ -181,7 +184,7 @@
mHourHandTriangle = createHand(
triangleProgram,
0.1f /* width */,
- 0.5f /* height */,
+ 0.6f /* height */,
new float[]{
0.9f /* red */,
0.9f /* green */,
@@ -204,14 +207,14 @@
final float eyeY = (float) Math.sin(cameraAngle);
Matrix.setLookAtM(mViewMatrices[i],
0, // dest index
- eyeX, eyeY, -3, // eye
+ eyeX, eyeY, EYE_Z, // eye
0, 0, 0, // center
0, 1, 0); // up vector
}
Matrix.setLookAtM(mAmbientViewMatrix,
0, // dest index
- 0, 0, -3, // eye
+ 0, 0, EYE_Z, // eye
0, 0, 0, // center
0, 1, 0); // up vector
}
@@ -378,8 +381,7 @@
registerReceiver();
// Update time zone in case it changed while we were detached.
- mTime.clear(TimeZone.getDefault().getID());
- mTime.setToNow();
+ mCalendar.setTimeZone(TimeZone.getDefault());
invalidate();
} else {
@@ -436,26 +438,28 @@
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Compute angle indices for the three hands.
- mTime.setToNow();
- final int secIndex = mTime.second * 360 / 60;
- final int minIndex = mTime.minute * 360 / 60;
- final int hoursIndex = (mTime.hour % 12) * 360 / 12 + mTime.minute * 360 / 60 / 12;
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
+ float seconds =
+ mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f;
+ float minutes = mCalendar.get(Calendar.MINUTE) + seconds / 60f;
+ float hours = mCalendar.get(Calendar.HOUR) + minutes / 60f;
+ final int secIndex = (int) (seconds / 60f * 360f);
+ final int minIndex = (int) (minutes / 60f * 360f);
+ final int hoursIndex = (int) (hours / 12f * 360f);
// Draw triangles from back to front. Don't draw the second hand in ambient mode.
- {
- // Combine the model matrix with the projection and camera view.
- Matrix.multiplyMM(mMvpMatrix, 0, vpMatrix, 0, mModelMatrices[hoursIndex], 0);
- // Draw the triangle.
- mHourHandTriangle.draw(mMvpMatrix);
- }
- {
- // Combine the model matrix with the projection and camera view.
- Matrix.multiplyMM(mMvpMatrix, 0, vpMatrix, 0, mModelMatrices[minIndex], 0);
+ // Combine the model matrix with the projection and camera view.
+ Matrix.multiplyMM(mMvpMatrix, 0, vpMatrix, 0, mModelMatrices[hoursIndex], 0);
- // Draw the triangle.
- mMinuteHandTriangle.draw(mMvpMatrix);
- }
+ // Draw the triangle.
+ mHourHandTriangle.draw(mMvpMatrix);
+
+ // Combine the model matrix with the projection and camera view.
+ Matrix.multiplyMM(mMvpMatrix, 0, vpMatrix, 0, mModelMatrices[minIndex], 0);
+
+ // Draw the triangle.
+ mMinuteHandTriangle.draw(mMvpMatrix);
if (!isInAmbientMode()) {
// Combine the model matrix with the projection and camera view.
Matrix.multiplyMM(mMvpMatrix, 0, vpMatrix, 0, mModelMatrices[secIndex], 0);
@@ -463,11 +467,10 @@
// Draw the triangle.
mSecondHandTriangle.draw(mMvpMatrix);
}
- {
- // Draw the major and minor ticks.
- mMajorTickTriangles.draw(vpMatrix);
- mMinorTickTriangles.draw(vpMatrix);
- }
+
+ // Draw the major and minor ticks.
+ mMajorTickTriangles.draw(vpMatrix);
+ mMinorTickTriangles.draw(vpMatrix);
// Draw every frame as long as we're visible and in interactive mode.
if (isVisible() && !isInAmbientMode()) {
diff --git a/samples/browseable/WatchFace/_index.jd b/samples/browseable/WatchFace/_index.jd
index fcba857..8c803fa 100644
--- a/samples/browseable/WatchFace/_index.jd
+++ b/samples/browseable/WatchFace/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="WatchFace"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/WatchViewStub/_index.jd b/samples/browseable/WatchViewStub/_index.jd
index 7341f92..e518356 100644
--- a/samples/browseable/WatchViewStub/_index.jd
+++ b/samples/browseable/WatchViewStub/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="WatchViewStub"
sample.group=Wearable
@jd:body
diff --git a/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-colors.xml b/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-colors.xml
index 34c9cd1..8b6ec3f 100644
--- a/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-colors.xml
+++ b/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-colors.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
diff --git a/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-template-styles.xml b/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-template-styles.xml
index 0b2948f..c778e4f 100644
--- a/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-template-styles.xml
+++ b/samples/browseable/XYZTouristAttractions/Application/res/values-v21/base-template-styles.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<!-- Activity themes -->
diff --git a/samples/browseable/XYZTouristAttractions/Application/res/values/base-strings.xml b/samples/browseable/XYZTouristAttractions/Application/res/values/base-strings.xml
index e551fe1..90b90ef 100644
--- a/samples/browseable/XYZTouristAttractions/Application/res/values/base-strings.xml
+++ b/samples/browseable/XYZTouristAttractions/Application/res/values/base-strings.xml
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<resources>
<string name="app_name">XYZTouristAttractions</string>
<string name="intro_message">
diff --git a/samples/browseable/XYZTouristAttractions/_index.jd b/samples/browseable/XYZTouristAttractions/_index.jd
index a48e947..78bfc12 100644
--- a/samples/browseable/XYZTouristAttractions/_index.jd
+++ b/samples/browseable/XYZTouristAttractions/_index.jd
@@ -1,3 +1,4 @@
+
page.tags="XYZTouristAttractions"
sample.group=Wearable
@jd:body
diff --git a/samples/samples_source.prop_template b/samples/samples_source.prop_template
index d3cdfd5..523d6bd 100644
--- a/samples/samples_source.prop_template
+++ b/samples/samples_source.prop_template
@@ -1,4 +1,4 @@
Pkg.UserSrc=false
-Pkg.Revision=1
+Pkg.Revision=2
AndroidVersion.ApiLevel=${PLATFORM_SDK_VERSION}
AndroidVersion.CodeName=${PLATFORM_VERSION_CODENAME}
diff --git a/scripts/gdbclient b/scripts/gdbclient
index 5113977..b74a8f0 100755
--- a/scripts/gdbclient
+++ b/scripts/gdbclient
@@ -13,16 +13,16 @@
source $ANDROID_BUILD_TOP/build/envsetup.sh
function adb_get_product_device() {
- local candidate=`adb shell getprop ro.product.device | sed s/.$//`
+ local candidate=`adb shell getprop ro.product.device | tr -d '\r\n'`
if [ -z $candidate ]; then
- candidate=`adb shell getprop ro.hardware | sed s/.$//`
+ candidate=`adb shell getprop ro.hardware | tr -d '\r\n'`
fi
echo $candidate
}
# returns 0 when process is not traced
function adb_get_traced_by() {
- echo `adb shell cat /proc/$1/status | grep -e "^TracerPid:" | sed "s/^TracerPid:\t//" | sed s/.$//`
+ echo `adb shell cat /proc/$1/status | grep -e "^TracerPid:" | sed "s/^TracerPid:\t//" | tr -d '\r\n'`
}
function get_symbols_directory()
@@ -95,7 +95,7 @@
fi
fi
- local EXE=`adb shell readlink /proc/$PID/exe | sed s/.$//`
+ local EXE=`adb shell readlink /proc/$PID/exe | tr -d '\r\n'`
if [ -z "$EXE" ]; then
echo "Error: no such pid=$PID - is process still alive?"
@@ -126,7 +126,7 @@
local GDB=
local GDB64=
- local CPU_ABI=`adb shell getprop ro.product.cpu.abilist | sed s/.$//`
+ local CPU_ABI=`adb shell getprop ro.product.cpu.abilist | tr -d '\r\n'`
# TODO: Derive this differently to correctly support multi-arch. We could try to parse
# /proc/pid/exe. Right now, we prefer 64bit by checking those entries first.
# TODO: Correctly support native bridge, which makes parsing abilist very brittle.