diff --git a/samples/browseable/ActivitySceneTransitionBasic/AndroidManifest.xml b/samples/browseable/ActivitySceneTransitionBasic/AndroidManifest.xml
new file mode 100644
index 000000000..ae64d6f4c
--- /dev/null
+++ b/samples/browseable/ActivitySceneTransitionBasic/AndroidManifest.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+ + Demonstrates how to the use Activity scene transitions when transitions + from one Activity to another. Uses a combination of moveImage and changeBounds + to nicely transition a grid of images to an Activity with a large image and detail + text. + +
diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/drawable-hdpi/ic_launcher.png b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..a598447aa Binary files /dev/null and b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/drawable-hdpi/tile.9.png b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/drawable-mdpi/ic_launcher.png b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..8aaa6c942 Binary files /dev/null and b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..3667baaa5 Binary files /dev/null and b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..e3c4a3291 Binary files /dev/null and b/samples/browseable/ActivitySceneTransitionBasic/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/ActivitySceneTransitionBasic/res/layout/activity_main.xml b/samples/browseable/ActivitySceneTransitionBasic/res/layout/activity_main.xml new file mode 100755 index 000000000..be1aa49d9 --- /dev/null +++ b/samples/browseable/ActivitySceneTransitionBasic/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + +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.
+ */ +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/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogFragment.java b/samples/browseable/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/ActivitySceneTransitionBasic/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/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogNode.java b/samples/browseable/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/ActivitySceneTransitionBasic/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/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogView.java b/samples/browseable/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/ActivitySceneTransitionBasic/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/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogWrapper.java b/samples/browseable/ActivitySceneTransitionBasic/src/com.example.android.common.logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/ActivitySceneTransitionBasic/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/ActivitySceneTransitionBasic/src/com.example.android.common.logger/MessageOnlyLogFilter.java b/samples/browseable/ActivitySceneTransitionBasic/src/com.example.android.common.logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/ActivitySceneTransitionBasic/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/AppRestrictionEnforcer/AndroidManifest.xml b/samples/browseable/AppRestrictionEnforcer/AndroidManifest.xml new file mode 100644 index 000000000..c66b4b33e --- /dev/null +++ b/samples/browseable/AppRestrictionEnforcer/AndroidManifest.xml @@ -0,0 +1,58 @@ + + + ++ + This sample demonstrates how to set restrictions to other apps as a profile owner. + Use AppRestrictionSchema sample as a app with available restrictions. + +
diff --git a/samples/browseable/AppRestrictionEnforcer/res/drawable-hdpi/ic_launcher.png b/samples/browseable/AppRestrictionEnforcer/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..e7bd161ef Binary files /dev/null and b/samples/browseable/AppRestrictionEnforcer/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionEnforcer/res/drawable-hdpi/tile.9.png b/samples/browseable/AppRestrictionEnforcer/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/AppRestrictionEnforcer/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/AppRestrictionEnforcer/res/drawable-mdpi/ic_launcher.png b/samples/browseable/AppRestrictionEnforcer/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..4c42c9c45 Binary files /dev/null and b/samples/browseable/AppRestrictionEnforcer/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionEnforcer/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/AppRestrictionEnforcer/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..3ec336888 Binary files /dev/null and b/samples/browseable/AppRestrictionEnforcer/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionEnforcer/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/AppRestrictionEnforcer/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..730f80cd2 Binary files /dev/null and b/samples/browseable/AppRestrictionEnforcer/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionEnforcer/res/layout/activity_main.xml b/samples/browseable/AppRestrictionEnforcer/res/layout/activity_main.xml new file mode 100755 index 000000000..be1aa49d9 --- /dev/null +++ b/samples/browseable/AppRestrictionEnforcer/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + ++ + This sample shows how to use app restrictions. This application has one boolean + restriction with a key \"can_say_hello\" that defines whether the only feature of this + app (press the button to show \"Hello\" message) is enabled or disabled. Use + AppRestrictionEnforcer sample to toggle the restriction. + +
diff --git a/samples/browseable/AppRestrictionSchema/res/drawable-hdpi/ic_launcher.png b/samples/browseable/AppRestrictionSchema/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..74344d7c3 Binary files /dev/null and b/samples/browseable/AppRestrictionSchema/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionSchema/res/drawable-hdpi/tile.9.png b/samples/browseable/AppRestrictionSchema/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/AppRestrictionSchema/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/AppRestrictionSchema/res/drawable-mdpi/ic_launcher.png b/samples/browseable/AppRestrictionSchema/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..a01dbd77b Binary files /dev/null and b/samples/browseable/AppRestrictionSchema/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionSchema/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/AppRestrictionSchema/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..19bb139de Binary files /dev/null and b/samples/browseable/AppRestrictionSchema/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionSchema/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/AppRestrictionSchema/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..9922ae6e0 Binary files /dev/null and b/samples/browseable/AppRestrictionSchema/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/AppRestrictionSchema/res/layout-w720dp/activity_main.xml b/samples/browseable/AppRestrictionSchema/res/layout-w720dp/activity_main.xml new file mode 100755 index 000000000..c9a52f621 --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/res/layout-w720dp/activity_main.xml @@ -0,0 +1,73 @@ + ++ * 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(); + AppRestrictionSchemaFragment fragment = new AppRestrictionSchemaFragment(); + 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/AppRestrictionSchema/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.common/activities/SampleActivityBase.java new file mode 100644 index 000000000..3228927b7 --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/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/AppRestrictionSchema/src/com.example.android.common/logger/Log.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.common/logger/Log.java new file mode 100644 index 000000000..17503c568 --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/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. + * + *
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.
+ */ +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/AppRestrictionSchema/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/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/AppRestrictionSchema/src/com.example.android.common/logger/LogNode.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/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/AppRestrictionSchema/src/com.example.android.common/logger/LogView.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/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/AppRestrictionSchema/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/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/AppRestrictionSchema/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/AppRestrictionSchema/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/AppRestrictionSchema/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/BasicManagedProfile/AndroidManifest.xml b/samples/browseable/BasicManagedProfile/AndroidManifest.xml new file mode 100644 index 000000000..29020c3e8 --- /dev/null +++ b/samples/browseable/BasicManagedProfile/AndroidManifest.xml @@ -0,0 +1,62 @@ + + + ++ + This sample demonstrates how to create a managed profile. You can also learn how to + enable or disable other apps and how to set restrictions to them. Intents can be + configured to be forwarded between primary account and managed profile. Finally, you can + wipe all the data associated with the profile. + Note that there can only be one managed profile on a device. + +
diff --git a/samples/browseable/BasicManagedProfile/res/drawable-hdpi/ic_launcher.png b/samples/browseable/BasicManagedProfile/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..c8feb76ac Binary files /dev/null and b/samples/browseable/BasicManagedProfile/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/BasicManagedProfile/res/drawable-hdpi/tile.9.png b/samples/browseable/BasicManagedProfile/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/BasicManagedProfile/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/BasicManagedProfile/res/drawable-mdpi/ic_launcher.png b/samples/browseable/BasicManagedProfile/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..4bf549ef7 Binary files /dev/null and b/samples/browseable/BasicManagedProfile/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/BasicManagedProfile/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/BasicManagedProfile/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..33afaaa7b Binary files /dev/null and b/samples/browseable/BasicManagedProfile/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/BasicManagedProfile/res/drawable-xxhdpi/badge.png b/samples/browseable/BasicManagedProfile/res/drawable-xxhdpi/badge.png new file mode 100644 index 000000000..77a88cf30 Binary files /dev/null and b/samples/browseable/BasicManagedProfile/res/drawable-xxhdpi/badge.png differ diff --git a/samples/browseable/BasicManagedProfile/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/BasicManagedProfile/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d6f927a4b Binary files /dev/null and b/samples/browseable/BasicManagedProfile/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/BasicManagedProfile/res/drawable/ic_launcher_badged.xml b/samples/browseable/BasicManagedProfile/res/drawable/ic_launcher_badged.xml new file mode 100644 index 000000000..b91b9bd10 --- /dev/null +++ b/samples/browseable/BasicManagedProfile/res/drawable/ic_launcher_badged.xml @@ -0,0 +1,25 @@ + + ++ + This sample demonstrates the basic use of Camera2 API. Check the source code to see how + you can display camera preview and take pictures. + +
diff --git a/samples/browseable/Camera2Basic/res/drawable-hdpi/ic_action_info.png b/samples/browseable/Camera2Basic/res/drawable-hdpi/ic_action_info.png new file mode 100644 index 000000000..32bd1aabc Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-hdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-hdpi/ic_launcher.png b/samples/browseable/Camera2Basic/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..ac6cf278d Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-hdpi/tile.9.png b/samples/browseable/Camera2Basic/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-mdpi/ic_action_info.png b/samples/browseable/Camera2Basic/res/drawable-mdpi/ic_action_info.png new file mode 100644 index 000000000..8efbbf8b3 Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-mdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-mdpi/ic_launcher.png b/samples/browseable/Camera2Basic/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..65f92a522 Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-xhdpi/ic_action_info.png b/samples/browseable/Camera2Basic/res/drawable-xhdpi/ic_action_info.png new file mode 100644 index 000000000..ba143ea7a Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-xhdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/Camera2Basic/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..6fd13181e Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-xxhdpi/ic_action_info.png b/samples/browseable/Camera2Basic/res/drawable-xxhdpi/ic_action_info.png new file mode 100644 index 000000000..394eb7e53 Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-xxhdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Basic/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/Camera2Basic/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..4513cf2e9 Binary files /dev/null and b/samples/browseable/Camera2Basic/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Basic/res/layout-land/fragment_camera2_basic.xml b/samples/browseable/Camera2Basic/res/layout-land/fragment_camera2_basic.xml new file mode 100644 index 000000000..3a3e2ff36 --- /dev/null +++ b/samples/browseable/Camera2Basic/res/layout-land/fragment_camera2_basic.xml @@ -0,0 +1,59 @@ + ++ + This sample demonstrates how to record video using Camera2 API. + +
diff --git a/samples/browseable/Camera2Video/res/drawable-hdpi/ic_action_info.png b/samples/browseable/Camera2Video/res/drawable-hdpi/ic_action_info.png new file mode 100644 index 000000000..32bd1aabc Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-hdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-hdpi/ic_launcher.png b/samples/browseable/Camera2Video/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..88bc107bb Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-hdpi/tile.9.png b/samples/browseable/Camera2Video/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-mdpi/ic_action_info.png b/samples/browseable/Camera2Video/res/drawable-mdpi/ic_action_info.png new file mode 100644 index 000000000..8efbbf8b3 Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-mdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-mdpi/ic_launcher.png b/samples/browseable/Camera2Video/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..28a5a4248 Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-xhdpi/ic_action_info.png b/samples/browseable/Camera2Video/res/drawable-xhdpi/ic_action_info.png new file mode 100644 index 000000000..ba143ea7a Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-xhdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/Camera2Video/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..2811666b0 Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-xxhdpi/ic_action_info.png b/samples/browseable/Camera2Video/res/drawable-xxhdpi/ic_action_info.png new file mode 100644 index 000000000..394eb7e53 Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-xxhdpi/ic_action_info.png differ diff --git a/samples/browseable/Camera2Video/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/Camera2Video/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..0e8ab469a Binary files /dev/null and b/samples/browseable/Camera2Video/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/Camera2Video/res/layout-land/fragment_camera2_video.xml b/samples/browseable/Camera2Video/res/layout-land/fragment_camera2_video.xml new file mode 100644 index 000000000..aa139a959 --- /dev/null +++ b/samples/browseable/Camera2Video/res/layout-land/fragment_camera2_video.xml @@ -0,0 +1,58 @@ + ++ + This sample demonstrates how to use CardView introduced in the support library for the + Android L preview. + +
diff --git a/samples/browseable/CardView/res/drawable-hdpi/ic_launcher.png b/samples/browseable/CardView/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..36f4db559 Binary files /dev/null and b/samples/browseable/CardView/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/CardView/res/drawable-hdpi/tile.9.png b/samples/browseable/CardView/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/CardView/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/CardView/res/drawable-mdpi/ic_launcher.png b/samples/browseable/CardView/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..f4ca06538 Binary files /dev/null and b/samples/browseable/CardView/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/CardView/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/CardView/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..6464a93f1 Binary files /dev/null and b/samples/browseable/CardView/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/CardView/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/CardView/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..5a017baee Binary files /dev/null and b/samples/browseable/CardView/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/CardView/res/layout/activity_card_view.xml b/samples/browseable/CardView/res/layout/activity_card_view.xml new file mode 100644 index 000000000..e32b7a616 --- /dev/null +++ b/samples/browseable/CardView/res/layout/activity_card_view.xml @@ -0,0 +1,27 @@ + + ++ + Basic sample to demonstrate clipping on a View. + +
diff --git a/samples/browseable/ClippingBasic/res/drawable-hdpi/ic_launcher.png b/samples/browseable/ClippingBasic/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..d79207bf6 Binary files /dev/null and b/samples/browseable/ClippingBasic/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/ClippingBasic/res/drawable-hdpi/tile.9.png b/samples/browseable/ClippingBasic/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/ClippingBasic/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/ClippingBasic/res/drawable-mdpi/ic_launcher.png b/samples/browseable/ClippingBasic/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..3ee83ada0 Binary files /dev/null and b/samples/browseable/ClippingBasic/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/ClippingBasic/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/ClippingBasic/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..3b1ae0ad5 Binary files /dev/null and b/samples/browseable/ClippingBasic/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/ClippingBasic/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/ClippingBasic/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..64b728de4 Binary files /dev/null and b/samples/browseable/ClippingBasic/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/ClippingBasic/res/drawable/gradient_drawable.xml b/samples/browseable/ClippingBasic/res/drawable/gradient_drawable.xml new file mode 100644 index 000000000..c6377cc3e --- /dev/null +++ b/samples/browseable/ClippingBasic/res/drawable/gradient_drawable.xml @@ -0,0 +1,24 @@ + + + ++ * 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(); + ClippingBasicFragment fragment = new ClippingBasicFragment(); + 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/ClippingBasic/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/ClippingBasic/src/com.example.android.common/activities/SampleActivityBase.java new file mode 100644 index 000000000..3228927b7 --- /dev/null +++ b/samples/browseable/ClippingBasic/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/ClippingBasic/src/com.example.android.common/logger/Log.java b/samples/browseable/ClippingBasic/src/com.example.android.common/logger/Log.java new file mode 100644 index 000000000..17503c568 --- /dev/null +++ b/samples/browseable/ClippingBasic/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. + * + *
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.
+ */ +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/ClippingBasic/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/ClippingBasic/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/ClippingBasic/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/ClippingBasic/src/com.example.android.common/logger/LogNode.java b/samples/browseable/ClippingBasic/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/ClippingBasic/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/ClippingBasic/src/com.example.android.common/logger/LogView.java b/samples/browseable/ClippingBasic/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/ClippingBasic/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/ClippingBasic/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/ClippingBasic/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/ClippingBasic/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/ClippingBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/ClippingBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/ClippingBasic/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/DocumentCentricApps/AndroidManifest.xml b/samples/browseable/DocumentCentricApps/AndroidManifest.xml new file mode 100644 index 000000000..a1378efdd --- /dev/null +++ b/samples/browseable/DocumentCentricApps/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + ++ + This sample shows the basic usage of the new \"Document Centric Apps\" API. + It let\'s you create new documents in the system overview menu and persists its + state through reboots. If \"Task per document\" is checked a new task will be + created for every new document in the overview menu. + +
diff --git a/samples/browseable/DocumentCentricApps/res/drawable-hdpi/ic_launcher.png b/samples/browseable/DocumentCentricApps/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..b1efaf4b2 Binary files /dev/null and b/samples/browseable/DocumentCentricApps/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricApps/res/drawable-hdpi/tile.9.png b/samples/browseable/DocumentCentricApps/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/DocumentCentricApps/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/DocumentCentricApps/res/drawable-mdpi/ic_launcher.png b/samples/browseable/DocumentCentricApps/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..f5f9244f2 Binary files /dev/null and b/samples/browseable/DocumentCentricApps/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricApps/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/DocumentCentricApps/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..5d07b3f06 Binary files /dev/null and b/samples/browseable/DocumentCentricApps/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricApps/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/DocumentCentricApps/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..6ef21e1f4 Binary files /dev/null and b/samples/browseable/DocumentCentricApps/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricApps/res/layout/activity_document_centric_main.xml b/samples/browseable/DocumentCentricApps/res/layout/activity_document_centric_main.xml new file mode 100755 index 000000000..5f62415ed --- /dev/null +++ b/samples/browseable/DocumentCentricApps/res/layout/activity_document_centric_main.xml @@ -0,0 +1,63 @@ + + + + ++ + This sample shows how to relinquish identity to activities above it in the task stack. + +
diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/ic_launcher.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..b1efaf4b2 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/new_icon.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/new_icon.png new file mode 100755 index 000000000..34767f3dd Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/new_icon.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/tile.9.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-mdpi/ic_launcher.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..f5f9244f2 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-mdpi/new_icon.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-mdpi/new_icon.png new file mode 100755 index 000000000..f1b91b9e6 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-mdpi/new_icon.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..5d07b3f06 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xhdpi/new_icon.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xhdpi/new_icon.png new file mode 100755 index 000000000..412a06d62 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xhdpi/new_icon.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..6ef21e1f4 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xxhdpi/new_icon.png b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xxhdpi/new_icon.png new file mode 100755 index 000000000..a159b1648 Binary files /dev/null and b/samples/browseable/DocumentCentricRelinquishIdentity/res/drawable-xxhdpi/new_icon.png differ diff --git a/samples/browseable/DocumentCentricRelinquishIdentity/res/layout/activity_document.xml b/samples/browseable/DocumentCentricRelinquishIdentity/res/layout/activity_document.xml new file mode 100644 index 000000000..b9f675575 --- /dev/null +++ b/samples/browseable/DocumentCentricRelinquishIdentity/res/layout/activity_document.xml @@ -0,0 +1,35 @@ + + + ++ * To relinquish its identity the base activity must have the activity attribute + * android:relinquishTaskIdentity=”true” in the manifest. + *
+ */ +public class RelinquishIdentityActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_relinquish_identity); + } + + public void createNewDocument(View view) { + final Intent intent = newDocumentIntent(); + startActivity(intent); + } + + /** + * Returns an new intent to start {@link NewDocumentActivity} + * as a new document in recents.. + */ + private Intent newDocumentIntent() { + final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class); + newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + // Always launch in a new task. + newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + return newDocumentIntent; + } + +} diff --git a/samples/browseable/DrawableTinting/AndroidManifest.xml b/samples/browseable/DrawableTinting/AndroidManifest.xml new file mode 100644 index 000000000..9aa3976ec --- /dev/null +++ b/samples/browseable/DrawableTinting/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + ++ + Sample that shows applying tinting and color filters to Drawables both programmatically + and as Drawable resources in XML. + \n\nTinting is set on a nine-patch drawable through the "tint" and "tintMode" parameters. + A color state list is referenced as the tint color, which defines colors for different + states of a View (for example disabled/enabled, focused, pressed or selected). + \n\nProgrammatically, tinting is applied to a Drawable through its "setColorFilter" method, + with a reference to a color and a PorterDuff blend mode. The color and blend mode can be + changed from the UI to see the effect of different options. + +
diff --git a/samples/browseable/DrawableTinting/res/color/custom_tint.xml b/samples/browseable/DrawableTinting/res/color/custom_tint.xml new file mode 100644 index 000000000..983880ae7 --- /dev/null +++ b/samples/browseable/DrawableTinting/res/color/custom_tint.xml @@ -0,0 +1,37 @@ + + + + +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.
+ */ +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/DrawableTinting/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/DrawableTinting/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/DrawableTinting/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/DrawableTinting/src/com.example.android.common/logger/LogNode.java b/samples/browseable/DrawableTinting/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/DrawableTinting/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/DrawableTinting/src/com.example.android.common/logger/LogView.java b/samples/browseable/DrawableTinting/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/DrawableTinting/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/DrawableTinting/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/DrawableTinting/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/DrawableTinting/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/DrawableTinting/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/DrawableTinting/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/DrawableTinting/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/DrawableTinting/src/com.example.android.drawabletinting/DrawableTintingFragment.java b/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/DrawableTintingFragment.java new file mode 100644 index 000000000..cd46fb95e --- /dev/null +++ b/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/DrawableTintingFragment.java @@ -0,0 +1,316 @@ +/* +* Copyright 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. +*/ + +package com.example.android.drawabletinting; + +import android.graphics.Color; +import android.graphics.PorterDuff; +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; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.Spinner; +import android.widget.SpinnerAdapter; +import android.widget.TextView; + +import com.example.android.common.logger.Log; + +/** + * Sample that shows tinting of Drawables programmatically and of Drawable resources in XML. + * Tinting is set on a nine-patch drawable through the "tint" and "tintMode" parameters. + * A color state list is referenced as the tint color, which defines colors for different + * states of a View (for example disabled/enabled, focused, pressed or selected). + * Programmatically, tinting is applied to a Drawable through its "setColorFilter" method, with + * a reference to a color and a PorterDuff blend mode. The color and blend mode can be + * changed from the UI. + * + * @see android.graphics.drawable.Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode) + * @see android.graphics.drawable.Drawable#setTint(android.content.res.ColorStateList, android.graphics.PorterDuff.Mode) + */ +public class DrawableTintingFragment extends Fragment { + + /** + * String that identifies logging output from this Fragment. + */ + private static final String TAG = "DrawableTintingFragment"; + + /** + * Image that tinting is applied to programmatically. + */ + private ImageView mImage; + + /** + * Seekbar for alpha component of tinting color. + */ + private SeekBar mAlphaBar; + /** + * Seekbar for red component of tinting color. + */ + private SeekBar mRedBar; + /** + * Seekbar for green bar of tinting color. + */ + private SeekBar mGreenBar; + /** + * Seekbar for blue bar of tinting color. + */ + private SeekBar mBlueBar; + + /** + * Text label for alpha component seekbar. + */ + private TextView mAlphaText; + /** + * Text label for red component seekbar. + */ + private TextView mRedText; + /** + * Text label for green component seekbar. + */ + private TextView mGreenText; + /** + * Text label for blue component seekbar. + */ + private TextView mBlueText; + + /** + * Selector for blend type for color tinting. + */ + private Spinner mBlendSpinner; + + /** + * Computed color for tinting of drawable. + */ + private int mHintColor; + + /** + * Selected color tinting mode. + */ + private PorterDuff.Mode mMode; + + /** + * Identifier for state of blend mod spinner in state bundle. + */ + private static final String STATE_BLEND = "DRAWABLETINTING_BLEND"; + /** + * Identifier for state of alpha seek bar in state bundle. + */ + private static final String STATE_ALPHA = "DRAWABLETINTING_ALPHA"; + /** + * Identifier for state of red seek bar in state bundle. + */ + private static final String STATE_RED = "DRAWABLETINTING_RED"; + /** + * Identifier for state of green seek bar in state bundle. + */ + private static final String STATE_GREEN = "DRAWABLETINTING_GREEN"; + /** + * Identifier for state of blue seek bar in state bundle. + */ + private static final String STATE_BLUE = "DRAWABLETINTING_BLUE"; + + /** + * Available tinting modes. Note that this array must be kept in sync with the + *blend_modes string array that provides labels for these modes.
+ */
+ private static final PorterDuff.Mode[] MODES = new PorterDuff.Mode[]{
+ PorterDuff.Mode.ADD,
+ PorterDuff.Mode.CLEAR,
+ PorterDuff.Mode.DARKEN,
+ PorterDuff.Mode.DST,
+ PorterDuff.Mode.DST_ATOP,
+ PorterDuff.Mode.DST_IN,
+ PorterDuff.Mode.DST_OUT,
+ PorterDuff.Mode.DST_OVER,
+ PorterDuff.Mode.LIGHTEN,
+ PorterDuff.Mode.MULTIPLY,
+ PorterDuff.Mode.OVERLAY,
+ PorterDuff.Mode.SCREEN,
+ PorterDuff.Mode.SRC,
+ PorterDuff.Mode.SRC_ATOP,
+ PorterDuff.Mode.SRC_IN,
+ PorterDuff.Mode.SRC_OUT,
+ PorterDuff.Mode.SRC_OVER,
+ PorterDuff.Mode.XOR
+ };
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.tinting_fragment, null);
+
+ // Set a drawable as the image to display
+ mImage = (ImageView) v.findViewById(R.id.image);
+ mImage.setImageResource(R.drawable.btn_default_normal_holo);
+
+ // Get text labels and seekbars for the four color components: ARGB
+ mAlphaBar = (SeekBar) v.findViewById(R.id.alphaSeek);
+ mAlphaText = (TextView) v.findViewById(R.id.alphaText);
+ mGreenBar = (SeekBar) v.findViewById(R.id.greenSeek);
+ mGreenText = (TextView) v.findViewById(R.id.greenText);
+ mRedBar = (SeekBar) v.findViewById(R.id.redSeek);
+ mRedText = (TextView) v.findViewById(R.id.redText);
+ mBlueText = (TextView) v.findViewById(R.id.blueText);
+ mBlueBar = (SeekBar) v.findViewById(R.id.blueSeek);
+
+ // Set a listener to update tinted image when selections have changed
+ mAlphaBar.setOnSeekBarChangeListener(mSeekBarListener);
+ mRedBar.setOnSeekBarChangeListener(mSeekBarListener);
+ mGreenBar.setOnSeekBarChangeListener(mSeekBarListener);
+ mBlueBar.setOnSeekBarChangeListener(mSeekBarListener);
+
+
+ // Set up the spinner for blend mode selection from a string array resource
+ mBlendSpinner = (Spinner) v.findViewById(R.id.blendSpinner);
+ SpinnerAdapter sa = ArrayAdapter.createFromResource(getActivity(),
+ R.array.blend_modes, android.R.layout.simple_spinner_dropdown_item);
+ mBlendSpinner.setAdapter(sa);
+ // Set a listener to update the tinted image when a blend mode is selected
+ mBlendSpinner.setOnItemSelectedListener(mBlendListener);
+ // Select the first item
+ mBlendSpinner.setSelection(0);
+ mMode = MODES[0];
+
+ if (savedInstanceState != null) {
+ // Restore the previous state if this fragment has been restored
+ mBlendSpinner.setSelection(savedInstanceState.getInt(STATE_BLEND));
+ mAlphaBar.setProgress(savedInstanceState.getInt(STATE_ALPHA));
+ mRedBar.setProgress(savedInstanceState.getInt(STATE_RED));
+ mGreenBar.setProgress(savedInstanceState.getInt(STATE_GREEN));
+ mBlueBar.setProgress(savedInstanceState.getInt(STATE_BLUE));
+ }
+
+ // Apply the default blend mode and color
+ updateTint(getColor(), getTintMode());
+
+ return v;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ Log.d(TAG, "state saved.");
+ outState.putInt(STATE_BLEND, mBlendSpinner.getSelectedItemPosition());
+ outState.putInt(STATE_ALPHA, mAlphaBar.getProgress());
+ outState.putInt(STATE_RED, mRedBar.getProgress());
+ outState.putInt(STATE_GREEN, mGreenBar.getProgress());
+ outState.putInt(STATE_BLUE, mBlueBar.getProgress());
+ }
+
+ /**
+ * Computes the {@link Color} value from selection on ARGB sliders.
+ *
+ * @return color computed from selected ARGB values
+ */
+ public int getColor() {
+ final int alpha = mAlphaBar.getProgress();
+ final int red = mRedBar.getProgress();
+ final int green = mGreenBar.getProgress();
+ final int blue = mBlueBar.getProgress();
+
+ return Color.argb(alpha, red, green, blue);
+ }
+
+ /**
+ * Returns the {@link android.graphics.PorterDuff.Mode} for the selected tint mode option.
+ *
+ * @return selected tint mode
+ */
+ public PorterDuff.Mode getTintMode() {
+ return MODES[mBlendSpinner.getSelectedItemPosition()];
+ }
+
+ /**
+ * Update the tint of the image with the color set in the seekbars and selected blend mode.
+ * The seekbars are set to a maximum of 255, with one for each of the four components of the
+ * ARGB color. (Alpha, Red, Green, Blue.) Once a color has been computed using
+ * {@link Color#argb(int, int, int, int)}, it is set togethe with the blend mode on the background
+ * image using
+ * {@link android.widget.ImageView#setColorFilter(int, android.graphics.PorterDuff.Mode)}.
+ */
+ public void updateTint(int color, PorterDuff.Mode mode) {
+ // Set the color hint of the image: ARGB
+ mHintColor = color;
+
+ // Set the color tint mode based on the selection of the Spinner
+ mMode = mode;
+
+ // Log selection
+ Log.d(TAG, String.format("Updating tint with color [ARGB: %d,%d,%d,%d] and mode [%s]",
+ Color.alpha(color), Color.red(color), Color.green(color), Color.blue(color),
+ mode.toString()));
+
+ // Apply the color tint for the selected tint mode
+ mImage.setColorFilter(mHintColor, mMode);
+
+ // Update the text for each label with the value of each channel
+ mAlphaText.setText(getString(R.string.value_alpha, Color.alpha(color)));
+ mRedText.setText(getString(R.string.value_red, Color.red(color)));
+ mGreenText.setText(getString(R.string.value_green, Color.green(color)));
+ mBlueText.setText(getString(R.string.value_blue, Color.blue(color)));
+ }
+
+ /**
+ * Listener that updates the tint when a blend mode is selected.
+ */
+ private AdapterView.OnItemSelectedListener mBlendListener =
+ new AdapterView.OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(AdapterView> adapterView, View view, int i, long l) {
+ // Selected a blend mode and update the tint of image
+ updateTint(getColor(), getTintMode());
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> adapterView) {
+
+ }
+
+ };
+
+ /**
+ * Seekbar listener that updates the tinted color when the progress bar has changed.
+ */
+ private SeekBar.OnSeekBarChangeListener mSeekBarListener =
+ new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
+ // Update the tinted color from all selections in the UI
+ updateTint(getColor(), getTintMode());
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ };
+}
diff --git a/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/MainActivity.java b/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/MainActivity.java
new file mode 100644
index 000000000..d00bc379d
--- /dev/null
+++ b/samples/browseable/DrawableTinting/src/com.example.android.drawabletinting/MainActivity.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.
+*/
+
+package com.example.android.drawabletinting;
+
+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.
+ *
+ * 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();
+ DrawableTintingFragment fragment = new DrawableTintingFragment();
+ 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/ElevationBasic/AndroidManifest.xml b/samples/browseable/ElevationBasic/AndroidManifest.xml
new file mode 100644
index 000000000..a70cd857e
--- /dev/null
+++ b/samples/browseable/ElevationBasic/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+ + This sample demonstrates two alternative ways to move a view in the z-axis. The + first view has a fixed elevation using XML and the second one is raised when the user + taps on it, using setTranslationZ(). + +
diff --git a/samples/browseable/ElevationBasic/res/drawable-hdpi/ic_launcher.png b/samples/browseable/ElevationBasic/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..c28e40d6a Binary files /dev/null and b/samples/browseable/ElevationBasic/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationBasic/res/drawable-hdpi/tile.9.png b/samples/browseable/ElevationBasic/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/ElevationBasic/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/ElevationBasic/res/drawable-mdpi/ic_launcher.png b/samples/browseable/ElevationBasic/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..71738ffb8 Binary files /dev/null and b/samples/browseable/ElevationBasic/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationBasic/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/ElevationBasic/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..788ac1fac Binary files /dev/null and b/samples/browseable/ElevationBasic/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationBasic/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/ElevationBasic/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..72359c397 Binary files /dev/null and b/samples/browseable/ElevationBasic/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationBasic/res/drawable/shape.xml b/samples/browseable/ElevationBasic/res/drawable/shape.xml new file mode 100644 index 000000000..22ffe0536 --- /dev/null +++ b/samples/browseable/ElevationBasic/res/drawable/shape.xml @@ -0,0 +1,20 @@ + + +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.
+ */ +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/ElevationBasic/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/ElevationBasic/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/ElevationBasic/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/ElevationBasic/src/com.example.android.common/logger/LogNode.java b/samples/browseable/ElevationBasic/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/ElevationBasic/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/ElevationBasic/src/com.example.android.common/logger/LogView.java b/samples/browseable/ElevationBasic/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/ElevationBasic/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/ElevationBasic/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/ElevationBasic/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/ElevationBasic/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/ElevationBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/ElevationBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/ElevationBasic/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/ElevationBasic/src/com.example.android.elevationbasic/ElevationBasicFragment.java b/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/ElevationBasicFragment.java new file mode 100644 index 000000000..71edea5b3 --- /dev/null +++ b/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/ElevationBasicFragment.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +package com.example.android.elevationbasic; + +import android.support.v4.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import com.example.android.common.logger.Log; + +public class ElevationBasicFragment extends Fragment { + + private final static String TAG = "ElevationBasicFragment"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + /** + * Inflates an XML containing two shapes: the first has a fixed elevation + * and the second ones raises when tapped. + */ + View rootView = inflater.inflate(R.layout.elevation_basic, container, false); + + View shape2 = rootView.findViewById(R.id.floating_shape_2); + + /** + * Sets a {@Link View.OnTouchListener} that responds to a touch event on shape2. + */ + shape2.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + int action = motionEvent.getActionMasked(); + /* Raise view on ACTION_DOWN and lower it on ACTION_UP. */ + switch (action) { + case MotionEvent.ACTION_DOWN: + Log.d(TAG, "ACTION_DOWN on view."); + view.setTranslationZ(120); + break; + case MotionEvent.ACTION_UP: + Log.d(TAG, "ACTION_UP on view."); + view.setTranslationZ(0); + break; + default: + return false; + } + return true; + } + }); + return rootView; + } +} \ No newline at end of file diff --git a/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/MainActivity.java b/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/MainActivity.java new file mode 100644 index 000000000..f4285d2e0 --- /dev/null +++ b/samples/browseable/ElevationBasic/src/com.example.android.elevationbasic/MainActivity.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. +*/ + +package com.example.android.elevationbasic; + +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. + *
+ * 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();
+ ElevationBasicFragment fragment = new ElevationBasicFragment();
+ 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/ElevationDrag/AndroidManifest.xml b/samples/browseable/ElevationDrag/AndroidManifest.xml
new file mode 100644
index 000000000..9fd7d538b
--- /dev/null
+++ b/samples/browseable/ElevationDrag/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+ + This sample demonstrates a drag and drop action on different shapes. Elevation and + z-translation are used to render the shadows and the views are clipped using different + Outlines. + +
diff --git a/samples/browseable/ElevationDrag/res/drawable-hdpi/ic_launcher.png b/samples/browseable/ElevationDrag/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..8d34f6a63 Binary files /dev/null and b/samples/browseable/ElevationDrag/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationDrag/res/drawable-hdpi/tile.9.png b/samples/browseable/ElevationDrag/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/ElevationDrag/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/ElevationDrag/res/drawable-mdpi/ic_launcher.png b/samples/browseable/ElevationDrag/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..8d9cd3e48 Binary files /dev/null and b/samples/browseable/ElevationDrag/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationDrag/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/ElevationDrag/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09e4c8d7e Binary files /dev/null and b/samples/browseable/ElevationDrag/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationDrag/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/ElevationDrag/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..232dc77f0 Binary files /dev/null and b/samples/browseable/ElevationDrag/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/ElevationDrag/res/layout-w720dp/activity_main.xml b/samples/browseable/ElevationDrag/res/layout-w720dp/activity_main.xml new file mode 100755 index 000000000..c9a52f621 --- /dev/null +++ b/samples/browseable/ElevationDrag/res/layout-w720dp/activity_main.xml @@ -0,0 +1,73 @@ + +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.
+ */ +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/ElevationDrag/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/ElevationDrag/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/ElevationDrag/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/ElevationDrag/src/com.example.android.common/logger/LogNode.java b/samples/browseable/ElevationDrag/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/ElevationDrag/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/ElevationDrag/src/com.example.android.common/logger/LogView.java b/samples/browseable/ElevationDrag/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/ElevationDrag/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/ElevationDrag/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/ElevationDrag/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/ElevationDrag/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/ElevationDrag/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/ElevationDrag/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/ElevationDrag/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/ElevationDrag/src/com.example.android.elevationdrag/DragFrameLayout.java b/samples/browseable/ElevationDrag/src/com.example.android.elevationdrag/DragFrameLayout.java new file mode 100644 index 000000000..0b2a8d2da --- /dev/null +++ b/samples/browseable/ElevationDrag/src/com.example.android.elevationdrag/DragFrameLayout.java @@ -0,0 +1,143 @@ +/* + * 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. + */ + +package com.example.android.elevationdrag; + +import android.content.Context; +import android.support.v4.widget.ViewDragHelper; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; + +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link FrameLayout} that allows the user to drag and reposition child views. + */ +public class DragFrameLayout extends FrameLayout { + + /** + * The list of {@link View}s that will be draggable. + */ + private List
+ * 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();
+ ElevationDragFragment fragment = new ElevationDragFragment();
+ 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/FloatingActionButtonBasic/AndroidManifest.xml b/samples/browseable/FloatingActionButtonBasic/AndroidManifest.xml
new file mode 100644
index 000000000..8f26c99ed
--- /dev/null
+++ b/samples/browseable/FloatingActionButtonBasic/AndroidManifest.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ + This sample shows the two sizes of Floating Action Buttons and how to interact with + them. + +
diff --git a/samples/browseable/FloatingActionButtonBasic/res/animator/fab_anim.xml b/samples/browseable/FloatingActionButtonBasic/res/animator/fab_anim.xml new file mode 100644 index 000000000..dd83cd307 --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/res/animator/fab_anim.xml @@ -0,0 +1,37 @@ + + + +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.
+ */ +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/FloatingActionButtonBasic/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/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/FloatingActionButtonBasic/src/com.example.android.common/logger/LogNode.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/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/FloatingActionButtonBasic/src/com.example.android.common/logger/LogView.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/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/FloatingActionButtonBasic/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/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/FloatingActionButtonBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/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/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/FloatingActionButton.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/FloatingActionButton.java new file mode 100644 index 000000000..12fdd1c47 --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/FloatingActionButton.java @@ -0,0 +1,160 @@ +/* + * Copyright 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. + */ + +package com.example.android.floatingactionbuttonbasic; + +import android.content.Context; +import android.graphics.Outline; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewOutlineProvider; +import android.widget.Checkable; +import android.widget.FrameLayout; + +/** + * A Floating Action Button is a {@link android.widget.Checkable} view distinguished by a circled + * icon floating above the UI, with special motion behaviors. + */ +public class FloatingActionButton extends FrameLayout implements Checkable { + + /** + * Interface definition for a callback to be invoked when the checked state + * of a compound button changes. + */ + public static interface OnCheckedChangeListener { + + /** + * Called when the checked state of a FAB has changed. + * + * @param fabView The FAB view whose state has changed. + * @param isChecked The new checked state of buttonView. + */ + void onCheckedChanged(FloatingActionButton fabView, boolean isChecked); + } + + /** + * An array of states. + */ + private static final int[] CHECKED_STATE_SET = { + android.R.attr.state_checked + }; + + private static final String TAG = "FloatingActionButton"; + + // A boolean that tells if the FAB is checked or not. + private boolean mChecked; + + // A listener to communicate that the FAB has changed it's state + private OnCheckedChangeListener mOnCheckedChangeListener; + + public FloatingActionButton(Context context) { + this(context, null, 0, 0); + } + + public FloatingActionButton(Context context, AttributeSet attrs) { + this(context, attrs, 0, 0); + } + + public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr); + + setClickable(true); + + // Set the outline provider for this view. The provider is given the outline which it can + // then modify as needed. In this case we set the outline to be an oval fitting the height + // and width. + setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, getWidth(), getHeight()); + } + }); + + // Finally, enable clipping to the outline, using the provider we set above + setClipToOutline(true); + } + + /** + * Sets the checked/unchecked state of the FAB. + * @param checked + */ + public void setChecked(boolean checked) { + // If trying to set the current state, ignore. + if (checked == mChecked) { + return; + } + mChecked = checked; + + // Now refresh the drawable state (so the icon changes) + refreshDrawableState(); + + if (mOnCheckedChangeListener != null) { + mOnCheckedChangeListener.onCheckedChanged(this, checked); + } + } + + /** + * Register a callback to be invoked when the checked state of this button + * changes. + * + * @param listener the callback to call on checked state change + */ + public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { + mOnCheckedChangeListener = listener; + } + + @Override + public boolean isChecked() { + return mChecked; + } + + @Override + public void toggle() { + setChecked(!mChecked); + } + + /** + * Override performClick() so that we can toggle the checked state when the view is clicked + */ + @Override + public boolean performClick() { + toggle(); + return super.performClick(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // As we have changed size, we should invalidate the outline so that is the the + // correct size + invalidateOutline(); + } + + @Override + protected int[] onCreateDrawableState(int extraSpace) { + final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); + if (isChecked()) { + mergeDrawableStates(drawableState, CHECKED_STATE_SET); + } + return drawableState; + } +} diff --git a/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/FloatingActionButtonBasicFragment.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/FloatingActionButtonBasicFragment.java new file mode 100644 index 000000000..817cfb704 --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/FloatingActionButtonBasicFragment.java @@ -0,0 +1,67 @@ +/* + * Copyright 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. + */ + +package com.example.android.floatingactionbuttonbasic; + +import com.example.android.common.logger.Log; + +import android.app.Activity; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + + +/** + * This fragment inflates a layout with two Floating Action Buttons and acts as a listener to + * changes on them. + */ +public class FloatingActionButtonBasicFragment extends Fragment implements FloatingActionButton.OnCheckedChangeListener{ + + private final static String TAG = "FloatingActionButtonBasicFragment"; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View rootView = inflater.inflate(R.layout.fab_layout, container, false); + + // Make this {@link Fragment} listen for changes in both FABs. + FloatingActionButton fab1 = (FloatingActionButton) rootView.findViewById(R.id.fab_1); + fab1.setOnCheckedChangeListener(this); + FloatingActionButton fab2 = (FloatingActionButton) rootView.findViewById(R.id.fab_2); + fab2.setOnCheckedChangeListener(this); + return rootView; + } + + + @Override + public void onCheckedChanged(FloatingActionButton fabView, boolean isChecked) { + // When a FAB is toggled, log the action. + switch (fabView.getId()){ + case R.id.fab_1: + Log.d(TAG, String.format("FAB 1 was %s.", isChecked ? "checked" : "unchecked")); + break; + case R.id.fab_2: + Log.d(TAG, String.format("FAB 2 was %s.", isChecked ? "checked" : "unchecked")); + break; + default: + break; + } + } +} diff --git a/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/MainActivity.java b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/MainActivity.java new file mode 100644 index 000000000..b88fc7a9b --- /dev/null +++ b/samples/browseable/FloatingActionButtonBasic/src/com.example.android.floatingactionbuttonbasic/MainActivity.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. +*/ + +package com.example.android.floatingactionbuttonbasic; + +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. + *
+ * 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();
+ FloatingActionButtonBasicFragment fragment = new FloatingActionButtonBasicFragment();
+ 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/HdrViewfinder/AndroidManifest.xml b/samples/browseable/HdrViewfinder/AndroidManifest.xml
new file mode 100644
index 000000000..772b7dfdf
--- /dev/null
+++ b/samples/browseable/HdrViewfinder/AndroidManifest.xml
@@ -0,0 +1,55 @@
+
+
+
+ + This demo implements a real-time high-dynamic-range camera viewfinder, by alternating + the sensor\'s exposure time between two exposure values on even and odd frames, and then + compositing together the latest two frames whenever a new frame is captured. + +
diff --git a/samples/browseable/HdrViewfinder/res/drawable-hdpi/ic_action_info.png b/samples/browseable/HdrViewfinder/res/drawable-hdpi/ic_action_info.png new file mode 100644 index 000000000..32bd1aabc Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-hdpi/ic_action_info.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-hdpi/ic_launcher.png b/samples/browseable/HdrViewfinder/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..18f79c131 Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-hdpi/tile.9.png b/samples/browseable/HdrViewfinder/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-mdpi/ic_action_info.png b/samples/browseable/HdrViewfinder/res/drawable-mdpi/ic_action_info.png new file mode 100644 index 000000000..8efbbf8b3 Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-mdpi/ic_action_info.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-mdpi/ic_launcher.png b/samples/browseable/HdrViewfinder/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..e70a7dc9c Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-xhdpi/ic_action_info.png b/samples/browseable/HdrViewfinder/res/drawable-xhdpi/ic_action_info.png new file mode 100644 index 000000000..ba143ea7a Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-xhdpi/ic_action_info.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/HdrViewfinder/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..ed25c5a79 Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-xxhdpi/ic_action_info.png b/samples/browseable/HdrViewfinder/res/drawable-xxhdpi/ic_action_info.png new file mode 100644 index 000000000..394eb7e53 Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-xxhdpi/ic_action_info.png differ diff --git a/samples/browseable/HdrViewfinder/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/HdrViewfinder/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..90867ffe6 Binary files /dev/null and b/samples/browseable/HdrViewfinder/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/HdrViewfinder/res/layout/activity_main.xml b/samples/browseable/HdrViewfinder/res/layout/activity_main.xml new file mode 100755 index 000000000..be1aa49d9 --- /dev/null +++ b/samples/browseable/HdrViewfinder/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + +Depending on the layout, the FixedAspectSurfaceView may not be able to maintain the + * requested aspect ratio. This can happen if both the width and the height are exactly + * determined by the layout. To avoid this, ensure that either the height or the width is + * adjustable by the view; for example, by setting the layout parameters to be WRAP_CONTENT for + * the dimension that is best adjusted to maintain the aspect ratio.
+ */ +public class FixedAspectSurfaceView extends SurfaceView { + + /** + * Desired width/height ratio + */ + private float mAspectRatio; + + private GestureDetector mGestureDetector; + + public FixedAspectSurfaceView(Context context, AttributeSet attrs) { + super(context, attrs); + + // Get initial aspect ratio from custom attributes + TypedArray a = + context.getTheme().obtainStyledAttributes(attrs, + R.styleable.FixedAspectSurfaceView, 0, 0); + setAspectRatio(a.getFloat( + R.styleable.FixedAspectSurfaceView_aspectRatio, 1.f)); + a.recycle(); + } + + /** + * Set the desired aspect ratio for this view. + * + * @param aspect the desired width/height ratio in the current UI orientation. Must be a + * positive value. + */ + public void setAspectRatio(float aspect) { + if (aspect <= 0) { + throw new IllegalArgumentException("Aspect ratio must be positive"); + } + mAspectRatio = aspect; + requestLayout(); + } + + /** + * Set a gesture listener to listen for touch events + */ + public void setGestureListener(Context context, GestureDetector.OnGestureListener listener) { + if (listener == null) { + mGestureDetector = null; + } else { + mGestureDetector = new GestureDetector(context, listener); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + // General goal: Adjust dimensions to maintain the requested aspect ratio as much + // as possible. Depending on the measure specs handed down, this may not be possible + + // Only set one of these to true + boolean scaleWidth = false; + boolean scaleHeight = false; + + // Sort out which dimension to scale, if either can be. There are 9 combinations of + // possible measure specs; a few cases below handle multiple combinations + if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) { + // Can't adjust sizes at all, do nothing + } else if (widthMode == MeasureSpec.EXACTLY) { + // Width is fixed, heightMode either AT_MOST or UNSPECIFIED, so adjust height + scaleHeight = true; + } else if (heightMode == MeasureSpec.EXACTLY) { + // Height is fixed, widthMode either AT_MOST or UNSPECIFIED, so adjust width + scaleWidth = true; + } else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) { + // Need to fit into box <= [width, height] in size. + // Maximize the View's area while maintaining aspect ratio + // This means keeping one dimension as large as possible and shrinking the other + float boxAspectRatio = width / (float) height; + if (boxAspectRatio > mAspectRatio) { + // Box is wider than requested aspect; pillarbox + scaleWidth = true; + } else { + // Box is narrower than requested aspect; letterbox + scaleHeight = true; + } + } else if (widthMode == MeasureSpec.AT_MOST) { + // Maximize width, heightSpec is UNSPECIFIED + scaleHeight = true; + } else if (heightMode == MeasureSpec.AT_MOST) { + // Maximize height, widthSpec is UNSPECIFIED + scaleWidth = true; + } else { + // Both MeasureSpecs are UNSPECIFIED. This is probably a pathological layout, + // with width == height == 0 + // but arbitrarily scale height anyway + scaleHeight = true; + } + + // Do the scaling + if (scaleWidth) { + width = (int) (height * mAspectRatio); + } else if (scaleHeight) { + height = (int) (width / mAspectRatio); + } + + // Override width/height if needed for EXACTLY and AT_MOST specs + width = View.resolveSizeAndState(width, widthMeasureSpec, 0); + height = View.resolveSizeAndState(height, heightMeasureSpec, 0); + + // Finally set the calculated dimensions + setMeasuredDimension(width, height); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mGestureDetector != null) { + return mGestureDetector.onTouchEvent(event); + } + return false; + } +} diff --git a/samples/browseable/HdrViewfinder/src/com.example.android.hdrviewfinder/HdrViewfinderActivity.java b/samples/browseable/HdrViewfinder/src/com.example.android.hdrviewfinder/HdrViewfinderActivity.java new file mode 100644 index 000000000..79f1bb61e --- /dev/null +++ b/samples/browseable/HdrViewfinder/src/com.example.android.hdrviewfinder/HdrViewfinderActivity.java @@ -0,0 +1,524 @@ +/* + * 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. + */ + +package com.example.android.hdrviewfinder; + +import android.app.Activity; +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.CaptureRequest; +import android.hardware.camera2.CaptureResult; +import android.hardware.camera2.TotalCaptureResult; +import android.hardware.camera2.params.StreamConfigurationMap; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.renderscript.RenderScript; +import android.util.Log; +import android.util.Size; +import android.view.GestureDetector; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +/** + * A small demo of advanced camera functionality with the Android camera2 API. + * + *This demo implements a real-time high-dynamic-range camera viewfinder, + * by alternating the sensor's exposure time between two exposure values on even and odd + * frames, and then compositing together the latest two frames whenever a new frame is + * captured.
+ * + *The demo has three modes: Regular auto-exposure viewfinder, split-screen manual exposure, + * and the fused HDR viewfinder. The latter two use manual exposure controlled by the user, + * by swiping up/down on the right and left halves of the viewfinder. The left half controls + * the exposure time of even frames, and the right half controls the exposure time of odd frames. + *
+ * + *In split-screen mode, the even frames are shown on the left and the odd frames on the right, + * so the user can see two different exposures of the scene simultaneously. In fused HDR mode, + * the even/odd frames are merged together into a single image. By selecting different exposure + * values for the even/odd frames, the fused image has a higher dynamic range than the regular + * viewfinder.
+ * + *The HDR fusion and the split-screen viewfinder processing is done with RenderScript; as is the + * necessary YUV->RGB conversion. The camera subsystem outputs YUV images naturally, while the GPU + * and display subsystems generally only accept RGB data. Therefore, after the images are + * fused/composited, a standard YUV->RGB color transform is applied before the the data is written + * to the output Allocation. The HDR fusion algorithm is very simple, and tends to result in + * lower-contrast scenes, but has very few artifacts and can run very fast.
+ * + *Data is passed between the subsystems (camera, RenderScript, and display) using the + * Android {@link android.view.Surface} class, which allows for zero-copy transport of large + * buffers between processes and subsystems.
+ */ +public class HdrViewfinderActivity extends Activity implements + SurfaceHolder.Callback, CameraOps.ErrorDisplayer, CameraOps.CameraReadyListener { + + private static final String TAG = "HdrViewfinderDemo"; + + private static final String FRAGMENT_DIALOG = "dialog"; + + /** + * View for the camera preview. + */ + private FixedAspectSurfaceView mPreviewView; + + /** + * This shows the current mode of the app. + */ + private TextView mModeText; + + // These show lengths of exposure for even frames, exposure for odd frames, and auto exposure. + private TextView mEvenExposureText, mOddExposureText, mAutoExposureText; + + private Handler mUiHandler; + + private CameraCharacteristics mCameraInfo; + + private Surface mPreviewSurface; + private Surface mProcessingHdrSurface; + private Surface mProcessingNormalSurface; + CaptureRequest.Builder mHdrBuilder; + ArrayList+ + This sample demonstrates the use of animation interpolators and path animations for + Material Design. It shows how an ObjectAnimator is used to animate two properties of a + view (scale X and Y) along a path. + +
diff --git a/samples/browseable/Interpolator/res/drawable-hdpi/ic_launcher.png b/samples/browseable/Interpolator/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..14a1e3a3b Binary files /dev/null and b/samples/browseable/Interpolator/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/Interpolator/res/drawable-hdpi/tile.9.png b/samples/browseable/Interpolator/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/Interpolator/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/Interpolator/res/drawable-mdpi/ic_launcher.png b/samples/browseable/Interpolator/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..e328c4242 Binary files /dev/null and b/samples/browseable/Interpolator/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/Interpolator/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/Interpolator/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..c78e0c4e0 Binary files /dev/null and b/samples/browseable/Interpolator/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/Interpolator/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/Interpolator/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..0be3d8bef Binary files /dev/null and b/samples/browseable/Interpolator/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/Interpolator/res/layout-w720dp/activity_main.xml b/samples/browseable/Interpolator/res/layout-w720dp/activity_main.xml new file mode 100755 index 000000000..c9a52f621 --- /dev/null +++ b/samples/browseable/Interpolator/res/layout-w720dp/activity_main.xml @@ -0,0 +1,73 @@ + +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.
+ */ +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/Interpolator/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/Interpolator/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/Interpolator/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/Interpolator/src/com.example.android.common/logger/LogNode.java b/samples/browseable/Interpolator/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/Interpolator/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/Interpolator/src/com.example.android.common/logger/LogView.java b/samples/browseable/Interpolator/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/Interpolator/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/Interpolator/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/Interpolator/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/Interpolator/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/Interpolator/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/Interpolator/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/Interpolator/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/Interpolator/src/com.example.android.interpolator/InterpolatorFragment.java b/samples/browseable/Interpolator/src/com.example.android.interpolator/InterpolatorFragment.java new file mode 100644 index 000000000..07ecc9530 --- /dev/null +++ b/samples/browseable/Interpolator/src/com.example.android.interpolator/InterpolatorFragment.java @@ -0,0 +1,244 @@ +/* +* Copyright 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. +*/ + +package com.example.android.interpolator; + +import android.animation.ObjectAnimator; +import android.graphics.Path; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.SeekBar; +import android.widget.Spinner; +import android.widget.TextView; + +import com.example.android.common.logger.Log; + +/** + * This sample demonstrates the use of animation interpolators and path animations for + * Material Design. + * It shows how an {@link android.animation.ObjectAnimator} is used to animate two properties of a + * view (scale X and Y) along a path. + */ +public class InterpolatorFragment extends Fragment { + + /** + * View that is animated. + */ + private View mView; + /** + * Spinner for selection of interpolator. + */ + private Spinner mInterpolatorSpinner; + /** + * SeekBar for selection of duration of animation. + */ + private SeekBar mDurationSeekbar; + /** + * TextView that shows animation selected in SeekBar. + */ + private TextView mDurationLabel; + + /** + * Interpolators used for animation. + */ + private Interpolator mInterpolators[]; + /** + * Path for in (shrinking) animation, from 100% scale to 20%. + */ + private Path mPathIn; + /** + * Path for out (growing) animation, from 20% to 100%. + */ + private Path mPathOut; + + /** + * Set to true if View is animated out (is shrunk). + */ + private boolean mIsOut = false; + + /** + * Default duration of animation in ms. + */ + private static final int INITIAL_DURATION_MS = 750; + + /** + * String used for logging. + */ + public static final String TAG = "InterpolatorplaygroundFragment"; + + public InterpolatorFragment() { + // Required empty public constructor + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + // Inflate the fragment_animation layout + View v = inflater.inflate(R.layout.interpolator_fragment, container, false); + + // Set up the 'animate' button, when it is clicked the view is animated with the options + // selected: the Interpolator, duration and animation path + Button button = (Button) v.findViewById(R.id.animateButton); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + // Interpolator selected in the spinner + Interpolator interpolator = mInterpolators[mInterpolatorSpinner.getSelectedItemPosition()]; + // Duration selected in SeekBar + long duration = mDurationSeekbar.getProgress(); + // Animation path is based on whether animating in or out + Path path = mIsOut ? mPathIn : mPathOut; + + // Log animation details + Log.i(TAG, String.format("Starting animation: [%d ms, %s, %s]", + duration, (String) mInterpolatorSpinner.getSelectedItem(), + ((mIsOut) ? "Out (growing)" : "In (shrinking)"))); + + // Start the animation with the selected options + startAnimation(interpolator, duration, path); + + // Toggle direction of animation (path) + mIsOut = !mIsOut; + } + }); + + // Get the label to display the selected duration + mDurationLabel = (TextView) v.findViewById(R.id.durationLabel); + + // Initialize Interpolators programmatically by loading them from their XML definitions + // provided by the framework. + mInterpolators = new Interpolator[]{ + new AnimationUtils().loadInterpolator(getActivity(), + android.R.interpolator.linear), + new AnimationUtils().loadInterpolator(getActivity(), + android.R.interpolator.fast_out_linear_in), + new AnimationUtils().loadInterpolator(getActivity(), + android.R.interpolator.fast_out_slow_in), + new AnimationUtils().loadInterpolator(getActivity(), + android.R.interpolator.linear_out_slow_in) + }; + + // Load names of interpolators from a resource + String[] interpolatorNames = getResources().getStringArray(R.array.interpolator_names); + + // Set up the Spinner with the names of interpolators + mInterpolatorSpinner = (Spinner) v.findViewById(R.id.interpolatorSpinner); + ArrayAdapter
+ * 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();
+ InterpolatorFragment fragment = new InterpolatorFragment();
+ 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/JobScheduler/AndroidManifest.xml b/samples/browseable/JobScheduler/AndroidManifest.xml
new file mode 100644
index 000000000..06a927b94
--- /dev/null
+++ b/samples/browseable/JobScheduler/AndroidManifest.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ + Demonstration of the JobScheduler API, which provides an interface for scheduling + background tasks when certain tasks apply. + +
diff --git a/samples/browseable/JobScheduler/res/drawable-hdpi/ic_launcher.png b/samples/browseable/JobScheduler/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..9cb5f741d Binary files /dev/null and b/samples/browseable/JobScheduler/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/JobScheduler/res/drawable-hdpi/tile.9.png b/samples/browseable/JobScheduler/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/JobScheduler/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/JobScheduler/res/drawable-mdpi/ic_launcher.png b/samples/browseable/JobScheduler/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..869355b5c Binary files /dev/null and b/samples/browseable/JobScheduler/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/JobScheduler/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/JobScheduler/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..679fc16f7 Binary files /dev/null and b/samples/browseable/JobScheduler/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/JobScheduler/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/JobScheduler/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..1734fd354 Binary files /dev/null and b/samples/browseable/JobScheduler/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/JobScheduler/res/layout/activity_main.xml b/samples/browseable/JobScheduler/res/layout/activity_main.xml new file mode 100755 index 000000000..be1aa49d9 --- /dev/null +++ b/samples/browseable/JobScheduler/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + +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.
+ */ +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/JobScheduler/src/com.example.android.common.logger/LogFragment.java b/samples/browseable/JobScheduler/src/com.example.android.common.logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/JobScheduler/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/JobScheduler/src/com.example.android.common.logger/LogNode.java b/samples/browseable/JobScheduler/src/com.example.android.common.logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/JobScheduler/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/JobScheduler/src/com.example.android.common.logger/LogView.java b/samples/browseable/JobScheduler/src/com.example.android.common.logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/JobScheduler/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/JobScheduler/src/com.example.android.common.logger/LogWrapper.java b/samples/browseable/JobScheduler/src/com.example.android.common.logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/JobScheduler/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/JobScheduler/src/com.example.android.common.logger/MessageOnlyLogFilter.java b/samples/browseable/JobScheduler/src/com.example.android.common.logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/JobScheduler/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/JobScheduler/src/com.example.android.jobscheduler/MainActivity.java b/samples/browseable/JobScheduler/src/com.example.android.jobscheduler/MainActivity.java new file mode 100644 index 000000000..f495bf1b6 --- /dev/null +++ b/samples/browseable/JobScheduler/src/com.example.android.jobscheduler/MainActivity.java @@ -0,0 +1,195 @@ +/* + * 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.jobscheduler; + +import android.app.Activity; +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.text.TextUtils; +import android.view.View; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.TextView; +import android.widget.Toast; + +import com.example.android.jobscheduler.service.TestJobService; + +public class MainActivity extends Activity { + + private static final String TAG = "MainActivity"; + + public static final int MSG_UNCOLOUR_START = 0; + public static final int MSG_UNCOLOUR_STOP = 1; + public static final int MSG_SERVICE_OBJ = 2; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.sample_main); + Resources res = getResources(); + defaultColor = res.getColor(R.color.none_received); + startJobColor = res.getColor(R.color.start_received); + stopJobColor = res.getColor(R.color.stop_received); + + // Set up UI. + mShowStartView = (TextView) findViewById(R.id.onstart_textview); + mShowStopView = (TextView) findViewById(R.id.onstop_textview); + mParamsTextView = (TextView) findViewById(R.id.task_params); + mDelayEditText = (EditText) findViewById(R.id.delay_time); + mDeadlineEditText = (EditText) findViewById(R.id.deadline_time); + mWiFiConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_unmetered); + mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any); + mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging); + mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle); + mServiceComponent = new ComponentName(this, TestJobService.class); + // Start service and provide it a way to communicate with us. + Intent startServiceIntent = new Intent(this, TestJobService.class); + startServiceIntent.putExtra("messenger", new Messenger(mHandler)); + startService(startServiceIntent); + } + // UI fields. + int defaultColor; + int startJobColor; + int stopJobColor; + + private TextView mShowStartView; + private TextView mShowStopView; + private TextView mParamsTextView; + private EditText mDelayEditText; + private EditText mDeadlineEditText; + private RadioButton mWiFiConnectivityRadioButton; + private RadioButton mAnyConnectivityRadioButton; + private CheckBox mRequiresChargingCheckBox; + private CheckBox mRequiresIdleCheckbox; + + ComponentName mServiceComponent; + /** Service object to interact scheduled jobs. */ + TestJobService mTestService; + + private static int kJobId = 0; + + Handler mHandler = new Handler(/* default looper */) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_UNCOLOUR_START: + mShowStartView.setBackgroundColor(defaultColor); + break; + case MSG_UNCOLOUR_STOP: + mShowStopView.setBackgroundColor(defaultColor); + break; + case MSG_SERVICE_OBJ: + mTestService = (TestJobService) msg.obj; + mTestService.setUiCallback(MainActivity.this); + } + } + }; + + private boolean ensureTestService() { + if (mTestService == null) { + Toast.makeText(MainActivity.this, "Service null, never got callback?", + Toast.LENGTH_SHORT).show(); + return false; + } + return true; + } + + /** + * UI onclick listener to schedule a job. What this job is is defined in + * TestJobService#scheduleJob(). + */ + public void scheduleJob(View v) { + if (!ensureTestService()) { + return; + } + + JobInfo.Builder builder = new JobInfo.Builder(kJobId++, mServiceComponent); + + String delay = mDelayEditText.getText().toString(); + if (delay != null && !TextUtils.isEmpty(delay)) { + builder.setMinimumLatency(Long.valueOf(delay) * 1000); + } + String deadline = mDeadlineEditText.getText().toString(); + if (deadline != null && !TextUtils.isEmpty(deadline)) { + builder.setOverrideDeadline(Long.valueOf(deadline) * 1000); + } + boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked(); + boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked(); + if (requiresUnmetered) { + builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED); + } else if (requiresAnyConnectivity) { + builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY); + } + builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked()); + builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked()); + + mTestService.scheduleJob(builder.build()); + + } + + public void cancelAllJobs(View v) { + JobScheduler tm = + (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); + tm.cancelAll(); + } + + /** + * UI onclick listener to call jobFinished() in our service. + */ + public void finishJob(View v) { + if (!ensureTestService()) { + return; + } + mTestService.callJobFinished(); + mParamsTextView.setText(""); + } + + /** + * Receives callback from the service when a job has landed + * on the app. Colours the UI and post a message to + * uncolour it after a second. + */ + public void onReceivedStartJob(JobParameters params) { + mShowStartView.setBackgroundColor(startJobColor); + Message m = Message.obtain(mHandler, MSG_UNCOLOUR_START); + mHandler.sendMessageDelayed(m, 1000L); // uncolour in 1 second. + mParamsTextView.setText("Executing: " + params.getJobId() + " " + params.getExtras()); + } + + /** + * Receives callback from the service when a job that + * previously landed on the app must stop executing. + * Colours the UI and post a message to uncolour it after a + * second. + */ + public void onReceivedStopJob() { + mShowStopView.setBackgroundColor(stopJobColor); + Message m = Message.obtain(mHandler, MSG_UNCOLOUR_STOP); + mHandler.sendMessageDelayed(m, 2000L); // uncolour in 1 second. + mParamsTextView.setText(""); + } +} diff --git a/samples/browseable/JobScheduler/src/com.example.android.jobscheduler/service/TestJobService.java b/samples/browseable/JobScheduler/src/com.example.android.jobscheduler/service/TestJobService.java new file mode 100644 index 000000000..8608be570 --- /dev/null +++ b/samples/browseable/JobScheduler/src/com.example.android.jobscheduler/service/TestJobService.java @@ -0,0 +1,127 @@ +/* + * Copyright 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.jobscheduler.service; + +import android.app.job.JobInfo; +import android.app.job.JobScheduler; +import android.app.job.JobParameters; +import android.app.job.JobService; +import android.content.Context; +import android.content.Intent; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.util.Log; + +import com.example.android.jobscheduler.MainActivity; + +import java.util.LinkedList; + + +/** + * Service to handle callbacks from the JobScheduler. Requests scheduled with the JobScheduler + * ultimately land on this service's "onStartJob" method. Currently all this does is post a message + * to the app's main activity to change the state of the UI. + */ +public class TestJobService extends JobService { + private static final String TAG = "SyncService"; + + @Override + public void onCreate() { + super.onCreate(); + Log.i(TAG, "Service created"); + } + + @Override + public void onDestroy() { + super.onDestroy(); + Log.i(TAG, "Service destroyed"); + } + + /** + * When the app's MainActivity is created, it starts this service. This is so that the + * activity and this service can communicate back and forth. See "setUiCalback()" + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Messenger callback = intent.getParcelableExtra("messenger"); + Message m = Message.obtain(); + m.what = MainActivity.MSG_SERVICE_OBJ; + m.obj = this; + try { + callback.send(m); + } catch (RemoteException e) { + Log.e(TAG, "Error passing service object back to activity."); + } + return START_NOT_STICKY; + } + + @Override + public boolean onStartJob(JobParameters params) { + // We don't do any real 'work' in this sample app. All we'll + // do is track which jobs have landed on our service, and + // update the UI accordingly. + jobParamsMap.add(params); + if (mActivity != null) { + mActivity.onReceivedStartJob(params); + } + Log.i(TAG, "on start job: " + params.getJobId()); + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + // Stop tracking these job parameters, as we've 'finished' executing. + jobParamsMap.remove(params); + if (mActivity != null) { + mActivity.onReceivedStopJob(); + } + Log.i(TAG, "on stop job: " + params.getJobId()); + return true; + } + + MainActivity mActivity; + private final LinkedList+ + This sample demonstrates how new features for notifications introduced in Android L + are used such as Heads-Up notifications, visibility, people, category and priority + metadata. (Priority metadata has been present since Jelly Bean, but actually unused). + +
diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_contact_picture.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_contact_picture.png new file mode 100644 index 000000000..00d0ec43a Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_contact_picture.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_launcher.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..015d24866 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_launcher_notification.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_launcher_notification.png new file mode 100644 index 000000000..4b058c1d5 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_launcher_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_private.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_private.png new file mode 100644 index 000000000..663f93e9e Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_private.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_private_notification.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_private_notification.png new file mode 100644 index 000000000..dbf5139f3 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_private_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_public.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_public.png new file mode 100644 index 000000000..033281dd7 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_public.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_public_notification.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_public_notification.png new file mode 100644 index 000000000..fe1ee8172 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_public_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_secret.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_secret.png new file mode 100644 index 000000000..a22dbdfc9 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_secret.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/ic_secret_notification.png b/samples/browseable/LNotifications/res/drawable-hdpi/ic_secret_notification.png new file mode 100644 index 000000000..577662401 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/ic_secret_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-hdpi/tile.9.png b/samples/browseable/LNotifications/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_contact_picture.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_contact_picture.png new file mode 100644 index 000000000..771cb6bb8 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_contact_picture.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_launcher.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..605a25654 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_launcher_notification.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_launcher_notification.png new file mode 100644 index 000000000..72cd1b32d Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_launcher_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_private.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_private.png new file mode 100644 index 000000000..2556153ef Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_private.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_private_notification.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_private_notification.png new file mode 100644 index 000000000..df9396495 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_private_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_public.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_public.png new file mode 100644 index 000000000..ff0c65319 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_public.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_public_notification.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_public_notification.png new file mode 100644 index 000000000..7c69019cf Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_public_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_secret.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_secret.png new file mode 100644 index 000000000..28431640e Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_secret.png differ diff --git a/samples/browseable/LNotifications/res/drawable-mdpi/ic_secret_notification.png b/samples/browseable/LNotifications/res/drawable-mdpi/ic_secret_notification.png new file mode 100644 index 000000000..652e8b0a4 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-mdpi/ic_secret_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_contact_picture.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_contact_picture.png new file mode 100644 index 000000000..bdba57b6b Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_contact_picture.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..c08bafa5f Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_launcher_notification.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_launcher_notification.png new file mode 100644 index 000000000..9a42c7a76 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_launcher_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_private.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_private.png new file mode 100644 index 000000000..823d9420e Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_private.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_private_notification.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_private_notification.png new file mode 100644 index 000000000..497a1ac10 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_private_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_public.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_public.png new file mode 100644 index 000000000..93b89ff1b Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_public.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_public_notification.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_public_notification.png new file mode 100644 index 000000000..1d6f1f1e7 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_public_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_secret.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_secret.png new file mode 100644 index 000000000..5124eee74 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_secret.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xhdpi/ic_secret_notification.png b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_secret_notification.png new file mode 100644 index 000000000..8388dd546 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xhdpi/ic_secret_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_contact_picture.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_contact_picture.png new file mode 100644 index 000000000..b36ec1730 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_contact_picture.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..1224b3915 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_launcher_notification.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_launcher_notification.png new file mode 100644 index 000000000..e25fff176 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_launcher_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_private.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_private.png new file mode 100644 index 000000000..4e4d3d677 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_private.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_private_notification.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_private_notification.png new file mode 100644 index 000000000..dd5de277c Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_private_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_public.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_public.png new file mode 100644 index 000000000..6aede4e56 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_public.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_public_notification.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_public_notification.png new file mode 100644 index 000000000..9b8c59f2c Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_public_notification.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_secret.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_secret.png new file mode 100644 index 000000000..d1e126c6e Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_secret.png differ diff --git a/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_secret_notification.png b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_secret_notification.png new file mode 100644 index 000000000..be59c8f71 Binary files /dev/null and b/samples/browseable/LNotifications/res/drawable-xxhdpi/ic_secret_notification.png differ diff --git a/samples/browseable/LNotifications/res/layout/activity_main.xml b/samples/browseable/LNotifications/res/layout/activity_main.xml new file mode 100755 index 000000000..be1aa49d9 --- /dev/null +++ b/samples/browseable/LNotifications/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + ++ + This example illustrates a common usage of the DrawerLayout widget in the Android + support library. + +
diff --git a/samples/browseable/NavigationDrawer/res/drawable-hdpi/action_search.png b/samples/browseable/NavigationDrawer/res/drawable-hdpi/action_search.png new file mode 100755 index 000000000..f12e005eb Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-hdpi/action_search.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-hdpi/drawer_shadow.9.png b/samples/browseable/NavigationDrawer/res/drawable-hdpi/drawer_shadow.9.png new file mode 100644 index 000000000..224cc4ff4 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-hdpi/drawer_shadow.9.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-hdpi/ic_drawer.png b/samples/browseable/NavigationDrawer/res/drawable-hdpi/ic_drawer.png new file mode 100644 index 000000000..ff7b1def9 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-hdpi/ic_drawer.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-hdpi/ic_launcher.png b/samples/browseable/NavigationDrawer/res/drawable-hdpi/ic_launcher.png new file mode 100755 index 000000000..b460d6021 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-hdpi/tile.9.png b/samples/browseable/NavigationDrawer/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-mdpi/action_search.png b/samples/browseable/NavigationDrawer/res/drawable-mdpi/action_search.png new file mode 100755 index 000000000..587d9e0bf Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-mdpi/action_search.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-mdpi/drawer_shadow.9.png b/samples/browseable/NavigationDrawer/res/drawable-mdpi/drawer_shadow.9.png new file mode 100644 index 000000000..3797f99c0 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-mdpi/drawer_shadow.9.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-mdpi/ic_drawer.png b/samples/browseable/NavigationDrawer/res/drawable-mdpi/ic_drawer.png new file mode 100644 index 000000000..fb681ba26 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-mdpi/ic_drawer.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-mdpi/ic_launcher.png b/samples/browseable/NavigationDrawer/res/drawable-mdpi/ic_launcher.png new file mode 100755 index 000000000..dee53f408 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-xhdpi/action_search.png b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/action_search.png new file mode 100755 index 000000000..3549f84dd Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/action_search.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-xhdpi/drawer_shadow.9.png b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/drawer_shadow.9.png new file mode 100644 index 000000000..fa3d853e9 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/drawer_shadow.9.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-xhdpi/ic_drawer.png b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/ic_drawer.png new file mode 100644 index 000000000..b9bc3d70f Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/ic_drawer.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/ic_launcher.png new file mode 100755 index 000000000..d4e121531 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-xhdpi/sample_dashboard_item_background.9.png b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/sample_dashboard_item_background.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-xhdpi/sample_dashboard_item_background.9.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/NavigationDrawer/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..6ef21e1f4 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/earth.jpg b/samples/browseable/NavigationDrawer/res/drawable/earth.jpg new file mode 100644 index 000000000..6cabbf4ac Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/earth.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/jupiter.jpg b/samples/browseable/NavigationDrawer/res/drawable/jupiter.jpg new file mode 100644 index 000000000..24e8eea35 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/jupiter.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/mars.jpg b/samples/browseable/NavigationDrawer/res/drawable/mars.jpg new file mode 100644 index 000000000..db253ef5e Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/mars.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/mercury.jpg b/samples/browseable/NavigationDrawer/res/drawable/mercury.jpg new file mode 100644 index 000000000..531790b99 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/mercury.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/neptune.jpg b/samples/browseable/NavigationDrawer/res/drawable/neptune.jpg new file mode 100644 index 000000000..88467c5f7 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/neptune.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/saturn.jpg b/samples/browseable/NavigationDrawer/res/drawable/saturn.jpg new file mode 100644 index 000000000..8219d1879 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/saturn.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/uranus.jpg b/samples/browseable/NavigationDrawer/res/drawable/uranus.jpg new file mode 100644 index 000000000..fa32e3796 Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/uranus.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/drawable/venus.jpg b/samples/browseable/NavigationDrawer/res/drawable/venus.jpg new file mode 100644 index 000000000..e04f0789e Binary files /dev/null and b/samples/browseable/NavigationDrawer/res/drawable/venus.jpg differ diff --git a/samples/browseable/NavigationDrawer/res/layout/activity_main.xml b/samples/browseable/NavigationDrawer/res/layout/activity_main.xml new file mode 100755 index 000000000..88cdb8056 --- /dev/null +++ b/samples/browseable/NavigationDrawer/res/layout/activity_main.xml @@ -0,0 +1,41 @@ + + +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.
+ */ +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/NavigationDrawer/src/com.example.android.common.logger/LogFragment.java b/samples/browseable/NavigationDrawer/src/com.example.android.common.logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/NavigationDrawer/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/NavigationDrawer/src/com.example.android.common.logger/LogNode.java b/samples/browseable/NavigationDrawer/src/com.example.android.common.logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/NavigationDrawer/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/NavigationDrawer/src/com.example.android.common.logger/LogView.java b/samples/browseable/NavigationDrawer/src/com.example.android.common.logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/NavigationDrawer/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/NavigationDrawer/src/com.example.android.common.logger/LogWrapper.java b/samples/browseable/NavigationDrawer/src/com.example.android.common.logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/NavigationDrawer/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/NavigationDrawer/src/com.example.android.common.logger/MessageOnlyLogFilter.java b/samples/browseable/NavigationDrawer/src/com.example.android.common.logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/NavigationDrawer/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/NavigationDrawer/src/com.example.android.navigationdrawer/MainActivity.java b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/MainActivity.java new file mode 100644 index 000000000..665edf37f --- /dev/null +++ b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/MainActivity.java @@ -0,0 +1,107 @@ +/* +* 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.navigationdrawer; + +import android.app.Activity; +import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.TextView; + +/** + * A simple launcher activity offering access to the individual samples in this project. + */ +public class MainActivity extends Activity implements AdapterView.OnItemClickListener { + private Sample[] mSamples; + private GridView mGridView; + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Prepare list of samples in this dashboard. + mSamples = new Sample[]{ + new Sample(R.string.navigationdraweractivity_title, R.string.navigationdraweractivity_description, + NavigationDrawerActivity.class), + }; + + // Prepare the GridView + mGridView = (GridView) findViewById(android.R.id.list); + mGridView.setAdapter(new SampleAdapter()); + mGridView.setOnItemClickListener(this); + } + + @Override + public void onItemClick(AdapterView> container, View view, int position, long id) { + startActivity(mSamples[position].intent); + } + + private class SampleAdapter extends BaseAdapter { + @Override + public int getCount() { + return mSamples.length; + } + + @Override + public Object getItem(int position) { + return mSamples[position]; + } + + @Override + public long getItemId(int position) { + return mSamples[position].hashCode(); + } + + @Override + public View getView(int position, View convertView, ViewGroup container) { + if (convertView == null) { + convertView = getLayoutInflater().inflate(R.layout.sample_dashboard_item, + container, false); + } + + ((TextView) convertView.findViewById(android.R.id.text1)).setText( + mSamples[position].titleResId); + ((TextView) convertView.findViewById(android.R.id.text2)).setText( + mSamples[position].descriptionResId); + return convertView; + } + } + + private class Sample { + int titleResId; + int descriptionResId; + Intent intent; + + private Sample(int titleResId, int descriptionResId, Intent intent) { + this.intent = intent; + this.titleResId = titleResId; + this.descriptionResId = descriptionResId; + } + + private Sample(int titleResId, int descriptionResId, + Class extends Activity> activityClass) { + this(titleResId, descriptionResId, + new Intent(MainActivity.this, activityClass)); + } + } +} diff --git a/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/NavigationDrawerActivity.java b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/NavigationDrawerActivity.java new file mode 100644 index 000000000..117675701 --- /dev/null +++ b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/NavigationDrawerActivity.java @@ -0,0 +1,247 @@ +/* + * 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. + */ + +package com.example.android.navigationdrawer; + +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.app.SearchManager; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.v4.app.ActionBarDrawerToggle; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.Toast; + +import java.util.Locale; + +/** + * This example illustrates a common usage of the DrawerLayout widget + * in the Android support library. + * + *When a navigation (left) drawer is present, the host activity should detect presses of + * the action bar's Up affordance as a signal to open and close the navigation drawer. The + * ActionBarDrawerToggle facilitates this behavior. + * Items within the drawer should fall into one of two categories:
+ * + *Right side drawers should be used for actions, not navigation. This follows the pattern + * established by the Action Bar that navigation should be to the left and actions to the right. + * An action should be an operation performed on the current contents of the window, + * for example enabling or disabling a data overlay on top of the current content.
+ */ +public class NavigationDrawerActivity extends Activity implements PlanetAdapter.OnItemClickListener { + private DrawerLayout mDrawerLayout; + private RecyclerView mDrawerList; + private ActionBarDrawerToggle mDrawerToggle; + + private CharSequence mDrawerTitle; + private CharSequence mTitle; + private String[] mPlanetTitles; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_navigation_drawer); + + mTitle = mDrawerTitle = getTitle(); + mPlanetTitles = getResources().getStringArray(R.array.planets_array); + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + mDrawerList = (RecyclerView) findViewById(R.id.left_drawer); + + // set a custom shadow that overlays the main content when the drawer opens + mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); + // improve performance by indicating the list if fixed size. + mDrawerList.setHasFixedSize(true); + mDrawerList.setLayoutManager(new LinearLayoutManager(this)); + + // set up the drawer's list view with items and click listener + mDrawerList.setAdapter(new PlanetAdapter(mPlanetTitles, this)); + // enable ActionBar app icon to behave as action to toggle nav drawer + getActionBar().setDisplayHomeAsUpEnabled(true); + getActionBar().setHomeButtonEnabled(true); + + // ActionBarDrawerToggle ties together the the proper interactions + // between the sliding drawer and the action bar app icon + mDrawerToggle = new ActionBarDrawerToggle( + this, /* host Activity */ + mDrawerLayout, /* DrawerLayout object */ + R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */ + R.string.drawer_open, /* "open drawer" description for accessibility */ + R.string.drawer_close /* "close drawer" description for accessibility */ + ) { + public void onDrawerClosed(View view) { + getActionBar().setTitle(mTitle); + invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() + } + + public void onDrawerOpened(View drawerView) { + getActionBar().setTitle(mDrawerTitle); + invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() + } + }; + mDrawerLayout.setDrawerListener(mDrawerToggle); + + if (savedInstanceState == null) { + selectItem(0); + } + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.navigation_drawer, menu); + return true; + } + + /* Called whenever we call invalidateOptionsMenu() */ + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + // If the nav drawer is open, hide action items related to the content view + boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList); + menu.findItem(R.id.action_websearch).setVisible(!drawerOpen); + return super.onPrepareOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // The action bar home/up action should open or close the drawer. + // ActionBarDrawerToggle will take care of this. + if (mDrawerToggle.onOptionsItemSelected(item)) { + return true; + } + // Handle action buttons + switch (item.getItemId()) { + case R.id.action_websearch: + // create intent to perform web search for this planet + Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); + intent.putExtra(SearchManager.QUERY, getActionBar().getTitle()); + // catch event that there's no activity to handle intent + if (intent.resolveActivity(getPackageManager()) != null) { + startActivity(intent); + } else { + Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show(); + } + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + /* The click listener for RecyclerView in the navigation drawer */ + @Override + public void onClick(View view, int position) { + selectItem(position); + } + + private void selectItem(int position) { + // update the main content by replacing fragments + Fragment fragment = PlanetFragment.newInstance(position); + + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction ft = fragmentManager.beginTransaction(); + ft.replace(R.id.content_frame, fragment); + ft.commit(); + + // update selected item title, then close the drawer + setTitle(mPlanetTitles[position]); + mDrawerLayout.closeDrawer(mDrawerList); + } + + @Override + public void setTitle(CharSequence title) { + mTitle = title; + getActionBar().setTitle(mTitle); + } + + /** + * When using the ActionBarDrawerToggle, you must call it during + * onPostCreate() and onConfigurationChanged()... + */ + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + // Sync the toggle state after onRestoreInstanceState has occurred. + mDrawerToggle.syncState(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + // Pass any configuration change to the drawer toggls + mDrawerToggle.onConfigurationChanged(newConfig); + } + + /** + * Fragment that appears in the "content_frame", shows a planet + */ + public static class PlanetFragment extends Fragment { + public static final String ARG_PLANET_NUMBER = "planet_number"; + + public PlanetFragment() { + // Empty constructor required for fragment subclasses + } + + public static Fragment newInstance(int position) { + Fragment fragment = new PlanetFragment(); + Bundle args = new Bundle(); + args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position); + fragment.setArguments(args); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_planet, container, false); + int i = getArguments().getInt(ARG_PLANET_NUMBER); + String planet = getResources().getStringArray(R.array.planets_array)[i]; + + int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()), + "drawable", getActivity().getPackageName()); + ImageView iv = ((ImageView) rootView.findViewById(R.id.image)); + iv.setImageResource(imageId); + + getActivity().setTitle(planet); + return rootView; + } + } +} diff --git a/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/PlanetAdapter.java b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/PlanetAdapter.java new file mode 100644 index 000000000..5b449d0fc --- /dev/null +++ b/samples/browseable/NavigationDrawer/src/com.example.android.navigationdrawer/PlanetAdapter.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +package com.example.android.navigationdrawer; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.TextView; + +/** + * Adapter for the planet data used in our drawer menu, + */ +public class PlanetAdapter extends RecyclerView.Adapter+ + Demonstration of using RecyclerView with a LayoutManager to create a vertical ListView. + +
diff --git a/samples/browseable/RecyclerView/res/drawable-hdpi/ic_launcher.png b/samples/browseable/RecyclerView/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..bcb72b12f Binary files /dev/null and b/samples/browseable/RecyclerView/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/RecyclerView/res/drawable-hdpi/tile.9.png b/samples/browseable/RecyclerView/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/RecyclerView/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/RecyclerView/res/drawable-mdpi/ic_launcher.png b/samples/browseable/RecyclerView/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..37e5bce60 Binary files /dev/null and b/samples/browseable/RecyclerView/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/RecyclerView/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/RecyclerView/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..1c4a85a02 Binary files /dev/null and b/samples/browseable/RecyclerView/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/RecyclerView/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/RecyclerView/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..b26545c36 Binary files /dev/null and b/samples/browseable/RecyclerView/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/RecyclerView/res/layout-w720dp/activity_main.xml b/samples/browseable/RecyclerView/res/layout-w720dp/activity_main.xml new file mode 100755 index 000000000..c9a52f621 --- /dev/null +++ b/samples/browseable/RecyclerView/res/layout-w720dp/activity_main.xml @@ -0,0 +1,73 @@ + +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.
+ */ +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/RecyclerView/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/RecyclerView/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/RecyclerView/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/RecyclerView/src/com.example.android.common/logger/LogNode.java b/samples/browseable/RecyclerView/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/RecyclerView/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/RecyclerView/src/com.example.android.common/logger/LogView.java b/samples/browseable/RecyclerView/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/RecyclerView/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/RecyclerView/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/RecyclerView/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/RecyclerView/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/RecyclerView/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/RecyclerView/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/RecyclerView/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/RecyclerView/src/com.example.android.recyclerview/CustomAdapter.java b/samples/browseable/RecyclerView/src/com.example.android.recyclerview/CustomAdapter.java new file mode 100644 index 000000000..f8e3baecf --- /dev/null +++ b/samples/browseable/RecyclerView/src/com.example.android.recyclerview/CustomAdapter.java @@ -0,0 +1,91 @@ +/* +* 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. +*/ + +package com.example.android.recyclerview; + +import com.example.android.common.logger.Log; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +/** + * Provide views to RecyclerView with data from mDataSet. + */ +public class CustomAdapter extends RecyclerView.Adapter
+ * 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();
+ RecyclerViewFragment fragment = new RecyclerViewFragment();
+ 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/RecyclerView/src/com.example.android.recyclerview/RecyclerViewFragment.java b/samples/browseable/RecyclerView/src/com.example.android.recyclerview/RecyclerViewFragment.java
new file mode 100644
index 000000000..4f4a5966a
--- /dev/null
+++ b/samples/browseable/RecyclerView/src/com.example.android.recyclerview/RecyclerViewFragment.java
@@ -0,0 +1,81 @@
+/*
+* 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.
+*/
+
+package com.example.android.recyclerview;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Demonstrates the use of RecyclerView with a LinearLayoutManager.
+ */
+public class RecyclerViewFragment extends Fragment {
+
+ private static final String TAG = "RecyclerViewFragment";
+
+ protected RecyclerView mRecyclerView;
+ protected RecyclerView.Adapter mAdapter;
+ protected RecyclerView.LayoutManager mLayoutManager;
+ protected String[] mDataset;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Initialize dataset, this data would usually come from a local content provider or
+ // remote server.
+ initDataset();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false);
+ rootView.setTag(TAG);
+
+ // BEGIN_INCLUDE(initializeRecyclerView)
+ mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
+
+ // LinearLayoutManager is used here, this will layout the elements in a similar fashion
+ // to the way ListView would layout elements. The RecyclerView.LayoutManager defines how
+ // elements are laid out.
+ mLayoutManager = new LinearLayoutManager(getActivity());
+ mRecyclerView.setLayoutManager(mLayoutManager);
+
+ mAdapter = new CustomAdapter(mDataset);
+ // Set CustomAdapter as the adapter for RecyclerView.
+ mRecyclerView.setAdapter(mAdapter);
+ // END_INCLUDE(initializeRecyclerView)
+
+ return rootView;
+ }
+
+ /**
+ * Generates Strings for RecyclerView's adapter. This data would usually come
+ * from a local content provider or remote server.
+ */
+ private void initDataset() {
+ mDataset = new String[60];
+ for (int i=0; i < 60; i++) {
+ mDataset[i] = "This is element #" + i;
+ }
+ }
+}
diff --git a/samples/browseable/RevealEffectBasic/AndroidManifest.xml b/samples/browseable/RevealEffectBasic/AndroidManifest.xml
new file mode 100644
index 000000000..da8646b71
--- /dev/null
+++ b/samples/browseable/RevealEffectBasic/AndroidManifest.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ + Basic sample to demonstrate the reveal effect. + +
diff --git a/samples/browseable/RevealEffectBasic/res/drawable-hdpi/ic_launcher.png b/samples/browseable/RevealEffectBasic/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..5acc60aa6 Binary files /dev/null and b/samples/browseable/RevealEffectBasic/res/drawable-hdpi/ic_launcher.png differ diff --git a/samples/browseable/RevealEffectBasic/res/drawable-hdpi/tile.9.png b/samples/browseable/RevealEffectBasic/res/drawable-hdpi/tile.9.png new file mode 100644 index 000000000..135862883 Binary files /dev/null and b/samples/browseable/RevealEffectBasic/res/drawable-hdpi/tile.9.png differ diff --git a/samples/browseable/RevealEffectBasic/res/drawable-mdpi/ic_launcher.png b/samples/browseable/RevealEffectBasic/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..d3977a605 Binary files /dev/null and b/samples/browseable/RevealEffectBasic/res/drawable-mdpi/ic_launcher.png differ diff --git a/samples/browseable/RevealEffectBasic/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/RevealEffectBasic/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..71532a7aa Binary files /dev/null and b/samples/browseable/RevealEffectBasic/res/drawable-xhdpi/ic_launcher.png differ diff --git a/samples/browseable/RevealEffectBasic/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/RevealEffectBasic/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..33d9879cb Binary files /dev/null and b/samples/browseable/RevealEffectBasic/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/samples/browseable/RevealEffectBasic/res/layout-w720dp/activity_main.xml b/samples/browseable/RevealEffectBasic/res/layout-w720dp/activity_main.xml new file mode 100755 index 000000000..c9a52f621 --- /dev/null +++ b/samples/browseable/RevealEffectBasic/res/layout-w720dp/activity_main.xml @@ -0,0 +1,73 @@ + +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.
+ */ +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/RevealEffectBasic/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/RevealEffectBasic/src/com.example.android.common/logger/LogFragment.java new file mode 100644 index 000000000..b302acd4b --- /dev/null +++ b/samples/browseable/RevealEffectBasic/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/RevealEffectBasic/src/com.example.android.common/logger/LogNode.java b/samples/browseable/RevealEffectBasic/src/com.example.android.common/logger/LogNode.java new file mode 100644 index 000000000..bc37cabc0 --- /dev/null +++ b/samples/browseable/RevealEffectBasic/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/RevealEffectBasic/src/com.example.android.common/logger/LogView.java b/samples/browseable/RevealEffectBasic/src/com.example.android.common/logger/LogView.java new file mode 100644 index 000000000..c01542b91 --- /dev/null +++ b/samples/browseable/RevealEffectBasic/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/RevealEffectBasic/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/RevealEffectBasic/src/com.example.android.common/logger/LogWrapper.java new file mode 100644 index 000000000..16a9e7ba2 --- /dev/null +++ b/samples/browseable/RevealEffectBasic/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/RevealEffectBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/RevealEffectBasic/src/com.example.android.common/logger/MessageOnlyLogFilter.java new file mode 100644 index 000000000..19967dcd4 --- /dev/null +++ b/samples/browseable/RevealEffectBasic/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/RevealEffectBasic/src/com.example.android.revealeffectbasic/MainActivity.java b/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/MainActivity.java new file mode 100644 index 000000000..e9b27d9cf --- /dev/null +++ b/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/MainActivity.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. +*/ + +package com.example.android.revealeffectbasic; + +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. + *+ * 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(); + RevealEffectBasicFragment fragment = new RevealEffectBasicFragment(); + 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/RevealEffectBasic/src/com.example.android.revealeffectbasic/RevealEffectBasicFragment.java b/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/RevealEffectBasicFragment.java new file mode 100644 index 000000000..152061984 --- /dev/null +++ b/samples/browseable/RevealEffectBasic/src/com.example.android.revealeffectbasic/RevealEffectBasicFragment.java @@ -0,0 +1,79 @@ +/* + * Copyright 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. + */ +package com.example.android.revealeffectbasic; + +import com.example.android.common.logger.Log; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.support.v4.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewAnimationUtils; +import android.view.ViewGroup; +import android.view.animation.AccelerateDecelerateInterpolator; + +/** + * This sample shows a view that is revealed when a button is clicked. + */ +public class RevealEffectBasicFragment extends Fragment { + + private final static String TAG = "RevealEffectBasicFragment"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View rootView = inflater.inflate(R.layout.reveal_effect_basic, container, false); + + View button = rootView.findViewById(R.id.button); + + // Set a listener to reveal the view when clicked. + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + View shape = rootView.findViewById(R.id.circle); + + // Create a reveal {@link Animator} that starts clipping the view from + // the top left corner until the whole view is covered. + Animator animator = ViewAnimationUtils.createCircularReveal( + shape, + 0, + 0, + 0, + (float) Math.hypot(shape.getWidth(), shape.getHeight())); + + // Set a natural ease-in/ease-out interpolator. + animator.setInterpolator(new AccelerateDecelerateInterpolator()); + + // Finally start the animation + animator.start(); + + Log.d(TAG, "Starting Reveal animation"); + } + }); + + return rootView; + } + +} \ No newline at end of file