Merge "Bump minSdk to 9 everywhere where it was < 9"
diff --git a/build.gradle b/build.gradle
index a58ad47..3c11c7e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,7 +9,7 @@
maven { url "../../prebuilts/maven_repo/android" }
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.0-alpha1'
+ classpath 'com.android.tools.build:gradle:2.1.0-alpha4'
}
}
diff --git a/customtabs/api/current.txt b/customtabs/api/current.txt
index 556da16..9b24129 100644
--- a/customtabs/api/current.txt
+++ b/customtabs/api/current.txt
@@ -14,7 +14,10 @@
public class CustomTabsClient {
method public static boolean bindCustomTabsService(android.content.Context, java.lang.String, android.support.customtabs.CustomTabsServiceConnection);
+ method public static boolean connectAndInitialize(android.content.Context, java.lang.String);
method public android.os.Bundle extraCommand(java.lang.String, android.os.Bundle);
+ method public static java.lang.String getPackageName(android.content.Context, java.util.List<java.lang.String>);
+ method public static java.lang.String getPackageName(android.content.Context, java.util.List<java.lang.String>, boolean);
method public android.support.customtabs.CustomTabsSession newSession(android.support.customtabs.CustomTabsCallback);
method public boolean warmup(long);
}
diff --git a/customtabs/src/android/support/customtabs/CustomTabsClient.java b/customtabs/src/android/support/customtabs/CustomTabsClient.java
index 7cc5c76..75e99bd 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsClient.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsClient.java
@@ -20,11 +20,15 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
+import android.support.annotation.Nullable;
import android.text.TextUtils;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -62,7 +66,95 @@
}
/**
+ * Returns the preferred package to use for Custom Tabs, preferring the default VIEW handler.
+ *
+ * @see {@link #getPackageName(Context, List<String>, boolean)}.
+ */
+ public static String getPackageName(Context context, @Nullable List<String> packages) {
+ return getPackageName(context, packages, false);
+ }
+
+ /**
+ * Returns the preferred package to use for Custom Tabs.
+ *
+ * Unless <code>ignoreDefault</code> is true, if the default VIEW handler supports Custom Tabs,
+ * its package name will be returned, irrespective of the content of <code>packages</code>.
+ *
+ * @param context {@link Context} to use for querying the packages.
+ * @param packages Ordered list of packages to test for Custom Tabs support, in
+ * decreasing order of priority.
+ * @param ignoreDefault If set, don't systematically prefer the default VIEW handler.
+ * @return The preferred package name for handling Custom Tabs, or <code>null</code>.
+ */
+ public static String getPackageName(
+ Context context, @Nullable List<String> packages, boolean ignoreDefault) {
+ PackageManager pm = context.getPackageManager();
+
+ List<String> packageNames = packages == null ? new ArrayList<String>() : packages;
+ Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
+
+ if (!ignoreDefault) {
+ ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
+ if (defaultViewHandlerInfo != null) {
+ String packageName = defaultViewHandlerInfo.activityInfo.packageName;
+ packageNames = new ArrayList<String>(packageNames.size() + 1);
+ packageNames.add(packageName);
+ if (packages != null) packageNames.addAll(packages);
+ }
+ }
+
+ Intent serviceIntent = new Intent(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
+ for (String packageName : packageNames) {
+ serviceIntent.setPackage(packageName);
+ if (pm.resolveService(serviceIntent, 0) != null) return packageName;
+ }
+ return null;
+ }
+
+ /**
+ * Connects to the Custom Tabs warmup service, and initializes the browser.
+ *
+ * This convenience method connects to the service, and immediately warms up the Custom Tabs
+ * implementation. Since service connection is asynchronous, the return code is not the return
+ * code of warmup.
+ * This call is optional, and clients are encouraged to connect to the service, call
+ * <code>warmup()</code> and create a session. In this case, calling this method is not
+ * necessary.
+ *
+ * @param context {@link Context} to use to connect to the remote service.
+ * @param packageName Package name of the target implamentation.
+ * @return Whether the binding was successful.
+ */
+ public static boolean connectAndInitialize(Context context, String packageName) {
+ if (packageName == null) return false;
+ final Context applicationContext = context.getApplicationContext();
+ CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
+ @Override
+ public final void onCustomTabsServiceConnected(
+ ComponentName name, CustomTabsClient client) {
+ client.warmup(0);
+ // Unbinding immediately makes the target process "Empty", provided that it is
+ // not used by anyone else, and doesn't contain any Activity. This makes it
+ // likely to get killed, but is preferable to keeping the connection around.
+ applicationContext.unbindService(this);
+ }
+
+ @Override
+ public final void onServiceDisconnected(ComponentName componentName) { }
+ };
+ try {
+ return bindCustomTabsService(applicationContext, packageName, connection);
+ } catch (SecurityException e) {
+ return false;
+ }
+ }
+
+ /**
* Warm up the browser process.
+ *
+ * Allows the browser application to pre-initialize itself in the background. Significantly
+ * speeds up URL opening in the browser. This is asynchronous and can be called several times.
+ *
* @param flags Reserved for future use.
* @return Whether the warmup was successful.
*/
diff --git a/v17/leanback/src/android/support/v17/leanback/app/OnboardingFragment.java b/v17/leanback/src/android/support/v17/leanback/app/OnboardingFragment.java
index 9e170f7..bfd0f14 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/OnboardingFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/OnboardingFragment.java
@@ -616,22 +616,23 @@
Animator navigatorFadeOutAnimator = AnimatorInflater.loadAnimator(getActivity(),
R.animator.lb_onboarding_page_indicator_fade_out);
navigatorFadeOutAnimator.setTarget(mPageIndicator);
- Animator buttonFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
- R.animator.lb_onboarding_start_button_fade_in);
- buttonFadeInAnimator.setTarget(mStartButton);
- animators.add(navigatorFadeOutAnimator);
navigatorFadeOutAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mPageIndicator.setVisibility(View.GONE);
}
});
+ animators.add(navigatorFadeOutAnimator);
+ Animator buttonFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_start_button_fade_in);
+ buttonFadeInAnimator.setTarget(mStartButton);
animators.add(buttonFadeInAnimator);
} else if (previousPage == getPageCount() - 1) {
mPageIndicator.setVisibility(View.VISIBLE);
Animator navigatorFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
R.animator.lb_onboarding_page_indicator_fade_in);
navigatorFadeInAnimator.setTarget(mPageIndicator);
+ animators.add(navigatorFadeInAnimator);
Animator buttonFadeOutAnimator = AnimatorInflater.loadAnimator(getActivity(),
R.animator.lb_onboarding_start_button_fade_out);
buttonFadeOutAnimator.setTarget(mStartButton);
@@ -641,9 +642,7 @@
mStartButton.setVisibility(View.GONE);
}
});
- mAnimator = new AnimatorSet();
- mAnimator.playTogether(navigatorFadeInAnimator, buttonFadeOutAnimator);
- mAnimator.start();
+ animators.add(buttonFadeOutAnimator);
}
mAnimator = new AnimatorSet();
mAnimator.playTogether(animators);
diff --git a/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
index 4fc4718..d873f61 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
@@ -618,22 +618,23 @@
Animator navigatorFadeOutAnimator = AnimatorInflater.loadAnimator(getActivity(),
R.animator.lb_onboarding_page_indicator_fade_out);
navigatorFadeOutAnimator.setTarget(mPageIndicator);
- Animator buttonFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
- R.animator.lb_onboarding_start_button_fade_in);
- buttonFadeInAnimator.setTarget(mStartButton);
- animators.add(navigatorFadeOutAnimator);
navigatorFadeOutAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mPageIndicator.setVisibility(View.GONE);
}
});
+ animators.add(navigatorFadeOutAnimator);
+ Animator buttonFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
+ R.animator.lb_onboarding_start_button_fade_in);
+ buttonFadeInAnimator.setTarget(mStartButton);
animators.add(buttonFadeInAnimator);
} else if (previousPage == getPageCount() - 1) {
mPageIndicator.setVisibility(View.VISIBLE);
Animator navigatorFadeInAnimator = AnimatorInflater.loadAnimator(getActivity(),
R.animator.lb_onboarding_page_indicator_fade_in);
navigatorFadeInAnimator.setTarget(mPageIndicator);
+ animators.add(navigatorFadeInAnimator);
Animator buttonFadeOutAnimator = AnimatorInflater.loadAnimator(getActivity(),
R.animator.lb_onboarding_start_button_fade_out);
buttonFadeOutAnimator.setTarget(mStartButton);
@@ -643,9 +644,7 @@
mStartButton.setVisibility(View.GONE);
}
});
- mAnimator = new AnimatorSet();
- mAnimator.playTogether(navigatorFadeInAnimator, buttonFadeOutAnimator);
- mAnimator.start();
+ animators.add(buttonFadeOutAnimator);
}
mAnimator = new AnimatorSet();
mAnimator.playTogether(animators);
diff --git a/v4/api/current.txt b/v4/api/current.txt
index d8c4df3..9921c59 100644
--- a/v4/api/current.txt
+++ b/v4/api/current.txt
@@ -536,6 +536,7 @@
field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
+ field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
@@ -664,6 +665,7 @@
method public android.support.v4.app.NotificationCompat.Builder setPriority(int);
method public android.support.v4.app.NotificationCompat.Builder setProgress(int, int, boolean);
method public android.support.v4.app.NotificationCompat.Builder setPublicVersion(android.app.Notification);
+ method public android.support.v4.app.NotificationCompat.Builder setRemoteInputHistory(java.lang.CharSequence[]);
method public android.support.v4.app.NotificationCompat.Builder setShowWhen(boolean);
method public android.support.v4.app.NotificationCompat.Builder setSmallIcon(int);
method public android.support.v4.app.NotificationCompat.Builder setSmallIcon(int, int);
diff --git a/v4/api24/android/support/v4/app/NotificationCompatApi24.java b/v4/api24/android/support/v4/app/NotificationCompatApi24.java
index 91ad8e4..f775255 100644
--- a/v4/api24/android/support/v4/app/NotificationCompatApi24.java
+++ b/v4/api24/android/support/v4/app/NotificationCompatApi24.java
@@ -57,7 +57,7 @@
boolean useChronometer, int priority, CharSequence subText, boolean localOnly,
String category, ArrayList<String> people, Bundle extras, int color,
int visibility, Notification publicVersion, String groupKey, boolean groupSummary,
- String sortKey) {
+ String sortKey, CharSequence[] remoteInputHistory) {
b = new Notification.Builder(context)
.setWhen(n.when)
.setShowWhen(showWhen)
@@ -92,7 +92,8 @@
.setCategory(category)
.setColor(color)
.setVisibility(visibility)
- .setPublicVersion(publicVersion);
+ .setPublicVersion(publicVersion)
+ .setRemoteInputHistory(remoteInputHistory);
for (String person: people) {
b.addPerson(person);
}
diff --git a/v4/java/android/support/v4/app/NotificationCompat.java b/v4/java/android/support/v4/app/NotificationCompat.java
index 819cd14..8b1bc10 100644
--- a/v4/java/android/support/v4/app/NotificationCompat.java
+++ b/v4/java/android/support/v4/app/NotificationCompat.java
@@ -220,6 +220,22 @@
public static final String EXTRA_SUB_TEXT = "android.subText";
/**
+ * Notification extras key: this is the remote input history, as supplied to
+ * {@link Builder#setRemoteInputHistory(CharSequence[])}.
+ *
+ * Apps can fill this through {@link Builder#setRemoteInputHistory(CharSequence[])}
+ * with the most recent inputs that have been sent through a {@link RemoteInput} of this
+ * Notification and are expected to clear it once the it is no longer relevant (e.g. for chat
+ * notifications once the other party has responded).
+ *
+ * The extra with this key is of type CharSequence[] and contains the most recent entry at
+ * the 0 index, the second most recent at the 1 index, etc.
+ *
+ * @see Builder#setRemoteInputHistory(CharSequence[])
+ */
+ public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+
+ /**
* Notification extras key: this is a small piece of additional text as supplied to
* {@link Builder#setContentInfo(CharSequence)}.
*/
@@ -837,7 +853,7 @@
b.mProgressMax, b.mProgress, b.mProgressIndeterminate, b.mShowWhen,
b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mCategory,
b.mPeople, b.mExtras, b.mColor, b.mVisibility, b.mPublicVersion,
- b.mGroupKey, b.mGroupSummary, b.mSortKey);
+ b.mGroupKey, b.mGroupSummary, b.mSortKey, b.mRemoteInputHistory);
addActionsToBuilder(builder, b.mActions);
addStyleToBuilderApi24(builder, b.mStyle);
Notification notification = extender.build(b, builder);
@@ -992,6 +1008,8 @@
public Style mStyle;
/** @hide */
public CharSequence mSubText;
+ /** @hide */
+ public CharSequence[] mRemoteInputHistory;
int mProgressMax;
int mProgress;
boolean mProgressIndeterminate;
@@ -1125,6 +1143,25 @@
}
/**
+ * Set the remote input history.
+ *
+ * This should be set to the most recent inputs that have been sent
+ * through a {@link RemoteInput} of this Notification and cleared once the it is no
+ * longer relevant (e.g. for chat notifications once the other party has responded).
+ *
+ * The most recent input must be stored at the 0 index, the second most recent at the
+ * 1 index, etc. Note that the system will limit both how far back the inputs will be shown
+ * and how much of each individual input is shown.
+ *
+ * <p>Note: The reply text will only be shown on notifications that have least one action
+ * with a {@code RemoteInput}.</p>
+ */
+ public Builder setRemoteInputHistory(CharSequence[] text) {
+ mRemoteInputHistory = text;
+ return this;
+ }
+
+ /**
* Set the large number at the right-hand side of the notification. This is
* equivalent to setContentInfo, although it might show the number in a different
* font size for readability.
diff --git a/v4/java/android/support/v4/widget/MaterialProgressDrawable.java b/v4/java/android/support/v4/widget/MaterialProgressDrawable.java
index db46186..50939ad 100644
--- a/v4/java/android/support/v4/widget/MaterialProgressDrawable.java
+++ b/v4/java/android/support/v4/widget/MaterialProgressDrawable.java
@@ -16,11 +16,6 @@
package android.support.v4.widget;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.Animation;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.Transformation;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -32,13 +27,17 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.DisplayMetrics;
import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.Transformation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -54,7 +53,7 @@
private static final Interpolator MATERIAL_INTERPOLATOR = new FastOutSlowInInterpolator();
private static final float FULL_ROTATION = 1080.0f;
- @Retention(RetentionPolicy.CLASS)
+ @Retention(RetentionPolicy.SOURCE)
@IntDef({LARGE, DEFAULT})
public @interface ProgressDrawableSize {}
// Maps to ProgressBar.Large style