Merge "[WebView Support Library] Add ServiceWorker non-framework support." into pi-dev
diff --git a/annotations/api/current.txt b/annotations/api/current.txt
new file mode 100644
index 0000000..7c7450d
--- /dev/null
+++ b/annotations/api/current.txt
@@ -0,0 +1,180 @@
+package androidx.annotation {
+
+ public abstract class AnimRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class AnimatorRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class AnyRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class AnyThread implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class ArrayRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class AttrRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class BinderThread implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class BoolRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class CallSuper implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class CheckResult implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class ColorInt implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class ColorLong implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class ColorRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class DimenRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Dimension implements java.lang.annotation.Annotation {
+ field public static final int DP = 0; // 0x0
+ field public static final int PX = 1; // 0x1
+ field public static final int SP = 2; // 0x2
+ }
+
+ public abstract class DrawableRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class FloatRange implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class FontRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class FractionRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class GuardedBy implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class HalfFloat implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class IdRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class IntDef implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class IntRange implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class IntegerRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class InterpolatorRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Keep implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class LayoutRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class LongDef implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class MainThread implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class MenuRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class NavigationRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class NonNull implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Nullable implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class PluralsRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Px implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class RawRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class RequiresApi implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class RequiresFeature implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class RequiresPermission implements java.lang.annotation.Annotation {
+ }
+
+ public static abstract class RequiresPermission.Read implements java.lang.annotation.Annotation {
+ }
+
+ public static abstract class RequiresPermission.Write implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class RestrictTo implements java.lang.annotation.Annotation {
+ }
+
+ public static final class RestrictTo.Scope extends java.lang.Enum {
+ method public static androidx.annotation.RestrictTo.Scope valueOf(java.lang.String);
+ method public static final androidx.annotation.RestrictTo.Scope[] values();
+ enum_constant public static final deprecated androidx.annotation.RestrictTo.Scope GROUP_ID;
+ enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY;
+ enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY_GROUP;
+ enum_constant public static final androidx.annotation.RestrictTo.Scope SUBCLASSES;
+ enum_constant public static final androidx.annotation.RestrictTo.Scope TESTS;
+ }
+
+ public abstract class Size implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class StringDef implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class StringRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class StyleRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class StyleableRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class TransitionRes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class UiThread implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class VisibleForTesting implements java.lang.annotation.Annotation {
+ field public static final int NONE = 5; // 0x5
+ field public static final int PACKAGE_PRIVATE = 3; // 0x3
+ field public static final int PRIVATE = 2; // 0x2
+ field public static final int PROTECTED = 4; // 0x4
+ }
+
+ public abstract class WorkerThread implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class XmlRes implements java.lang.annotation.Annotation {
+ }
+
+}
+
diff --git a/app-toolkit/core-testing/api/current.txt b/app-toolkit/core-testing/api/current.txt
index 69f5d7a..37e16fb 100644
--- a/app-toolkit/core-testing/api/current.txt
+++ b/app-toolkit/core-testing/api/current.txt
@@ -1,4 +1,4 @@
-package androidx.executor.testing {
+package androidx.arch.core.executor.testing {
public class CountingTaskExecutorRule extends org.junit.rules.TestWatcher {
ctor public CountingTaskExecutorRule();
diff --git a/app-toolkit/core-testing/src/androidTest/java/androidx/executor/testing/CountingTaskExecutorRuleTest.java b/app-toolkit/core-testing/src/androidTest/java/androidx/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
similarity index 97%
rename from app-toolkit/core-testing/src/androidTest/java/androidx/executor/testing/CountingTaskExecutorRuleTest.java
rename to app-toolkit/core-testing/src/androidTest/java/androidx/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
index 2e3cfb5..200e64f 100644
--- a/app-toolkit/core-testing/src/androidTest/java/androidx/executor/testing/CountingTaskExecutorRuleTest.java
+++ b/app-toolkit/core-testing/src/androidTest/java/androidx/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.executor.testing;
+package androidx.arch.core.executor.testing;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -22,7 +22,7 @@
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import org.junit.Rule;
import org.junit.Test;
diff --git a/app-toolkit/core-testing/src/main/AndroidManifest.xml b/app-toolkit/core-testing/src/main/AndroidManifest.xml
index d169e00..f5cee7e 100644
--- a/app-toolkit/core-testing/src/main/AndroidManifest.xml
+++ b/app-toolkit/core-testing/src/main/AndroidManifest.xml
@@ -15,5 +15,5 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.arch.core.testing">
+ package="androidx.arch.core.testing">
</manifest>
diff --git a/app-toolkit/core-testing/src/main/java/androidx/executor/JunitTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/JunitTaskExecutorRule.java
similarity index 98%
rename from app-toolkit/core-testing/src/main/java/androidx/executor/JunitTaskExecutorRule.java
rename to app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/JunitTaskExecutorRule.java
index 4fb7584..b02339d 100644
--- a/app-toolkit/core-testing/src/main/java/androidx/executor/JunitTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/JunitTaskExecutorRule.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.executor;
+package androidx.arch.core.executor;
import androidx.annotation.RestrictTo;
diff --git a/app-toolkit/core-testing/src/main/java/androidx/executor/TaskExecutorWithFakeMainThread.java b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/TaskExecutorWithFakeMainThread.java
similarity index 98%
rename from app-toolkit/core-testing/src/main/java/androidx/executor/TaskExecutorWithFakeMainThread.java
rename to app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/TaskExecutorWithFakeMainThread.java
index 8afd7fb..a9c1ff6 100644
--- a/app-toolkit/core-testing/src/main/java/androidx/executor/TaskExecutorWithFakeMainThread.java
+++ b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/TaskExecutorWithFakeMainThread.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.executor;
+package androidx.arch.core.executor;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
diff --git a/app-toolkit/core-testing/src/main/java/androidx/executor/testing/CountingTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/testing/CountingTaskExecutorRule.java
similarity index 96%
rename from app-toolkit/core-testing/src/main/java/androidx/executor/testing/CountingTaskExecutorRule.java
rename to app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/testing/CountingTaskExecutorRule.java
index 20e4669..d3c9878 100644
--- a/app-toolkit/core-testing/src/main/java/androidx/executor/testing/CountingTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/testing/CountingTaskExecutorRule.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package androidx.executor.testing;
+package androidx.arch.core.executor.testing;
import android.os.SystemClock;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.DefaultTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.DefaultTaskExecutor;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
diff --git a/app-toolkit/core-testing/src/main/java/androidx/executor/testing/InstantTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/testing/InstantTaskExecutorRule.java
similarity index 92%
rename from app-toolkit/core-testing/src/main/java/androidx/executor/testing/InstantTaskExecutorRule.java
rename to app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/testing/InstantTaskExecutorRule.java
index 1d8e83f..8c5d0b5 100644
--- a/app-toolkit/core-testing/src/main/java/androidx/executor/testing/InstantTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/androidx/arch/core/executor/testing/InstantTaskExecutorRule.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package androidx.executor.testing;
+package androidx.arch.core.executor.testing;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.TaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.TaskExecutor;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
diff --git a/app-toolkit/core-testing/src/test/java/androidx/executor/testing/InstantTaskExecutorRuleTest.java b/app-toolkit/core-testing/src/test/java/androidx/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
similarity index 95%
rename from app-toolkit/core-testing/src/test/java/androidx/executor/testing/InstantTaskExecutorRuleTest.java
rename to app-toolkit/core-testing/src/test/java/androidx/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
index a901a69..ecbcfd5 100644
--- a/app-toolkit/core-testing/src/test/java/androidx/executor/testing/InstantTaskExecutorRuleTest.java
+++ b/app-toolkit/core-testing/src/test/java/androidx/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package androidx.executor.testing;
+package androidx.arch.core.executor.testing;
import static org.junit.Assert.assertTrue;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import org.junit.Rule;
import org.junit.Test;
diff --git a/app-toolkit/runtime/src/main/AndroidManifest.xml b/app-toolkit/runtime/src/main/AndroidManifest.xml
index 3f40068..e56fa1a 100644
--- a/app-toolkit/runtime/src/main/AndroidManifest.xml
+++ b/app-toolkit/runtime/src/main/AndroidManifest.xml
@@ -15,5 +15,5 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.arch.core">
+ package="androidx.arch.core">
</manifest>
diff --git a/app-toolkit/runtime/src/main/java/androidx/executor/ArchTaskExecutor.java b/app-toolkit/runtime/src/main/java/androidx/arch/core/executor/ArchTaskExecutor.java
similarity index 98%
rename from app-toolkit/runtime/src/main/java/androidx/executor/ArchTaskExecutor.java
rename to app-toolkit/runtime/src/main/java/androidx/arch/core/executor/ArchTaskExecutor.java
index 25182ac..a38dff8 100644
--- a/app-toolkit/runtime/src/main/java/androidx/executor/ArchTaskExecutor.java
+++ b/app-toolkit/runtime/src/main/java/androidx/arch/core/executor/ArchTaskExecutor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.executor;
+package androidx.arch.core.executor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
diff --git a/app-toolkit/runtime/src/main/java/androidx/executor/DefaultTaskExecutor.java b/app-toolkit/runtime/src/main/java/androidx/arch/core/executor/DefaultTaskExecutor.java
similarity index 97%
rename from app-toolkit/runtime/src/main/java/androidx/executor/DefaultTaskExecutor.java
rename to app-toolkit/runtime/src/main/java/androidx/arch/core/executor/DefaultTaskExecutor.java
index 4c77cc8..a942324 100644
--- a/app-toolkit/runtime/src/main/java/androidx/executor/DefaultTaskExecutor.java
+++ b/app-toolkit/runtime/src/main/java/androidx/arch/core/executor/DefaultTaskExecutor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.executor;
+package androidx.arch.core.executor;
import android.os.Handler;
import android.os.Looper;
diff --git a/app-toolkit/runtime/src/main/java/androidx/executor/TaskExecutor.java b/app-toolkit/runtime/src/main/java/androidx/arch/core/executor/TaskExecutor.java
similarity index 97%
rename from app-toolkit/runtime/src/main/java/androidx/executor/TaskExecutor.java
rename to app-toolkit/runtime/src/main/java/androidx/arch/core/executor/TaskExecutor.java
index cf9442c..4b3c5fa 100644
--- a/app-toolkit/runtime/src/main/java/androidx/executor/TaskExecutor.java
+++ b/app-toolkit/runtime/src/main/java/androidx/arch/core/executor/TaskExecutor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.executor;
+package androidx.arch.core.executor;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
diff --git a/app-toolkit/settings.gradle b/app-toolkit/settings.gradle
index b463df7..3cd11cc 100644
--- a/app-toolkit/settings.gradle
+++ b/app-toolkit/settings.gradle
@@ -59,6 +59,7 @@
includeProject(":lifecycle:lifecycle-livedata-core", new File(supportRoot, "lifecycle/livedata-core"))
includeProject(":lifecycle:lifecycle-livedata", new File(supportRoot, "lifecycle/livedata"))
includeProject(":lifecycle:lifecycle-reactivestreams", new File(supportRoot, "lifecycle/reactivestreams"))
+includeProject(":lifecycle:lifecycle-reactivestreams-ktx", new File(supportRoot, "lifecycle/reactivestreams/ktx"))
includeProject(":lifecycle:lifecycle-runtime", new File(supportRoot, "lifecycle/runtime"))
includeProject(":lifecycle:lifecycle-viewmodel", new File(supportRoot, "lifecycle/viewmodel"))
includeProject(":paging:integration-tests:testapp", new File(supportRoot, "paging/integration-tests/testapp"))
@@ -75,6 +76,7 @@
includeProject(":room:room-testing", new File(supportRoot, "room/testing"))
includeProject(":sqlite:sqlite", new File(supportRoot, "persistence/db"))
includeProject(":sqlite:sqlite-framework", new File(supportRoot, "persistence/db-framework"))
+includeProject(":sqlite:sqlite-ktx", new File(supportRoot, "persistence/db/ktx"))
includeProject(":jetifier-core", new File(supportRoot, "jetifier/jetifier/core"))
includeProject(":jetifier-gradle-plugin", new File(supportRoot, "jetifier/jetifier/gradle-plugin"))
diff --git a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
index 213a8a8..36321af 100644
--- a/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/DiffAndDocs.kt
@@ -39,11 +39,60 @@
data class DacOptions(val libraryroot: String, val dataname: String)
object DiffAndDocs {
+ private lateinit var allChecksTask: Task
+ private lateinit var generateDocsTask: GenerateDocsTask
+
@JvmStatic
- fun configureDiffAndDocs(
- root: Project,
- supportRootFolder: File,
- dacOptions: DacOptions) = configure(root, supportRootFolder, dacOptions)
+ fun configureDiffAndDocs(root: Project, supportRootFolder: File, dacOptions: DacOptions): Task {
+ allChecksTask = root.tasks.create("anchorCheckApis")
+ val doclavaConfiguration = root.configurations.getByName("doclava")
+ val generateSdkApiTask = createGenerateSdkApiTask(root, doclavaConfiguration)
+ generateDocsTask = createGenerateDocsTask(root, generateSdkApiTask,
+ doclavaConfiguration, supportRootFolder, dacOptions)
+ createDistDocsTask(root, generateDocsTask)
+ return allChecksTask
+ }
+
+ fun registerJavaProject(project: Project, extension: SupportLibraryExtension) {
+ if (!hasApiTasks(project, extension)) {
+ return
+ }
+ val compileJava = project.properties["compileJava"] as JavaCompile
+ registerJavaProjectForDocsTask(generateDocsTask, compileJava)
+ if (!hasApiFolder(project)) {
+ project.logger.info("Project ${project.name} doesn't have an api folder, " +
+ "ignoring API tasks.")
+ return
+ }
+ val tasks = initializeApiChecksForProject(project, generateDocsTask)
+ registerJavaProjectForDocsTask(tasks.generateApi, compileJava)
+ registerJavaProjectForDocsTask(tasks.generateDiffs, compileJava)
+ allChecksTask.dependsOn(tasks.checkApiTask)
+ }
+
+ fun registerAndroidProject(project: Project, library: LibraryExtension,
+ extension: SupportLibraryExtension) {
+ if (!hasApiTasks(project, extension)) {
+ return
+ }
+ library.libraryVariants.all { variant ->
+ if (variant.name == "release") {
+ registerAndroidProjectForDocsTask(generateDocsTask, variant)
+ if (!hasJavaSources(variant)) {
+ return@all
+ }
+ if (!hasApiFolder(project)) {
+ project.logger.info("Project ${project.name} doesn't have " +
+ "an api folder, ignoring API tasks.")
+ return@all
+ }
+ val tasks = initializeApiChecksForProject(project, generateDocsTask)
+ registerAndroidProjectForDocsTask(tasks.generateApi, variant)
+ registerAndroidProjectForDocsTask(tasks.generateDiffs, variant)
+ allChecksTask.dependsOn(tasks.checkApiTask)
+ }
+ }
+ }
}
private data class CheckApiConfig(
@@ -492,70 +541,18 @@
return Tasks(generateApi, generateDiffTask, checkApi)
}
-private fun configure(root: Project, supportRootFolder: File, dacOptions: DacOptions): Task {
- val allChecks = root.tasks.create("AnchorCheckApis")
- val doclavaConfiguration = root.configurations.getByName("doclava")
- val generateSdkApiTask = createGenerateSdkApiTask(root, doclavaConfiguration)
-
- val generateDocsTask = createGenerateDocsTask(root, generateSdkApiTask,
- doclavaConfiguration, supportRootFolder, dacOptions)
- createDistDocsTask(root, generateDocsTask)
-
- root.subprojects { subProject ->
- subProject.afterEvaluate { project ->
- val extension = if (project.hasProperty("supportLibrary")) {
- project.properties["supportLibrary"] as SupportLibraryExtension
- } else {
- null
- }
- if (extension == null || !extension.publish) {
- project.logger.info("Project ${project.name} is not published, ignoring API tasks.")
- return@afterEvaluate
- }
-
- if (!extension.generateDocs) {
- project.logger.info("Project ${project.name} specified generateDocs = false, " +
- "ignoring API tasks.")
- return@afterEvaluate
- }
-
- val library = project.extensions.findByType(LibraryExtension::class.java)
- if (library != null) {
- library.libraryVariants.all { variant ->
- if (variant.name == "release") {
- registerAndroidProjectForDocsTask(generateDocsTask, variant)
- if (!hasJavaSources(variant)) {
- return@all
- }
- if (!hasApiFolder(project)) {
- project.logger.info("Project ${project.name} doesn't have " +
- "an api folder, ignoring API tasks.")
- return@all
- }
- val tasks = initializeApiChecksForProject(project, generateDocsTask)
- registerAndroidProjectForDocsTask(tasks.generateApi, variant)
- registerAndroidProjectForDocsTask(tasks.generateDiffs, variant)
- allChecks.dependsOn(tasks.checkApiTask)
- }
- }
- } else if (project.hasProperty("compileJava")) {
- val compileJava = project.properties["compileJava"] as JavaCompile
- registerJavaProjectForDocsTask(generateDocsTask, compileJava)
- if (!hasApiFolder(project)) {
- project.logger.info("Project ${project.name} doesn't have an api folder, " +
- "ignoring API tasks.")
- return@afterEvaluate
- }
- project.afterEvaluate { proj ->
- val tasks = initializeApiChecksForProject(proj, generateDocsTask)
- registerJavaProjectForDocsTask(tasks.generateApi, compileJava)
- registerJavaProjectForDocsTask(tasks.generateDiffs, compileJava)
- allChecks.dependsOn(tasks.checkApiTask)
- }
- }
- }
+fun hasApiTasks(project: Project, extension: SupportLibraryExtension): Boolean {
+ if (!extension.publish) {
+ project.logger.info("Project ${project.name} is not published, ignoring API tasks.")
+ return false
}
- return allChecks
+
+ if (!extension.generateDocs) {
+ project.logger.info("Project ${project.name} specified generateDocs = false, " +
+ "ignoring API tasks.")
+ return false
+ }
+ return true
}
private fun sdkApiFile(project: Project) = File(project.docsDir(), "release/sdk_current.txt")
diff --git a/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt
index 0d3fa3a..d65dd5e 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt
@@ -64,6 +64,7 @@
library.compileOptions.setTargetCompatibility(javaVersion)
VersionFileWriterTask.setUpAndroidLibrary(project, library)
+ DiffAndDocs.registerAndroidProject(project, library, supportLibraryExtension)
}
project.apply(mapOf("plugin" to "com.android.library"))
diff --git a/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt
index 24546f1..e8bd816 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SupportJavaLibraryPlugin.kt
@@ -46,6 +46,7 @@
convention.sourceCompatibility = JavaVersion.VERSION_1_7
convention.targetCompatibility = JavaVersion.VERSION_1_7
}
+ DiffAndDocs.registerJavaProject(project, supportLibraryExtension)
}
project.apply(mapOf("plugin" to ErrorProneBasePlugin::class.java))
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 6fea40e..9cd1a93 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -36,7 +36,7 @@
const val LINT = "com.android.tools.lint:lint:26.0.0"
const val MOCKITO_CORE = "org.mockito:mockito-core:2.7.6"
const val MULTIDEX = "androidx.multidex:multidex:2.0.0"
-const val NULLAWAY = "com.uber.nullaway:nullaway:0.2.0"
+const val NULLAWAY = "com.uber.nullaway:nullaway:0.3.7"
const val REACTIVE_STREAMS = "org.reactivestreams:reactive-streams:1.0.0"
const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.0.6"
const val TEST_RUNNER = "com.android.support.test:runner:1.0.1"
diff --git a/collection/api/current.txt b/collection/api/current.txt
new file mode 100644
index 0000000..5f644fe
--- /dev/null
+++ b/collection/api/current.txt
@@ -0,0 +1,163 @@
+package androidx.collection {
+
+ public class ArrayMap<K, V> extends androidx.collection.SimpleArrayMap implements java.util.Map {
+ ctor public ArrayMap();
+ ctor public ArrayMap(int);
+ ctor public ArrayMap(androidx.collection.SimpleArrayMap);
+ method public boolean containsAll(java.util.Collection<?>);
+ method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public java.util.Set<K> keySet();
+ method public void putAll(java.util.Map<? extends K, ? extends V>);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public java.util.Collection<V> values();
+ }
+
+ public final class ArraySet<E> implements java.util.Collection java.util.Set {
+ ctor public ArraySet();
+ ctor public ArraySet(int);
+ ctor public ArraySet(androidx.collection.ArraySet<E>);
+ ctor public ArraySet(java.util.Collection<E>);
+ method public boolean add(E);
+ method public void addAll(androidx.collection.ArraySet<? extends E>);
+ method public boolean addAll(java.util.Collection<? extends E>);
+ method public void clear();
+ method public boolean contains(java.lang.Object);
+ method public boolean containsAll(java.util.Collection<?>);
+ method public void ensureCapacity(int);
+ method public int indexOf(java.lang.Object);
+ method public boolean isEmpty();
+ method public java.util.Iterator<E> iterator();
+ method public boolean remove(java.lang.Object);
+ method public boolean removeAll(androidx.collection.ArraySet<? extends E>);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public E removeAt(int);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public int size();
+ method public java.lang.Object[] toArray();
+ method public <T> T[] toArray(T[]);
+ method public E valueAt(int);
+ }
+
+ public final class CircularArray<E> {
+ ctor public CircularArray();
+ ctor public CircularArray(int);
+ method public void addFirst(E);
+ method public void addLast(E);
+ method public void clear();
+ method public E get(int);
+ method public E getFirst();
+ method public E getLast();
+ method public boolean isEmpty();
+ method public E popFirst();
+ method public E popLast();
+ method public void removeFromEnd(int);
+ method public void removeFromStart(int);
+ method public int size();
+ }
+
+ public final class CircularIntArray {
+ ctor public CircularIntArray();
+ ctor public CircularIntArray(int);
+ method public void addFirst(int);
+ method public void addLast(int);
+ method public void clear();
+ method public int get(int);
+ method public int getFirst();
+ method public int getLast();
+ method public boolean isEmpty();
+ method public int popFirst();
+ method public int popLast();
+ method public void removeFromEnd(int);
+ method public void removeFromStart(int);
+ method public int size();
+ }
+
+ public class LongSparseArray<E> implements java.lang.Cloneable {
+ ctor public LongSparseArray();
+ ctor public LongSparseArray(int);
+ method public void append(long, E);
+ method public void clear();
+ method public androidx.collection.LongSparseArray<E> clone();
+ method public void delete(long);
+ method public E get(long);
+ method public E get(long, E);
+ method public int indexOfKey(long);
+ method public int indexOfValue(E);
+ method public boolean isEmpty();
+ method public long keyAt(int);
+ method public void put(long, E);
+ method public void remove(long);
+ method public void removeAt(int);
+ method public void setValueAt(int, E);
+ method public int size();
+ method public E valueAt(int);
+ }
+
+ public class LruCache<K, V> {
+ ctor public LruCache(int);
+ method protected V create(K);
+ method public final synchronized int createCount();
+ method protected void entryRemoved(boolean, K, V, V);
+ method public final void evictAll();
+ method public final synchronized int evictionCount();
+ method public final V get(K);
+ method public final synchronized int hitCount();
+ method public final synchronized int maxSize();
+ method public final synchronized int missCount();
+ method public final V put(K, V);
+ method public final synchronized int putCount();
+ method public final V remove(K);
+ method public void resize(int);
+ method public final synchronized int size();
+ method protected int sizeOf(K, V);
+ method public final synchronized java.util.Map<K, V> snapshot();
+ method public final synchronized java.lang.String toString();
+ method public void trimToSize(int);
+ }
+
+ public class SimpleArrayMap<K, V> {
+ ctor public SimpleArrayMap();
+ ctor public SimpleArrayMap(int);
+ ctor public SimpleArrayMap(androidx.collection.SimpleArrayMap<K, V>);
+ method public void clear();
+ method public boolean containsKey(java.lang.Object);
+ method public boolean containsValue(java.lang.Object);
+ method public void ensureCapacity(int);
+ method public V get(java.lang.Object);
+ method public int indexOfKey(java.lang.Object);
+ method public boolean isEmpty();
+ method public K keyAt(int);
+ method public V put(K, V);
+ method public void putAll(androidx.collection.SimpleArrayMap<? extends K, ? extends V>);
+ method public V remove(java.lang.Object);
+ method public V removeAt(int);
+ method public V setValueAt(int, V);
+ method public int size();
+ method public V valueAt(int);
+ }
+
+ public class SparseArrayCompat<E> implements java.lang.Cloneable {
+ ctor public SparseArrayCompat();
+ ctor public SparseArrayCompat(int);
+ method public void append(int, E);
+ method public void clear();
+ method public androidx.collection.SparseArrayCompat<E> clone();
+ method public void delete(int);
+ method public E get(int);
+ method public E get(int, E);
+ method public int indexOfKey(int);
+ method public int indexOfValue(E);
+ method public boolean isEmpty();
+ method public int keyAt(int);
+ method public void put(int, E);
+ method public void remove(int);
+ method public void removeAt(int);
+ method public void removeAtRange(int, int);
+ method public void setValueAt(int, E);
+ method public int size();
+ method public E valueAt(int);
+ }
+
+}
+
diff --git a/collection-ktx/OWNERS b/collection/ktx/OWNERS
similarity index 100%
rename from collection-ktx/OWNERS
rename to collection/ktx/OWNERS
diff --git a/collection-ktx/build.gradle b/collection/ktx/build.gradle
similarity index 100%
rename from collection-ktx/build.gradle
rename to collection/ktx/build.gradle
diff --git a/collection-ktx/src/main/java/androidx/collection/ArrayMap.kt b/collection/ktx/src/main/java/androidx/collection/ArrayMap.kt
similarity index 100%
rename from collection-ktx/src/main/java/androidx/collection/ArrayMap.kt
rename to collection/ktx/src/main/java/androidx/collection/ArrayMap.kt
diff --git a/collection-ktx/src/main/java/androidx/collection/ArraySet.kt b/collection/ktx/src/main/java/androidx/collection/ArraySet.kt
similarity index 100%
rename from collection-ktx/src/main/java/androidx/collection/ArraySet.kt
rename to collection/ktx/src/main/java/androidx/collection/ArraySet.kt
diff --git a/collection-ktx/src/main/java/androidx/collection/LongSparseArray.kt b/collection/ktx/src/main/java/androidx/collection/LongSparseArray.kt
similarity index 100%
rename from collection-ktx/src/main/java/androidx/collection/LongSparseArray.kt
rename to collection/ktx/src/main/java/androidx/collection/LongSparseArray.kt
diff --git a/collection-ktx/src/main/java/androidx/collection/LruCache.kt b/collection/ktx/src/main/java/androidx/collection/LruCache.kt
similarity index 100%
rename from collection-ktx/src/main/java/androidx/collection/LruCache.kt
rename to collection/ktx/src/main/java/androidx/collection/LruCache.kt
diff --git a/collection-ktx/src/main/java/androidx/collection/SparseArray.kt b/collection/ktx/src/main/java/androidx/collection/SparseArray.kt
similarity index 100%
rename from collection-ktx/src/main/java/androidx/collection/SparseArray.kt
rename to collection/ktx/src/main/java/androidx/collection/SparseArray.kt
diff --git a/collection-ktx/src/test/java/androidx/collection/ArrayMapTest.kt b/collection/ktx/src/test/java/androidx/collection/ArrayMapTest.kt
similarity index 100%
rename from collection-ktx/src/test/java/androidx/collection/ArrayMapTest.kt
rename to collection/ktx/src/test/java/androidx/collection/ArrayMapTest.kt
diff --git a/collection-ktx/src/test/java/androidx/collection/ArraySetTest.kt b/collection/ktx/src/test/java/androidx/collection/ArraySetTest.kt
similarity index 100%
rename from collection-ktx/src/test/java/androidx/collection/ArraySetTest.kt
rename to collection/ktx/src/test/java/androidx/collection/ArraySetTest.kt
diff --git a/collection-ktx/src/test/java/androidx/collection/LongSparseArrayTest.kt b/collection/ktx/src/test/java/androidx/collection/LongSparseArrayTest.kt
similarity index 100%
rename from collection-ktx/src/test/java/androidx/collection/LongSparseArrayTest.kt
rename to collection/ktx/src/test/java/androidx/collection/LongSparseArrayTest.kt
diff --git a/collection-ktx/src/test/java/androidx/collection/LruCacheTest.kt b/collection/ktx/src/test/java/androidx/collection/LruCacheTest.kt
similarity index 100%
rename from collection-ktx/src/test/java/androidx/collection/LruCacheTest.kt
rename to collection/ktx/src/test/java/androidx/collection/LruCacheTest.kt
diff --git a/collection-ktx/src/test/java/androidx/collection/SparseArrayTest.kt b/collection/ktx/src/test/java/androidx/collection/SparseArrayTest.kt
similarity index 100%
rename from collection-ktx/src/test/java/androidx/collection/SparseArrayTest.kt
rename to collection/ktx/src/test/java/androidx/collection/SparseArrayTest.kt
diff --git a/compat/api/current.txt b/compat/api/current.txt
index 143e239..52ae6ea 100644
--- a/compat/api/current.txt
+++ b/compat/api/current.txt
@@ -870,6 +870,7 @@
method public static void colorToLAB(int, double[]);
method public static void colorToXYZ(int, double[]);
method public static int compositeColors(int, int);
+ method public static android.graphics.Color compositeColors(android.graphics.Color, android.graphics.Color);
method public static double distanceEuclidean(double[], double[]);
method public static int setAlphaComponent(int, int);
}
@@ -878,6 +879,19 @@
method public static boolean hasGlyph(android.graphics.Paint, java.lang.String);
}
+ public final class PathSegment {
+ ctor public PathSegment(android.graphics.PointF, float, android.graphics.PointF, float);
+ method public android.graphics.PointF getEnd();
+ method public float getEndFraction();
+ method public android.graphics.PointF getStart();
+ method public float getStartFraction();
+ }
+
+ public final class PathUtils {
+ method public static java.util.Collection<androidx.core.graphics.PathSegment> flatten(android.graphics.Path);
+ method public static java.util.Collection<androidx.core.graphics.PathSegment> flatten(android.graphics.Path, float);
+ }
+
}
package androidx.core.graphics.drawable {
@@ -904,13 +918,29 @@
}
public class IconCompat {
+ method public static androidx.core.graphics.drawable.IconCompat createFromBundle(android.os.Bundle);
+ method public static androidx.core.graphics.drawable.IconCompat createFromIcon(android.graphics.drawable.Icon);
method public static androidx.core.graphics.drawable.IconCompat createWithAdaptiveBitmap(android.graphics.Bitmap);
method public static androidx.core.graphics.drawable.IconCompat createWithBitmap(android.graphics.Bitmap);
method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(java.lang.String);
method public static androidx.core.graphics.drawable.IconCompat createWithContentUri(android.net.Uri);
method public static androidx.core.graphics.drawable.IconCompat createWithData(byte[], int, int);
method public static androidx.core.graphics.drawable.IconCompat createWithResource(android.content.Context, int);
+ method public int getResId();
+ method public static int getResId(android.graphics.drawable.Icon);
+ method public java.lang.String getResPackage();
+ method public static java.lang.String getResPackage(android.graphics.drawable.Icon);
+ method public int getType();
+ method public static int getType(android.graphics.drawable.Icon);
+ method public android.net.Uri getUri();
+ method public android.net.Uri getUri(android.graphics.drawable.Icon);
+ method public android.graphics.drawable.Drawable loadDrawable(android.content.Context);
+ method public androidx.core.graphics.drawable.IconCompat setTint(int);
+ method public androidx.core.graphics.drawable.IconCompat setTintList(android.content.res.ColorStateList);
+ method public androidx.core.graphics.drawable.IconCompat setTintMode(android.graphics.PorterDuff.Mode);
+ method public android.os.Bundle toBundle();
method public android.graphics.drawable.Icon toIcon();
+ field public static final int TYPE_UNKOWN = -1; // 0xffffffff
}
public abstract class RoundedBitmapDrawable extends android.graphics.drawable.Drawable {
diff --git a/compat/res/values/dimens.xml b/compat/res/values/dimens.xml
index 1dcff5e..41abbe6 100644
--- a/compat/res/values/dimens.xml
+++ b/compat/res/values/dimens.xml
@@ -70,4 +70,10 @@
<!-- the paddingtop on the right side of the notification (for time etc.) -->
<dimen name="notification_right_side_padding_top">2dp</dimen>
+
+ <!-- the maximum width of the large icon, above which it will be downscaled -->
+ <dimen name="notification_icon_max_width">320dp</dimen>
+
+ <!-- the maximum height of the large icon, above which it will be downscaled -->
+ <dimen name="notification_icon_max_height">320dp</dimen>
</resources>
diff --git a/compat/src/androidTest/java/androidx/core/graphics/ColorUtilsTest.java b/compat/src/androidTest/java/androidx/core/graphics/ColorUtilsTest.java
index f637f39..2940599 100644
--- a/compat/src/androidTest/java/androidx/core/graphics/ColorUtilsTest.java
+++ b/compat/src/androidTest/java/androidx/core/graphics/ColorUtilsTest.java
@@ -16,10 +16,16 @@
package androidx.core.graphics;
+import static android.graphics.ColorSpace.Named.CIE_LAB;
+import static android.graphics.ColorSpace.Named.SRGB;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.graphics.Color;
+import android.graphics.ColorSpace;
+import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -82,6 +88,57 @@
.setWhiteMinAlpha30(0.39f).setWhiteMinAlpha45(0.54f));
}
+ @SdkSuppress(minSdkVersion = 26)
+ @Test public void addColorsDifferentModels() {
+ Color lab = Color.valueOf(54.0f, 80.0f, 70.0f, 1.0f, ColorSpace.get(CIE_LAB));
+ Color rgb = Color.valueOf(0.0f, 0.5f, 0.0f, 0.5f, ColorSpace.get(SRGB));
+ try {
+ ColorUtils.compositeColors(rgb, lab);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertEquals("Color models must match (RGB vs. LAB)", e.getMessage());
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = 26)
+ @Test public void addColorsSameColorSpace() {
+ Color result = ColorUtils.compositeColors(Color.valueOf(0x7f007f00),
+ Color.valueOf(0x7f7f0000));
+ assertEquals(0.16f, result.red(), 1e-2f);
+ assertEquals(0.33f, result.green(), 1e-2f);
+ assertEquals(0.00f, result.blue(), 1e-2f);
+ assertEquals(0.75f, result.alpha(), 1e-2f);
+ }
+
+ @SdkSuppress(minSdkVersion = 26)
+ @Test public void addColorsDifferentColorSpace() {
+ ColorSpace p3 = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
+ Color red = Color.valueOf(0.5f, 0.0f, 0.0f, 0.5f, p3);
+ Color green = Color.valueOf(0x7f007f00);
+
+ Color mixed = ColorUtils.compositeColors(green, red);
+ assertEquals(p3, mixed.getColorSpace());
+ assertEquals(0.31f, mixed.red(), 1e-2f);
+ assertEquals(0.33f, mixed.green(), 1e-2f);
+ assertEquals(0.09f, mixed.blue(), 1e-2f);
+ assertEquals(0.75f, mixed.alpha(), 1e-2f);
+ }
+
+ @SdkSuppress(minSdkVersion = 26)
+ @Test public void addColorsZeroAlpha() {
+ // Test potential divide by zero
+ assertEquals(0, ColorUtils.compositeColors(Color.valueOf(0x00007f00),
+ Color.valueOf(0x007f0000)).toArgb());
+
+ // Test low alpha
+ Color result = ColorUtils.compositeColors(Color.valueOf(0.0f, 1.0f, 0.0f, 0.0001f),
+ Color.valueOf(1.0f, 0.0f, 0.0f, 0.0001f));
+ assertEquals(0.50f, result.red(), 1e-2f);
+ assertEquals(0.50f, result.green(), 1e-2f);
+ assertEquals(0.00f, result.blue(), 1e-2f);
+ assertEquals(2e-4f, result.alpha(), 1e-5f);
+ }
+
@Test
public void testColorToHSL() {
for (TestEntry entry : sEntryList) {
diff --git a/compat/src/androidTest/java/androidx/core/graphics/PathUtilsTest.java b/compat/src/androidTest/java/androidx/core/graphics/PathUtilsTest.java
new file mode 100644
index 0000000..682ac25
--- /dev/null
+++ b/compat/src/androidTest/java/androidx/core/graphics/PathUtilsTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.graphics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
+
+import android.graphics.Path;
+import android.graphics.PointF;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@SmallTest
+public final class PathUtilsTest {
+ @SdkSuppress(minSdkVersion = 26)
+ @Test public void flattenEmptyPath() {
+ for (PathSegment segment : PathUtils.flatten(new Path())) {
+ fail("An empty path should not have segments: " + segment);
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = 26)
+ @Test public void flatten() {
+ Path p = new Path();
+
+ // Single line
+ p.lineTo(10.0f, 10.0f);
+ assertEquals(
+ new PathSegment(new PointF(), 0.0f, new PointF(10.0f, 10.0f), 1.0f),
+ PathUtils.flatten(p).iterator().next());
+
+ // Only moves
+ p.reset();
+ p.moveTo(10.0f, 10.0f);
+ p.moveTo(20.0f, 20.0f);
+ for (PathSegment segment : PathUtils.flatten(p)) {
+ fail("A path with only moves should not have segments: " + segment);
+ }
+
+ // Mix of moves/lines
+ p.reset();
+ p.moveTo(10.0f, 10.0f);
+ p.lineTo(20.0f, 20.0f);
+ p.lineTo(60.0f, 20.0f);
+
+ int count = 0;
+ for (PathSegment segment : PathUtils.flatten(p)) {
+ count++;
+ assertNotEquals(segment.getStartFraction(), segment.getEndFraction());
+ }
+ assertEquals(2, count);
+
+ // Mix of moves/lines, starts with moves, ends with moves
+ p.reset();
+ // Start with several moves
+ p.moveTo(5.0f, 5.0f);
+ p.moveTo(10.0f, 10.0f);
+ p.lineTo(20.0f, 20.0f);
+ p.lineTo(30.0f, 10.0f);
+ // Several moves in the middle
+ p.moveTo(40.0f, 10.0f);
+ p.moveTo(50.0f, 10.0f);
+ p.lineTo(60.0f, 20.0f);
+ // End with several moves
+ p.moveTo(10.0f, 10.0f);
+ p.moveTo(30.0f, 30.0f);
+
+ count = 0;
+ for (PathSegment segment : PathUtils.flatten(p)) {
+ count++;
+ assertNotEquals(segment.getStartFraction(), segment.getEndFraction());
+ }
+ assertEquals(3, count);
+ }
+}
+
diff --git a/compat/src/androidTest/java/androidx/core/graphics/drawable/IconCompatTest.java b/compat/src/androidTest/java/androidx/core/graphics/drawable/IconCompatTest.java
index 219737b..75ad1d5 100644
--- a/compat/src/androidTest/java/androidx/core/graphics/drawable/IconCompatTest.java
+++ b/compat/src/androidTest/java/androidx/core/graphics/drawable/IconCompatTest.java
@@ -24,13 +24,17 @@
import android.content.Context;
import android.content.Intent;
+import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.Build;
+import android.os.Bundle;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
@@ -43,12 +47,19 @@
import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IconCompatTest {
+ private Context mContext = InstrumentationRegistry.getContext();
+
private static void verifyClippedCircle(Bitmap bitmap, int fillColor, int size) {
assertEquals(size, bitmap.getHeight());
assertEquals(bitmap.getWidth(), bitmap.getHeight());
@@ -87,7 +98,7 @@
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.RED);
Intent intent = new Intent();
- IconCompat.createWithBitmap(bitmap).addToShortcutIntent(intent, null);
+ IconCompat.createWithBitmap(bitmap).addToShortcutIntent(intent, null, mContext);
assertEquals(bitmap, intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON));
}
@@ -99,7 +110,7 @@
Intent intent = new Intent();
Drawable badge = ContextCompat.getDrawable(context, R.drawable.test_drawable_blue);
- IconCompat.createWithBitmap(bitmap).addToShortcutIntent(intent, badge);
+ IconCompat.createWithBitmap(bitmap).addToShortcutIntent(intent, badge, mContext);
assertNotSame(bitmap, intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON));
verifyBadgeBitmap(intent, Color.RED, ContextCompat.getColor(context, R.color.test_blue));
@@ -112,14 +123,14 @@
// No badge
IconCompat.createWithResource(context, R.drawable.test_drawable_green)
- .addToShortcutIntent(intent, null);
+ .addToShortcutIntent(intent, null, mContext);
assertNotNull(intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE));
assertNull(intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON));
intent = new Intent();
Drawable badge = ContextCompat.getDrawable(context, R.drawable.test_drawable_red);
IconCompat.createWithResource(context, R.drawable.test_drawable_blue)
- .addToShortcutIntent(intent, badge);
+ .addToShortcutIntent(intent, badge, mContext);
assertNull(intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE));
verifyBadgeBitmap(intent, ContextCompat.getColor(context, R.color.test_blue),
@@ -142,7 +153,7 @@
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.GREEN);
Intent intent = new Intent();
- IconCompat.createWithAdaptiveBitmap(bitmap).addToShortcutIntent(intent, null);
+ IconCompat.createWithAdaptiveBitmap(bitmap).addToShortcutIntent(intent, null, mContext);
Bitmap clipped = intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
verifyClippedCircle(clipped, Color.GREEN, clipped.getWidth());
@@ -209,4 +220,108 @@
// Drawables behave the same
assertTrue(orgBitmap.sameAs(compatBitmap));
}
+
+ @Test
+ public void testBitmapIconCompat() {
+ verifyIconCompatValidity(
+ IconCompat.createWithBitmap(Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888)));
+ }
+
+ @Test
+ public void testDataIconCompat() {
+ byte[] data = new byte[4];
+ data[0] = data[1] = data[2] = data[3] = (byte) 255;
+ verifyIconCompatValidity(IconCompat.createWithData(data, 0, 4));
+ }
+
+ @Test
+ public void testFileIconCompat() throws IOException {
+ File file = new File(mContext.getFilesDir(), "testimage.jpg");
+ try {
+ writeSampleImage(file);
+ assertTrue(file.exists());
+
+ verifyIconCompatValidity(IconCompat.createWithContentUri(Uri.fromFile(file)));
+
+ verifyIconCompatValidity(IconCompat.createWithContentUri(file.toURI().toString()));
+ } finally {
+ file.delete();
+ }
+ }
+
+ @Test
+ public void testResourceIconCompat() {
+ verifyIconCompatValidity(IconCompat.createWithResource(mContext, R.drawable.bmp_test));
+ }
+
+ @Test
+ public void testBitmapIconCompat_getType() {
+ IconCompat icon = IconCompat.createWithBitmap(Bitmap.createBitmap(16, 16,
+ Bitmap.Config.ARGB_8888));
+ assertEquals(IconCompat.TYPE_BITMAP, icon.getType());
+ }
+
+ @Test
+ public void testDataIconCompat_getType() {
+ byte[] data = new byte[4];
+ data[0] = data[1] = data[2] = data[3] = (byte) 255;
+ IconCompat icon = IconCompat.createWithData(data, 0, 4);
+ assertEquals(IconCompat.TYPE_DATA, icon.getType());
+ }
+
+ @Test
+ public void testFileIconCompat_getType() throws IOException {
+ File file = new File(mContext.getFilesDir(), "testimage.jpg");
+ try {
+ writeSampleImage(file);
+ assertTrue(file.exists());
+ String filePath = file.toURI().getPath();
+
+ IconCompat icon = IconCompat.createWithContentUri(Uri.fromFile(file));
+ assertEquals(IconCompat.TYPE_URI, icon.getType());
+ assertEquals(filePath, icon.getUri().getPath());
+
+ icon = IconCompat.createWithContentUri(file.toURI().toString());
+ assertEquals(IconCompat.TYPE_URI, icon.getType());
+ assertEquals(filePath, icon.getUri().getPath());
+ } finally {
+ file.delete();
+ }
+ }
+
+ @Test
+ public void testResourceIconCompat_getType() {
+ IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.bmp_test);
+ assertEquals(IconCompat.TYPE_RESOURCE, icon.getType());
+ assertEquals("androidx.core.test", icon.getResPackage());
+ assertEquals(R.drawable.bmp_test, icon.getResId());
+ }
+
+ private void writeSampleImage(File imagefile) throws IOException {
+ try (InputStream source = mContext.getResources().openRawResource(R.drawable.testimage);
+ OutputStream target = new FileOutputStream(imagefile)) {
+ byte[] buffer = new byte[1024];
+ for (int len = source.read(buffer); len >= 0; len = source.read(buffer)) {
+ target.write(buffer, 0, len);
+ }
+ }
+ }
+
+ // Check if the created icon is valid and doesn't cause crashes for the public methods.
+ private void verifyIconCompatValidity(IconCompat icon) {
+ assertNotNull(icon);
+
+ // tint properties.
+ icon.setTint(Color.BLUE);
+ icon.setTintList(ColorStateList.valueOf(Color.RED));
+ icon.setTintMode(PorterDuff.Mode.XOR);
+
+ // Parcelable methods.
+ Bundle b = icon.toBundle();
+
+ assertNotNull(IconCompat.createFromBundle(b));
+
+ // loading drawable synchronously.
+ assertNotNull(icon.loadDrawable(mContext));
+ }
}
diff --git a/compat/src/androidTest/java/androidx/core/view/DragStartHelperTest.java b/compat/src/androidTest/java/androidx/core/view/DragStartHelperTest.java
index 268eead..f6e5d30 100644
--- a/compat/src/androidTest/java/androidx/core/view/DragStartHelperTest.java
+++ b/compat/src/androidTest/java/androidx/core/view/DragStartHelperTest.java
@@ -28,11 +28,9 @@
import android.app.Instrumentation;
import android.graphics.Point;
-import android.os.Build;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
-import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -42,7 +40,6 @@
import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
import androidx.core.test.R;
import org.junit.Before;
@@ -52,7 +49,6 @@
import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
-@RequiresApi(13)
@RunWith(AndroidJUnit4.class)
public class DragStartHelperTest {
@@ -169,7 +165,6 @@
}
@SmallTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void mouseClick() throws Throwable {
final DragStartListener listener = createListener(true);
@@ -184,7 +179,6 @@
}
@SmallTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void mousePressWithSecondaryButton() throws Throwable {
final DragStartListener listener = createListener(true);
@@ -201,7 +195,6 @@
}
@SmallTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void mouseDrag() throws Throwable {
final DragStartListener listener = createListener(true);
@@ -220,7 +213,6 @@
}
@SmallTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void mouseDragWithNonprimaryButton() throws Throwable {
final DragStartListener listener = createListener(true);
@@ -240,7 +232,6 @@
}
@SmallTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void mouseDragUsingTouchListener() throws Throwable {
final DragStartListener listener = createListener(true);
@@ -266,7 +257,6 @@
}
@SmallTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void mouseDragWhenListenerReturnsFalse() throws Throwable {
final DragStartListener listener = createListener(false);
@@ -290,7 +280,6 @@
}
@LargeTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Test
public void mouseLongPress() throws Throwable {
final DragStartListener listener = createListener(true);
diff --git a/compat/src/androidTest/res/drawable/bmp_test.bmp b/compat/src/androidTest/res/drawable/bmp_test.bmp
new file mode 100644
index 0000000..5ec6dd4
--- /dev/null
+++ b/compat/src/androidTest/res/drawable/bmp_test.bmp
Binary files differ
diff --git a/compat/src/androidTest/res/drawable/testimage.jpg b/compat/src/androidTest/res/drawable/testimage.jpg
new file mode 100644
index 0000000..754df0c
--- /dev/null
+++ b/compat/src/androidTest/res/drawable/testimage.jpg
Binary files differ
diff --git a/compat/src/main/java/androidx/core/app/FrameMetricsAggregator.java b/compat/src/main/java/androidx/core/app/FrameMetricsAggregator.java
index 3598684..dd2824a 100644
--- a/compat/src/main/java/androidx/core/app/FrameMetricsAggregator.java
+++ b/compat/src/main/java/androidx/core/app/FrameMetricsAggregator.java
@@ -335,8 +335,8 @@
private static final int NANOS_PER_MS = 1000000;
// rounding value adds half a millisecond, for rounding to nearest ms
private static final int NANOS_ROUNDING_VALUE = NANOS_PER_MS / 2;
- private int mTrackingFlags;
- private SparseIntArray[] mMetrics = new SparseIntArray[LAST_INDEX + 1];
+ int mTrackingFlags;
+ SparseIntArray[] mMetrics = new SparseIntArray[LAST_INDEX + 1];
private ArrayList<WeakReference<Activity>> mActivities = new ArrayList<>();
private static HandlerThread sHandlerThread = null;
private static Handler sHandler = null;
diff --git a/compat/src/main/java/androidx/core/app/NotificationCompat.java b/compat/src/main/java/androidx/core/app/NotificationCompat.java
index 32e5ea9..b8b5205 100644
--- a/compat/src/main/java/androidx/core/app/NotificationCompat.java
+++ b/compat/src/main/java/androidx/core/app/NotificationCompat.java
@@ -963,11 +963,37 @@
* Set the large icon that is shown in the ticker and notification.
*/
public Builder setLargeIcon(Bitmap icon) {
- mLargeIcon = icon;
+ mLargeIcon = reduceLargeIconSize(icon);
return this;
}
/**
+ * Reduce the size of a notification icon if it's overly large. The framework does
+ * this automatically starting from API 27.
+ */
+ private Bitmap reduceLargeIconSize(Bitmap icon) {
+ if (icon == null || Build.VERSION.SDK_INT >= 27) {
+ return icon;
+ }
+
+ Resources res = mContext.getResources();
+ int maxWidth = res.getDimensionPixelSize(R.dimen.notification_icon_max_width);
+ int maxHeight = res.getDimensionPixelSize(R.dimen.notification_icon_max_height);
+ if (icon.getWidth() <= maxWidth && icon.getHeight() <= maxHeight) {
+ return icon;
+ }
+
+ double scale = Math.min(
+ maxWidth / (double) Math.max(1, icon.getWidth()),
+ maxHeight / (double) Math.max(1, icon.getHeight()));
+ return Bitmap.createScaledBitmap(
+ icon,
+ (int) Math.ceil(icon.getWidth() * scale),
+ (int) Math.ceil(icon.getHeight() * scale),
+ true /* filtered */);
+ }
+
+ /**
* Set the sound to play. It will play on the default stream.
*
* <p>
@@ -2921,7 +2947,7 @@
private final RemoteInput[] mDataOnlyRemoteInputs;
private boolean mAllowGeneratedReplies;
- private boolean mShowsUserInterface = true;
+ boolean mShowsUserInterface = true;
private final @SemanticAction int mSemanticAction;
diff --git a/compat/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java b/compat/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
index 5c3a8b8..7eea551 100644
--- a/compat/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
+++ b/compat/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
@@ -36,18 +36,18 @@
*/
public class ShortcutInfoCompat {
- private Context mContext;
- private String mId;
+ Context mContext;
+ String mId;
- private Intent[] mIntents;
- private ComponentName mActivity;
+ Intent[] mIntents;
+ ComponentName mActivity;
- private CharSequence mLabel;
- private CharSequence mLongLabel;
- private CharSequence mDisabledMessage;
+ CharSequence mLabel;
+ CharSequence mLongLabel;
+ CharSequence mDisabledMessage;
- private IconCompat mIcon;
- private boolean mIsAlwaysBadged;
+ IconCompat mIcon;
+ boolean mIsAlwaysBadged;
private ShortcutInfoCompat() { }
@@ -93,7 +93,7 @@
badge = mContext.getApplicationInfo().loadIcon(pm);
}
}
- mIcon.addToShortcutIntent(outIntent, badge);
+ mIcon.addToShortcutIntent(outIntent, badge, mContext);
}
return outIntent;
}
diff --git a/compat/src/main/java/androidx/core/graphics/ColorUtils.java b/compat/src/main/java/androidx/core/graphics/ColorUtils.java
index c36142c..6c1e37f 100644
--- a/compat/src/main/java/androidx/core/graphics/ColorUtils.java
+++ b/compat/src/main/java/androidx/core/graphics/ColorUtils.java
@@ -16,14 +16,18 @@
package androidx.core.graphics;
+import android.annotation.SuppressLint;
import android.graphics.Color;
import androidx.annotation.ColorInt;
import androidx.annotation.FloatRange;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
+import java.util.Objects;
+
/**
* A set of color-related utility methods, building upon those available in {@code Color}.
*/
@@ -60,6 +64,69 @@
return Color.argb(a, r, g, b);
}
+ /**
+ * Composites two translucent colors together. More specifically, adds two colors using
+ * the {@linkplain android.graphics.PorterDuff.Mode#SRC_OVER source over} blending mode. The
+ * colors must not be pre-multiplied and the result is a non pre-multiplied color.
+ * <p>
+ * If the two colors have different color spaces, the foreground color is converted to the
+ * color space of the background color.
+ * <p>
+ * The following example creates a purple color by blending opaque blue with
+ * semi-translucent red:
+ *
+ * <pre>{@code
+ * Color purple = ColorUtils.compositeColors(
+ * Color.valueOf(1f, 0f, 0f, 0.5f),
+ * Color.valueOf(0f, 0f, 1f));
+ * }</pre>
+ *
+ * <em>Note:</em> This method requires API 26 or newer.
+ *
+ * @throws IllegalArgumentException if the
+ * {@linkplain android.graphics.Color#getModel models} of the colors do not match
+ */
+ @RequiresApi(26)
+ @NonNull
+ public static Color compositeColors(@NonNull Color foreground, @NonNull Color background) {
+ if (!Objects.equals(foreground.getModel(), background.getModel())) {
+ throw new IllegalArgumentException(
+ "Color models must match (" + foreground.getModel() + " vs. "
+ + background.getModel() + ")");
+ }
+
+ Color s = Objects.equals(background.getColorSpace(), foreground.getColorSpace())
+ ? foreground
+ : foreground.convert(background.getColorSpace());
+
+ float[] src = s.getComponents();
+ float[] dst = background.getComponents();
+
+ float sa = s.alpha();
+ // Destination alpha pre-composited
+ float da = background.alpha() * (1.0f - sa);
+
+ // Index of the alpha component
+ @SuppressLint("Range") // TODO Remove after upgrading Android Gradle Plugin to 3.1 or newer.
+ int ai = background.getComponentCount() - 1;
+
+ // Final alpha: src_alpha + dst_alpha * (1 - src_alpha)
+ dst[ai] = sa + da;
+
+ // Divide by final alpha to return non pre-multiplied color
+ if (dst[ai] > 0) {
+ sa /= dst[ai];
+ da /= dst[ai];
+ }
+
+ // Composite non-alpha components
+ for (int i = 0; i < ai; i++) {
+ dst[i] = src[i] * sa + dst[i] * da;
+ }
+
+ return Color.valueOf(dst, background.getColorSpace());
+ }
+
private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
}
diff --git a/compat/src/main/java/androidx/core/graphics/PathSegment.java b/compat/src/main/java/androidx/core/graphics/PathSegment.java
new file mode 100644
index 0000000..a5fe5cb
--- /dev/null
+++ b/compat/src/main/java/androidx/core/graphics/PathSegment.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.graphics;
+
+import static androidx.core.util.Preconditions.checkNotNull;
+
+import android.graphics.Path;
+import android.graphics.PointF;
+
+import androidx.annotation.NonNull;
+
+/**
+ * A line segment that represents an approximate fraction of a {@link Path} after
+ * {@linkplain PathUtils#flatten(Path) flattening}.
+ */
+public final class PathSegment {
+ private final PointF mStart;
+ private final float mStartFraction;
+ private final PointF mEnd;
+ private final float mEndFraction;
+
+ public PathSegment(@NonNull PointF start, float startFraction, @NonNull PointF end,
+ float endFraction) {
+ mStart = checkNotNull(start, "start == null");
+ mStartFraction = startFraction;
+ mEnd = checkNotNull(end, "end == null");
+ mEndFraction = endFraction;
+ }
+
+ /** The start point of the line segment. */
+ @NonNull
+ public PointF getStart() {
+ return mStart;
+ }
+
+ /**
+ * Fraction along the length of the path that the {@linkplain #getStart() start point} resides.
+ */
+ public float getStartFraction() {
+ return mStartFraction;
+ }
+
+ /** The end point of the line segment. */
+ @NonNull
+ public PointF getEnd() {
+ return mEnd;
+ }
+
+ /**
+ * Fraction along the length of the path that the {@linkplain #getEnd() end point} resides.
+ */
+ public float getEndFraction() {
+ return mEndFraction;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PathSegment)) return false;
+ PathSegment that = (PathSegment) o;
+ return Float.compare(mStartFraction, that.mStartFraction) == 0
+ && Float.compare(mEndFraction, that.mEndFraction) == 0
+ && mStart.equals(that.mStart)
+ && mEnd.equals(that.mEnd);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mStart.hashCode();
+ result = 31 * result + (mStartFraction != +0.0f ? Float.floatToIntBits(mStartFraction) : 0);
+ result = 31 * result + mEnd.hashCode();
+ result = 31 * result + (mEndFraction != +0.0f ? Float.floatToIntBits(mEndFraction) : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "PathSegment{"
+ + "start=" + mStart
+ + ", startFraction=" + mStartFraction
+ + ", end=" + mEnd
+ + ", endFraction=" + mEndFraction
+ + '}';
+ }
+}
diff --git a/compat/src/main/java/androidx/core/graphics/PathUtils.java b/compat/src/main/java/androidx/core/graphics/PathUtils.java
new file mode 100644
index 0000000..65e49f6
--- /dev/null
+++ b/compat/src/main/java/androidx/core/graphics/PathUtils.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.graphics;
+
+import android.graphics.Path;
+import android.graphics.PointF;
+
+import androidx.annotation.FloatRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/** A set of path-related utility methods. */
+public final class PathUtils {
+ /**
+ * Flattens (or approximate) a {@link Path} with a series of line segments using a 0.5 pixel
+ * error.
+ *
+ * <em>Note:</em> This method requires API 26 or newer.
+ *
+ * @see #flatten(Path, float)
+ */
+ @RequiresApi(26)
+ @NonNull
+ public static Collection<PathSegment> flatten(@NonNull Path path) {
+ return flatten(path, 0.5f);
+ }
+
+ /**
+ * Flattens (or approximate) a {@link Path} with a series of line segments.
+ *
+ * <em>Note:</em> This method requires API 26 or newer.
+ *
+ * @param error The acceptable error for a line on the Path. Typically this would be
+ * 0.5 so that the error is less than half a pixel.
+ *
+ * @see Path#approximate
+ */
+ @RequiresApi(26)
+ @NonNull
+ public static Collection<PathSegment> flatten(@NonNull final Path path,
+ @FloatRange(from = 0) final float error) {
+ float[] pathData = path.approximate(error);
+ int pointCount = pathData.length / 3;
+ List<PathSegment> segments = new ArrayList<>(pointCount);
+ for (int i = 1; i < pointCount; i++) {
+ int index = i * 3;
+ int prevIndex = (i - 1) * 3;
+
+ float d = pathData[index];
+ float x = pathData[index + 1];
+ float y = pathData[index + 2];
+
+ float pd = pathData[prevIndex];
+ float px = pathData[prevIndex + 1];
+ float py = pathData[prevIndex + 2];
+
+ if (d != pd && (x != px || y != py)) {
+ segments.add(new PathSegment(new PointF(px, py), pd, new PointF(x, y), d));
+ }
+ }
+ return segments;
+ }
+
+ private PathUtils() {
+ }
+}
diff --git a/compat/src/main/java/androidx/core/graphics/TypefaceCompat.java b/compat/src/main/java/androidx/core/graphics/TypefaceCompat.java
index 042068a..746950c 100644
--- a/compat/src/main/java/androidx/core/graphics/TypefaceCompat.java
+++ b/compat/src/main/java/androidx/core/graphics/TypefaceCompat.java
@@ -45,7 +45,7 @@
public class TypefaceCompat {
private static final String TAG = "TypefaceCompat";
- private static final TypefaceCompatImpl sTypefaceCompatImpl;
+ private static final TypefaceCompatBaseImpl sTypefaceCompatImpl;
static {
if (BuildCompat.isAtLeastP()) {
sTypefaceCompatImpl = new TypefaceCompatApi28Impl();
@@ -66,20 +66,6 @@
*/
private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
- interface TypefaceCompatImpl {
- // Create Typeface from XML which root node is "font-family"
- Typeface createFromFontFamilyFilesResourceEntry(
- Context context, FontFamilyFilesResourceEntry entry, Resources resources,
- int style);
-
- Typeface createFromFontInfo(Context context,
- @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts,
- int style);
-
- Typeface createFromResourcesFontFile(
- Context context, Resources resources, int id, String path, int style);
- }
-
private TypefaceCompat() {}
/**
diff --git a/compat/src/main/java/androidx/core/graphics/TypefaceCompatBaseImpl.java b/compat/src/main/java/androidx/core/graphics/TypefaceCompatBaseImpl.java
index 3b03cb3..d1cec8a 100644
--- a/compat/src/main/java/androidx/core/graphics/TypefaceCompatBaseImpl.java
+++ b/compat/src/main/java/androidx/core/graphics/TypefaceCompatBaseImpl.java
@@ -25,7 +25,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.core.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry;
import androidx.core.content.res.FontResourcesParserCompat.FontFileResourceEntry;
@@ -40,8 +39,7 @@
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
-@RequiresApi(14)
-class TypefaceCompatBaseImpl implements TypefaceCompat.TypefaceCompatImpl {
+class TypefaceCompatBaseImpl {
private static final String TAG = "TypefaceCompatBaseImpl";
private static final String CACHE_FILE_PREFIX = "cached_font_";
@@ -104,7 +102,6 @@
}
}
- @Override
public Typeface createFromFontInfo(Context context,
@Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, int style) {
// When we load from file, we can only load one font so just take the first one.
@@ -138,7 +135,6 @@
}
@Nullable
- @Override
public Typeface createFromFontFamilyFilesResourceEntry(Context context,
FontFamilyFilesResourceEntry entry, Resources resources, int style) {
FontFileResourceEntry best = findBestEntry(entry, style);
@@ -153,7 +149,6 @@
* Used by Resources to load a font resource of type font file.
*/
@Nullable
- @Override
public Typeface createFromResourcesFontFile(
Context context, Resources resources, int id, String path, int style) {
final File tmpFile = TypefaceCompatUtil.getTempFile(context);
diff --git a/compat/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java b/compat/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java
index 1e0e440..ceee4c5 100644
--- a/compat/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java
+++ b/compat/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java
@@ -311,11 +311,6 @@
return new WrappedDrawableApi21(drawable);
}
return drawable;
- } else if (Build.VERSION.SDK_INT >= 19) {
- if (!(drawable instanceof TintAwareDrawable)) {
- return new WrappedDrawableApi19(drawable);
- }
- return drawable;
} else {
if (!(drawable instanceof TintAwareDrawable)) {
return new WrappedDrawableApi14(drawable);
diff --git a/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java b/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java
index 1089d94..6dbe266 100644
--- a/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java
+++ b/compat/src/main/java/androidx/core/graphics/drawable/IconCompat.java
@@ -16,36 +16,106 @@
package androidx.core.graphics.drawable;
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import android.app.ActivityManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.PorterDuff;
import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
+import androidx.annotation.IdRes;
+import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.core.content.ContextCompat;
+import androidx.core.content.res.ResourcesCompat;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
/**
* Helper for accessing features in {@link android.graphics.drawable.Icon}.
*/
public class IconCompat {
+ private static final String TAG = "IconCompat";
+
+ /**
+ * Value returned when the type of an {@link Icon} cannot be determined.
+ * @see #getType(Icon)
+ */
+ public static final int TYPE_UNKOWN = -1;
+
+ // TODO: Switch these to the public constants in the beta branch.
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ public static final int TYPE_BITMAP = 1;
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ public static final int TYPE_RESOURCE = 2;
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ public static final int TYPE_DATA = 3;
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ public static final int TYPE_URI = 4;
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ public static final int TYPE_ADAPTIVE_BITMAP = 5;
+
+
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ @IntDef({TYPE_BITMAP, TYPE_RESOURCE, TYPE_DATA, TYPE_URI, TYPE_ADAPTIVE_BITMAP})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IconType {
+ }
+
// Ratio of expected size to actual icon size
private static final float ADAPTIVE_ICON_INSET_FACTOR = 1 / 4f;
private static final float DEFAULT_VIEW_PORT_SCALE = 1 / (1 + 2 * ADAPTIVE_ICON_INSET_FACTOR);
@@ -56,11 +126,12 @@
private static final int KEY_SHADOW_ALPHA = 61;
private static final int AMBIENT_SHADOW_ALPHA = 30;
- private static final int TYPE_BITMAP = 1;
- private static final int TYPE_RESOURCE = 2;
- private static final int TYPE_DATA = 3;
- private static final int TYPE_URI = 4;
- private static final int TYPE_ADAPTIVE_BITMAP = 5;
+ private static final String EXTRA_TYPE = "type";
+ private static final String EXTRA_OBJ = "obj";
+ private static final String EXTRA_INT1 = "int1";
+ private static final String EXTRA_INT2 = "int2";
+ private static final String EXTRA_TINT_LIST = "tint_list";
+ private static final String EXTRA_TINT_MODE = "tint_mode";
private final int mType;
@@ -81,6 +152,10 @@
// TYPE_DATA: data length
private int mInt2;
+ private ColorStateList mTintList = null;
+ static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; // SRC_IN
+ private PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE;
+
/**
* Create an Icon pointing to a drawable resource.
* @param context The context for the application whose resources should be used to resolve the
@@ -94,7 +169,7 @@
}
final IconCompat rep = new IconCompat(TYPE_RESOURCE);
rep.mInt1 = resId;
- rep.mObj1 = context;
+ rep.mObj1 = context.getPackageName();
return rep;
}
@@ -179,6 +254,104 @@
this.mType = mType;
}
+
+ /**
+ * Gets the type of the icon provided.
+ * <p>
+ * Note that new types may be added later, so callers should guard against other
+ * types being returned.
+ */
+ @IconType
+ public int getType() {
+ if (mType == TYPE_UNKOWN && Build.VERSION.SDK_INT >= 23) {
+ return getType((Icon) mObj1);
+ }
+ return mType;
+ }
+
+ /**
+ * Gets the package used to create this icon.
+ * <p>
+ * Only valid for icons of type TYPE_RESOURCE.
+ * Note: This package may not be available if referenced in the future, and it is
+ * up to the caller to ensure safety if this package is re-used and/or persisted.
+ */
+ @NonNull
+ public String getResPackage() {
+ if (mType == TYPE_UNKOWN && Build.VERSION.SDK_INT >= 23) {
+ return getResPackage((Icon) mObj1);
+ }
+ if (mType != TYPE_RESOURCE) {
+ throw new IllegalStateException("called getResPackage() on " + this);
+ }
+ return (String) mObj1;
+ }
+
+ /**
+ * Gets the resource id used to create this icon.
+ * <p>
+ * Only valid for icons of type TYPE_RESOURCE.
+ * Note: This resource may not be available if the application changes at all, and it is
+ * up to the caller to ensure safety if this resource is re-used and/or persisted.
+ */
+ @IdRes
+ public int getResId() {
+ if (mType == TYPE_UNKOWN && Build.VERSION.SDK_INT >= 23) {
+ return getResId((Icon) mObj1);
+ }
+ if (mType != TYPE_RESOURCE) {
+ throw new IllegalStateException("called getResId() on " + this);
+ }
+ return mInt1;
+ }
+
+ /**
+ * Gets the uri used to create this icon.
+ * <p>
+ * Only valid for icons of type TYPE_URI.
+ * Note: This uri may not be available in the future, and it is
+ * up to the caller to ensure safety if this uri is re-used and/or persisted.
+ */
+ @NonNull
+ public Uri getUri() {
+ if (mType == TYPE_UNKOWN && Build.VERSION.SDK_INT >= 23) {
+ return getUri((Icon) mObj1);
+ }
+ return Uri.parse((String) mObj1);
+ }
+
+ /**
+ * Store a color to use whenever this Icon is drawn.
+ *
+ * @param tint a color, as in {@link Drawable#setTint(int)}
+ * @return this same object, for use in chained construction
+ */
+ public IconCompat setTint(@ColorInt int tint) {
+ return setTintList(ColorStateList.valueOf(tint));
+ }
+
+ /**
+ * Store a color to use whenever this Icon is drawn.
+ *
+ * @param tintList as in {@link Drawable#setTintList(ColorStateList)}, null to remove tint
+ * @return this same object, for use in chained construction
+ */
+ public IconCompat setTintList(ColorStateList tintList) {
+ mTintList = tintList;
+ return this;
+ }
+
+ /**
+ * Store a blending mode to use whenever this Icon is drawn.
+ *
+ * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null
+ * @return this same object, for use in chained construction
+ */
+ public IconCompat setTintMode(PorterDuff.Mode mode) {
+ mTintMode = mode;
+ return this;
+ }
+
/**
* Convert this compat object to {@link Icon} object.
*
@@ -186,35 +359,141 @@
*/
@RequiresApi(23)
public Icon toIcon() {
+ Icon icon;
switch (mType) {
+ case TYPE_UNKOWN:
+ // When type is unknown we are just wrapping an icon.
+ return (Icon) mObj1;
case TYPE_BITMAP:
- return Icon.createWithBitmap((Bitmap) mObj1);
+ icon = Icon.createWithBitmap((Bitmap) mObj1);
+ break;
case TYPE_ADAPTIVE_BITMAP:
if (Build.VERSION.SDK_INT >= 26) {
- return Icon.createWithAdaptiveBitmap((Bitmap) mObj1);
+ icon = Icon.createWithAdaptiveBitmap((Bitmap) mObj1);
} else {
- return Icon.createWithBitmap(
+ icon = Icon.createWithBitmap(
createLegacyIconFromAdaptiveIcon((Bitmap) mObj1, false));
}
+ break;
case TYPE_RESOURCE:
- return Icon.createWithResource((Context) mObj1, mInt1);
+ icon = Icon.createWithResource((String) mObj1, mInt1);
+ break;
case TYPE_DATA:
- return Icon.createWithData((byte[]) mObj1, mInt1, mInt2);
+ icon = Icon.createWithData((byte[]) mObj1, mInt1, mInt2);
+ break;
case TYPE_URI:
- return Icon.createWithContentUri((String) mObj1);
+ icon = Icon.createWithContentUri((String) mObj1);
+ break;
default:
throw new IllegalArgumentException("Unknown type");
}
+ if (mTintList != null) {
+ icon.setTintList(mTintList);
+ }
+ if (mTintMode != DEFAULT_TINT_MODE) {
+ icon.setTintMode(mTintMode);
+ }
+ return icon;
}
+
+
/**
- * Use {@link #addToShortcutIntent(Intent, Drawable)} instead
- * @hide
+ * Returns a Drawable that can be used to draw the image inside this Icon, constructing it
+ * if necessary.
+ *
+ * @param context {@link android.content.Context Context} in which to load the drawable; used
+ * to access {@link android.content.res.Resources Resources}, for example.
+ * @return A fresh instance of a drawable for this image, yours to keep.
*/
- @RestrictTo(LIBRARY_GROUP)
- @Deprecated
- public void addToShortcutIntent(@NonNull Intent outIntent) {
- addToShortcutIntent(outIntent, null);
+ public Drawable loadDrawable(Context context) {
+ if (Build.VERSION.SDK_INT >= 23) {
+ return toIcon().loadDrawable(context);
+ }
+ final Drawable result = loadDrawableInner(context);
+ if (result != null && (mTintList != null || mTintMode != DEFAULT_TINT_MODE)) {
+ result.mutate();
+ DrawableCompat.setTintList(result, mTintList);
+ DrawableCompat.setTintMode(result, mTintMode);
+ }
+ return result;
+ }
+
+
+ /**
+ * Do the heavy lifting of loading the drawable, but stop short of applying any tint.
+ */
+ private Drawable loadDrawableInner(Context context) {
+ switch (mType) {
+ case TYPE_BITMAP:
+ return new BitmapDrawable(context.getResources(), (Bitmap) mObj1);
+ case TYPE_ADAPTIVE_BITMAP:
+ return new BitmapDrawable(context.getResources(),
+ createLegacyIconFromAdaptiveIcon((Bitmap) mObj1, false));
+ case TYPE_RESOURCE:
+ Resources res;
+ // figure out where to load resources from
+ String resPackage = (String) mObj1;
+ if (TextUtils.isEmpty(resPackage)) {
+ // if none is specified, try the given context
+ resPackage = context.getPackageName();
+ }
+ if ("android".equals(resPackage)) {
+ res = Resources.getSystem();
+ } else {
+ final PackageManager pm = context.getPackageManager();
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(
+ resPackage, PackageManager.MATCH_UNINSTALLED_PACKAGES);
+ if (ai != null) {
+ res = pm.getResourcesForApplication(ai);
+ } else {
+ break;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, String.format("Unable to find pkg=%s for icon %s",
+ resPackage, this), e);
+ break;
+ }
+ }
+ try {
+ return ResourcesCompat.getDrawable(res, mInt1, context.getTheme());
+ } catch (RuntimeException e) {
+ Log.e(TAG, String.format("Unable to load resource 0x%08x from pkg=%s",
+ mInt1,
+ mObj1),
+ e);
+ }
+ break;
+ case TYPE_DATA:
+ return new BitmapDrawable(context.getResources(),
+ BitmapFactory.decodeByteArray((byte[]) mObj1, mInt1, mInt2)
+ );
+ case TYPE_URI:
+ final Uri uri = Uri.parse((String) mObj1);
+ final String scheme = uri.getScheme();
+ InputStream is = null;
+ if (ContentResolver.SCHEME_CONTENT.equals(scheme)
+ || ContentResolver.SCHEME_FILE.equals(scheme)) {
+ try {
+ is = context.getContentResolver().openInputStream(uri);
+ } catch (Exception e) {
+ Log.w(TAG, "Unable to load image from URI: " + uri, e);
+ }
+ } else {
+ try {
+ is = new FileInputStream(new File((String) mObj1));
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Unable to load image from path: " + uri, e);
+ }
+ }
+ if (is != null) {
+ return new BitmapDrawable(context.getResources(),
+ BitmapFactory.decodeStream(is));
+ }
+ break;
+ }
+ return null;
}
/**
@@ -222,7 +501,8 @@
*/
@RestrictTo(LIBRARY_GROUP)
@SuppressWarnings("deprecation")
- public void addToShortcutIntent(@NonNull Intent outIntent, @Nullable Drawable badge) {
+ public void addToShortcutIntent(@NonNull Intent outIntent, @Nullable Drawable badge,
+ @NonNull Context c) {
Bitmap icon;
switch (mType) {
case TYPE_BITMAP:
@@ -236,23 +516,28 @@
icon = createLegacyIconFromAdaptiveIcon((Bitmap) mObj1, true);
break;
case TYPE_RESOURCE:
- if (badge == null) {
- outIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
- Intent.ShortcutIconResource.fromContext((Context) mObj1, mInt1));
- return;
- } else {
- Context context = (Context) mObj1;
- Drawable dr = ContextCompat.getDrawable(context, mInt1);
- if (dr.getIntrinsicWidth() <= 0 || dr.getIntrinsicHeight() <= 0) {
- int size = ((ActivityManager) context.getSystemService(
- Context.ACTIVITY_SERVICE)).getLauncherLargeIconSize();
- icon = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ try {
+ Context context = c.createPackageContext((String) mObj1, 0);
+ if (badge == null) {
+ outIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
+ Intent.ShortcutIconResource.fromContext(context, mInt1));
+ return;
} else {
- icon = Bitmap.createBitmap(dr.getIntrinsicWidth(), dr.getIntrinsicHeight(),
- Bitmap.Config.ARGB_8888);
+ Drawable dr = ContextCompat.getDrawable(context, mInt1);
+ if (dr.getIntrinsicWidth() <= 0 || dr.getIntrinsicHeight() <= 0) {
+ int size = ((ActivityManager) context.getSystemService(
+ Context.ACTIVITY_SERVICE)).getLauncherLargeIconSize();
+ icon = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ } else {
+ icon = Bitmap.createBitmap(dr.getIntrinsicWidth(),
+ dr.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ }
+ dr.setBounds(0, 0, icon.getWidth(), icon.getHeight());
+ dr.draw(new Canvas(icon));
}
- dr.setBounds(0, 0, icon.getWidth(), icon.getHeight());
- dr.draw(new Canvas(icon));
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalArgumentException("Can't find package " + mObj1, e);
}
break;
default:
@@ -269,6 +554,192 @@
}
/**
+ * Adds this Icon to a Bundle that can be read back with the same parameters
+ * to {@link #createFromBundle(Bundle)}.
+ */
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ switch (mType) {
+ case TYPE_BITMAP:
+ case TYPE_ADAPTIVE_BITMAP:
+ bundle.putParcelable(EXTRA_OBJ, (Bitmap) mObj1);
+ break;
+ case TYPE_UNKOWN:
+ // When unknown just wrapping an Icon.
+ bundle.putParcelable(EXTRA_OBJ, (Parcelable) mObj1);
+ break;
+ case TYPE_RESOURCE:
+ case TYPE_URI:
+ bundle.putString(EXTRA_OBJ, (String) mObj1);
+ break;
+ case TYPE_DATA:
+ bundle.putByteArray(EXTRA_OBJ, (byte[]) mObj1);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid icon");
+ }
+ bundle.putInt(EXTRA_TYPE, mType);
+ bundle.putInt(EXTRA_INT1, mInt1);
+ bundle.putInt(EXTRA_INT2, mInt2);
+ if (mTintList != null) {
+ bundle.putParcelable(EXTRA_TINT_LIST, mTintList);
+ }
+ if (mTintMode != DEFAULT_TINT_MODE) {
+ bundle.putString(EXTRA_TINT_MODE, mTintMode.name());
+ }
+ return bundle;
+ }
+
+ /**
+ * Extracts an icon from a bundle that was added using {@link #toBundle()}.
+ */
+ public static @Nullable IconCompat createFromBundle(@NonNull Bundle bundle) {
+ int type = bundle.getInt(EXTRA_TYPE);
+ IconCompat icon = new IconCompat(type);
+ icon.mInt1 = bundle.getInt(EXTRA_INT1);
+ icon.mInt2 = bundle.getInt(EXTRA_INT2);
+ if (bundle.containsKey(EXTRA_TINT_LIST)) {
+ icon.mTintList = bundle.getParcelable(EXTRA_TINT_LIST);
+ }
+ if (bundle.containsKey(EXTRA_TINT_MODE)) {
+ icon.mTintMode = PorterDuff.Mode.valueOf(
+ bundle.getString(EXTRA_TINT_MODE));
+ }
+ switch (type) {
+ case TYPE_BITMAP:
+ case TYPE_ADAPTIVE_BITMAP:
+ case TYPE_UNKOWN:
+ icon.mObj1 = bundle.getParcelable(EXTRA_OBJ);
+ break;
+ case TYPE_RESOURCE:
+ case TYPE_URI:
+ icon.mObj1 = bundle.getString(EXTRA_OBJ);
+ break;
+ case TYPE_DATA:
+ icon.mObj1 = bundle.getByteArray(EXTRA_OBJ);
+ break;
+ default:
+ Log.w(TAG, "Unknown type " + type);
+ return null;
+ }
+ return icon;
+ }
+
+ /**
+ * Creates an IconCompat from an Icon.
+ */
+ @RequiresApi(23)
+ @Nullable
+ public static IconCompat createFromIcon(@NonNull Icon icon) {
+ IconCompat iconCompat = new IconCompat(TYPE_UNKOWN);
+ iconCompat.mObj1 = icon;
+ return iconCompat;
+ }
+
+ /**
+ * Gets the type of the icon provided.
+ * <p>
+ * Note that new types may be added later, so callers should guard against other
+ * types being returned. Returns {@link #TYPE_UNKOWN} when the type cannot be
+ * determined.
+ */
+ @IconType
+ @RequiresApi(23)
+ public static int getType(Icon icon) {
+ // TODO: Switch to public APIs on P+ in beta branch.
+ try {
+ return (int) icon.getClass().getMethod("getType").invoke(icon);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Unable to get icon type " + icon, e);
+ return TYPE_UNKOWN;
+ } catch (InvocationTargetException e) {
+ Log.e(TAG, "Unable to get icon type " + icon, e);
+ return TYPE_UNKOWN;
+ } catch (NoSuchMethodException e) {
+ Log.e(TAG, "Unable to get icon type " + icon, e);
+ return TYPE_UNKOWN;
+ }
+ }
+
+ /**
+ * Gets the package used to create this icon.
+ * <p>
+ * Only valid for icons of type TYPE_RESOURCE.
+ * Note: This package may not be available if referenced in the future, and it is
+ * up to the caller to ensure safety if this package is re-used and/or persisted.
+ * Returns {@code null} when the value cannot be gotten.
+ */
+ @Nullable
+ @RequiresApi(23)
+ public static String getResPackage(Icon icon) {
+ // TODO: Switch to public APIs on P+ in beta branch.
+ try {
+ return (String) icon.getClass().getMethod("getResPackage").invoke(icon);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Unable to get icon package", e);
+ return null;
+ } catch (InvocationTargetException e) {
+ Log.e(TAG, "Unable to get icon package", e);
+ return null;
+ } catch (NoSuchMethodException e) {
+ Log.e(TAG, "Unable to get icon package", e);
+ return null;
+ }
+ }
+
+ /**
+ * Gets the resource used to create this icon.
+ * <p>
+ * Only valid for icons of type TYPE_RESOURCE.
+ * Note: This resource may not be available if the application changes at all, and it is
+ * up to the caller to ensure safety if this resource is re-used and/or persisted.
+ * Returns {@code 0} if the id cannot be gotten.
+ */
+ @IdRes
+ @RequiresApi(23)
+ public static int getResId(Icon icon) {
+ // TODO: Switch to public APIs on P+ in beta branch.
+ try {
+ return (int) icon.getClass().getMethod("getResId").invoke(icon);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Unable to get icon resource", e);
+ return 0;
+ } catch (InvocationTargetException e) {
+ Log.e(TAG, "Unable to get icon resource", e);
+ return 0;
+ } catch (NoSuchMethodException e) {
+ Log.e(TAG, "Unable to get icon resource", e);
+ return 0;
+ }
+ }
+
+ /**
+ * Gets the uri used to create this icon.
+ * <p>
+ * Only valid for icons of type TYPE_URI.
+ * Note: This uri may not be available in the future, and it is
+ * up to the caller to ensure safety if this uri is re-used and/or persisted.
+ * Returns {@code null} if the uri cannot be gotten.
+ */
+ @Nullable
+ @RequiresApi(23)
+ public Uri getUri(Icon icon) {
+ // TODO: Switch to public APIs on P+ in beta branch.
+ try {
+ return (Uri) icon.getClass().getMethod("getUri").invoke(icon);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Unable to get icon uri", e);
+ return null;
+ } catch (InvocationTargetException e) {
+ Log.e(TAG, "Unable to get icon uri", e);
+ return null;
+ } catch (NoSuchMethodException e) {
+ Log.e(TAG, "Unable to get icon uri", e);
+ return null;
+ }
+ }
+
+ /**
* Converts a bitmap following the adaptive icon guide lines, into a bitmap following the
* shortcut icon guide lines.
* The returned bitmap will always have same width and height and clipped to a circle.
diff --git a/compat/src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java b/compat/src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java
index 19ecb5c..cbee87f 100644
--- a/compat/src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java
+++ b/compat/src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java
@@ -32,7 +32,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
/**
* A Drawable that wraps a bitmap and can be drawn with rounded corners. You can create a
@@ -44,7 +43,6 @@
* {@link android.graphics.Canvas}.
* </p>
*/
-@RequiresApi(9)
public abstract class RoundedBitmapDrawable extends Drawable {
private static final int DEFAULT_PAINT_FLAGS =
Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG;
diff --git a/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi14.java b/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi14.java
index 021084c..b57ff37 100644
--- a/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi14.java
+++ b/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi14.java
@@ -192,6 +192,16 @@
}
@Override
+ public void setAutoMirrored(boolean mirrored) {
+ mDrawable.setAutoMirrored(mirrored);
+ }
+
+ @Override
+ public boolean isAutoMirrored() {
+ return mDrawable.isAutoMirrored();
+ }
+
+ @Override
@Nullable
public ConstantState getConstantState() {
if (mState != null && mState.canConstantState()) {
diff --git a/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi19.java b/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi19.java
deleted file mode 100644
index 8f615f8..0000000
--- a/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi19.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.core.graphics.drawable;
-
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(19)
-class WrappedDrawableApi19 extends WrappedDrawableApi14 {
-
- WrappedDrawableApi19(Drawable drawable) {
- super(drawable);
- }
-
- WrappedDrawableApi19(DrawableWrapperState state, Resources resources) {
- super(state, resources);
- }
-
- @Override
- public void setAutoMirrored(boolean mirrored) {
- mDrawable.setAutoMirrored(mirrored);
- }
-
- @Override
- public boolean isAutoMirrored() {
- return mDrawable.isAutoMirrored();
- }
-
- @NonNull
- @Override
- DrawableWrapperState mutateConstantState() {
- return new DrawableWrapperStateKitKat(mState, null);
- }
-
- private static class DrawableWrapperStateKitKat extends DrawableWrapperState {
- DrawableWrapperStateKitKat(@Nullable DrawableWrapperState orig,
- @Nullable Resources res) {
- super(orig, res);
- }
-
- @NonNull
- @Override
- public Drawable newDrawable(@Nullable Resources res) {
- return new WrappedDrawableApi19(this, res);
- }
- }
-}
diff --git a/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi21.java b/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi21.java
index 3be9595..7a7dd5e 100644
--- a/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi21.java
+++ b/compat/src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi21.java
@@ -36,7 +36,7 @@
import java.lang.reflect.Method;
@RequiresApi(21)
-class WrappedDrawableApi21 extends WrappedDrawableApi19 {
+class WrappedDrawableApi21 extends WrappedDrawableApi14 {
private static final String TAG = "WrappedDrawableApi21";
private static Method sIsProjectedDrawableMethod;
diff --git a/compat/src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java b/compat/src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java
index 89a096e..e468635 100644
--- a/compat/src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java
+++ b/compat/src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java
@@ -143,7 +143,7 @@
}
@RequiresApi(23)
- private static CryptoObject unwrapCryptoObject(FingerprintManager.CryptoObject cryptoObject) {
+ static CryptoObject unwrapCryptoObject(FingerprintManager.CryptoObject cryptoObject) {
if (cryptoObject == null) {
return null;
} else if (cryptoObject.getCipher() != null) {
diff --git a/compat/src/main/java/androidx/core/os/LocaleListHelper.java b/compat/src/main/java/androidx/core/os/LocaleListHelper.java
index dd210bc..0a656bc 100644
--- a/compat/src/main/java/androidx/core/os/LocaleListHelper.java
+++ b/compat/src/main/java/androidx/core/os/LocaleListHelper.java
@@ -24,7 +24,6 @@
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.annotation.Size;
@@ -40,7 +39,6 @@
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
-@RequiresApi(14)
final class LocaleListHelper {
private final Locale[] mList;
// This is a comma-separated list of the locales in the LocaleListHelper created at construction
diff --git a/compat/src/main/java/androidx/core/provider/FontsContractCompat.java b/compat/src/main/java/androidx/core/provider/FontsContractCompat.java
index 60963a9..2429c2b 100644
--- a/compat/src/main/java/androidx/core/provider/FontsContractCompat.java
+++ b/compat/src/main/java/androidx/core/provider/FontsContractCompat.java
@@ -171,7 +171,7 @@
/* package */ static final int RESULT_CODE_WRONG_CERTIFICATES = -2;
// Note -3 is used by FontRequestCallback to indicate the font failed to load.
- private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
+ static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
private static final int BACKGROUND_THREAD_KEEP_ALIVE_DURATION_MS = 10000;
private static final SelfDestructiveThread sBackgroundThread =
@@ -179,7 +179,7 @@
BACKGROUND_THREAD_KEEP_ALIVE_DURATION_MS);
@NonNull
- private static TypefaceResult getFontInternal(final Context context, final FontRequest request,
+ static TypefaceResult getFontInternal(final Context context, final FontRequest request,
int style) {
FontFamilyResult result;
try {
@@ -200,9 +200,9 @@
return new TypefaceResult(null, resultCode);
}
- private static final Object sLock = new Object();
+ static final Object sLock = new Object();
@GuardedBy("sLock")
- private static final SimpleArrayMap<String, ArrayList<ReplyCallback<TypefaceResult>>>
+ static final SimpleArrayMap<String, ArrayList<ReplyCallback<TypefaceResult>>>
sPendingReplies = new SimpleArrayMap<>();
private static final class TypefaceResult {
diff --git a/compat/src/main/java/androidx/core/provider/SelfDestructiveThread.java b/compat/src/main/java/androidx/core/provider/SelfDestructiveThread.java
index 9a51af1..bf17e31 100644
--- a/compat/src/main/java/androidx/core/provider/SelfDestructiveThread.java
+++ b/compat/src/main/java/androidx/core/provider/SelfDestructiveThread.java
@@ -210,7 +210,7 @@
}
}
- private void onInvokeRunnable(Runnable runnable) {
+ void onInvokeRunnable(Runnable runnable) {
runnable.run();
synchronized (mLock) {
mHandler.removeMessages(MSG_DESTRUCTION);
@@ -219,7 +219,7 @@
}
}
- private void onDestruction() {
+ void onDestruction() {
synchronized (mLock) {
if (mHandler.hasMessages(MSG_INVOKE_RUNNABLE)) {
// This happens if post() is called after onDestruction and before synchronization
diff --git a/compat/src/main/java/androidx/core/text/BidiFormatter.java b/compat/src/main/java/androidx/core/text/BidiFormatter.java
index a53d7f6..66d64aa 100644
--- a/compat/src/main/java/androidx/core/text/BidiFormatter.java
+++ b/compat/src/main/java/androidx/core/text/BidiFormatter.java
@@ -82,7 +82,7 @@
/**
* The default text direction heuristic.
*/
- private static final TextDirectionHeuristicCompat DEFAULT_TEXT_DIRECTION_HEURISTIC = FIRSTSTRONG_LTR;
+ static final TextDirectionHeuristicCompat DEFAULT_TEXT_DIRECTION_HEURISTIC = FIRSTSTRONG_LTR;
/**
* Unicode "Left-To-Right Embedding" (LRE) character.
@@ -214,12 +214,12 @@
private static final int FLAG_STEREO_RESET = 2;
private static final int DEFAULT_FLAGS = FLAG_STEREO_RESET;
- private static final BidiFormatter DEFAULT_LTR_INSTANCE = new BidiFormatter(
+ static final BidiFormatter DEFAULT_LTR_INSTANCE = new BidiFormatter(
false /* LTR context */,
DEFAULT_FLAGS,
DEFAULT_TEXT_DIRECTION_HEURISTIC);
- private static final BidiFormatter DEFAULT_RTL_INSTANCE = new BidiFormatter(
+ static final BidiFormatter DEFAULT_RTL_INSTANCE = new BidiFormatter(
true /* RTL context */,
DEFAULT_FLAGS,
DEFAULT_TEXT_DIRECTION_HEURISTIC);
@@ -259,7 +259,7 @@
* @param flags The option flags.
* @param heuristic The default text direction heuristic.
*/
- private BidiFormatter(boolean isRtlContext, int flags, TextDirectionHeuristicCompat heuristic) {
+ BidiFormatter(boolean isRtlContext, int flags, TextDirectionHeuristicCompat heuristic) {
mIsRtlContext = isRtlContext;
mFlags = flags;
mDefaultTextDirectionHeuristicCompat = heuristic;
@@ -512,7 +512,7 @@
* @param locale The Locale whose directionality will be checked to be RTL or LTR
* @return true if the {@code locale} directionality is RTL. False otherwise.
*/
- private static boolean isRtlLocale(Locale locale) {
+ static boolean isRtlLocale(Locale locale) {
return (TextUtilsCompat.getLayoutDirectionFromLocale(locale) == ViewCompat.LAYOUT_DIRECTION_RTL);
}
@@ -956,4 +956,4 @@
return Character.DIRECTIONALITY_OTHER_NEUTRALS;
}
}
-}
\ No newline at end of file
+}
diff --git a/compat/src/main/java/androidx/core/util/Pair.java b/compat/src/main/java/androidx/core/util/Pair.java
index 72407e6..9db1f1f 100644
--- a/compat/src/main/java/androidx/core/util/Pair.java
+++ b/compat/src/main/java/androidx/core/util/Pair.java
@@ -53,11 +53,7 @@
return false;
}
Pair<?, ?> p = (Pair<?, ?>) o;
- return objectsEqual(p.first, first) && objectsEqual(p.second, second);
- }
-
- private static boolean objectsEqual(Object a, Object b) {
- return a == b || (a != null && a.equals(b));
+ return ObjectsCompat.equals(p.first, first) && ObjectsCompat.equals(p.second, second);
}
/**
diff --git a/drawerlayout/src/main/java/androidx/drawerlayout/widget/DrawerLayout.java b/drawerlayout/src/main/java/androidx/drawerlayout/widget/DrawerLayout.java
index 4b868f5..f51dff5 100644
--- a/drawerlayout/src/main/java/androidx/drawerlayout/widget/DrawerLayout.java
+++ b/drawerlayout/src/main/java/androidx/drawerlayout/widget/DrawerLayout.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -35,6 +36,7 @@
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.Gravity;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -241,6 +243,9 @@
private final ArrayList<View> mNonDrawerViews;
+ private Rect mChildHitRect;
+ private Matrix mChildInvertedMatrix;
+
/**
* Listener for monitoring events about drawers.
*/
@@ -751,6 +756,59 @@
}
/**
+ * Returns true if x and y coord in DrawerLayout's coordinate space are inside the bounds of the
+ * child's coordinate space.
+ */
+ private boolean isInBoundsOfChild(float x, float y, View child) {
+ if (mChildHitRect == null) {
+ mChildHitRect = new Rect();
+ }
+ child.getHitRect(mChildHitRect);
+ return mChildHitRect.contains((int) x, (int) y);
+ }
+
+ /**
+ * Copied from ViewGroup#dispatchTransformedGenericPointerEvent(MotionEvent, View) then modified
+ * in order to make calls that are otherwise too visibility restricted to make.
+ */
+ private boolean dispatchTransformedGenericPointerEvent(MotionEvent event, View child) {
+ boolean handled;
+ final Matrix childMatrix = child.getMatrix();
+ if (!childMatrix.isIdentity()) {
+ MotionEvent transformedEvent = getTransformedMotionEvent(event, child);
+ handled = child.dispatchGenericMotionEvent(transformedEvent);
+ transformedEvent.recycle();
+ } else {
+ final float offsetX = getScrollX() - child.getLeft();
+ final float offsetY = getScrollY() - child.getTop();
+ event.offsetLocation(offsetX, offsetY);
+ handled = child.dispatchGenericMotionEvent(event);
+ event.offsetLocation(-offsetX, -offsetY);
+ }
+ return handled;
+ }
+
+ /**
+ * Copied from ViewGroup#getTransformedMotionEvent(MotionEvent, View) then modified in order to
+ * make calls that are otherwise too visibility restricted to make.
+ */
+ private MotionEvent getTransformedMotionEvent(MotionEvent event, View child) {
+ final float offsetX = getScrollX() - child.getLeft();
+ final float offsetY = getScrollY() - child.getTop();
+ final MotionEvent transformedEvent = MotionEvent.obtain(event);
+ transformedEvent.offsetLocation(offsetX, offsetY);
+ final Matrix childMatrix = child.getMatrix();
+ if (!childMatrix.isIdentity()) {
+ if (mChildInvertedMatrix == null) {
+ mChildInvertedMatrix = new Matrix();
+ }
+ childMatrix.invert(mChildInvertedMatrix);
+ transformedEvent.transform(mChildInvertedMatrix);
+ }
+ return transformedEvent;
+ }
+
+ /**
* Resolve the shared state of all drawers from the component ViewDragHelpers.
* Should be called whenever a ViewDragHelper's state changes.
*/
@@ -1472,6 +1530,43 @@
}
@Override
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+
+ // If this is not a pointer event, or if this is an hover exit, or we are not displaying
+ // that the content view can't be interacted with, then don't override and do anything
+ // special.
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0
+ || event.getAction() == MotionEvent.ACTION_HOVER_EXIT
+ || mScrimOpacity <= 0) {
+ return super.dispatchGenericMotionEvent(event);
+ }
+
+ final int childrenCount = getChildCount();
+ if (childrenCount != 0) {
+ final float x = event.getX();
+ final float y = event.getY();
+
+ // Walk through children from top to bottom.
+ for (int i = childrenCount - 1; i >= 0; i--) {
+ final View child = getChildAt(i);
+
+ // If the event is out of bounds or the child is the content view, don't dispatch
+ // to it.
+ if (!isInBoundsOfChild(x, y, child) || isContentView(child)) {
+ continue;
+ }
+
+ // If a child handles it, return true.
+ if (dispatchTransformedGenericPointerEvent(event, child)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent ev) {
mLeftDragger.processTouchEvent(ev);
mRightDragger.processTouchEvent(ev);
diff --git a/emoji/core/api/current.txt b/emoji/core/api/current.txt
index 785f44a..7b343a1 100644
--- a/emoji/core/api/current.txt
+++ b/emoji/core/api/current.txt
@@ -9,6 +9,7 @@
method public boolean hasEmojiGlyph(java.lang.CharSequence);
method public boolean hasEmojiGlyph(java.lang.CharSequence, int);
method public static androidx.emoji.text.EmojiCompat init(androidx.emoji.text.EmojiCompat.Config);
+ method public void load();
method public java.lang.CharSequence process(java.lang.CharSequence);
method public java.lang.CharSequence process(java.lang.CharSequence, int, int);
method public java.lang.CharSequence process(java.lang.CharSequence, int, int, int);
@@ -17,9 +18,12 @@
method public void unregisterInitCallback(androidx.emoji.text.EmojiCompat.InitCallback);
field public static final java.lang.String EDITOR_INFO_METAVERSION_KEY = "android.support.text.emoji.emojiCompat_metadataVersion";
field public static final java.lang.String EDITOR_INFO_REPLACE_ALL_KEY = "android.support.text.emoji.emojiCompat_replaceAll";
+ field public static final int LOAD_STATE_DEFAULT = 3; // 0x3
field public static final int LOAD_STATE_FAILED = 2; // 0x2
field public static final int LOAD_STATE_LOADING = 0; // 0x0
field public static final int LOAD_STATE_SUCCEEDED = 1; // 0x1
+ field public static final int LOAD_STRATEGY_DEFAULT = 0; // 0x0
+ field public static final int LOAD_STRATEGY_MANUAL = 1; // 0x1
field public static final int REPLACE_STRATEGY_ALL = 1; // 0x1
field public static final int REPLACE_STRATEGY_DEFAULT = 0; // 0x0
field public static final int REPLACE_STRATEGY_NON_EXISTENT = 2; // 0x2
@@ -31,6 +35,7 @@
method public androidx.emoji.text.EmojiCompat.Config registerInitCallback(androidx.emoji.text.EmojiCompat.InitCallback);
method public androidx.emoji.text.EmojiCompat.Config setEmojiSpanIndicatorColor(int);
method public androidx.emoji.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean);
+ method public androidx.emoji.text.EmojiCompat.Config setMetadataLoadStrategy(int);
method public androidx.emoji.text.EmojiCompat.Config setReplaceAll(boolean);
method public androidx.emoji.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean);
method public androidx.emoji.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean, java.util.List<java.lang.Integer>);
diff --git a/emoji/core/src/androidTest/java/androidx/emoji/text/ConfigTest.java b/emoji/core/src/androidTest/java/androidx/emoji/text/ConfigTest.java
index 34f31fd..c8d3dad 100644
--- a/emoji/core/src/androidTest/java/androidx/emoji/text/ConfigTest.java
+++ b/emoji/core/src/androidTest/java/androidx/emoji/text/ConfigTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -148,9 +149,25 @@
assertTrue(emojiCompat.isEmojiSpanIndicatorEnabled());
}
+ @Test
+ public void testBuild_manualLoadStrategy_doesNotCallMetadataLoaderLoad() {
+ final EmojiCompat.MetadataRepoLoader loader = mock(EmojiCompat.MetadataRepoLoader.class);
+ final EmojiCompat.Config config = new ValidTestConfig(loader)
+ .setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
+
+ EmojiCompat.reset(config);
+
+ verify(loader, never()).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+ assertEquals(EmojiCompat.LOAD_STATE_DEFAULT, EmojiCompat.get().getLoadState());
+ }
+
private static class ValidTestConfig extends EmojiCompat.Config {
ValidTestConfig() {
super(new TestConfigBuilder.TestEmojiDataLoader());
}
+
+ ValidTestConfig(EmojiCompat.MetadataRepoLoader loader) {
+ super(loader);
+ }
}
}
diff --git a/emoji/core/src/androidTest/java/androidx/emoji/text/EmojiCompatTest.java b/emoji/core/src/androidTest/java/androidx/emoji/text/EmojiCompatTest.java
index dd8f3b9..fd9df56 100644
--- a/emoji/core/src/androidTest/java/androidx/emoji/text/EmojiCompatTest.java
+++ b/emoji/core/src/androidTest/java/androidx/emoji/text/EmojiCompatTest.java
@@ -53,6 +53,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -691,6 +692,97 @@
metadataLoader.getLoaderLatch().countDown();
}
+ @Test(expected = IllegalStateException.class)
+ public void testLoad_throwsException_whenLoadStrategyDefault() {
+ final EmojiCompat.MetadataRepoLoader loader = mock(EmojiCompat.MetadataRepoLoader.class);
+ final EmojiCompat.Config config = new TestConfigBuilder.TestConfig(loader);
+ EmojiCompat.reset(config);
+
+ EmojiCompat.get().load();
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 18)
+ public void testLoad_pre19() {
+ final EmojiCompat.MetadataRepoLoader loader = spy(new TestConfigBuilder
+ .TestEmojiDataLoader());
+ final EmojiCompat.Config config = new TestConfigBuilder.TestConfig(loader)
+ .setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
+
+ EmojiCompat.reset(config);
+
+ verify(loader, never()).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+ assertEquals(EmojiCompat.LOAD_STATE_DEFAULT, EmojiCompat.get().getLoadState());
+
+ EmojiCompat.get().load();
+ assertEquals(EmojiCompat.LOAD_STATE_SUCCEEDED, EmojiCompat.get().getLoadState());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 19)
+ public void testLoad_startsLoading() {
+ final EmojiCompat.MetadataRepoLoader loader = spy(new TestConfigBuilder
+ .TestEmojiDataLoader());
+ final EmojiCompat.Config config = new TestConfigBuilder.TestConfig(loader)
+ .setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
+
+ EmojiCompat.reset(config);
+
+ verify(loader, never()).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+ assertEquals(EmojiCompat.LOAD_STATE_DEFAULT, EmojiCompat.get().getLoadState());
+
+ EmojiCompat.get().load();
+ verify(loader, times(1)).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+ assertEquals(EmojiCompat.LOAD_STATE_SUCCEEDED, EmojiCompat.get().getLoadState());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 19)
+ public void testLoad_onceSuccessDoesNotStartLoading() {
+ final EmojiCompat.MetadataRepoLoader loader = spy(new TestConfigBuilder
+ .TestEmojiDataLoader());
+ final EmojiCompat.Config config = new TestConfigBuilder.TestConfig(loader)
+ .setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
+
+ EmojiCompat.reset(config);
+
+ EmojiCompat.get().load();
+ verify(loader, times(1)).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+ assertEquals(EmojiCompat.LOAD_STATE_SUCCEEDED, EmojiCompat.get().getLoadState());
+
+ reset(loader);
+ EmojiCompat.get().load();
+ verify(loader, never()).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+ assertEquals(EmojiCompat.LOAD_STATE_SUCCEEDED, EmojiCompat.get().getLoadState());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 19)
+ public void testLoad_onceLoadingDoesNotStartLoading() throws InterruptedException {
+ final TestConfigBuilder.WaitingDataLoader loader = spy(
+ new TestConfigBuilder.WaitingDataLoader(true /*success*/));
+ final EmojiCompat.Config config = new TestConfigBuilder.TestConfig(loader)
+ .setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
+
+ EmojiCompat.reset(config);
+
+ verify(loader, never()).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+
+ EmojiCompat.get().load();
+ verify(loader, times(1)).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+ assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_LOADING);
+
+ reset(loader);
+
+ EmojiCompat.get().load();
+ verify(loader, never()).load(any(EmojiCompat.MetadataRepoLoaderCallback.class));
+
+ loader.getLoaderLatch().countDown();
+ loader.getTestLatch().await();
+
+ assertEquals(EmojiCompat.get().getLoadState(), EmojiCompat.LOAD_STATE_SUCCEEDED);
+ }
+
@Test
@SdkSuppress(maxSdkVersion = 18)
public void testGetAssetSignature() {
diff --git a/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiInputFilterTest.java b/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiInputFilterTest.java
index 27ea7c6..2882858 100644
--- a/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiInputFilterTest.java
+++ b/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiInputFilterTest.java
@@ -114,4 +114,16 @@
verify(mEmojiCompat, times(0)).process(any(Spannable.class), anyInt(), anyInt());
verify(mEmojiCompat, times(0)).registerInitCallback(any(EmojiCompat.InitCallback.class));
}
+
+ @Test
+ public void testFilter_withManualLoadStrategy() {
+ final Spannable testString = new SpannableString("abc");
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_DEFAULT);
+
+ final CharSequence result = mInputFilter.filter(testString, 0, 1, null, 0, 1);
+
+ assertNotNull(result);
+ verify(mEmojiCompat, times(0)).process(any(Spannable.class), anyInt(), anyInt());
+ verify(mEmojiCompat, times(1)).registerInitCallback(any(EmojiCompat.InitCallback.class));
+ }
}
diff --git a/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiTextWatcherTest.java b/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiTextWatcherTest.java
index fade6f7..b8f0154 100644
--- a/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiTextWatcherTest.java
+++ b/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiTextWatcherTest.java
@@ -109,4 +109,15 @@
verify(mEmojiCompat, times(1)).process(any(Spannable.class), anyInt(), anyInt(), anyInt(),
eq(EmojiCompat.REPLACE_STRATEGY_ALL));
}
+
+ @Test
+ public void testFilter_withManualLoadStrategy() {
+ final Spannable testString = new SpannableString("abc");
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_DEFAULT);
+
+ mTextWatcher.onTextChanged(testString, 0, 0, 1);
+
+ verify(mEmojiCompat, times(0)).process(any(Spannable.class), anyInt(), anyInt());
+ verify(mEmojiCompat, times(1)).registerInitCallback(any(EmojiCompat.InitCallback.class));
+ }
}
diff --git a/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiTransformationMethodTest.java b/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiTransformationMethodTest.java
new file mode 100644
index 0000000..cf74331
--- /dev/null
+++ b/emoji/core/src/androidTest/java/androidx/emoji/widget/EmojiTransformationMethodTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.emoji.widget;
+
+import static junit.framework.TestCase.assertSame;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import static androidx.emoji.util.EmojiMatcher.sameCharSequence;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.method.TransformationMethod;
+import android.view.View;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import androidx.emoji.text.EmojiCompat;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class EmojiTransformationMethodTest {
+
+ private EmojiTransformationMethod mTransformationMethod;
+ private TransformationMethod mWrappedTransformationMethod;
+ private View mView;
+ private EmojiCompat mEmojiCompat;
+ private final String mTestString = "abc";
+
+ @Before
+ public void setup() {
+ mEmojiCompat = mock(EmojiCompat.class);
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_SUCCEEDED);
+ when(mEmojiCompat.process(any(CharSequence.class))).thenAnswer(new Answer<CharSequence>() {
+ @Override
+ public CharSequence answer(InvocationOnMock invocation) {
+ Object[] args = invocation.getArguments();
+ return new SpannableString((String) args[0]);
+ }
+ });
+ EmojiCompat.reset(mEmojiCompat);
+
+ mView = mock(View.class);
+ when(mView.isInEditMode()).thenReturn(false);
+
+ mWrappedTransformationMethod = mock(TransformationMethod.class);
+ when(mWrappedTransformationMethod.getTransformation(any(CharSequence.class),
+ any(View.class))).thenAnswer(new Answer<CharSequence>() {
+ @Override
+ public CharSequence answer(InvocationOnMock invocation) {
+ Object[] args = invocation.getArguments();
+ return (String) args[0];
+ }
+ });
+
+ mTransformationMethod = new EmojiTransformationMethod(mWrappedTransformationMethod);
+ }
+
+ @Test
+ public void testFilter_withNullSource() {
+ assertNull(mTransformationMethod.getTransformation(null, mView));
+ verify(mEmojiCompat, never()).process(any(CharSequence.class));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testFilter_withNullView() {
+ mTransformationMethod.getTransformation("", null);
+ }
+
+ @Test
+ public void testFilter_withNullTransformationMethod() {
+ mTransformationMethod = new EmojiTransformationMethod(null);
+
+ final CharSequence result = mTransformationMethod.getTransformation(mTestString, mView);
+
+ assertTrue(TextUtils.equals(new SpannableString(mTestString), result));
+ verify(mEmojiCompat, times(1)).process(sameCharSequence(mTestString));
+ }
+
+ @Test
+ public void testFilter() {
+ final CharSequence result = mTransformationMethod.getTransformation(mTestString, mView);
+
+ assertTrue(TextUtils.equals(new SpannableString(mTestString), result));
+ assertTrue(result instanceof Spannable);
+ verify(mWrappedTransformationMethod, times(1)).getTransformation(
+ sameCharSequence(mTestString), same(mView));
+ verify(mEmojiCompat, times(1)).process(sameCharSequence(mTestString));
+ verify(mEmojiCompat, never()).registerInitCallback(any(EmojiCompat.InitCallback.class));
+ }
+
+ @Test
+ public void testFilter_whenEmojiCompatLoading() {
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_LOADING);
+
+ final CharSequence result = mTransformationMethod.getTransformation(mTestString, mView);
+
+ assertSame(mTestString, result);
+ verify(mWrappedTransformationMethod, times(1)).getTransformation(
+ sameCharSequence(mTestString), same(mView));
+ verify(mEmojiCompat, never()).process(sameCharSequence(mTestString));
+ verify(mEmojiCompat, never()).registerInitCallback(any(EmojiCompat.InitCallback.class));
+ }
+
+ @Test
+ public void testFilter_whenEmojiCompatLoadFailed() {
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_FAILED);
+
+ final CharSequence result = mTransformationMethod.getTransformation(mTestString, mView);
+
+ assertSame(mTestString, result);
+ verify(mWrappedTransformationMethod, times(1)).getTransformation(
+ sameCharSequence(mTestString), same(mView));
+ verify(mEmojiCompat, never()).process(sameCharSequence(mTestString));
+ verify(mEmojiCompat, never()).registerInitCallback(any(EmojiCompat.InitCallback.class));
+ }
+
+ @Test
+ public void testFilter_withManualLoadStrategy() {
+ when(mEmojiCompat.getLoadState()).thenReturn(EmojiCompat.LOAD_STATE_DEFAULT);
+
+ final CharSequence result = mTransformationMethod.getTransformation(mTestString, mView);
+
+ assertSame(mTestString, result);
+ verify(mWrappedTransformationMethod, times(1)).getTransformation(
+ sameCharSequence(mTestString), same(mView));
+ verify(mEmojiCompat, never()).process(sameCharSequence(mTestString));
+ verify(mEmojiCompat, never()).registerInitCallback(any(EmojiCompat.InitCallback.class));
+ }
+}
diff --git a/emoji/core/src/main/java/androidx/emoji/text/EmojiCompat.java b/emoji/core/src/main/java/androidx/emoji/text/EmojiCompat.java
index e7226ff..572606f 100644
--- a/emoji/core/src/main/java/androidx/emoji/text/EmojiCompat.java
+++ b/emoji/core/src/main/java/androidx/emoji/text/EmojiCompat.java
@@ -98,6 +98,11 @@
"android.support.text.emoji.emojiCompat_replaceAll";
/**
+ * EmojiCompat instance is constructed, however the initialization did not start yet.
+ */
+ public static final int LOAD_STATE_DEFAULT = 3;
+
+ /**
* EmojiCompat is initializing.
*/
public static final int LOAD_STATE_LOADING = 0;
@@ -117,7 +122,7 @@
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
- @IntDef({LOAD_STATE_LOADING, LOAD_STATE_SUCCEEDED, LOAD_STATE_FAILED})
+ @IntDef({LOAD_STATE_DEFAULT, LOAD_STATE_LOADING, LOAD_STATE_SUCCEEDED, LOAD_STATE_FAILED})
@Retention(RetentionPolicy.SOURCE)
public @interface LoadState {
}
@@ -147,6 +152,26 @@
}
/**
+ * {@link EmojiCompat} will start loading metadata when {@link #init(Config)} is called.
+ */
+ public static final int LOAD_STRATEGY_DEFAULT = 0;
+
+ /**
+ * {@link EmojiCompat} will wait for {@link #load()} to be called by developer in order to
+ * start loading metadata.
+ */
+ public static final int LOAD_STRATEGY_MANUAL = 1;
+
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY_GROUP)
+ @IntDef({LOAD_STRATEGY_DEFAULT, LOAD_STRATEGY_MANUAL})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LoadStrategy {
+ }
+
+ /**
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
@@ -207,18 +232,25 @@
private final int mEmojiSpanIndicatorColor;
/**
+ * @see Config#setMetadataLoadStrategy(int)
+ */
+ @LoadStrategy private final int mMetadataLoadStrategy;
+
+ /**
* Private constructor for singleton instance.
*
* @see #init(Config)
*/
private EmojiCompat(@NonNull final Config config) {
mInitLock = new ReentrantReadWriteLock();
+ mLoadState = LOAD_STATE_DEFAULT;
mReplaceAll = config.mReplaceAll;
mUseEmojiAsDefaultStyle = config.mUseEmojiAsDefaultStyle;
mEmojiAsDefaultStyleExceptions = config.mEmojiAsDefaultStyleExceptions;
mEmojiSpanIndicatorEnabled = config.mEmojiSpanIndicatorEnabled;
mEmojiSpanIndicatorColor = config.mEmojiSpanIndicatorColor;
mMetadataLoader = config.mMetadataLoader;
+ mMetadataLoadStrategy = config.mMetadataLoadStrategy;
mMainHandler = new Handler(Looper.getMainLooper());
mInitCallbacks = new ArraySet<>();
if (config.mInitCallbacks != null && !config.mInitCallbacks.isEmpty()) {
@@ -308,9 +340,30 @@
}
}
- private void loadMetadata() {
+ /**
+ * When {@link Config#setMetadataLoadStrategy(int)} is set to {@link #LOAD_STRATEGY_MANUAL},
+ * this function starts loading the metadata. Calling the function when
+ * {@link Config#setMetadataLoadStrategy(int)} is {@code not} set to
+ * {@link #LOAD_STRATEGY_MANUAL} will throw an exception. The load will {@code not} start if:
+ * <ul>
+ * <li>the metadata is already loaded successfully and {@link #getLoadState()} is
+ * {@link #LOAD_STATE_SUCCEEDED}.
+ * </li>
+ * <li>a previous load attempt is not finished yet and {@link #getLoadState()} is
+ * {@link #LOAD_STATE_LOADING}.</li>
+ * </ul>
+ *
+ * @throws IllegalStateException when {@link Config#setMetadataLoadStrategy(int)} is not set
+ * to {@link #LOAD_STRATEGY_MANUAL}
+ */
+ public void load() {
+ Preconditions.checkState(mMetadataLoadStrategy == LOAD_STRATEGY_MANUAL,
+ "Set metadataLoadStrategy to LOAD_STRATEGY_MANUAL to execute manual loading");
+ if (isInitialized()) return;
+
mInitLock.writeLock().lock();
try {
+ if (mLoadState == LOAD_STATE_LOADING) return;
mLoadState = LOAD_STATE_LOADING;
} finally {
mInitLock.writeLock().unlock();
@@ -319,6 +372,21 @@
mHelper.loadMetadata();
}
+ private void loadMetadata() {
+ mInitLock.writeLock().lock();
+ try {
+ if (mMetadataLoadStrategy == LOAD_STRATEGY_DEFAULT) {
+ mLoadState = LOAD_STATE_LOADING;
+ }
+ } finally {
+ mInitLock.writeLock().unlock();
+ }
+
+ if (getLoadState() == LOAD_STATE_LOADING) {
+ mHelper.loadMetadata();
+ }
+ }
+
private void onMetadataLoadSuccess() {
final Collection<InitCallback> initCallbacks = new ArrayList<>();
mInitLock.writeLock().lock();
@@ -393,8 +461,8 @@
* Returns loading state of the EmojiCompat instance. When used on devices running API 18 or
* below always returns {@link #LOAD_STATE_SUCCEEDED}.
*
- * @return one of {@link #LOAD_STATE_LOADING}, {@link #LOAD_STATE_SUCCEEDED},
- * {@link #LOAD_STATE_FAILED}
+ * @return one of {@link #LOAD_STATE_DEFAULT}, {@link #LOAD_STATE_LOADING},
+ * {@link #LOAD_STATE_SUCCEEDED}, {@link #LOAD_STATE_FAILED}
*/
public @LoadState int getLoadState() {
mInitLock.readLock().lock();
@@ -809,6 +877,7 @@
private Set<InitCallback> mInitCallbacks;
private boolean mEmojiSpanIndicatorEnabled;
private int mEmojiSpanIndicatorColor = Color.GREEN;
+ @LoadStrategy private int mMetadataLoadStrategy = LOAD_STRATEGY_DEFAULT;
/**
* Default constructor.
@@ -942,6 +1011,21 @@
}
/**
+ * Determines the strategy to start loading the metadata. By default {@link EmojiCompat}
+ * will start loading the metadata during {@link EmojiCompat#init(Config)}. When set to
+ * {@link EmojiCompat#LOAD_STRATEGY_MANUAL}, you should call {@link EmojiCompat#load()} to
+ * initiate metadata loading.
+ *
+ * @param strategy one of {@link EmojiCompat#LOAD_STRATEGY_DEFAULT},
+ * {@link EmojiCompat#LOAD_STRATEGY_MANUAL}
+ *
+ */
+ public Config setMetadataLoadStrategy(@LoadStrategy int strategy) {
+ mMetadataLoadStrategy = strategy;
+ return this;
+ }
+
+ /**
* Returns the {@link MetadataRepoLoader}.
*/
protected final MetadataRepoLoader getMetadataRepoLoader() {
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/EmojiInputFilter.java b/emoji/core/src/main/java/androidx/emoji/widget/EmojiInputFilter.java
index 22837a6..b44e859 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/EmojiInputFilter.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/EmojiInputFilter.java
@@ -79,6 +79,7 @@
return source;
case EmojiCompat.LOAD_STATE_LOADING:
+ case EmojiCompat.LOAD_STATE_DEFAULT:
EmojiCompat.get().registerInitCallback(getInitCallback());
return source;
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextWatcher.java b/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextWatcher.java
index 5d0e552..2197aff 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextWatcher.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextWatcher.java
@@ -80,6 +80,7 @@
mEmojiReplaceStrategy);
break;
case EmojiCompat.LOAD_STATE_LOADING:
+ case EmojiCompat.LOAD_STATE_DEFAULT:
EmojiCompat.get().registerInitCallback(getInitCallback());
break;
case EmojiCompat.LOAD_STATE_FAILED:
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/EmojiTransformationMethod.java b/emoji/core/src/main/java/androidx/emoji/widget/EmojiTransformationMethod.java
index c082c83..81fe615 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/EmojiTransformationMethod.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/EmojiTransformationMethod.java
@@ -57,6 +57,7 @@
return EmojiCompat.get().process(source);
case EmojiCompat.LOAD_STATE_LOADING:
case EmojiCompat.LOAD_STATE_FAILED:
+ case EmojiCompat.LOAD_STATE_DEFAULT:
default:
break;
}
diff --git a/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java b/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
index b4da25b..3011a62 100644
--- a/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
+++ b/fragment/src/main/java/androidx/fragment/app/BackStackRecord.java
@@ -22,6 +22,7 @@
import android.util.Log;
import android.view.View;
+import androidx.annotation.Nullable;
import androidx.core.util.LogWriter;
import androidx.core.view.ViewCompat;
@@ -214,7 +215,7 @@
int mTransitionStyle;
boolean mAddToBackStack;
boolean mAllowAddToBackStack = true;
- String mName;
+ @Nullable String mName;
boolean mCommitted;
int mIndex = -1;
@@ -348,6 +349,7 @@
}
@Override
+ @Nullable
public CharSequence getBreadCrumbTitle() {
if (mBreadCrumbTitleRes != 0) {
return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
@@ -356,6 +358,7 @@
}
@Override
+ @Nullable
public CharSequence getBreadCrumbShortTitle() {
if (mBreadCrumbShortTitleRes != 0) {
return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
@@ -372,7 +375,7 @@
}
@Override
- public FragmentTransaction add(Fragment fragment, String tag) {
+ public FragmentTransaction add(Fragment fragment, @Nullable String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
@@ -384,12 +387,12 @@
}
@Override
- public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
+ public FragmentTransaction add(int containerViewId, Fragment fragment, @Nullable String tag) {
doAddOp(containerViewId, fragment, tag, OP_ADD);
return this;
}
- private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
+ private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
final Class fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
@@ -432,7 +435,8 @@
}
@Override
- public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
+ public FragmentTransaction replace(int containerViewId, Fragment fragment,
+ @Nullable String tag) {
if (containerViewId == 0) {
throw new IllegalArgumentException("Must use non-zero containerViewId");
}
@@ -477,7 +481,7 @@
}
@Override
- public FragmentTransaction setPrimaryNavigationFragment(Fragment fragment) {
+ public FragmentTransaction setPrimaryNavigationFragment(@Nullable Fragment fragment) {
addOp(new Op(OP_SET_PRIMARY_NAV, fragment));
return this;
@@ -536,7 +540,7 @@
}
@Override
- public FragmentTransaction addToBackStack(String name) {
+ public FragmentTransaction addToBackStack(@Nullable String name) {
if (!mAllowAddToBackStack) {
throw new IllegalStateException(
"This FragmentTransaction is not allowed to be added to the back stack.");
@@ -569,7 +573,7 @@
}
@Override
- public FragmentTransaction setBreadCrumbTitle(CharSequence text) {
+ public FragmentTransaction setBreadCrumbTitle(@Nullable CharSequence text) {
mBreadCrumbTitleRes = 0;
mBreadCrumbTitleText = text;
return this;
@@ -583,7 +587,7 @@
}
@Override
- public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) {
+ public FragmentTransaction setBreadCrumbShortTitle(@Nullable CharSequence text) {
mBreadCrumbShortTitleRes = 0;
mBreadCrumbShortTitleText = text;
return this;
@@ -1008,6 +1012,7 @@
}
@Override
+ @Nullable
public String getName() {
return mName;
}
diff --git a/fragment/src/main/java/androidx/fragment/app/Fragment.java b/fragment/src/main/java/androidx/fragment/app/Fragment.java
index 90728c1..fc34d9e 100644
--- a/fragment/src/main/java/androidx/fragment/app/Fragment.java
+++ b/fragment/src/main/java/androidx/fragment/app/Fragment.java
@@ -98,6 +98,9 @@
// When instantiated from saved state, this is the saved state.
Bundle mSavedFragmentState;
SparseArray<Parcelable> mSavedViewState;
+ // If the userVisibleHint is changed before the state is set,
+ // it is stored here
+ @Nullable Boolean mSavedUserVisibleHint;
// Index into active fragment array.
int mIndex = -1;
@@ -959,8 +962,7 @@
if (mSavedFragmentState != null) {
// Ensure that if the user visible hint is set before the Fragment has
// restored its state that we don't lose the new value
- mSavedFragmentState.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG,
- mUserVisibleHint);
+ mSavedUserVisibleHint = isVisibleToUser;
}
}
diff --git a/fragment/src/main/java/androidx/fragment/app/FragmentController.java b/fragment/src/main/java/androidx/fragment/app/FragmentController.java
index 97c4b87..69a2b52 100644
--- a/fragment/src/main/java/androidx/fragment/app/FragmentController.java
+++ b/fragment/src/main/java/androidx/fragment/app/FragmentController.java
@@ -63,11 +63,15 @@
/**
* Returns a {@link LoaderManager}.
*
- * @deprecated Loaders are managed separately from FragmentController
+ * @deprecated Loaders are managed separately from FragmentController and this now throws an
+ * {@link UnsupportedOperationException}. Use {@link LoaderManager#getInstance} to obtain a
+ * LoaderManager.
+ * @see LoaderManager#getInstance
*/
@Deprecated
public LoaderManager getSupportLoaderManager() {
- return null;
+ throw new UnsupportedOperationException("Loaders are managed separately from "
+ + "FragmentController, use LoaderManager.getInstance() to obtain a LoaderManager.");
}
/**
diff --git a/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java b/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java
index 8d37cf1..3190604 100644
--- a/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java
+++ b/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java
@@ -28,6 +28,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
+import androidx.core.util.Preconditions;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -40,26 +41,27 @@
* applicable to the host.
*/
public abstract class FragmentHostCallback<E> extends FragmentContainer {
- private final Activity mActivity;
- final Context mContext;
- private final Handler mHandler;
- final int mWindowAnimations;
+ @Nullable private final Activity mActivity;
+ @NonNull private final Context mContext;
+ @NonNull private final Handler mHandler;
+ private final int mWindowAnimations;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
- public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
+ public FragmentHostCallback(@NonNull Context context, @NonNull Handler handler,
+ int windowAnimations) {
this(context instanceof Activity ? (Activity) context : null, context, handler,
windowAnimations);
}
- FragmentHostCallback(FragmentActivity activity) {
+ FragmentHostCallback(@NonNull FragmentActivity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
}
- FragmentHostCallback(Activity activity, Context context, Handler handler,
- int windowAnimations) {
+ FragmentHostCallback(@Nullable Activity activity, @NonNull Context context,
+ @NonNull Handler handler, int windowAnimations) {
mActivity = activity;
- mContext = context;
- mHandler = handler;
+ mContext = Preconditions.checkNotNull(context, "context == null");
+ mHandler = Preconditions.checkNotNull(handler, "handler == null");
mWindowAnimations = windowAnimations;
}
@@ -183,14 +185,17 @@
return true;
}
+ @Nullable
Activity getActivity() {
return mActivity;
}
+ @NonNull
Context getContext() {
return mContext;
}
+ @NonNull
Handler getHandler() {
return mHandler;
}
diff --git a/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index beb07f8..37c480d 100644
--- a/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -56,12 +56,12 @@
import androidx.annotation.CallSuper;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.StringRes;
import androidx.collection.ArraySet;
import androidx.core.util.DebugUtils;
import androidx.core.util.LogWriter;
-import androidx.core.util.Pair;
import androidx.core.view.ViewCompat;
import androidx.lifecycle.ViewModelStore;
@@ -110,6 +110,7 @@
* {@link FragmentTransaction#addToBackStack(String)
* FragmentTransaction.addToBackStack(String)} when creating this entry.
*/
+ @Nullable
public String getName();
/**
@@ -130,12 +131,14 @@
* Return the full bread crumb title for the entry, or null if it
* does not have one.
*/
+ @Nullable
public CharSequence getBreadCrumbTitle();
/**
* Return the short bread crumb title for the entry, or null if it
* does not have one.
*/
+ @Nullable
public CharSequence getBreadCrumbShortTitle();
}
@@ -162,6 +165,7 @@
* in the state, and if changes are made after the state is saved then they
* will be lost.</p>
*/
+ @NonNull
public abstract FragmentTransaction beginTransaction();
/**
@@ -205,6 +209,7 @@
* on the back stack associated with this ID are searched.
* @return The fragment if found or null otherwise.
*/
+ @Nullable
public abstract Fragment findFragmentById(@IdRes int id);
/**
@@ -215,7 +220,8 @@
* on the back stack are searched.
* @return The fragment if found or null otherwise.
*/
- public abstract Fragment findFragmentByTag(String tag);
+ @Nullable
+ public abstract Fragment findFragmentByTag(@Nullable String tag);
/**
* Flag for {@link #popBackStack(String, int)}
@@ -256,7 +262,7 @@
* the named state itself is popped. If null, only the top state is popped.
* @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
*/
- public abstract void popBackStack(String name, int flags);
+ public abstract void popBackStack(@Nullable String name, int flags);
/**
* Like {@link #popBackStack(String, int)}, but performs the operation immediately
@@ -264,7 +270,7 @@
* afterwards without forcing the start of postponed Transactions.
* @return Returns true if there was something popped, else false.
*/
- public abstract boolean popBackStackImmediate(String name, int flags);
+ public abstract boolean popBackStackImmediate(@Nullable String name, int flags);
/**
* Pop all back stack states up to the one with the given identifier.
@@ -299,18 +305,21 @@
* Return the BackStackEntry at index <var>index</var> in the back stack;
* entries start index 0 being the bottom of the stack.
*/
+ @NonNull
public abstract BackStackEntry getBackStackEntryAt(int index);
/**
* Add a new listener for changes to the fragment back stack.
*/
- public abstract void addOnBackStackChangedListener(OnBackStackChangedListener listener);
+ public abstract void addOnBackStackChangedListener(
+ @NonNull OnBackStackChangedListener listener);
/**
* Remove a listener that was previously added with
* {@link #addOnBackStackChangedListener(OnBackStackChangedListener)}.
*/
- public abstract void removeOnBackStackChangedListener(OnBackStackChangedListener listener);
+ public abstract void removeOnBackStackChangedListener(
+ @NonNull OnBackStackChangedListener listener);
/**
* Put a reference to a fragment in a Bundle. This Bundle can be
@@ -322,7 +331,8 @@
* @param key The name of the entry in the bundle.
* @param fragment The Fragment whose reference is to be stored.
*/
- public abstract void putFragment(Bundle bundle, String key, Fragment fragment);
+ public abstract void putFragment(@NonNull Bundle bundle, @NonNull String key,
+ @NonNull Fragment fragment);
/**
* Retrieve the current Fragment instance for a reference previously
@@ -333,7 +343,8 @@
* @return Returns the current Fragment instance that is associated with
* the given reference.
*/
- public abstract Fragment getFragment(Bundle bundle, String key);
+ @Nullable
+ public abstract Fragment getFragment(@NonNull Bundle bundle, @NonNull String key);
/**
* Get a list of all fragments that are currently added to the FragmentManager.
@@ -346,6 +357,7 @@
*
* @return A list of all fragments that are added to the FragmentManager.
*/
+ @NonNull
public abstract List<Fragment> getFragments();
/**
@@ -370,6 +382,7 @@
* @return The generated state. This will be null if there was no
* interesting state created by the fragment.
*/
+ @Nullable
public abstract Fragment.SavedState saveFragmentInstanceState(Fragment f);
/**
@@ -386,7 +399,7 @@
* @param cb Callbacks to register
* @param recursive true to automatically register this callback for all child FragmentManagers
*/
- public abstract void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb,
+ public abstract void registerFragmentLifecycleCallbacks(@NonNull FragmentLifecycleCallbacks cb,
boolean recursive);
/**
@@ -396,7 +409,8 @@
*
* @param cb Callbacks to unregister
*/
- public abstract void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb);
+ public abstract void unregisterFragmentLifecycleCallbacks(
+ @NonNull FragmentLifecycleCallbacks cb);
/**
* Return the currently active primary navigation fragment for this FragmentManager.
@@ -410,6 +424,7 @@
*
* @return the fragment designated as the primary navigation fragment
*/
+ @Nullable
public abstract Fragment getPrimaryNavigationFragment();
/**
@@ -458,7 +473,8 @@
* @param f Fragment changing state
* @param context Context that the Fragment is being attached to
*/
- public void onFragmentPreAttached(FragmentManager fm, Fragment f, Context context) {}
+ public void onFragmentPreAttached(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @NonNull Context context) {}
/**
* Called after the fragment has been attached to its host. Its host will have had
@@ -468,7 +484,8 @@
* @param f Fragment changing state
* @param context Context that the Fragment was attached to
*/
- public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {}
+ public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @NonNull Context context) {}
/**
* Called right before the fragment's {@link Fragment#onCreate(Bundle)} method is called.
@@ -479,8 +496,8 @@
* @param f Fragment changing state
* @param savedInstanceState Saved instance bundle from a previous instance
*/
- public void onFragmentPreCreated(FragmentManager fm, Fragment f,
- Bundle savedInstanceState) {}
+ public void onFragmentPreCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -491,7 +508,8 @@
* @param f Fragment changing state
* @param savedInstanceState Saved instance bundle from a previous instance
*/
- public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {}
+ public void onFragmentCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -502,8 +520,8 @@
* @param f Fragment changing state
* @param savedInstanceState Saved instance bundle from a previous instance
*/
- public void onFragmentActivityCreated(FragmentManager fm, Fragment f,
- Bundle savedInstanceState) {}
+ public void onFragmentActivityCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned a non-null view from the FragmentManager's
@@ -514,8 +532,8 @@
* @param v View returned by the fragment
* @param savedInstanceState Saved instance bundle from a previous instance
*/
- public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v,
- Bundle savedInstanceState) {}
+ public void onFragmentViewCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @NonNull View v, @Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -524,7 +542,7 @@
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
- public void onFragmentStarted(FragmentManager fm, Fragment f) {}
+ public void onFragmentStarted(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -533,7 +551,7 @@
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
- public void onFragmentResumed(FragmentManager fm, Fragment f) {}
+ public void onFragmentResumed(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -542,7 +560,7 @@
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
- public void onFragmentPaused(FragmentManager fm, Fragment f) {}
+ public void onFragmentPaused(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -551,7 +569,7 @@
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
- public void onFragmentStopped(FragmentManager fm, Fragment f) {}
+ public void onFragmentStopped(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -561,7 +579,8 @@
* @param f Fragment changing state
* @param outState Saved state bundle for the fragment
*/
- public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {}
+ public void onFragmentSaveInstanceState(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @NonNull Bundle outState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -570,7 +589,7 @@
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
- public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {}
+ public void onFragmentViewDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -579,7 +598,7 @@
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
- public void onFragmentDestroyed(FragmentManager fm, Fragment f) {}
+ public void onFragmentDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
@@ -588,7 +607,7 @@
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
- public void onFragmentDetached(FragmentManager fm, Fragment f) {}
+ public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {}
}
}
@@ -650,6 +669,16 @@
static final String VIEW_STATE_TAG = "android:view_state";
static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
+ private static final class FragmentLifecycleCallbacksHolder {
+ final FragmentLifecycleCallbacks mCallback;
+ final boolean mRecursive;
+
+ FragmentLifecycleCallbacksHolder(FragmentLifecycleCallbacks callback, boolean recursive) {
+ mCallback = callback;
+ mRecursive = recursive;
+ }
+ }
+
ArrayList<OpGenerator> mPendingActions;
boolean mExecutingActions;
@@ -665,14 +694,14 @@
ArrayList<Integer> mAvailBackStackIndices;
ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
- private final CopyOnWriteArrayList<Pair<FragmentLifecycleCallbacks, Boolean>>
+ private final CopyOnWriteArrayList<FragmentLifecycleCallbacksHolder>
mLifecycleCallbacks = new CopyOnWriteArrayList<>();
int mCurState = Fragment.INITIALIZING;
FragmentHostCallback mHost;
FragmentContainer mContainer;
Fragment mParent;
- Fragment mPrimaryNav;
+ @Nullable Fragment mPrimaryNav;
static Field sAnimationListenerField = null;
@@ -799,12 +828,12 @@
}
@Override
- public void popBackStack(final String name, final int flags) {
+ public void popBackStack(@Nullable final String name, final int flags) {
enqueueAction(new PopBackStackState(name, -1, flags), false);
}
@Override
- public boolean popBackStackImmediate(String name, int flags) {
+ public boolean popBackStackImmediate(@Nullable String name, int flags) {
checkStateLoss();
return popBackStackImmediate(name, -1, flags);
}
@@ -898,6 +927,7 @@
}
@Override
+ @Nullable
public Fragment getFragment(Bundle bundle, String key) {
int index = bundle.getInt(key, -1);
if (index == -1) {
@@ -952,6 +982,7 @@
}
@Override
+ @Nullable
public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) {
if (fragment.mIndex < 0) {
throwException( new IllegalStateException("Fragment " + fragment
@@ -1335,8 +1366,13 @@
f.mTargetRequestCode = f.mSavedFragmentState.getInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
}
- f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
- FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
+ if (f.mSavedUserVisibleHint != null) {
+ f.mUserVisibleHint = f.mSavedUserVisibleHint;
+ f.mSavedUserVisibleHint = null;
+ } else {
+ f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
+ FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
+ }
if (!f.mUserVisibleHint) {
f.mDeferStart = true;
if (newState > Fragment.STOPPED) {
@@ -1989,6 +2025,7 @@
}
@Override
+ @Nullable
public Fragment findFragmentById(int id) {
// First look through added fragments.
for (int i = mAdded.size() - 1; i >= 0; i--) {
@@ -2010,7 +2047,8 @@
}
@Override
- public Fragment findFragmentByTag(String tag) {
+ @Nullable
+ public Fragment findFragmentByTag(@Nullable String tag) {
if (tag != null) {
// First look through added fragments.
for (int i=mAdded.size()-1; i>=0; i--) {
@@ -3382,6 +3420,7 @@
}
@Override
+ @Nullable
public Fragment getPrimaryNavigationFragment() {
return mPrimaryNav;
}
@@ -3389,14 +3428,14 @@
@Override
public void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb,
boolean recursive) {
- mLifecycleCallbacks.add(new Pair<>(cb, recursive));
+ mLifecycleCallbacks.add(new FragmentLifecycleCallbacksHolder(cb, recursive));
}
@Override
public void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb) {
synchronized (mLifecycleCallbacks) {
for (int i = 0, N = mLifecycleCallbacks.size(); i < N; i++) {
- if (mLifecycleCallbacks.get(i).first == cb) {
+ if (mLifecycleCallbacks.get(i).mCallback == cb) {
mLifecycleCallbacks.remove(i);
break;
}
@@ -3404,7 +3443,8 @@
}
}
- void dispatchOnFragmentPreAttached(Fragment f, Context context, boolean onlyRecursive) {
+ void dispatchOnFragmentPreAttached(@NonNull Fragment f, @NonNull Context context,
+ boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3412,14 +3452,15 @@
.dispatchOnFragmentPreAttached(f, context, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentPreAttached(this, f, context);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentPreAttached(this, f, context);
}
}
}
- void dispatchOnFragmentAttached(Fragment f, Context context, boolean onlyRecursive) {
+ void dispatchOnFragmentAttached(@NonNull Fragment f, @NonNull Context context,
+ boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3427,14 +3468,14 @@
.dispatchOnFragmentAttached(f, context, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentAttached(this, f, context);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentAttached(this, f, context);
}
}
}
- void dispatchOnFragmentPreCreated(Fragment f, Bundle savedInstanceState,
+ void dispatchOnFragmentPreCreated(@NonNull Fragment f, @Nullable Bundle savedInstanceState,
boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
@@ -3443,14 +3484,15 @@
.dispatchOnFragmentPreCreated(f, savedInstanceState, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentPreCreated(this, f, savedInstanceState);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentPreCreated(this, f, savedInstanceState);
}
}
}
- void dispatchOnFragmentCreated(Fragment f, Bundle savedInstanceState, boolean onlyRecursive) {
+ void dispatchOnFragmentCreated(@NonNull Fragment f, @Nullable Bundle savedInstanceState,
+ boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3458,14 +3500,14 @@
.dispatchOnFragmentCreated(f, savedInstanceState, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentCreated(this, f, savedInstanceState);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentCreated(this, f, savedInstanceState);
}
}
}
- void dispatchOnFragmentActivityCreated(Fragment f, Bundle savedInstanceState,
+ void dispatchOnFragmentActivityCreated(@NonNull Fragment f, @Nullable Bundle savedInstanceState,
boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
@@ -3474,15 +3516,15 @@
.dispatchOnFragmentActivityCreated(f, savedInstanceState, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentActivityCreated(this, f, savedInstanceState);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentActivityCreated(this, f, savedInstanceState);
}
}
}
- void dispatchOnFragmentViewCreated(Fragment f, View v, Bundle savedInstanceState,
- boolean onlyRecursive) {
+ void dispatchOnFragmentViewCreated(@NonNull Fragment f, @NonNull View v,
+ @Nullable Bundle savedInstanceState, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3490,14 +3532,14 @@
.dispatchOnFragmentViewCreated(f, v, savedInstanceState, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentViewCreated(this, f, v, savedInstanceState);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentViewCreated(this, f, v, savedInstanceState);
}
}
}
- void dispatchOnFragmentStarted(Fragment f, boolean onlyRecursive) {
+ void dispatchOnFragmentStarted(@NonNull Fragment f, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3505,14 +3547,14 @@
.dispatchOnFragmentStarted(f, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentStarted(this, f);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentStarted(this, f);
}
}
}
- void dispatchOnFragmentResumed(Fragment f, boolean onlyRecursive) {
+ void dispatchOnFragmentResumed(@NonNull Fragment f, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3520,14 +3562,14 @@
.dispatchOnFragmentResumed(f, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentResumed(this, f);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentResumed(this, f);
}
}
}
- void dispatchOnFragmentPaused(Fragment f, boolean onlyRecursive) {
+ void dispatchOnFragmentPaused(@NonNull Fragment f, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3535,14 +3577,14 @@
.dispatchOnFragmentPaused(f, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentPaused(this, f);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentPaused(this, f);
}
}
}
- void dispatchOnFragmentStopped(Fragment f, boolean onlyRecursive) {
+ void dispatchOnFragmentStopped(@NonNull Fragment f, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3550,14 +3592,15 @@
.dispatchOnFragmentStopped(f, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentStopped(this, f);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentStopped(this, f);
}
}
}
- void dispatchOnFragmentSaveInstanceState(Fragment f, Bundle outState, boolean onlyRecursive) {
+ void dispatchOnFragmentSaveInstanceState(@NonNull Fragment f, @NonNull Bundle outState,
+ boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3565,14 +3608,14 @@
.dispatchOnFragmentSaveInstanceState(f, outState, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentSaveInstanceState(this, f, outState);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentSaveInstanceState(this, f, outState);
}
}
}
- void dispatchOnFragmentViewDestroyed(Fragment f, boolean onlyRecursive) {
+ void dispatchOnFragmentViewDestroyed(@NonNull Fragment f, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3580,14 +3623,14 @@
.dispatchOnFragmentViewDestroyed(f, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentViewDestroyed(this, f);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentViewDestroyed(this, f);
}
}
}
- void dispatchOnFragmentDestroyed(Fragment f, boolean onlyRecursive) {
+ void dispatchOnFragmentDestroyed(@NonNull Fragment f, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3595,14 +3638,14 @@
.dispatchOnFragmentDestroyed(f, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentDestroyed(this, f);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentDestroyed(this, f);
}
}
}
- void dispatchOnFragmentDetached(Fragment f, boolean onlyRecursive) {
+ void dispatchOnFragmentDetached(@NonNull Fragment f, boolean onlyRecursive) {
if (mParent != null) {
FragmentManager parentManager = mParent.getFragmentManager();
if (parentManager instanceof FragmentManagerImpl) {
@@ -3610,9 +3653,9 @@
.dispatchOnFragmentDetached(f, true);
}
}
- for (Pair<FragmentLifecycleCallbacks, Boolean> p : mLifecycleCallbacks) {
- if (!onlyRecursive || p.second) {
- p.first.onFragmentDetached(this, f);
+ for (FragmentLifecycleCallbacksHolder holder : mLifecycleCallbacks) {
+ if (!onlyRecursive || holder.mRecursive) {
+ holder.mCallback.onFragmentDetached(this, f);
}
}
}
diff --git a/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java b/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
index 4182258..be51ea4 100644
--- a/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
+++ b/fragment/src/main/java/androidx/fragment/app/FragmentTransaction.java
@@ -25,6 +25,7 @@
import androidx.annotation.AnimatorRes;
import androidx.annotation.IdRes;
import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.StringRes;
@@ -44,12 +45,14 @@
/**
* Calls {@link #add(int, Fragment, String)} with a 0 containerViewId.
*/
- public abstract FragmentTransaction add(Fragment fragment, String tag);
+ @NonNull
+ public abstract FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag);
/**
* Calls {@link #add(int, Fragment, String)} with a null tag.
*/
- public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment);
/**
* Add a fragment to the activity state. This fragment may optionally
@@ -66,13 +69,16 @@
*
* @return Returns the same FragmentTransaction instance.
*/
- public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment,
+ @NonNull
+ public abstract FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment,
@Nullable String tag);
/**
* Calls {@link #replace(int, Fragment, String)} with a null tag.
*/
- public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction replace(@IdRes int containerViewId,
+ @NonNull Fragment fragment);
/**
* Replace an existing fragment that was added to a container. This is
@@ -90,8 +96,9 @@
*
* @return Returns the same FragmentTransaction instance.
*/
- public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment,
- @Nullable String tag);
+ @NonNull
+ public abstract FragmentTransaction replace(@IdRes int containerViewId,
+ @NonNull Fragment fragment, @Nullable String tag);
/**
* Remove an existing fragment. If it was added to a container, its view
@@ -101,7 +108,8 @@
*
* @return Returns the same FragmentTransaction instance.
*/
- public abstract FragmentTransaction remove(Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction remove(@NonNull Fragment fragment);
/**
* Hides an existing fragment. This is only relevant for fragments whose
@@ -112,7 +120,8 @@
*
* @return Returns the same FragmentTransaction instance.
*/
- public abstract FragmentTransaction hide(Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction hide(@NonNull Fragment fragment);
/**
* Shows a previously hidden fragment. This is only relevant for fragments whose
@@ -123,7 +132,8 @@
*
* @return Returns the same FragmentTransaction instance.
*/
- public abstract FragmentTransaction show(Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction show(@NonNull Fragment fragment);
/**
* Detach the given fragment from the UI. This is the same state as
@@ -136,7 +146,8 @@
*
* @return Returns the same FragmentTransaction instance.
*/
- public abstract FragmentTransaction detach(Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction detach(@NonNull Fragment fragment);
/**
* Re-attach a fragment after it had previously been detached from
@@ -148,7 +159,8 @@
*
* @return Returns the same FragmentTransaction instance.
*/
- public abstract FragmentTransaction attach(Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction attach(@NonNull Fragment fragment);
/**
* Set a currently active fragment in this FragmentManager as the primary navigation fragment.
@@ -166,7 +178,8 @@
* @param fragment the fragment to set as the primary navigation fragment
* @return the same FragmentTransaction instance
*/
- public abstract FragmentTransaction setPrimaryNavigationFragment(Fragment fragment);
+ @NonNull
+ public abstract FragmentTransaction setPrimaryNavigationFragment(@Nullable Fragment fragment);
/**
* @return <code>true</code> if this transaction contains no operations,
@@ -212,6 +225,7 @@
* @param exit An animation or animator resource ID used for the exit animation on the
* view of the fragment being removed or detached.
*/
+ @NonNull
public abstract FragmentTransaction setCustomAnimations(@AnimatorRes @AnimRes int enter,
@AnimatorRes @AnimRes int exit);
@@ -232,6 +246,7 @@
* view of the fragment being removed or detached caused by
* {@link FragmentManager#popBackStack()} or similar methods.
*/
+ @NonNull
public abstract FragmentTransaction setCustomAnimations(@AnimatorRes @AnimRes int enter,
@AnimatorRes @AnimRes int exit, @AnimatorRes @AnimRes int popEnter,
@AnimatorRes @AnimRes int popExit);
@@ -248,19 +263,23 @@
* @see Fragment#setSharedElementReturnTransition(Object)
* @see Fragment#setSharedElementEnterTransition(Object)
*/
- public abstract FragmentTransaction addSharedElement(View sharedElement, String name);
+ @NonNull
+ public abstract FragmentTransaction addSharedElement(@NonNull View sharedElement,
+ @NonNull String name);
/**
* Select a standard transition animation for this transaction. May be
* one of {@link #TRANSIT_NONE}, {@link #TRANSIT_FRAGMENT_OPEN},
* {@link #TRANSIT_FRAGMENT_CLOSE}, or {@link #TRANSIT_FRAGMENT_FADE}.
*/
+ @NonNull
public abstract FragmentTransaction setTransition(@Transit int transit);
/**
* Set a custom style resource that will be used for resolving transit
* animations.
*/
+ @NonNull
public abstract FragmentTransaction setTransitionStyle(@StyleRes int styleRes);
/**
@@ -270,6 +289,7 @@
*
* @param name An optional name for this back stack state, or null.
*/
+ @NonNull
public abstract FragmentTransaction addToBackStack(@Nullable String name);
/**
@@ -286,6 +306,7 @@
* addToBackStack will throw {@link IllegalStateException}. If addToBackStack
* has already been called, this method will throw IllegalStateException.
*/
+ @NonNull
public abstract FragmentTransaction disallowAddToBackStack();
/**
@@ -294,6 +315,7 @@
*
* @param res A string resource containing the title.
*/
+ @NonNull
public abstract FragmentTransaction setBreadCrumbTitle(@StringRes int res);
/**
@@ -301,7 +323,8 @@
* method is <em>not</em> recommended, as the string can not be changed
* later if the locale changes.
*/
- public abstract FragmentTransaction setBreadCrumbTitle(CharSequence text);
+ @NonNull
+ public abstract FragmentTransaction setBreadCrumbTitle(@Nullable CharSequence text);
/**
* Set the short title to show as a bread crumb when this transaction
@@ -309,6 +332,7 @@
*
* @param res A string resource containing the title.
*/
+ @NonNull
public abstract FragmentTransaction setBreadCrumbShortTitle(@StringRes int res);
/**
@@ -316,7 +340,8 @@
* method is <em>not</em> recommended, as the string can not be changed
* later if the locale changes.
*/
- public abstract FragmentTransaction setBreadCrumbShortTitle(CharSequence text);
+ @NonNull
+ public abstract FragmentTransaction setBreadCrumbShortTitle(@Nullable CharSequence text);
/**
* Sets whether or not to allow optimizing operations within and across
@@ -346,6 +371,7 @@
* or {@code false} to disable optimizing out redundant
* operations on this transaction.
*/
+ @NonNull
public abstract FragmentTransaction setReorderingAllowed(boolean reorderingAllowed);
/**
@@ -375,7 +401,8 @@
* @return this FragmentTransaction
* @throws IllegalStateException if {@link #addToBackStack(String)} has been called
*/
- public abstract FragmentTransaction runOnCommit(Runnable runnable);
+ @NonNull
+ public abstract FragmentTransaction runOnCommit(@NonNull Runnable runnable);
/**
* Schedules a commit of this transaction. The commit does
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 70c7ad6..f05ac0d 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=../../../../tools/external/gradle/gradle-4.5-bin.zip
+distributionUrl=../../../../tools/external/gradle/gradle-4.6-bin.zip
diff --git a/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java b/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java
index 99f47d2..d5b339a 100644
--- a/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java
+++ b/heifwriter/src/androidTest/java/androidx/heifwriter/HeifWriterTest.java
@@ -18,12 +18,6 @@
import static android.support.test.InstrumentationRegistry.getContext;
-import static androidx.heifwriter.HeifWriter.INPUT_MODE_BITMAP;
-import static androidx.heifwriter.HeifWriter.INPUT_MODE_BUFFER;
-import static androidx.heifwriter.HeifWriter.INPUT_MODE_SURFACE;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.media.MediaExtractor;
@@ -34,13 +28,21 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+
+import static androidx.heifwriter.HeifWriter.INPUT_MODE_BITMAP;
+import static androidx.heifwriter.HeifWriter.INPUT_MODE_BUFFER;
+import static androidx.heifwriter.HeifWriter.INPUT_MODE_SURFACE;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.heifwriter.test.R;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -555,8 +557,12 @@
MediaFormat format = extractor.getTrackFormat(0);
int gridWidth = format.getInteger(MediaFormat.KEY_GRID_WIDTH);
int gridHeight = format.getInteger(MediaFormat.KEY_GRID_HEIGHT);
- assertEquals("Wrong grid width", 512, gridWidth);
- assertEquals("Wrong grid height", 512, gridHeight);
+ int gridRows = format.getInteger(MediaFormat.KEY_GRID_ROWS);
+ int gridCols = format.getInteger(MediaFormat.KEY_GRID_COLS);
+ assertTrue("Wrong grid width or cols",
+ ((width + gridWidth - 1) / gridWidth) == gridCols);
+ assertTrue("Wrong grid height or rows",
+ ((height + gridHeight - 1) / gridHeight) == gridRows);
extractor.release();
}
}
diff --git a/heifwriter/src/main/java/androidx/heifwriter/HeifEncoder.java b/heifwriter/src/main/java/androidx/heifwriter/HeifEncoder.java
index 85aa925..3020b96 100644
--- a/heifwriter/src/main/java/androidx/heifwriter/HeifEncoder.java
+++ b/heifwriter/src/main/java/androidx/heifwriter/HeifEncoder.java
@@ -17,14 +17,9 @@
package androidx.heifwriter;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
-import android.opengl.GLES20;
-import android.opengl.GLUtils;
-import android.os.Looper;
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import android.media.Image;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
@@ -32,13 +27,19 @@
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaFormat;
+import android.opengl.GLES20;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Looper;
import android.os.Process;
import android.util.Log;
import android.util.Range;
import android.view.Surface;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -179,25 +180,14 @@
throw new IllegalArgumentException("invalid encoder inputs");
}
- mEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_HEVC);
-
- mWidth = width;
- mHeight = height;
-
- if (useGrid) {
- mGridWidth = GRID_WIDTH;
- mGridHeight = GRID_HEIGHT;
- mGridRows = (height + GRID_HEIGHT - 1) / GRID_HEIGHT;
- mGridCols = (width + GRID_WIDTH - 1) / GRID_WIDTH;
- } else {
- mGridWidth = mWidth;
- mGridHeight = mHeight;
- mGridRows = 1;
- mGridCols = 1;
+ boolean useHeicEncoder = false;
+ try {
+ mEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC);
+ useHeicEncoder = true;
+ } catch (Exception e) {
+ mEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_HEVC);
}
- mNumTiles = mGridRows * mGridCols;
-
mInputMode = inputMode;
mCallback = cb;
@@ -218,13 +208,61 @@
CodecCapabilities.COLOR_FormatYUV420Flexible;
// TODO: determine how to set bitrate and framerate, or use constant quality
- MediaFormat codecFormat = MediaFormat.createVideoFormat(
- MediaFormat.MIMETYPE_VIDEO_HEVC, mGridWidth, mGridHeight);
+ mWidth = width;
+ mHeight = height;
+
+ int gridWidth, gridHeight, gridRows, gridCols;
+
+ useGrid = useGrid && (width > GRID_WIDTH || height > GRID_HEIGHT);
+
+ if (useGrid) {
+ gridWidth = GRID_WIDTH;
+ gridHeight = GRID_HEIGHT;
+ gridRows = (height + GRID_HEIGHT - 1) / GRID_HEIGHT;
+ gridCols = (width + GRID_WIDTH - 1) / GRID_WIDTH;
+ } else {
+ gridWidth = mWidth;
+ gridHeight = mHeight;
+ gridRows = 1;
+ gridCols = 1;
+ }
+
+ MediaFormat codecFormat;
+ if (useHeicEncoder) {
+ codecFormat = MediaFormat.createVideoFormat(
+ MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC, mWidth, mHeight);
+ } else {
+ codecFormat = MediaFormat.createVideoFormat(
+ MediaFormat.MIMETYPE_VIDEO_HEVC, gridWidth, gridHeight);
+ }
+
+ if (useGrid) {
+ codecFormat.setInteger(MediaFormat.KEY_GRID_WIDTH, gridWidth);
+ codecFormat.setInteger(MediaFormat.KEY_GRID_HEIGHT, gridHeight);
+ codecFormat.setInteger(MediaFormat.KEY_GRID_COLS, gridCols);
+ codecFormat.setInteger(MediaFormat.KEY_GRID_ROWS, gridRows);
+ }
+
+ if (useHeicEncoder) {
+ mGridWidth = width;
+ mGridHeight = height;
+ mGridRows = 1;
+ mGridCols = 1;
+ } else {
+ mGridWidth = gridWidth;
+ mGridHeight = gridHeight;
+ mGridRows = gridRows;
+ mGridCols = gridCols;
+ }
+ mNumTiles = mGridRows * mGridCols;
+
codecFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 0);
codecFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
MediaCodecInfo.CodecCapabilities caps =
- mEncoder.getCodecInfo().getCapabilitiesForType(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ mEncoder.getCodecInfo().getCapabilitiesForType(useHeicEncoder
+ ? MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC
+ : MediaFormat.MIMETYPE_VIDEO_HEVC);
MediaCodecInfo.EncoderCapabilities encoderCaps = caps.getEncoderCapabilities();
codecFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mNumTiles);
@@ -262,34 +300,36 @@
if (useSurfaceInternally) {
mEncoderSurface = mEncoder.createInputSurface();
- boolean useGLCopy = (mNumTiles > 1) || (inputMode == INPUT_MODE_BITMAP);
- mEOSTracker = new SurfaceEOSTracker(useGLCopy);
+ boolean copyTiles = (mNumTiles > 1);
+ mEOSTracker = new SurfaceEOSTracker(copyTiles);
- if (useGLCopy) {
- mEncoderEglSurface = new EglWindowSurface(mEncoderSurface);
- mEncoderEglSurface.makeCurrent();
+ if (inputMode == INPUT_MODE_SURFACE) {
+ if (copyTiles) {
+ mEncoderEglSurface = new EglWindowSurface(mEncoderSurface);
+ mEncoderEglSurface.makeCurrent();
- mRectBlt = new EglRectBlt(
- new Texture2dProgram((inputMode == INPUT_MODE_BITMAP) ?
- Texture2dProgram.TEXTURE_2D :
- Texture2dProgram.TEXTURE_EXT),
- mWidth, mHeight);
+ mRectBlt = new EglRectBlt(
+ new Texture2dProgram((inputMode == INPUT_MODE_BITMAP)
+ ? Texture2dProgram.TEXTURE_2D
+ : Texture2dProgram.TEXTURE_EXT),
+ mWidth, mHeight);
- mTextureId = mRectBlt.createTextureObject();
+ mTextureId = mRectBlt.createTextureObject();
- if (inputMode == INPUT_MODE_SURFACE) {
- // use single buffer mode to block on input
- mInputTexture = new SurfaceTexture(mTextureId, true);
- mInputTexture.setOnFrameAvailableListener(this);
- mInputTexture.setDefaultBufferSize(mWidth, mHeight);
- mInputSurface = new Surface(mInputTexture);
+ if (inputMode == INPUT_MODE_SURFACE) {
+ // use single buffer mode to block on input
+ mInputTexture = new SurfaceTexture(mTextureId, true);
+ mInputTexture.setOnFrameAvailableListener(this);
+ mInputTexture.setDefaultBufferSize(mWidth, mHeight);
+ mInputSurface = new Surface(mInputTexture);
+ }
+
+ // make uncurrent since onFrameAvailable could be called on arbituray thread.
+ // making the context current on a different thread will cause error.
+ mEncoderEglSurface.makeUnCurrent();
+ } else {
+ mInputSurface = mEncoderSurface;
}
-
- // make uncurrent since the onFrameAvailable could be called on arbituray thread.
- // making the context current on a different thread will cause error.
- mEncoderEglSurface.makeUnCurrent();
- } else {
- mInputSurface = mEncoderSurface;
}
} else {
for (int i = 0; i < INPUT_BUFFER_POOL_SIZE; i++) {
@@ -321,7 +361,20 @@
computePresentationTime(mInputIndex + mNumTiles - 1));
if (takeFrame) {
- copyTilesGL(mTmpMatrix);
+ // Copies from surface texture to encoder inputs using GL.
+ GLES20.glViewport(0, 0, mGridWidth, mGridHeight);
+
+ for (int row = 0; row < mGridRows; row++) {
+ for (int col = 0; col < mGridCols; col++) {
+ int left = col * mGridWidth;
+ int top = row * mGridHeight;
+ mSrcRect.set(left, top, left + mGridWidth, top + mGridHeight);
+ mRectBlt.copyRect(mTextureId, mTmpMatrix, mSrcRect);
+ mEncoderEglSurface.setPresentationTime(
+ 1000 * computePresentationTime(mInputIndex++));
+ mEncoderEglSurface.swapBuffers();
+ }
+ }
}
surfaceTexture.releaseTexImage();
@@ -407,21 +460,16 @@
if (!takeFrame) return;
synchronized (this) {
- if (mEncoderEglSurface == null) {
- return;
+ for (int row = 0; row < mGridRows; row++) {
+ for (int col = 0; col < mGridCols; col++) {
+ int left = col * mGridWidth;
+ int top = row * mGridHeight;
+ mSrcRect.set(left, top, left + mGridWidth, top + mGridHeight);
+ Canvas canvas = mEncoderSurface.lockCanvas(null);
+ canvas.drawBitmap(bitmap, mSrcRect, mDstRect, null);
+ mEncoderSurface.unlockCanvasAndPost(canvas);
+ }
}
-
- mEncoderEglSurface.makeCurrent();
-
- // load the bitmap to texture
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId);
- GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
-
- copyTilesGL(Texture2dProgram.V_FLIP_MATRIX);
-
- // make uncurrent since the onFrameAvailable could be called on arbituray thread.
- // making the context current on a different thread will cause error.
- mEncoderEglSurface.makeUnCurrent();
}
}
@@ -594,28 +642,6 @@
}
/**
- * Copies from source frame to encoder inputs using GL. The source could be either
- * client's input surface, or the input bitmap loaded to texture.
- *
- * @param texMatrix The texture matrix to use. See the shader program in
- * {@link Texture2dProgram} as well as {@link SurfaceTexture} for more details.
- */
- private void copyTilesGL(float[] texMatrix) {
- GLES20.glViewport(0, 0, mGridWidth, mGridHeight);
-
- for (int row = 0; row < mGridRows; row++) {
- for (int col = 0; col < mGridCols; col++) {
- int left = col * mGridWidth;
- int top = row * mGridHeight;
- mSrcRect.set(left, top, left + mGridWidth, top + mGridHeight);
- mRectBlt.copyRect(mTextureId, texMatrix, mSrcRect);
- mEncoderEglSurface.setPresentationTime(1000 * computePresentationTime(mInputIndex++));
- mEncoderEglSurface.swapBuffers();
- }
- }
- }
-
- /**
* Routine to release all resources. Must be run on the same looper that
* handles the MediaCodec callbacks.
*/
@@ -677,7 +703,7 @@
private class SurfaceEOSTracker {
private static final boolean DEBUG_EOS = false;
- final boolean mUseGLCopy;
+ final boolean mCopyTiles;
long mInputEOSTimeNs = -1;
long mLastInputTimeNs = -1;
long mEncoderEOSTimeUs = -1;
@@ -685,14 +711,14 @@
long mLastOutputTimeUs = -1;
boolean mSignaled;
- SurfaceEOSTracker(boolean useGLCopy) {
- mUseGLCopy = useGLCopy;
+ SurfaceEOSTracker(boolean copyTiles) {
+ mCopyTiles = copyTiles;
}
synchronized void updateInputEOSTime(long timestampNs) {
if (DEBUG_EOS) Log.d(TAG, "updateInputEOSTime: " + timestampNs);
- if (mUseGLCopy) {
+ if (mCopyTiles) {
if (mInputEOSTimeNs < 0) {
mInputEOSTimeNs = timestampNs;
}
@@ -773,15 +799,18 @@
if (DEBUG) Log.d(TAG, "onOutputFormatChanged: " + format);
- format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC);
- format.setInteger(MediaFormat.KEY_WIDTH, mWidth);
- format.setInteger(MediaFormat.KEY_HEIGHT, mHeight);
+ if (!MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC.equals(
+ format.getString(MediaFormat.KEY_MIME))) {
+ format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC);
+ format.setInteger(MediaFormat.KEY_WIDTH, mWidth);
+ format.setInteger(MediaFormat.KEY_HEIGHT, mHeight);
- if (mNumTiles > 1) {
- format.setInteger(MediaFormat.KEY_GRID_WIDTH, mGridWidth);
- format.setInteger(MediaFormat.KEY_GRID_HEIGHT, mGridHeight);
- format.setInteger(MediaFormat.KEY_GRID_ROWS, mGridRows);
- format.setInteger(MediaFormat.KEY_GRID_COLS, mGridCols);
+ if (mNumTiles > 1) {
+ format.setInteger(MediaFormat.KEY_GRID_WIDTH, mGridWidth);
+ format.setInteger(MediaFormat.KEY_GRID_HEIGHT, mGridHeight);
+ format.setInteger(MediaFormat.KEY_GRID_ROWS, mGridRows);
+ format.setInteger(MediaFormat.KEY_GRID_COLS, mGridCols);
+ }
}
mCallback.onOutputFormatChanged(HeifEncoder.this, format);
@@ -800,8 +829,12 @@
public void onOutputBufferAvailable(MediaCodec codec, int index, BufferInfo info) {
if (codec != mEncoder || mOutputEOS) return;
- if (DEBUG) Log.d(TAG, "onInputBufferAvailable: " + index + ", time "
- + info.presentationTimeUs + ", size " + info.size + ", flags " + info.flags);
+ if (DEBUG) {
+ Log.d(TAG, "onOutputBufferAvailable: " + index
+ + ", time " + info.presentationTimeUs
+ + ", size " + info.size
+ + ", flags " + info.flags);
+ }
if ((info.size > 0) && ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0)) {
ByteBuffer outputBuffer = codec.getOutputBuffer(index);
diff --git a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/PackageMap.kt b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/PackageMap.kt
index 448c1b8..23888d3 100644
--- a/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/PackageMap.kt
+++ b/jetifier/jetifier/core/src/main/kotlin/android/support/tools/jetifier/core/transform/PackageMap.kt
@@ -244,6 +244,66 @@
PackageRule(
from = "androidx/slice/builders",
to = "androidx/slice/builders"
+ ),
+ PackageRule(
+ from = "android/arch/paging/runtime",
+ to = "androidx/paging/runtime"
+ ),
+ PackageRule(
+ from = "android/arch/core/testing",
+ to = "androidx/arch/core/testing"
+ ),
+ PackageRule(
+ from = "android/arch/core",
+ to = "androidx/arch/core"
+ ),
+ PackageRule(
+ from = "android/arch/persistence/db/framework",
+ to = "androidx/sqlite/db/framework"
+ ),
+ PackageRule(
+ from = "android/arch/persistence/db",
+ to = "androidx/sqlite/db"
+ ),
+ PackageRule(
+ from = "android/arch/persistence/room/rxjava2",
+ to = "androidx/room/rxjava2"
+ ),
+ PackageRule(
+ from = "android/arch/persistence/room/guava",
+ to = "androidx/room/guava"
+ ),
+ PackageRule(
+ from = "android/arch/persistence/room/testing",
+ to = "androidx/room/testing"
+ ),
+ PackageRule(
+ from = "android/arch/persistence/room",
+ to = "androidx/room"
+ ),
+ PackageRule(
+ from = "android/arch/lifecycle/extensions",
+ to = "androidx/lifecycle/extensions"
+ ),
+ PackageRule(
+ from = "android/arch/lifecycle/livedata/core",
+ to = "androidx/lifecycle/livedata/core"
+ ),
+ PackageRule(
+ from = "android/arch/lifecycle",
+ to = "androidx/lifecycle"
+ ),
+ PackageRule(
+ from = "android/arch/lifecycle/viewmodel",
+ to = "androidx/lifecycle/viewmodel"
+ ),
+ PackageRule(
+ from = "android/arch/lifecycle/livedata",
+ to = "androidx/lifecycle/livedata"
+ ),
+ PackageRule(
+ from = "android/arch/lifecycle/reactivestreams",
+ to = "androidx/lifecycle/reactivestreams"
)
)
diff --git a/jetifier/jetifier/core/src/main/resources/default.config b/jetifier/jetifier/core/src/main/resources/default.config
index 748aa8f..4dc5fda 100644
--- a/jetifier/jetifier/core/src/main/resources/default.config
+++ b/jetifier/jetifier/core/src/main/resources/default.config
@@ -14,1094 +14,1122 @@
{
# Skip packages that don't match the following regex
- restrictToPackagePrefixes: [
+ "restrictToPackagePrefixes": [
"android/support/",
- "androix/temp",
- # "android/arch/", - skip arch for now
+ "android/arch/",
+ "android/databinding/"
],
- rules: [
+ "rules": [
# Ignore
{
- from: "(.*)BuildConfig",
- to: "ignoreInPreprocessorOnly"
+ "from": "(.*)BuildConfig",
+ "to": "ignoreInPreprocessorOnly"
},
{
- from: "(.*)/package-info",
- to: "ignoreInPreprocessorOnly"
+ "from": "(.*)/package-info",
+ "to": "ignoreInPreprocessorOnly"
},
{
- from: "android/support/design/internal/(.*)",
- to: "ignore"
+ "from": "android/support/design/internal/(.*)",
+ "to": "ignore"
},
{
- from: "android/support/test/(.*)",
- to: "ignore"
+ "from": "android/support/test/(.*)",
+ "to": "ignore"
},
{
- from: "android/support/exifinterface/test/R(.*)",
- to: "ignore"
+ "from": "android/support/exifinterface/test/R(.*)",
+ "to": "ignore"
},
#Resources
{
- from: "android/support/compat/R(.*)",
- to: "androidx/core/R{0}"
+ "from": "android/support/compat/R(.*)",
+ "to": "androidx/core/R{0}"
},
{
- from: "android/support/mediacompat/R(.*)",
- to: "androidx/media/R{0}"
+ "from": "android/support/mediacompat/R(.*)",
+ "to": "androidx/media/R{0}"
},
{
- from: "android/support/v7/cardview/R(.*)",
- to: "androidx/cardview/R{0}"
+ "from": "android/support/v7/cardview/R(.*)",
+ "to": "androidx/cardview/R{0}"
},
{
- from: "android/support/percent/R(.*)",
- to: "androidx/percentlayout/R{0}"
+ "from": "android/support/percent/R(.*)",
+ "to": "androidx/percentlayout/R{0}"
},
{
- from: "android/support/coordinatorlayout/R(.*)",
- to: "androidx/coordinatorlayout/R{0}"
+ "from": "android/support/coordinatorlayout/R(.*)",
+ "to": "androidx/coordinatorlayout/R{0}"
},
{
- from: "android/support/text/emoji/R(.*)",
- to: "androidx/emoji/R{0}"
+ "from": "android/support/text/emoji/R(.*)",
+ "to": "androidx/emoji/R{0}"
},
{
- from: "android/support/v7/recyclerview/R(.*)",
- to: "androidx/recyclerview/R{0}"
+ "from": "android/support/v7/recyclerview/R(.*)",
+ "to": "androidx/recyclerview/R{0}"
},
{
- from: "android/support/v7/gridlayout/R(.*)",
- to: "androidx/gridlayout/R{0}"
+ "from": "android/support/v7/gridlayout/R(.*)",
+ "to": "androidx/gridlayout/R{0}"
},
{
- from: "android/support/v7/appcompat/R(.*)",
- to: "androidx/appcompat/R{0}"
+ "from": "android/support/v7/appcompat/R(.*)",
+ "to": "androidx/appcompat/R{0}"
},
{
- from: "android/support/customtabs/R(.*)",
- to: "androidx/browser/R{0}"
+ "from": "android/support/customtabs/R(.*)",
+ "to": "androidx/browser/R{0}"
},
{
- from: "android/support/v7/mediarouter/R(.*)",
- to: "androidx/mediarouter/R{0}"
+ "from": "android/support/v7/mediarouter/R(.*)",
+ "to": "androidx/mediarouter/R{0}"
},
# Legacy
{
- from: "android/support/v4/app/ActionBarDrawerToggle(.*)",
- to: "androidx/legacy/app/ActionBarDrawerToggle{0}"
+ "from": "android/support/v4/app/ActionBarDrawerToggle(.*)",
+ "to": "androidx/legacy/app/ActionBarDrawerToggle{0}"
},
{
- from: "android/support/v4/widget/Space(.*)",
- to: "androidx/legacy/widget/Space{0}"
+ "from": "android/support/v4/widget/Space(.*)",
+ "to": "androidx/legacy/widget/Space{0}"
},
{
- from: "android/support/v4/content/WakefulBroadcastReceiver(.*)",
- to: "androidx/legacy/content/WakefulBroadcastReceiver{0}"
+ "from": "android/support/v4/content/WakefulBroadcastReceiver(.*)",
+ "to": "androidx/legacy/content/WakefulBroadcastReceiver{0}"
},
{
- from: "android/support/v13/view/ViewCompat(.*)",
- to: "androidx/legacy/view/ViewCompat{0}"
+ "from": "android/support/v13/view/ViewCompat(.*)",
+ "to": "androidx/legacy/view/ViewCompat{0}"
},
{
- from: "android/support/v13/app/ActivityCompat(.*)",
- to: "androidx/legacy/app/ActivityCompat{0}"
+ "from": "android/support/v13/app/ActivityCompat(.*)",
+ "to": "androidx/legacy/app/ActivityCompat{0}"
},
{
- from: "android/support/v13/app/FragmentCompat(.*)",
- to: "androidx/legacy/app/FragmentCompat{0}"
+ "from": "android/support/v13/app/FragmentCompat(.*)",
+ "to": "androidx/legacy/app/FragmentCompat{0}"
},
{
- from: "android/support/v13/app/FragmentPagerAdapter(.*)",
- to: "androidx/legacy/app/FragmentPagerAdapter{0}"
+ "from": "android/support/v13/app/FragmentPagerAdapter(.*)",
+ "to": "androidx/legacy/app/FragmentPagerAdapter{0}"
},
{
- from: "android/support/v13/app/FragmentStatePagerAdapter(.*)",
- to: "androidx/legacy/app/FragmentStatePagerAdapter{0}"
+ "from": "android/support/v13/app/FragmentStatePagerAdapter(.*)",
+ "to": "androidx/legacy/app/FragmentStatePagerAdapter{0}"
},
{
- from: "android/support/v13/app/FragmentTabHost(.*)",
- to: "androidx/legacy/app/FragmentTabHost{0}"
+ "from": "android/support/v13/app/FragmentTabHost(.*)",
+ "to": "androidx/legacy/app/FragmentTabHost{0}"
},
# Re-map Recycler view
{
- from: "android/support/v7/widget/AdapterHelper(.*)",
- to: "androidx/recyclerview/widget/AdapterHelper{0}"
+ "from": "android/support/v7/widget/AdapterHelper(.*)",
+ "to": "androidx/recyclerview/widget/AdapterHelper{0}"
},
{
- from: "android/support/v7/widget/ChildHelper(.*)",
- to: "androidx/recyclerview/widget/ChildHelper{0}"
+ "from": "android/support/v7/widget/ChildHelper(.*)",
+ "to": "androidx/recyclerview/widget/ChildHelper{0}"
},
{
- from: "android/support/v7/widget/DefaultItemAnimator(.*)",
- to: "androidx/recyclerview/widget/DefaultItemAnimator{0}"
+ "from": "android/support/v7/widget/DefaultItemAnimator(.*)",
+ "to": "androidx/recyclerview/widget/DefaultItemAnimator{0}"
},
{
- from: "android/support/v7/widget/DividerItemDecoration(.*)",
- to: "androidx/recyclerview/widget/DividerItemDecoration{0}"
+ "from": "android/support/v7/widget/DividerItemDecoration(.*)",
+ "to": "androidx/recyclerview/widget/DividerItemDecoration{0}"
},
{
- from: "android/support/v7/widget/FastScroller(.*)",
- to: "androidx/recyclerview/widget/FastScroller{0}"
+ "from": "android/support/v7/widget/FastScroller(.*)",
+ "to": "androidx/recyclerview/widget/FastScroller{0}"
},
{
- from: "android/support/v7/widget/GapWorker(.*)",
- to: "androidx/recyclerview/widget/GapWorker{0}"
+ "from": "android/support/v7/widget/GapWorker(.*)",
+ "to": "androidx/recyclerview/widget/GapWorker{0}"
},
{
- from: "android/support/v7/widget/GridLayoutManager(.*)",
- to: "androidx/recyclerview/widget/GridLayoutManager{0}"
+ "from": "android/support/v7/widget/GridLayoutManager(.*)",
+ "to": "androidx/recyclerview/widget/GridLayoutManager{0}"
},
{
- from: "android/support/v7/widget/LayoutState(.*)",
- to: "androidx/recyclerview/widget/LayoutState{0}"
+ "from": "android/support/v7/widget/LayoutState(.*)",
+ "to": "androidx/recyclerview/widget/LayoutState{0}"
},
{
- from: "android/support/v7/widget/LinearLayoutManager(.*)",
- to: "androidx/recyclerview/widget/LinearLayoutManager{0}"
+ "from": "android/support/v7/widget/LinearLayoutManager(.*)",
+ "to": "androidx/recyclerview/widget/LinearLayoutManager{0}"
},
{
- from: "android/support/v7/widget/LinearSmoothScroller(.*)",
- to: "androidx/recyclerview/widget/LinearSmoothScroller{0}"
+ "from": "android/support/v7/widget/LinearSmoothScroller(.*)",
+ "to": "androidx/recyclerview/widget/LinearSmoothScroller{0}"
},
{
- from: "android/support/v7/widget/LinearSnapHelper(.*)",
- to: "androidx/recyclerview/widget/LinearSnapHelper{0}"
+ "from": "android/support/v7/widget/LinearSnapHelper(.*)",
+ "to": "androidx/recyclerview/widget/LinearSnapHelper{0}"
},
{
- from: "android/support/v7/widget/OpReorderer(.*)",
- to: "androidx/recyclerview/widget/OpReorderer{0}"
+ "from": "android/support/v7/widget/OpReorderer(.*)",
+ "to": "androidx/recyclerview/widget/OpReorderer{0}"
},
{
- from: "android/support/v7/widget/OrientationHelper(.*)",
- to: "androidx/recyclerview/widget/OrientationHelper{0}"
+ "from": "android/support/v7/widget/OrientationHelper(.*)",
+ "to": "androidx/recyclerview/widget/OrientationHelper{0}"
},
{
- from: "android/support/v7/widget/PagerSnapHelper(.*)",
- to: "androidx/recyclerview/widget/PagerSnapHelper{0}"
+ "from": "android/support/v7/widget/PagerSnapHelper(.*)",
+ "to": "androidx/recyclerview/widget/PagerSnapHelper{0}"
},
{
- from: "android/support/v7/widget/PositionMap(.*)",
- to: "androidx/recyclerview/widget/PositionMap{0}"
+ "from": "android/support/v7/widget/PositionMap(.*)",
+ "to": "androidx/recyclerview/widget/PositionMap{0}"
},
{
- from: "android/support/v7/widget/RecyclerViewAccessibilityDelegate(.*)",
- to: "androidx/recyclerview/widget/RecyclerViewAccessibilityDelegate{0}"
+ "from": "android/support/v7/widget/RecyclerViewAccessibilityDelegate(.*)",
+ "to": "androidx/recyclerview/widget/RecyclerViewAccessibilityDelegate{0}"
},
{
- from: "android/support/v7/widget/RecyclerView(.*)",
- to: "androidx/recyclerview/widget/RecyclerView{0}"
+ "from": "android/support/v7/widget/RecyclerView(.*)",
+ "to": "androidx/recyclerview/widget/RecyclerView{0}"
},
{
- from: "android/support/v7/widget/ScrollbarHelper(.*)",
- to: "androidx/recyclerview/widget/ScrollbarHelper{0}"
+ "from": "android/support/v7/widget/ScrollbarHelper(.*)",
+ "to": "androidx/recyclerview/widget/ScrollbarHelper{0}"
},
{
- from: "android/support/v7/widget/SimpleItemAnimator(.*)",
- to: "androidx/recyclerview/widget/SimpleItemAnimator{0}"
+ "from": "android/support/v7/widget/SimpleItemAnimator(.*)",
+ "to": "androidx/recyclerview/widget/SimpleItemAnimator{0}"
},
{
- from: "android/support/v7/widget/SnapHelper(.*)",
- to: "androidx/recyclerview/widget/SnapHelper{0}"
+ "from": "android/support/v7/widget/SnapHelper(.*)",
+ "to": "androidx/recyclerview/widget/SnapHelper{0}"
},
{
- from: "android/support/v7/widget/StaggeredGridLayoutManager(.*)",
- to: "androidx/recyclerview/widget/StaggeredGridLayoutManager{0}"
+ "from": "android/support/v7/widget/StaggeredGridLayoutManager(.*)",
+ "to": "androidx/recyclerview/widget/StaggeredGridLayoutManager{0}"
},
{
- from: "android/support/v7/widget/ViewBoundsCheck(.*)",
- to: "androidx/recyclerview/widget/ViewBoundsCheck{0}"
+ "from": "android/support/v7/widget/ViewBoundsCheck(.*)",
+ "to": "androidx/recyclerview/widget/ViewBoundsCheck{0}"
},
{
- from: "android/support/v7/widget/ViewInfoStore(.*)",
- to: "androidx/recyclerview/widget/ViewInfoStore{0}"
+ "from": "android/support/v7/widget/ViewInfoStore(.*)",
+ "to": "androidx/recyclerview/widget/ViewInfoStore{0}"
},
{
- from: "android/support/v7/recyclerview/extensions/(.*)",
- to: "androidx/recyclerview/widget/{0}"
+ "from": "android/support/v7/recyclerview/extensions/(.*)",
+ "to": "androidx/recyclerview/widget/{0}"
},
{
- from: "android/support/v7/util/(.*)",
- to: "androidx/recyclerview/widget/{0}"
+ "from": "android/support/v7/util/(.*)",
+ "to": "androidx/recyclerview/widget/{0}"
},
{
- from: "android/support/v7/widget/helper/(.*)",
- to: "androidx/recyclerview/widget/{0}"
+ "from": "android/support/v7/widget/helper/(.*)",
+ "to": "androidx/recyclerview/widget/{0}"
},
{
- from: "android/support/v7/widget/util/(.*)",
- to: "androidx/recyclerview/widget/{0}"
+ "from": "android/support/v7/widget/util/(.*)",
+ "to": "androidx/recyclerview/widget/{0}"
},
# Re-map
{
- from: "android/support/wear/(.*)",
- to: "androidx/wear/{0}"
+ "from": "android/support/wear/(.*)",
+ "to": "androidx/wear/{0}"
},
{
- from: "android/support/v7/preference/(.*)",
- to: "androidx/preference/{0}"
+ "from": "android/support/v7/preference/(.*)",
+ "to": "androidx/preference/{0}"
},
{
- from: "android/support/v7/internal/widget/PreferenceImageView(.*)",
- to: "androidx/preference/internal/PreferenceImageView{0}"
+ "from": "android/support/v7/internal/widget/PreferenceImageView(.*)",
+ "to": "androidx/preference/internal/PreferenceImageView{0}"
},
{
- from: "android/support/v14/preference/(.*)",
- to: "androidx/preference/{0}"
+ "from": "android/support/v14/preference/(.*)",
+ "to": "androidx/preference/{0}"
},
{
- from: "android/support/v7/graphics/ColorCutQuantizer(.*)",
- to: "androidx/palette/graphics/ColorCutQuantizer{0}"
+ "from": "android/support/v7/graphics/ColorCutQuantizer(.*)",
+ "to": "androidx/palette/graphics/ColorCutQuantizer{0}"
},
{
- from: "android/support/v7/graphics/Palette(.*)",
- to: "androidx/palette/graphics/Palette{0}"
+ "from": "android/support/v7/graphics/Palette(.*)",
+ "to": "androidx/palette/graphics/Palette{0}"
},
{
- from: "android/support/v7/graphics/Target(.*)",
- to: "androidx/palette/graphics/Target{0}"
+ "from": "android/support/v7/graphics/Target(.*)",
+ "to": "androidx/palette/graphics/Target{0}"
},
{
- from: "android/support/v7/app/MediaRoute(.*)",
- to: "androidx/mediarouter/app/MediaRoute{0}"
+ "from": "android/support/v7/app/MediaRoute(.*)",
+ "to": "androidx/mediarouter/app/MediaRoute{0}"
},
{
- from: "android/support/v7/app/OverlayListView(.*)",
- to: "androidx/mediarouter/app/OverlayListView{0}"
+ "from": "android/support/v7/app/OverlayListView(.*)",
+ "to": "androidx/mediarouter/app/OverlayListView{0}"
},
{
- from: "android/support/v7/media/(.*)",
- to: "androidx/mediarouter/media/{0}"
+ "from": "android/support/v7/media/(.*)",
+ "to": "androidx/mediarouter/media/{0}"
},
{
- from: "android/support/v7/widget/CardView(.*)",
- to: "androidx/cardview/widget/CardView{0}"
+ "from": "android/support/v7/widget/CardView(.*)",
+ "to": "androidx/cardview/widget/CardView{0}"
},
{
- from: "android/support/v7/widget/RoundRectDrawable(.*)",
- to: "androidx/cardview/widget/RoundRectDrawable{0}"
+ "from": "android/support/v7/widget/RoundRectDrawable(.*)",
+ "to": "androidx/cardview/widget/RoundRectDrawable{0}"
},
{
- from: "android/support/v7/widget/RoundRectDrawableWithShadow(.*)",
- to: "androidx/cardview/widget/RoundRectDrawableWithShadow{0}"
+ "from": "android/support/v7/widget/RoundRectDrawableWithShadow(.*)",
+ "to": "androidx/cardview/widget/RoundRectDrawableWithShadow{0}"
},
{
- from: "android/support/v7/widget/GridLayout(.*)",
- to: "androidx/gridlayout/widget/GridLayout{0}"
+ "from": "android/support/v7/widget/GridLayout(.*)",
+ "to": "androidx/gridlayout/widget/GridLayout{0}"
},
{
- from: "android/support/v7/(.*)",
- to: "androidx/appcompat/{0}"
+ "from": "android/support/v7/(.*)",
+ "to": "androidx/appcompat/{0}"
},
{
- from: "android/support/graphics/drawable/(.*)",
- to: "androidx/vectordrawable/graphics/drawable/{0}"
+ "from": "android/support/graphics/drawable/(.*)",
+ "to": "androidx/vectordrawable/graphics/drawable/{0}"
},
{
- from: "android/support/customtabs/ICustomTabsCallback(.*)",
- to: "android/support/customtabs/ICustomTabsCallback/{0}"
+ "from": "android/support/customtabs/ICustomTabsCallback(.*)",
+ "to": "android/support/customtabs/ICustomTabsCallback/{0}"
},
{
- from: "android/support/customtabs/ICustomTabsService(.*)",
- to: "android/support/customtabs/ICustomTabsService/{0}"
+ "from": "android/support/customtabs/ICustomTabsService(.*)",
+ "to": "android/support/customtabs/ICustomTabsService/{0}"
},
{
- from: "android/support/customtabs/IPostMessageService(.*)",
- to: "android/support/customtabs/IPostMessageService/{0}"
+ "from": "android/support/customtabs/IPostMessageService(.*)",
+ "to": "android/support/customtabs/IPostMessageService/{0}"
},
{
- from: "android/support/customtabs/(.*)",
- to: "androidx/browser/customtabs/{0}"
+ "from": "android/support/customtabs/(.*)",
+ "to": "androidx/browser/customtabs/{0}"
},
{
- from: "android/support/media/tv/(.*)",
- to: "androidx/tvprovider/media/tv/{0}"
+ "from": "android/support/media/tv/(.*)",
+ "to": "androidx/tvprovider/media/tv/{0}"
},
{
- from: "android/support/media/ExifInterface(.*)",
- to: "androidx/exifinterface/media/ExifInterface{0}"
+ "from": "android/support/media/ExifInterface(.*)",
+ "to": "androidx/exifinterface/media/ExifInterface{0}"
},
{
- from: "android/support/v17/internal/widget/OutlineOnlyWithChildrenFrameLayout(.*)",
- to: "androidx/leanback/preference/internal/OutlineOnlyWithChildrenFrameLayout{0}"
+ "from": "android/support/v17/internal/widget/OutlineOnlyWithChildrenFrameLayout(.*)",
+ "to": "androidx/leanback/preference/internal/OutlineOnlyWithChildrenFrameLayout{0}"
},
{
- from: "android/support/v17/preference/(.*)",
- to: "androidx/leanback/preference/{0}"
+ "from": "android/support/v17/preference/(.*)",
+ "to": "androidx/leanback/preference/{0}"
},
{
- from: "android/support/v17/leanback/(.*)",
- to: "androidx/leanback/{0}"
+ "from": "android/support/v17/leanback/(.*)",
+ "to": "androidx/leanback/{0}"
},
{
- from: "android/support/percent/(.*)",
- to: "androidx/percentlayout/widget/{0}"
+ "from": "android/support/percent/(.*)",
+ "to": "androidx/percentlayout/widget/{0}"
},
{
- from: "android/support/app/recommendation/(.*)",
- to: "androidx/recommendation/app/{0}"
+ "from": "android/support/app/recommendation/(.*)",
+ "to": "androidx/recommendation/app/{0}"
},
{
- from: "android/support/annotation/(.*)",
- to: "androidx/annotation/{0}"
+ "from": "android/support/annotation/(.*)",
+ "to": "androidx/annotation/{0}"
},
{
- from: "android/support/transition/(.*)",
- to: "androidx/transition/{0}"
+ "from": "android/support/transition/(.*)",
+ "to": "androidx/transition/{0}"
},
{
- from: "android/support/text/emoji/bundled/BundledEmojiCompatConfig(.*)",
- to: "androidx/emoji/bundled/BundledEmojiCompatConfig{0}"
+ "from": "android/support/text/emoji/bundled/BundledEmojiCompatConfig(.*)",
+ "to": "androidx/emoji/bundled/BundledEmojiCompatConfig{0}"
},
{
- from: "android/support/text/emoji/widget/(.*)",
- to: "androidx/emoji/widget/{0}"
+ "from": "android/support/text/emoji/widget/(.*)",
+ "to": "androidx/emoji/widget/{0}"
},
{
- from: "android/support/text/emoji/(.*)",
- to: "androidx/emoji/text/{0}"
+ "from": "android/support/text/emoji/(.*)",
+ "to": "androidx/emoji/text/{0}"
},
{
- from: "android/support/content/(.*)",
- to: "androidx/contentpager/content/{0}"
+ "from": "android/support/content/(.*)",
+ "to": "androidx/contentpager/content/{0}"
},
{
- from: "android/support/v4/view/animation/PathInterpolatorApi14(.*)",
- to: "androidx/core/view/animation/PathInterpolatorApi14{0}"
+ "from": "android/support/v4/view/animation/PathInterpolatorApi14(.*)",
+ "to": "androidx/core/view/animation/PathInterpolatorApi14{0}"
},
{
- from: "android/support/v4/view/animation/PathInterpolatorCompat(.*)",
- to: "androidx/core/view/animation/PathInterpolatorCompat{0}"
+ "from": "android/support/v4/view/animation/PathInterpolatorCompat(.*)",
+ "to": "androidx/core/view/animation/PathInterpolatorCompat{0}"
},
{
- from: "android/support/animation/(.*)",
- to: "androidx/dynamicanimation/animation/{0}"
+ "from": "android/support/animation/(.*)",
+ "to": "androidx/dynamicanimation/animation/{0}"
},
{
- from: "android/support/v4/app/Fragment(.*)",
- to: "androidx/fragment/app/Fragment{0}"
+ "from": "android/support/v4/app/Fragment(.*)",
+ "to": "androidx/fragment/app/Fragment{0}"
},
{
- from: "android/support/v4/app/BaseFragment(.*)",
- to: "androidx/fragment/app/BaseFragment{0}"
+ "from": "android/support/v4/app/BaseFragment(.*)",
+ "to": "androidx/fragment/app/BaseFragment{0}"
},
{
- from: "android/support/v4/app/BackStack(.*)",
- to: "androidx/fragment/app/BackStack{0}"
+ "from": "android/support/v4/app/BackStack(.*)",
+ "to": "androidx/fragment/app/BackStack{0}"
},
{
- from: "android/support/v4/app/DialogFragment(.*)",
- to: "androidx/fragment/app/DialogFragment{0}"
+ "from": "android/support/v4/app/DialogFragment(.*)",
+ "to": "androidx/fragment/app/DialogFragment{0}"
},
{
- from: "android/support/v4/app/ListFragment(.*)",
- to: "androidx/fragment/app/ListFragment{0}"
+ "from": "android/support/v4/app/ListFragment(.*)",
+ "to": "androidx/fragment/app/ListFragment{0}"
},
{
- from: "android/support/v4/app/OneShotPreDrawListener(.*)",
- to: "androidx/fragment/app/OneShotPreDrawListener{0}"
+ "from": "android/support/v4/app/OneShotPreDrawListener(.*)",
+ "to": "androidx/fragment/app/OneShotPreDrawListener{0}"
},
{
- from: "android/support/v4/app/SuperNotCalledException(.*)",
- to: "androidx/fragment/app/SuperNotCalledException{0}"
+ "from": "android/support/v4/app/SuperNotCalledException(.*)",
+ "to": "androidx/fragment/app/SuperNotCalledException{0}"
},
# Media
{
- from: "android/support/v4/media/app/NotificationCompat(.*)",
- to: "androidx/media/app/NotificationCompat{0}"
+ "from": "android/support/v4/media/app/NotificationCompat(.*)",
+ "to": "androidx/media/app/NotificationCompat{0}"
},
{
- from: "android/support/v4/media/AudioAttributesCompat(.*)",
- to: "androidx/media/AudioAttributesCompat{0}"
+ "from": "android/support/v4/media/AudioAttributesCompat(.*)",
+ "to": "androidx/media/AudioAttributesCompat{0}"
},
{
- from: "android/support/v4/media/MediaBrowserCompatUtils(.*)",
- to: "androidx/media/MediaBrowserCompatUtils{0}"
+ "from": "android/support/v4/media/MediaBrowserCompatUtils(.*)",
+ "to": "androidx/media/MediaBrowserCompatUtils{0}"
},
{
- from: "android/support/v4/media/MediaBrowserProtocol(.*)",
- to: "androidx/media/MediaBrowserProtocol{0}"
+ "from": "android/support/v4/media/MediaBrowserProtocol(.*)",
+ "to": "androidx/media/MediaBrowserProtocol{0}"
},
{
- from: "android/support/v4/media/MediaBrowserServiceCompat(.*)",
- to: "androidx/media/MediaBrowserServiceCompat{0}"
+ "from": "android/support/v4/media/MediaBrowserServiceCompat(.*)",
+ "to": "androidx/media/MediaBrowserServiceCompat{0}"
},
{
- from: "android/support/v4/media/VolumeProviderCompat(.*)",
- to: "androidx/media/VolumeProviderCompat{0}"
+ "from": "android/support/v4/media/VolumeProviderCompat(.*)",
+ "to": "androidx/media/VolumeProviderCompat{0}"
},
{
- from: "android/support/v4/media/session/MediaButtonReceiver(.*)",
- to: "androidx/media/session/MediaButtonReceiver{0}"
+ "from": "android/support/v4/media/session/MediaButtonReceiver(.*)",
+ "to": "androidx/media/session/MediaButtonReceiver{0}"
},
{
- from: "android/support/v4/media/(.*)",
- to: "android/support/v4/media/{0}"
+ "from": "android/support/v4/media/(.*)",
+ "to": "android/support/v4/media/{0}"
},
# Rules involving libraries split
{
- from: "android/support/v4/widget/CursorAdapter(.*)",
- to: "androidx/cursoradapter/widget/CursorAdapter{0}"
+ "from": "android/support/v4/widget/CursorAdapter(.*)",
+ "to": "androidx/cursoradapter/widget/CursorAdapter{0}"
},
{
- from: "android/support/v4/widget/CursorFilter(.*)",
- to: "androidx/cursoradapter/widget/CursorFilter{0}"
+ "from": "android/support/v4/widget/CursorFilter(.*)",
+ "to": "androidx/cursoradapter/widget/CursorFilter{0}"
},
{
- from: "android/support/v4/widget/ResourceCursorAdapter(.*)",
- to: "androidx/cursoradapter/widget/ResourceCursorAdapter{0}"
+ "from": "android/support/v4/widget/ResourceCursorAdapter(.*)",
+ "to": "androidx/cursoradapter/widget/ResourceCursorAdapter{0}"
},
{
- from: "android/support/v4/widget/SimpleCursorAdapter(.*)",
- to: "androidx/cursoradapter/widget/SimpleCursorAdapter{0}"
+ "from": "android/support/v4/widget/SimpleCursorAdapter(.*)",
+ "to": "androidx/cursoradapter/widget/SimpleCursorAdapter{0}"
},
{
- from: "android/support/v4/app/LoaderManager(.*)",
- to: "androidx/loader/app/LoaderManager{0}"
+ "from": "android/support/v4/app/LoaderManager(.*)",
+ "to": "androidx/loader/app/LoaderManager{0}"
},
{
- from: "android/support/v4/content/Loader(.*)",
- to: "androidx/loader/content/Loader{0}"
+ "from": "android/support/v4/content/Loader(.*)",
+ "to": "androidx/loader/content/Loader{0}"
},
{
- from: "android/support/v4/content/CursorLoader(.*)",
- to: "androidx/loader/content/CursorLoader{0}"
+ "from": "android/support/v4/content/CursorLoader(.*)",
+ "to": "androidx/loader/content/CursorLoader{0}"
},
{
- from: "android/support/v4/content/AsyncTaskLoader(.*)",
- to: "androidx/loader/content/AsyncTaskLoader{0}"
+ "from": "android/support/v4/content/AsyncTaskLoader(.*)",
+ "to": "androidx/loader/content/AsyncTaskLoader{0}"
},
{
- from: "android/support/v4/content/ModernAsyncTask(.*)",
- to: "androidx/loader/content/ModernAsyncTask{0}"
+ "from": "android/support/v4/content/ModernAsyncTask(.*)",
+ "to": "androidx/loader/content/ModernAsyncTask{0}"
},
{
- from: "android/support/design/widget/CoordinatorLayout(.*)",
- to: "androidx/coordinatorlayout/widget/CoordinatorLayout{0}"
+ "from": "android/support/design/widget/CoordinatorLayout(.*)",
+ "to": "androidx/coordinatorlayout/widget/CoordinatorLayout{0}"
},
{
- from: "android/support/v4/widget/DirectedAcyclicGraph(.*)",
- to: "androidx/coordinatorlayout/widget/DirectedAcyclicGraph{0}"
+ "from": "android/support/v4/widget/DirectedAcyclicGraph(.*)",
+ "to": "androidx/coordinatorlayout/widget/DirectedAcyclicGraph{0}"
},
{
- from: "android/support/v4/widget/ViewGroupUtils(.*)",
- to: "androidx/coordinatorlayout/widget/ViewGroupUtils{0}"
+ "from": "android/support/v4/widget/ViewGroupUtils(.*)",
+ "to": "androidx/coordinatorlayout/widget/ViewGroupUtils{0}"
},
{
- from: "android/support/v4/view/ViewPager(.*)",
- to: "androidx/viewpager/widget/ViewPager{0}"
+ "from": "android/support/v4/view/ViewPager(.*)",
+ "to": "androidx/viewpager/widget/ViewPager{0}"
},
{
- from: "android/support/v4/view/PagerAdapter(.*)",
- to: "androidx/viewpager/widget/PagerAdapter{0}"
+ "from": "android/support/v4/view/PagerAdapter(.*)",
+ "to": "androidx/viewpager/widget/PagerAdapter{0}"
},
{
- from: "android/support/v4/view/PagerTabStrip(.*)",
- to: "androidx/viewpager/widget/PagerTabStrip{0}"
+ "from": "android/support/v4/view/PagerTabStrip(.*)",
+ "to": "androidx/viewpager/widget/PagerTabStrip{0}"
},
{
- from: "android/support/v4/view/PagerTitleStrip(.*)",
- to: "androidx/viewpager/widget/PagerTitleStrip{0}"
+ "from": "android/support/v4/view/PagerTitleStrip(.*)",
+ "to": "androidx/viewpager/widget/PagerTitleStrip{0}"
},
{
- from: "android/support/v4/view/AbsSavedState(.*)",
- to: "androidx/customview/view/AbsSavedState{0}"
+ "from": "android/support/v4/view/AbsSavedState(.*)",
+ "to": "androidx/customview/view/AbsSavedState{0}"
},
{
- from: "android/support/v4/widget/ExploreByTouchHelper(.*)",
- to: "androidx/customview/widget/ExploreByTouchHelper{0}"
+ "from": "android/support/v4/widget/ExploreByTouchHelper(.*)",
+ "to": "androidx/customview/widget/ExploreByTouchHelper{0}"
},
{
- from: "android/support/v4/widget/FocusStrategy(.*)",
- to: "androidx/customview/widget/FocusStrategy{0}"
+ "from": "android/support/v4/widget/FocusStrategy(.*)",
+ "to": "androidx/customview/widget/FocusStrategy{0}"
},
{
- from: "android/support/v4/widget/ViewDragHelper(.*)",
- to: "androidx/customview/widget/ViewDragHelper{0}"
+ "from": "android/support/v4/widget/ViewDragHelper(.*)",
+ "to": "androidx/customview/widget/ViewDragHelper{0}"
},
{
- from: "android/support/v4/view/animation/(.*)",
- to: "androidx/interpolator/view/animation/{0}"
+ "from": "android/support/v4/view/animation/(.*)",
+ "to": "androidx/interpolator/view/animation/{0}"
},
{
- from: "android/support/v4/widget/DrawerLayout(.*)",
- to: "androidx/drawerlayout/widget/DrawerLayout{0}"
+ "from": "android/support/v4/widget/DrawerLayout(.*)",
+ "to": "androidx/drawerlayout/widget/DrawerLayout{0}"
},
{
- from: "android/support/v4/widget/SlidingPaneLayout(.*)",
- to: "androidx/slidingpanelayout/widget/SlidingPaneLayout{0}"
+ "from": "android/support/v4/widget/SlidingPaneLayout(.*)",
+ "to": "androidx/slidingpanelayout/widget/SlidingPaneLayout{0}"
},
{
- from: "android/support/v4/view/AsyncLayoutInflater(.*)",
- to: "androidx/asynclayoutinflater/view/AsyncLayoutInflater{0}"
+ "from": "android/support/v4/view/AsyncLayoutInflater(.*)",
+ "to": "androidx/asynclayoutinflater/view/AsyncLayoutInflater{0}"
},
{
- from: "android/support/v4/widget/SwipeRefreshLayout(.*)",
- to: "androidx/swiperefreshlayout/widget/SwipeRefreshLayout{0}"
+ "from": "android/support/v4/widget/SwipeRefreshLayout(.*)",
+ "to": "androidx/swiperefreshlayout/widget/SwipeRefreshLayout{0}"
},
{
- from: "android/support/v4/widget/CircularProgressDrawable(.*)",
- to: "androidx/swiperefreshlayout/widget/CircularProgressDrawable{0}"
+ "from": "android/support/v4/widget/CircularProgressDrawable(.*)",
+ "to": "androidx/swiperefreshlayout/widget/CircularProgressDrawable{0}"
},
{
- from: "android/support/v4/widget/CircleImageView(.*)",
- to: "androidx/swiperefreshlayout/widget/CircleImageView{0}"
+ "from": "android/support/v4/widget/CircleImageView(.*)",
+ "to": "androidx/swiperefreshlayout/widget/CircleImageView{0}"
},
{
- from: "android/support/v4/util/ArrayMap(.*)",
- to: "androidx/collection/ArrayMap{0}"
+ "from": "android/support/v4/util/ArrayMap(.*)",
+ "to": "androidx/collection/ArrayMap{0}"
},
{
- from: "android/support/v4/util/ArraySet(.*)",
- to: "androidx/collection/ArraySet{0}"
+ "from": "android/support/v4/util/ArraySet(.*)",
+ "to": "androidx/collection/ArraySet{0}"
},
{
- from: "android/support/v4/util/CircularArray(.*)",
- to: "androidx/collection/CircularArray{0}"
+ "from": "android/support/v4/util/CircularArray(.*)",
+ "to": "androidx/collection/CircularArray{0}"
},
{
- from: "android/support/v4/util/CircularIntArray(.*)",
- to: "androidx/collection/CircularIntArray{0}"
+ "from": "android/support/v4/util/CircularIntArray(.*)",
+ "to": "androidx/collection/CircularIntArray{0}"
},
{
- from: "android/support/v4/util/ContainerHelpers(.*)",
- to: "androidx/collection/ContainerHelpers{0}"
+ "from": "android/support/v4/util/ContainerHelpers(.*)",
+ "to": "androidx/collection/ContainerHelpers{0}"
},
{
- from: "android/support/v4/util/LongSparseArray(.*)",
- to: "androidx/collection/LongSparseArray{0}"
+ "from": "android/support/v4/util/LongSparseArray(.*)",
+ "to": "androidx/collection/LongSparseArray{0}"
},
{
- from: "android/support/v4/util/LruCache(.*)",
- to: "androidx/collection/LruCache{0}"
+ "from": "android/support/v4/util/LruCache(.*)",
+ "to": "androidx/collection/LruCache{0}"
},
{
- from: "android/support/v4/util/MapCollections(.*)",
- to: "androidx/collection/MapCollections{0}"
+ "from": "android/support/v4/util/MapCollections(.*)",
+ "to": "androidx/collection/MapCollections{0}"
},
{
- from: "android/support/v4/util/SimpleArrayMap(.*)",
- to: "androidx/collection/SimpleArrayMap{0}"
+ "from": "android/support/v4/util/SimpleArrayMap(.*)",
+ "to": "androidx/collection/SimpleArrayMap{0}"
},
{
- from: "android/support/v4/util/SparseArrayCompat(.*)",
- to: "androidx/collection/SparseArrayCompat{0}"
+ "from": "android/support/v4/util/SparseArrayCompat(.*)",
+ "to": "androidx/collection/SparseArrayCompat{0}"
},
{
- from: "android/support/v4/provider/DocumentFile(.*)",
- to: "androidx/documentfile/provider/DocumentFile{0}"
+ "from": "android/support/v4/provider/DocumentFile(.*)",
+ "to": "androidx/documentfile/provider/DocumentFile{0}"
},
{
- from: "android/support/v4/provider/DocumentsContractApi19(.*)",
- to: "androidx/documentfile/provider/DocumentsContractApi19{0}"
+ "from": "android/support/v4/provider/DocumentsContractApi19(.*)",
+ "to": "androidx/documentfile/provider/DocumentsContractApi19{0}"
},
{
- from: "android/support/v4/provider/RawDocumentFile(.*)",
- to: "androidx/documentfile/provider/RawDocumentFile{0}"
+ "from": "android/support/v4/provider/RawDocumentFile(.*)",
+ "to": "androidx/documentfile/provider/RawDocumentFile{0}"
},
{
- from: "android/support/v4/provider/SingleDocumentFile(.*)",
- to: "androidx/documentfile/provider/SingleDocumentFile{0}"
+ "from": "android/support/v4/provider/SingleDocumentFile(.*)",
+ "to": "androidx/documentfile/provider/SingleDocumentFile{0}"
},
{
- from: "android/support/v4/provider/TreeDocumentFile(.*)",
- to: "androidx/documentfile/provider/TreeDocumentFile{0}"
+ "from": "android/support/v4/provider/TreeDocumentFile(.*)",
+ "to": "androidx/documentfile/provider/TreeDocumentFile{0}"
},
{
- from: "android/support/v4/content/LocalBroadcastManager(.*)",
- to: "androidx/localbroadcastmanager/content/LocalBroadcastManager{0}"
+ "from": "android/support/v4/content/LocalBroadcastManager(.*)",
+ "to": "androidx/localbroadcastmanager/content/LocalBroadcastManager{0}"
},
{
- from: "android/support/v4/print/(.*)",
- to: "androidx/print/{0}"
+ "from": "android/support/v4/print/(.*)",
+ "to": "androidx/print/{0}"
},
# Catch all for v4
{
- from: "android/support/v4/(.*)",
- to: "androidx/core/{0}"
+ "from": "android/support/v4/(.*)",
+ "to": "androidx/core/{0}"
},
{
- from: "android/support/v13/(.*)",
- to: "androidx/core/{0}"
+ "from": "android/support/v13/(.*)",
+ "to": "androidx/core/{0}"
},
# Design lib
{
- from: "android/support/design/(.*)",
- to: "android/support/design/{0}"
+ "from": "android/support/design/(.*)",
+ "to": "android/support/design/{0}"
+ },
+
+ # Arch
+ {
+ "from": "android/arch/core/(.*)",
+ "to": "androidx/arch/core/{0}"
+ },
+ {
+ "from": "android/arch/lifecycle/(.*)",
+ "to": "androidx/lifecycle/{0}"
+ },
+ {
+ "from": "android/arch/paging/(.*)",
+ "to": "androidx/paging/{0}"
+ },
+ {
+ "from": "android/arch/persistence/room/(.*)",
+ "to": "androidx/room/{0}"
+ },
+ {
+ "from": "android/arch/persistence/(.*)",
+ "to": "androidx/sqlite/{0}"
+ },
+
+ #Binding
+ {
+ "from": "android/databinding/(.*)",
+ "to": "androidx/databinding/{0}"
},
],
- slRules: [
+ "slRules": [
# Ignore
{
- from: "(.*)/package-info",
- to: "ignore"
+ "from": "(.*)/package-info",
+ "to": "ignore"
},
{
- from: "androidx/text/emoji/flatbuffer/(.*)",
- to: "ignore"
+ "from": "androidx/text/emoji/flatbuffer/(.*)",
+ "to": "ignore"
},
{
- from: "androidx/browser/browseractions/(.*)",
- to: "ignore"
+ "from": "androidx/browser/browseractions/(.*)",
+ "to": "ignore"
},
{
- from: "androidx/heifwriter/(.*)",
- to: "ignore"
+ "from": "androidx/heifwriter/(.*)",
+ "to": "ignore"
},
{
- from: "androidx/webkit/(.*)",
- to: "ignore"
+ "from": "androidx/webkit/(.*)",
+ "to": "ignore"
},
{
- from: "androidx/slice/(.*)",
- to: "ignore"
+ "from": "androidx/slice/(.*)",
+ "to": "ignore"
},
{
- from: "androidx/recyclerview/selection/(.*)",
- to: "ignore"
+ "from": "androidx/recyclerview/selection/(.*)",
+ "to": "ignore"
},
{
- from: "androidx/textclassifier/(.*)",
- to: "ignore"
+ "from": "androidx/textclassifier/(.*)",
+ "to": "ignore"
},
],
- pomRules: [
+ "pomRules": [
{
- from: { groupId: "com.android.support", artifactId: "animated-vector-drawable", version: "28.0.0" },
- to: [{ groupId: "androidx.vectordrawable", artifactId: "vectordrawable-animated", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "animated-vector-drawable", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.vectordrawable", "artifactId": "vectordrawable-animated", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "appcompat-v7", version: "28.0.0" },
- to: [{ groupId: "androidx.appcompat", artifactId: "appcompat", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "appcompat-v7", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.appcompat", "artifactId": "appcompat", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "cardview-v7", version: "28.0.0" },
- to: [{ groupId: "androidx.cardview", artifactId: "cardview", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "cardview-v7", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.cardview", "artifactId": "cardview", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "customtabs", version: "28.0.0" },
- to: [{ groupId: "androidx.browser", artifactId: "browser", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "customtabs", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.browser", "artifactId": "browser", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "design", version: "28.0.0" },
- to: [{ groupId: "com.google.android.material", artifactId: "material", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "design", "version": "28.0.0" },
+ "to": [{ "groupId": "com.google.android.material", "artifactId": "material", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "exifinterface", version: "28.0.0" },
- to: [{ groupId: "androidx.exifinterface", artifactId: "exifinterface", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "exifinterface", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.exifinterface", "artifactId": "exifinterface", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "gridlayout-v7", version: "28.0.0" },
- to: [{ groupId: "androidx.gridlayout", artifactId: "gridlayout", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "gridlayout-v7", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.gridlayout", "artifactId": "gridlayout", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "leanback-v17", version: "28.0.0" },
- to: [{ groupId: "androidx.leanback", artifactId: "leanback", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "leanback-v17", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.leanback", "artifactId": "leanback", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "mediarouter-v7", version: "28.0.0" },
- to: [{ groupId: "androidx.mediarouter", artifactId: "mediarouter", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "mediarouter-v7", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.mediarouter", "artifactId": "mediarouter", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "multidex", version: "28.0.0" },
- to: [{ groupId: "androidx.multidex", artifactId: "multidex", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "multidex", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.multidex", "artifactId": "multidex", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "multidex-instrumentation", version: "28.0.0" },
- to: [{ groupId: "androidx.multidex", artifactId: "multidex-instrumentation", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "multidex-instrumentation", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.multidex", "artifactId": "multidex-instrumentation", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "palette-v7", version: "28.0.0" },
- to: [{ groupId: "androidx.palette", artifactId: "palette", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "palette-v7", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.palette", "artifactId": "palette", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "percent", version: "28.0.0" },
- to: [{ groupId: "androidx.percentlayout", artifactId: "percentlayout", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "percent", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.percentlayout", "artifactId": "percentlayout", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "preference-leanback-v17", version: "28.0.0" },
- to: [{ groupId: "androidx.leanback", artifactId: "leanback-preference", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "preference-leanback-v17", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.leanback", "artifactId": "leanback-preference", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "preference-v14", version: "28.0.0" },
- to: [{ groupId: "androidx.legacy", artifactId: "legacy-preference-v14", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "preference-v14", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.legacy", "artifactId": "legacy-preference-v14", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "preference-v7", version: "28.0.0" },
- to: [{ groupId: "androidx.preference", artifactId: "preference", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "preference-v7", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.preference", "artifactId": "preference", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "recommendation", version: "28.0.0" },
- to: [{ groupId: "androidx.recommendation", artifactId: "recommendation", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "recommendation", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.recommendation", "artifactId": "recommendation", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "recyclerview-v7", version: "28.0.0" },
- to: [{ groupId: "androidx.recyclerview", artifactId: "recyclerview", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "recyclerview-v7", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.recyclerview", "artifactId": "recyclerview", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-annotations", version: "28.0.0" },
- to: [{ groupId: "androidx.annotation", artifactId: "annotation", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-annotations", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.annotation", "artifactId": "annotation", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-compat", version: "28.0.0" },
- to: [{ groupId: "androidx.core", artifactId: "core", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-compat", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.core", "artifactId": "core", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-content", version: "28.0.0" },
- to: [{ groupId: "androidx.contentpaging", artifactId: "contentpaging", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-content", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.contentpaging", "artifactId": "contentpaging", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-core-ui", version: "28.0.0" },
- to: [{ groupId: "androidx.legacy", artifactId: "legacy-support-core-ui", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-core-ui", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.legacy", "artifactId": "legacy-support-core-ui", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-core-utils", version: "28.0.0" },
- to: [{ groupId: "androidx.legacy", artifactId: "legacy-support-core-utils", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-core-utils", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.legacy", "artifactId": "legacy-support-core-utils", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-dynamic-animation", version: "28.0.0" },
- to: [{ groupId: "androidx.dynamicanimation", artifactId: "dynamicanimation", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-dynamic-animation", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.dynamicanimation", "artifactId": "dynamicanimation", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-emoji", version: "28.0.0" },
- to: [{ groupId: "androidx.emoji", artifactId: "emoji", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-emoji", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.emoji", "artifactId": "emoji", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-emoji-appcompat", version: "28.0.0" },
- to: [{ groupId: "androidx.emoji", artifactId: "emoji-appcompat", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-emoji-appcompat", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.emoji", "artifactId": "emoji-appcompat", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-emoji-bundled", version: "28.0.0" },
- to: [{ groupId: "androidx.emoji", artifactId: "emoji-bundled", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-emoji-bundled", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.emoji", "artifactId": "emoji-bundled", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-fragment", version: "28.0.0" },
- to: [{ groupId: "androidx.fragment", artifactId: "fragment", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-fragment", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.fragment", "artifactId": "fragment", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-media-compat", version: "28.0.0" },
- to: [{ groupId: "androidx.media", artifactId: "media", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-media-compat", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.media", "artifactId": "media", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-tv-provider", version: "28.0.0" },
- to: [{ groupId: "androidx.tvprovider", artifactId: "tvprovider", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-tv-provider", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.tvprovider", "artifactId": "tvprovider", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-v13", version: "28.0.0" },
- to: [{ groupId: "androidx.legacy", artifactId: "legacy-support-v13", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-v13", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.legacy", "artifactId": "legacy-support-v13", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-v4", version: "28.0.0" },
- to: [{ groupId: "androidx.legacy", artifactId: "legacy-support-v4", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-v4", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.legacy", "artifactId": "legacy-support-v4", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "support-vector-drawable", version: "28.0.0" },
- to: [{ groupId: "androidx.vectordrawable", artifactId: "vectordrawable", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "support-vector-drawable", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.vectordrawable", "artifactId": "vectordrawable", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "textclassifier", version: "28.0.0" },
- to: [{ groupId: "androidx.textclassifier", artifactId: "textclassifier", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "textclassifier", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.textclassifier", "artifactId": "textclassifier", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "transition", version: "28.0.0" },
- to: [{ groupId: "androidx.transition", artifactId: "transition", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "transition", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.transition", "artifactId": "transition", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "wear", version: "28.0.0" },
- to: [{ groupId: "androidx.wear", artifactId: "wear", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "wear", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.wear", "artifactId": "wear", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "asynclayoutinflater", version: "28.0.0" },
- to: [{ groupId: "androidx.asynclayoutinflater", artifactId: "asynclayoutinflater", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "asynclayoutinflater", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.asynclayoutinflater", "artifactId": "asynclayoutinflater", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "collections", version: "28.0.0" },
- to: [{ groupId: "androidx.collection", artifactId: "collection", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "collections", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.collection", "artifactId": "collection", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "coordinatorlayout", version: "28.0.0" },
- to: [{ groupId: "androidx.coordinatorlayout", artifactId: "coordinatorlayout", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "coordinatorlayout", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.coordinatorlayout", "artifactId": "coordinatorlayout", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "cursoradapter", version: "28.0.0" },
- to: [{ groupId: "androidx.cursoradapter", artifactId: "cursoradapter", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "cursoradapter", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.cursoradapter", "artifactId": "cursoradapter", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "customview", version: "28.0.0" },
- to: [{ groupId: "androidx.customview", artifactId: "customview", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "customview", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.customview", "artifactId": "customview", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "documentfile", version: "28.0.0" },
- to: [{ groupId: "androidx.documentfile", artifactId: "documentfile", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "documentfile", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.documentfile", "artifactId": "documentfile", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "drawerlayout", version: "28.0.0" },
- to: [{ groupId: "androidx.drawerlayout", artifactId: "drawerlayout", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "drawerlayout", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.drawerlayout", "artifactId": "drawerlayout", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "interpolator", version: "28.0.0" },
- to: [{ groupId: "androidx.interpolator", artifactId: "interpolator", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "interpolator", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.interpolator", "artifactId": "interpolator", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "loader", version: "28.0.0" },
- to: [{ groupId: "androidx.loader", artifactId: "loader", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "loader", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.loader", "artifactId": "loader", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "localbroadcastmanager", version: "28.0.0" },
- to: [{ groupId: "androidx.localbroadcastmanager", artifactId: "localbroadcastmanager", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "localbroadcastmanager", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.localbroadcastmanager", "artifactId": "localbroadcastmanager", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "print", version: "28.0.0" },
- to: [{ groupId: "androidx.print", artifactId: "print", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support", "artifactId": "print", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.print", "artifactId": "print", "version": "1.0.0" }]
+ },
+ {
+ "from": { "groupId": "com.android.support", "artifactId": "slidingpanelayout", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.slidingpanelayout", "artifactId": "slidingpanelayout", "version": "1.0.0" }]
+ },
+ {
+ "from": { "groupId": "com.android.support", "artifactId": "swiperefreshlayout", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.swiperefreshlayout", "artifactId": "swiperefreshlayout", "version": "1.0.0" }]
+ },
+ {
+ "from": { "groupId": "com.android.support", "artifactId": "viewpager", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.viewpager", "artifactId": "viewpager", "version": "1.0.0" }]
+ },
+ {
+ "from": { "groupId": "com.android.databinding", "artifactId": "adapters", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.databinding", "artifactId": "databinding-adapters", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "slidingpanelayout", version: "28.0.0" },
- to: [{ groupId: "androidx.slidingpanelayout", artifactId: "slidingpanelayout", version: "1.0.0" }]
+ "from": { "groupId": "com.android.databinding", "artifactId": "baseLibrary", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.databinding", "artifactId": "databinding-common", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "swiperefreshlayout", version: "28.0.0" },
- to: [{ groupId: "androidx.swiperefreshlayout", artifactId: "swiperefreshlayout", version: "1.0.0" }]
+ "from": { "groupId": "com.android.databinding", "artifactId": "compiler", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.databinding", "artifactId": "databinding-compiler", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support", artifactId: "viewpager", version: "28.0.0" },
- to: [{ groupId: "androidx.viewpager", artifactId: "viewpager", version: "1.0.0" }]
+ "from": { "groupId": "com.android.databinding", "artifactId": "compilerCommon", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.databinding", "artifactId": "databinding-compiler-common", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.databinding", artifactId: "adapters", version: "28.0.0" },
- to: [{ groupId: "androidx.databinding", artifactId: "databinding-adapters", version: "1.0.0" }]
+ "from": { "groupId": "com.android.databinding", "artifactId": "library", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.databinding", "artifactId": "databinding-runtime", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.databinding", artifactId: "baseLibrary", version: "28.0.0" },
- to: [{ groupId: "androidx.databinding", artifactId: "databinding-common", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.background.workmanager", "artifactId": "workmanager", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.work", "artifactId": "runtime", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.databinding", artifactId: "compiler", version: "28.0.0" },
- to: [{ groupId: "androidx.databinding", artifactId: "databinding-compiler", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.background.workmanager", "artifactId": "workmanager-firebase", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.work", "artifactId": "runtime-firebase", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.databinding", artifactId: "compilerCommon", version: "28.0.0" },
- to: [{ groupId: "androidx.databinding", artifactId: "databinding-compiler-common", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.navigation", "artifactId": "runtime", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.navigation", "artifactId": "navigation-runtime", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.databinding", artifactId: "library", version: "28.0.0" },
- to: [{ groupId: "androidx.databinding", artifactId: "databinding-runtime", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.navigation", "artifactId": "fragment", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.navigation", "artifactId": "navigation-fragment", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.background.workmanager", artifactId: "workmanager", version: "28.0.0" },
- to: [{ groupId: "androidx.work", artifactId: "runtime", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.core", "artifactId": "common", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.arch.core", "artifactId": "core-common", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.background.workmanager", artifactId: "workmanager-firebase", version: "28.0.0" },
- to: [{ groupId: "androidx.work", artifactId: "runtime-firebase", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.core", "artifactId": "core", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.arch.core", "artifactId": "core", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.navigation", artifactId: "runtime", version: "28.0.0" },
- to: [{ groupId: "androidx.navigation", artifactId: "navigation-runtime", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.core", "artifactId": "core-testing", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.arch.core", "artifactId": "core-testing", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.navigation", artifactId: "fragment", version: "28.0.0" },
- to: [{ groupId: "androidx.navigation", artifactId: "navigation-fragment", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.core", "artifactId": "runtime", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.arch.core", "artifactId": "core-runtime", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.core", artifactId: "common", version: "28.0.0" },
- to: [{ groupId: "androidx.arch.core", artifactId: "core-common", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "common", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-common", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.core", artifactId: "core", version: "28.0.0" },
- to: [{ groupId: "androidx.arch.core", artifactId: "core", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "common-java8", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-common-java8", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.core", artifactId: "core-testing", version: "28.0.0" },
- to: [{ groupId: "androidx.arch.core", artifactId: "core-testing", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "compiler", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-compiler", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.core", artifactId: "runtime", version: "28.0.0" },
- to: [{ groupId: "androidx.arch.core", artifactId: "core-runtime", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "extensions", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-extensions", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.lifecycle", artifactId: "common", version: "28.0.0" },
- to: [{ groupId: "androidx.lifecycle", artifactId: "lifecycle-common", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "reactivestreams", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-reactivestreams", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.lifecycle", artifactId: "common-java8", version: "28.0.0" },
- to: [{ groupId: "androidx.lifecycle", artifactId: "lifecycle-common-java8", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "runtime", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-runtime", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.lifecycle", artifactId: "compiler", version: "28.0.0" },
- to: [{ groupId: "androidx.lifecycle", artifactId: "lifecycle-compiler", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "viewmodel", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-viewmodel", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.lifecycle", artifactId: "extensions", version: "28.0.0" },
- to: [{ groupId: "androidx.lifecycle", artifactId: "lifecycle-extensions", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "livedata", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-livedata", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.lifecycle", artifactId: "reactivestreams", version: "28.0.0" },
- to: [{ groupId: "androidx.lifecycle", artifactId: "lifecycle-reactivestreams", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.lifecycle", "artifactId": "livedata-core", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.lifecycle", "artifactId": "lifecycle-livedata-core", "version": "1.0.0" }]
},
- #{
- # from: { groupId: "android.arch.lifecycle", artifactId: "runtime", version: "28.0.0" },
- # to: [{ groupId: "androidx.lifecycle", artifactId: "lifecycle-runtime", version: "1.0.0" }]
- #},
{
- from: { groupId: "android.arch.paging", artifactId: "common", version: "28.0.0" },
- to: [{ groupId: "androidx.paging", artifactId: "paging-common", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.paging", "artifactId": "common", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.paging", "artifactId": "paging-common", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.paging", artifactId: "runtime", version: "28.0.0" },
- to: [{ groupId: "androidx.paging", artifactId: "paging-runtime", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.paging", "artifactId": "runtime", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.paging", "artifactId": "paging-runtime", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence", artifactId: "db", version: "28.0.0" },
- to: [{ groupId: "androidx.sqlite", artifactId: "sqlite", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence", "artifactId": "db", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.sqlite", "artifactId": "sqlite", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence", artifactId: "db-framework", version: "28.0.0" },
- to: [{ groupId: "androidx.sqlite", artifactId: "sqlite-framework", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence", "artifactId": "db-framework", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.sqlite", "artifactId": "sqlite-framework", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence.room", artifactId: "common", version: "28.0.0" },
- to: [{ groupId: "androidx.room", artifactId: "room-common", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence.room", "artifactId": "common", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.room", "artifactId": "room-common", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence.room", artifactId: "compiler", version: "28.0.0" },
- to: [{ groupId: "androidx.room", artifactId: "room-compiler", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence.room", "artifactId": "compiler", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.room", "artifactId": "room-compiler", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence.room", artifactId: "migration", version: "28.0.0" },
- to: [{ groupId: "androidx.room", artifactId: "room-migration", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence.room", "artifactId": "migration", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.room", "artifactId": "room-migration", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence.room", artifactId: "runtime", version: "28.0.0" },
- to: [{ groupId: "androidx.room", artifactId: "room-runtime", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence.room", "artifactId": "runtime", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.room", "artifactId": "room-runtime", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence.room", artifactId: "rxjava2", version: "28.0.0" },
- to: [{ groupId: "androidx.room", artifactId: "room-rxjava2", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence.room", "artifactId": "rxjava2", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.room", "artifactId": "room-rxjava2", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence.room", artifactId: "testing", version: "28.0.0" },
- to: [{ groupId: "androidx.room", artifactId: "room-testing", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence.room", "artifactId": "testing", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.room", "artifactId": "room-testing", "version": "1.0.0" }]
},
{
- from: { groupId: "android.arch.persistence.room", artifactId: "guava", version: "28.0.0" },
- to: [{ groupId: "androidx.room", artifactId: "room-guava", version: "1.0.0" }]
+ "from": { "groupId": "android.arch.persistence.room", "artifactId": "guava", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.room", "artifactId": "room-guava", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.constraint", artifactId: "constraint-layout", version: "28.0.0" },
- to: [{ groupId: "androidx.constraintlayout", artifactId: "constraintlayout", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.constraint", "artifactId": "constraint-layout", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.constraintlayout", "artifactId": "constraintlayout", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.constraint", artifactId: "constraint-layout-solver", version: "28.0.0" },
- to: [{ groupId: "androidx.constraintlayout", artifactId: "constraintlayout-solver", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.constraint", "artifactId": "constraint-layout-solver", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.constraintlayout", "artifactId": "constraintlayout-solver", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test", artifactId: "exposed-instrumentation-api-publish", version: "28.0.0" },
- to: [{ groupId: "androidx.test", artifactId: "test-exposed-instrumentation-api-publish", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test", "artifactId": "exposed-instrumentation-api-publish", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test", "artifactId": "test-exposed-instrumentation-api-publish", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test", artifactId: "orchestrator", version: "28.0.0" },
- to: [{ groupId: "androidx.test", artifactId: "test-orchestrator", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test", "artifactId": "orchestrator", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test", "artifactId": "test-orchestrator", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test", artifactId: "rules", version: "28.0.0" },
- to: [{ groupId: "androidx.test", artifactId: "test-rules", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test", "artifactId": "rules", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test", "artifactId": "test-rules", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test", artifactId: "runner", version: "28.0.0" },
- to: [{ groupId: "androidx.test", artifactId: "test-runner", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test", "artifactId": "runner", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test", "artifactId": "test-runner", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test", artifactId: "testing-support-lib", version: "28.0.0" },
- to: [{ groupId: "androidx.test", artifactId: "test", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test", "artifactId": "testing-support-lib", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test", "artifactId": "test", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso", artifactId: "espresso-accessibility", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso", artifactId: "espresso-accessibility", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso", "artifactId": "espresso-accessibility", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso", "artifactId": "espresso-accessibility", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso", artifactId: "espresso-contrib", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso", artifactId: "espresso-contrib", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso", "artifactId": "espresso-contrib", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso", "artifactId": "espresso-contrib", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso", artifactId: "espresso-core", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso", artifactId: "espresso-core", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso", "artifactId": "espresso-core", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso", "artifactId": "espresso-core", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso", artifactId: "espresso-idling-resource", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso", artifactId: "espresso-idling-resource", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso", "artifactId": "espresso-idling-resource", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso", "artifactId": "espresso-idling-resource", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso", artifactId: "espresso-intents", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso", artifactId: "espresso-intents", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso", "artifactId": "espresso-intents", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso", "artifactId": "espresso-intents", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso", artifactId: "espresso-web", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso", artifactId: "espresso-web", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso", "artifactId": "espresso-web", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso", "artifactId": "espresso-web", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso.idling", artifactId: "idling-concurrent", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso.idling", artifactId: "idling-concurrent", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso.idling", "artifactId": "idling-concurrent", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso.idling", "artifactId": "idling-concurrent", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.espresso.idling", artifactId: "idling-net", version: "28.0.0" },
- to: [{ groupId: "androidx.test.espresso.idling", artifactId: "idling-net", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.espresso.idling", "artifactId": "idling-net", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.espresso.idling", "artifactId": "idling-net", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.janktesthelper", artifactId: "janktesthelper-v23", version: "28.0.0" },
- to: [{ groupId: "androidx.test.jank", artifactId: "jank", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.janktesthelper", "artifactId": "janktesthelper-v23", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.jank", "artifactId": "jank", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.services", artifactId: "test-services", version: "28.0.0" },
- to: [{ groupId: "androidx.test", artifactId: "test-services", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.services", "artifactId": "test-services", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test", "artifactId": "test-services", "version": "1.0.0" }]
},
{
- from: { groupId: "com.android.support.test.uiautomator", artifactId: "uiautomator-v18", version: "28.0.0" },
- to: [{ groupId: "androidx.test.uiautomator", artifactId: "uiautomator", version: "1.0.0" }]
+ "from": { "groupId": "com.android.support.test.uiautomator", "artifactId": "uiautomator-v18", "version": "28.0.0" },
+ "to": [{ "groupId": "androidx.test.uiautomator", "artifactId": "uiautomator", "version": "1.0.0" }]
},
# Keep it same
{
- from: { groupId: "androidx.slice", artifactId: "slices-core", version: "1.0.0" },
- to: [{ groupId: "androidx.slice", artifactId: "slices-core", version: "1.0.0" }]
+ "from": { "groupId": "androidx.slice", "artifactId": "slices-core", "version": "1.0.0" },
+ "to": [{ "groupId": "androidx.slice", "artifactId": "slices-core", "version": "1.0.0" }]
},
{
- from: { groupId: "androidx.slice", artifactId: "slices-builders", version: "1.0.0" },
- to: [{ groupId: "androidx.slice", artifactId: "slices-builders", version: "1.0.0" }]
+ "from": { "groupId": "androidx.slice", "artifactId": "slices-builders", "version": "1.0.0" },
+ "to": [{ "groupId": "androidx.slice", "artifactId": "slices-builders", "version": "1.0.0" }]
},
{
- from: { groupId: "androidx.slice", artifactId: "slices-view", version: "1.0.0" },
- to: [{ groupId: "androidx.slice", artifactId: "slices-view", version: "1.0.0" }]
- },
- # Temporary
- {
- from: { groupId: "android.arch.lifecycle", artifactId: "runtime", version: "1.1.0" },
- to: [{ groupId: "androidx.temp.arch.lifecycle", artifactId: "runtime", version: "2.0.0" }]
- },
- {
- from: { groupId: "android.arch.lifecycle", artifactId: "livedata-core", version: "1.1.0" },
- to: [{ groupId: "androidx.temp.arch.lifecycle", artifactId: "livedata-core", version: "2.0.0" }]
- },
- {
- from: { groupId: "android.arch.lifecycle", artifactId: "viewmodel", version: "1.1.0" },
- to: [{ groupId: "androidx.temp.arch.lifecycle", artifactId: "viewmodel", version: "2.0.0" }]
+ "from": { "groupId": "androidx.slice", "artifactId": "slices-view", "version": "1.0.0" },
+ "to": [{ "groupId": "androidx.slice", "artifactId": "slices-view", "version": "1.0.0" }]
}
],
- map: {
+ "map": {
# Types added in 28.0.0 (missing in 27.1.0)
- types: {
+ "types": {
}
},
- proGuardMap: {
- rules: {
+ "proGuardMap": {
+ "rules": {
"android/support/transition/ChangeBounds$*": "androidx/transition/ChangeBounds$*",
- "android/support/graphics/drawable/VectorDrawableCompat$*": "androidx/vectordrawable/graphics/drawable/VectorDrawableCompat$*"
+ "android/support/graphics/drawable/VectorDrawableCompat$*": "androidx/vectordrawable/graphics/drawable/VectorDrawableCompat$*",
+ "android/arch/persistence/room/paging/**": "androidx/room/paging/**"
}
}
}
diff --git a/jetifier/jetifier/core/src/main/resources/default.generated.config b/jetifier/jetifier/core/src/main/resources/default.generated.config
index 2fd93ad..ca86505 100644
--- a/jetifier/jetifier/core/src/main/resources/default.generated.config
+++ b/jetifier/jetifier/core/src/main/resources/default.generated.config
@@ -19,7 +19,8 @@
{
"restrictToPackagePrefixes": [
"android/support/",
- "androix/temp"
+ "android/arch/",
+ "android/databinding/"
],
"rules": [
{
@@ -411,10 +412,6 @@
"to": "androidx/media/AudioAttributesCompat{0}"
},
{
- "from": "android/support/v4/media/MediaBrowserCompat(.*)",
- "to": "androidx/media/MediaBrowserCompat{0}"
- },
- {
"from": "android/support/v4/media/MediaBrowserCompatUtils(.*)",
"to": "androidx/media/MediaBrowserCompatUtils{0}"
},
@@ -435,10 +432,6 @@
"to": "androidx/media/session/MediaButtonReceiver{0}"
},
{
- "from": "android/support/v4/media/session/MediaControllerCompat(.*)",
- "to": "androidx/media/session/MediaControllerCompat{0}"
- },
- {
"from": "android/support/v4/media/(.*)",
"to": "android/support/v4/media/{0}"
},
@@ -629,6 +622,30 @@
{
"from": "android/support/design/(.*)",
"to": "android/support/design/{0}"
+ },
+ {
+ "from": "android/arch/core/(.*)",
+ "to": "androidx/arch/core/{0}"
+ },
+ {
+ "from": "android/arch/lifecycle/(.*)",
+ "to": "androidx/lifecycle/{0}"
+ },
+ {
+ "from": "android/arch/paging/(.*)",
+ "to": "androidx/paging/{0}"
+ },
+ {
+ "from": "android/arch/persistence/room/(.*)",
+ "to": "androidx/room/{0}"
+ },
+ {
+ "from": "android/arch/persistence/(.*)",
+ "to": "androidx/sqlite/{0}"
+ },
+ {
+ "from": "android/databinding/(.*)",
+ "to": "androidx/databinding/{0}"
}
],
"slRules": [
@@ -1620,6 +1637,62 @@
},
{
"from": {
+ "groupId": "android.arch.lifecycle",
+ "artifactId": "runtime",
+ "version": "28.0.0"
+ },
+ "to": [
+ {
+ "groupId": "androidx.lifecycle",
+ "artifactId": "lifecycle-runtime",
+ "version": "1.0.0"
+ }
+ ]
+ },
+ {
+ "from": {
+ "groupId": "android.arch.lifecycle",
+ "artifactId": "viewmodel",
+ "version": "28.0.0"
+ },
+ "to": [
+ {
+ "groupId": "androidx.lifecycle",
+ "artifactId": "lifecycle-viewmodel",
+ "version": "1.0.0"
+ }
+ ]
+ },
+ {
+ "from": {
+ "groupId": "android.arch.lifecycle",
+ "artifactId": "livedata",
+ "version": "28.0.0"
+ },
+ "to": [
+ {
+ "groupId": "androidx.lifecycle",
+ "artifactId": "lifecycle-livedata",
+ "version": "1.0.0"
+ }
+ ]
+ },
+ {
+ "from": {
+ "groupId": "android.arch.lifecycle",
+ "artifactId": "livedata-core",
+ "version": "28.0.0"
+ },
+ "to": [
+ {
+ "groupId": "androidx.lifecycle",
+ "artifactId": "lifecycle-livedata-core",
+ "version": "1.0.0"
+ }
+ ]
+ },
+ {
+ "from": {
"groupId": "android.arch.paging",
"artifactId": "common",
"version": "28.0.0"
@@ -2065,48 +2138,6 @@
"version": "1.0.0"
}
]
- },
- {
- "from": {
- "groupId": "android.arch.lifecycle",
- "artifactId": "runtime",
- "version": "1.1.0"
- },
- "to": [
- {
- "groupId": "androidx.temp.arch.lifecycle",
- "artifactId": "runtime",
- "version": "2.0.0"
- }
- ]
- },
- {
- "from": {
- "groupId": "android.arch.lifecycle",
- "artifactId": "livedata-core",
- "version": "1.1.0"
- },
- "to": [
- {
- "groupId": "androidx.temp.arch.lifecycle",
- "artifactId": "livedata-core",
- "version": "2.0.0"
- }
- ]
- },
- {
- "from": {
- "groupId": "android.arch.lifecycle",
- "artifactId": "viewmodel",
- "version": "1.1.0"
- },
- "to": [
- {
- "groupId": "androidx.temp.arch.lifecycle",
- "artifactId": "viewmodel",
- "version": "2.0.0"
- }
- ]
}
],
"map": {
@@ -2119,22 +2150,61 @@
"android/support/annotation/ColorInt": "androidx/annotation/ColorInt",
"android/support/v7/widget/RecyclerView": "androidx/recyclerview/widget/RecyclerView",
"android/support/v7/widget/LinearLayoutManager": "androidx/recyclerview/widget/LinearLayoutManager",
+ "android/arch/lifecycle/LiveData": "androidx/lifecycle/LiveData",
+ "android/arch/lifecycle/Observer": "androidx/lifecycle/Observer",
"android/support/annotation/AttrRes": "androidx/annotation/AttrRes",
+ "android/databinding/BindingAdapter": "androidx/databinding/BindingAdapter",
+ "android/databinding/BindingMethod": "androidx/databinding/BindingMethod",
+ "android/databinding/ObservableMap": "androidx/databinding/ObservableMap",
+ "android/databinding/BindingBuildInfo": "androidx/databinding/BindingBuildInfo",
+ "android/databinding/Observable": "androidx/databinding/Observable",
+ "android/databinding/Untaggable": "androidx/databinding/Untaggable",
+ "android/databinding/InverseBindingMethod": "androidx/databinding/InverseBindingMethod",
+ "android/databinding/CallbackRegistry": "androidx/databinding/CallbackRegistry",
+ "android/databinding/BindingMethods": "androidx/databinding/BindingMethods",
+ "android/databinding/InverseBindingListener": "androidx/databinding/InverseBindingListener",
+ "android/databinding/BindingConversion": "androidx/databinding/BindingConversion",
+ "android/databinding/ObservableList": "androidx/databinding/ObservableList",
+ "android/databinding/InverseBindingMethods": "androidx/databinding/InverseBindingMethods",
+ "android/databinding/InverseMethod": "androidx/databinding/InverseMethod",
+ "android/databinding/Bindable": "androidx/databinding/Bindable",
+ "android/databinding/InverseBindingAdapter": "androidx/databinding/InverseBindingAdapter",
"android/support/design/drawable/DrawableUtils": "android/support/design/drawable/DrawableUtils",
"android/support/app/recommendation/ContentRecommendation": "androidx/recommendation/app/ContentRecommendation",
"android/support/annotation/DrawableRes": "androidx/annotation/DrawableRes",
"android/support/app/recommendation/RecommendationExtender": "androidx/recommendation/app/RecommendationExtender",
+ "android/arch/lifecycle/ErrorMessages": "androidx/lifecycle/ErrorMessages",
+ "android/arch/lifecycle/model/EventMethod": "androidx/lifecycle/model/EventMethod",
+ "android/arch/lifecycle/Elements_extKt": "androidx/lifecycle/Elements_extKt",
+ "android/arch/lifecycle/WriterKt": "androidx/lifecycle/WriterKt",
+ "android/arch/lifecycle/ObserversCollector": "androidx/lifecycle/ObserversCollector",
+ "android/arch/lifecycle/Validator": "androidx/lifecycle/Validator",
+ "android/arch/lifecycle/model/LifecycleObserverInfo": "androidx/lifecycle/model/LifecycleObserverInfo",
+ "android/arch/lifecycle/model/AdapterClassKt": "androidx/lifecycle/model/AdapterClassKt",
+ "android/arch/lifecycle/OnLifecycleEvent": "androidx/lifecycle/OnLifecycleEvent",
+ "android/arch/lifecycle/Lifecycle": "androidx/lifecycle/Lifecycle",
+ "android/arch/lifecycle/LifecycleObserver": "androidx/lifecycle/LifecycleObserver",
+ "android/arch/lifecycle/model/EventMethodCall": "androidx/lifecycle/model/EventMethodCall",
+ "android/arch/lifecycle/model/AdapterClass": "androidx/lifecycle/model/AdapterClass",
+ "android/arch/lifecycle/model/InputModel": "androidx/lifecycle/model/InputModel",
+ "android/arch/lifecycle/Lifecycling": "androidx/lifecycle/Lifecycling",
+ "android/arch/lifecycle/LifecycleProcessor": "androidx/lifecycle/LifecycleProcessor",
+ "android/arch/lifecycle/Input_collectorKt": "androidx/lifecycle/Input_collectorKt",
+ "android/arch/lifecycle/TransformationKt": "androidx/lifecycle/TransformationKt",
+ "android/arch/lifecycle/GeneratedAdapter": "androidx/lifecycle/GeneratedAdapter",
+ "android/arch/lifecycle/LifecycleOwner": "androidx/lifecycle/LifecycleOwner",
+ "android/arch/lifecycle/MethodCallsLogger": "androidx/lifecycle/MethodCallsLogger",
"android/support/v4/media/AudioAttributesCompat": "androidx/media/AudioAttributesCompat",
"android/support/v4/media/AudioAttributesCompatApi21": "androidx/media/AudioAttributesCompatApi21",
- "android/support/v4/media/MediaBrowserCompat": "androidx/media/MediaBrowserCompat",
+ "android/support/v4/media/MediaBrowserCompat": "android/support/v4/media/MediaBrowserCompat",
"android/support/v4/media/session/MediaSessionCompat": "android/support/v4/media/session/MediaSessionCompat",
- "android/support/v4/media/MediaBrowserCompatApi21": "androidx/media/MediaBrowserCompatApi21",
+ "android/support/v4/media/MediaBrowserCompatApi21": "android/support/v4/media/MediaBrowserCompatApi21",
"android/support/v4/os/ResultReceiver": "androidx/core/os/ResultReceiver",
- "android/support/v4/media/MediaBrowserCompatApi23": "androidx/media/MediaBrowserCompatApi23",
+ "android/support/v4/media/MediaBrowserCompatApi23": "android/support/v4/media/MediaBrowserCompatApi23",
"android/support/v4/media/session/IMediaSession": "android/support/v4/media/session/IMediaSession",
"android/support/v4/util/ArrayMap": "androidx/collection/ArrayMap",
"android/support/v4/app/BundleCompat": "androidx/core/app/BundleCompat",
- "android/support/v4/media/MediaBrowserCompatApi26": "androidx/media/MediaBrowserCompatApi26",
+ "android/support/v4/media/MediaBrowserCompatApi26": "android/support/v4/media/MediaBrowserCompatApi26",
"android/support/v4/media/MediaDescriptionCompat": "android/support/v4/media/MediaDescriptionCompat",
"android/support/v4/media/MediaBrowserCompatUtils": "androidx/media/MediaBrowserCompatUtils",
"android/support/v4/media/MediaBrowserProtocol": "androidx/media/MediaBrowserProtocol",
@@ -2159,11 +2229,11 @@
"android/support/v4/media/session/PlaybackStateCompat": "android/support/v4/media/session/PlaybackStateCompat",
"android/support/v4/media/session/ParcelableVolumeInfo": "android/support/v4/media/session/ParcelableVolumeInfo",
"android/support/v4/media/session/MediaButtonReceiver": "androidx/media/session/MediaButtonReceiver",
- "android/support/v4/media/session/MediaControllerCompat": "androidx/media/session/MediaControllerCompat",
- "android/support/v4/media/session/MediaControllerCompatApi21": "androidx/media/session/MediaControllerCompatApi21",
+ "android/support/v4/media/session/MediaControllerCompat": "android/support/v4/media/session/MediaControllerCompat",
+ "android/support/v4/media/session/MediaControllerCompatApi21": "android/support/v4/media/session/MediaControllerCompatApi21",
"android/support/v4/app/SupportActivity": "androidx/core/app/SupportActivity",
- "android/support/v4/media/session/MediaControllerCompatApi23": "androidx/media/session/MediaControllerCompatApi23",
- "android/support/v4/media/session/MediaControllerCompatApi24": "androidx/media/session/MediaControllerCompatApi24",
+ "android/support/v4/media/session/MediaControllerCompatApi23": "android/support/v4/media/session/MediaControllerCompatApi23",
+ "android/support/v4/media/session/MediaControllerCompatApi24": "android/support/v4/media/session/MediaControllerCompatApi24",
"android/support/v4/media/session/MediaSessionCompatApi21": "android/support/v4/media/session/MediaSessionCompatApi21",
"android/support/v4/media/session/MediaSessionCompatApi23": "android/support/v4/media/session/MediaSessionCompatApi23",
"android/support/v4/media/session/MediaSessionCompatApi24": "android/support/v4/media/session/MediaSessionCompatApi24",
@@ -2241,6 +2311,8 @@
"android/support/design/resources/TextAppearance": "android/support/design/resources/TextAppearance",
"android/support/design/resources/R": "android/support/design/resources/R",
"android/support/v4/content/res/ResourcesCompat": "androidx/core/content/res/ResourcesCompat",
+ "android/arch/lifecycle/DefaultLifecycleObserver": "androidx/lifecycle/DefaultLifecycleObserver",
+ "android/arch/lifecycle/FullLifecycleObserver": "androidx/lifecycle/FullLifecycleObserver",
"android/support/v7/widget/CardView": "androidx/cardview/widget/CardView",
"android/support/v7/widget/CardViewDelegate": "androidx/cardview/widget/CardViewDelegate",
"android/support/v7/cardview/R": "androidx/cardview/R",
@@ -2250,6 +2322,34 @@
"android/support/v7/widget/CardViewBaseImpl": "androidx/cardview/widget/CardViewBaseImpl",
"android/support/v7/widget/RoundRectDrawableWithShadow": "androidx/cardview/widget/RoundRectDrawableWithShadow",
"android/support/v7/widget/RoundRectDrawable": "androidx/cardview/widget/RoundRectDrawable",
+ "android/arch/persistence/room/DatabaseConfiguration": "androidx/room/DatabaseConfiguration",
+ "android/arch/persistence/db/SupportSQLiteOpenHelper": "androidx/sqlite/db/SupportSQLiteOpenHelper",
+ "android/arch/persistence/room/RoomDatabase": "androidx/room/RoomDatabase",
+ "android/arch/persistence/room/EntityDeletionOrUpdateAdapter": "androidx/room/EntityDeletionOrUpdateAdapter",
+ "android/arch/persistence/room/SharedSQLiteStatement": "androidx/room/SharedSQLiteStatement",
+ "android/arch/persistence/db/SupportSQLiteStatement": "androidx/sqlite/db/SupportSQLiteStatement",
+ "android/arch/persistence/room/EntityInsertionAdapter": "androidx/room/EntityInsertionAdapter",
+ "android/arch/persistence/room/InvalidationTracker": "androidx/room/InvalidationTracker",
+ "android/arch/persistence/db/SupportSQLiteDatabase": "androidx/sqlite/db/SupportSQLiteDatabase",
+ "android/arch/core/internal/SafeIterableMap": "androidx/arch/core/internal/SafeIterableMap",
+ "android/support/v4/util/ArraySet": "androidx/collection/ArraySet",
+ "android/arch/core/executor/ArchTaskExecutor": "androidx/arch/core/executor/ArchTaskExecutor",
+ "android/arch/persistence/room/Room": "androidx/room/Room",
+ "android/arch/persistence/room/migration/Migration": "androidx/room/migration/Migration",
+ "android/arch/persistence/db/framework/FrameworkSQLiteOpenHelperFactory": "androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory",
+ "android/support/v4/app/ActivityManagerCompat": "androidx/core/app/ActivityManagerCompat",
+ "android/support/v4/util/SparseArrayCompat": "androidx/collection/SparseArrayCompat",
+ "android/arch/persistence/db/SimpleSQLiteQuery": "androidx/sqlite/db/SimpleSQLiteQuery",
+ "android/arch/persistence/db/SupportSQLiteQuery": "androidx/sqlite/db/SupportSQLiteQuery",
+ "android/arch/persistence/room/RoomOpenHelper": "androidx/room/RoomOpenHelper",
+ "android/arch/persistence/room/RoomMasterTable": "androidx/room/RoomMasterTable",
+ "android/arch/persistence/room/RoomSQLiteQuery": "androidx/room/RoomSQLiteQuery",
+ "android/arch/persistence/db/SupportSQLiteProgram": "androidx/sqlite/db/SupportSQLiteProgram",
+ "android/arch/persistence/room/paging/LimitOffsetDataSource": "androidx/room/paging/LimitOffsetDataSource",
+ "android/arch/paging/PositionalDataSource": "androidx/paging/PositionalDataSource",
+ "android/arch/persistence/room/util/StringUtil": "androidx/room/util/StringUtil",
+ "android/arch/persistence/room/util/TableInfo": "androidx/room/util/TableInfo",
+ "android/arch/persistence/room/ColumnInfo": "androidx/room/ColumnInfo",
"android/support/text/emoji/bundled/BundledEmojiCompatConfig": "androidx/emoji/bundled/BundledEmojiCompatConfig",
"android/support/text/emoji/EmojiCompat": "androidx/emoji/text/EmojiCompat",
"android/support/v4/util/Preconditions": "androidx/core/util/Preconditions",
@@ -2257,6 +2357,8 @@
"android/support/v7/graphics/ColorCutQuantizer": "androidx/palette/graphics/ColorCutQuantizer",
"android/support/v7/graphics/Palette": "androidx/palette/graphics/Palette",
"android/support/v7/graphics/Target": "androidx/palette/graphics/Target",
+ "android/arch/persistence/room/EmptyResultSetException": "androidx/room/EmptyResultSetException",
+ "android/arch/persistence/room/RxRoom": "androidx/room/RxRoom",
"android/support/v4/app/ActionBarDrawerToggle": "androidx/legacy/app/ActionBarDrawerToggle",
"android/support/v4/widget/Space": "androidx/legacy/widget/Space",
"android/support/animation/AnimationHandler": "androidx/dynamicanimation/animation/AnimationHandler",
@@ -2267,6 +2369,12 @@
"android/support/animation/Force": "androidx/dynamicanimation/animation/Force",
"android/support/animation/SpringAnimation": "androidx/dynamicanimation/animation/SpringAnimation",
"android/support/animation/SpringForce": "androidx/dynamicanimation/animation/SpringForce",
+ "android/arch/persistence/db/framework/FrameworkSQLiteDatabase": "androidx/sqlite/db/framework/FrameworkSQLiteDatabase",
+ "android/arch/persistence/db/framework/FrameworkSQLiteProgram": "androidx/sqlite/db/framework/FrameworkSQLiteProgram",
+ "android/arch/persistence/db/framework/FrameworkSQLiteStatement": "androidx/sqlite/db/framework/FrameworkSQLiteStatement",
+ "android/arch/persistence/db/framework/FrameworkSQLiteOpenHelper": "androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper",
+ "android/arch/persistence/room/guava/GuavaRoom": "androidx/room/guava/GuavaRoom",
+ "android/arch/lifecycle/LiveDataReactiveStreams": "androidx/lifecycle/LiveDataReactiveStreams",
"android/support/v4/widget/CircleImageView": "androidx/swiperefreshlayout/widget/CircleImageView",
"android/support/v4/widget/CircularProgressDrawable": "androidx/swiperefreshlayout/widget/CircularProgressDrawable",
"android/support/v4/view/animation/FastOutSlowInInterpolator": "androidx/interpolator/view/animation/FastOutSlowInInterpolator",
@@ -2283,6 +2391,19 @@
"android/support/design/widget/FloatingActionButton": "android/support/design/widget/FloatingActionButton",
"android/support/v7/widget/Toolbar": "androidx/appcompat/widget/Toolbar",
"android/support/design/bottomappbar/R": "android/support/design/bottomappbar/R",
+ "android/arch/paging/AsyncPagedListDiffer": "androidx/paging/AsyncPagedListDiffer",
+ "android/arch/paging/PagedList": "androidx/paging/PagedList",
+ "android/support/v7/util/ListUpdateCallback": "androidx/recyclerview/widget/ListUpdateCallback",
+ "android/support/v7/util/DiffUtil": "androidx/recyclerview/widget/DiffUtil",
+ "android/arch/paging/PagedStorage": "androidx/paging/PagedStorage",
+ "android/support/v7/recyclerview/extensions/AsyncDifferConfig": "androidx/recyclerview/widget/AsyncDifferConfig",
+ "android/arch/paging/PagedStorageDiffHelper": "androidx/paging/PagedStorageDiffHelper",
+ "android/support/v7/util/AdapterListUpdateCallback": "androidx/recyclerview/widget/AdapterListUpdateCallback",
+ "android/arch/paging/LivePagedListBuilder": "androidx/paging/LivePagedListBuilder",
+ "android/arch/paging/DataSource": "androidx/paging/DataSource",
+ "android/arch/lifecycle/ComputableLiveData": "androidx/lifecycle/ComputableLiveData",
+ "android/arch/paging/LivePagedListProvider": "androidx/paging/LivePagedListProvider",
+ "android/arch/paging/PagedListAdapter": "androidx/paging/PagedListAdapter",
"android/support/design/chip/Chip": "android/support/design/chip/Chip",
"android/support/design/chip/ChipDrawable": "android/support/design/chip/ChipDrawable",
"android/support/v4/widget/ExploreByTouchHelper": "androidx/customview/widget/ExploreByTouchHelper",
@@ -2294,9 +2415,13 @@
"android/support/design/chip/ChipGroup": "android/support/design/chip/ChipGroup",
"android/support/v4/app/LoaderManager": "androidx/loader/app/LoaderManager",
"android/support/v4/content/Loader": "androidx/loader/content/Loader",
+ "android/arch/lifecycle/ViewModelStoreOwner": "androidx/lifecycle/ViewModelStoreOwner",
"android/support/v4/app/LoaderManagerImpl": "androidx/loader/app/LoaderManagerImpl",
+ "android/arch/lifecycle/ViewModelStore": "androidx/lifecycle/ViewModelStore",
+ "android/arch/lifecycle/MutableLiveData": "androidx/lifecycle/MutableLiveData",
"android/support/v4/util/DebugUtils": "androidx/core/util/DebugUtils",
- "android/support/v4/util/SparseArrayCompat": "androidx/collection/SparseArrayCompat",
+ "android/arch/lifecycle/ViewModelProvider": "androidx/lifecycle/ViewModelProvider",
+ "android/arch/lifecycle/ViewModel": "androidx/lifecycle/ViewModel",
"android/support/v4/content/AsyncTaskLoader": "androidx/loader/content/AsyncTaskLoader",
"android/support/v4/content/ModernAsyncTask": "androidx/loader/content/ModernAsyncTask",
"android/support/v4/os/OperationCanceledException": "androidx/core/os/OperationCanceledException",
@@ -2304,6 +2429,16 @@
"android/support/v4/content/CursorLoader": "androidx/loader/content/CursorLoader",
"android/support/v4/os/CancellationSignal": "androidx/core/os/CancellationSignal",
"android/support/v4/content/ContentResolverCompat": "androidx/core/content/ContentResolverCompat",
+ "android/arch/persistence/room/migration/bundle/DatabaseBundle": "androidx/room/migration/bundle/DatabaseBundle",
+ "android/arch/persistence/room/migration/bundle/SchemaEquality": "androidx/room/migration/bundle/SchemaEquality",
+ "android/arch/persistence/room/migration/bundle/EntityBundle": "androidx/room/migration/bundle/EntityBundle",
+ "android/arch/persistence/room/migration/bundle/SchemaEqualityUtil": "androidx/room/migration/bundle/SchemaEqualityUtil",
+ "android/arch/persistence/room/migration/bundle/FieldBundle": "androidx/room/migration/bundle/FieldBundle",
+ "android/arch/persistence/room/migration/bundle/IndexBundle": "androidx/room/migration/bundle/IndexBundle",
+ "android/arch/persistence/room/migration/bundle/BundleUtil": "androidx/room/migration/bundle/BundleUtil",
+ "android/arch/persistence/room/migration/bundle/PrimaryKeyBundle": "androidx/room/migration/bundle/PrimaryKeyBundle",
+ "android/arch/persistence/room/migration/bundle/ForeignKeyBundle": "androidx/room/migration/bundle/ForeignKeyBundle",
+ "android/arch/persistence/room/migration/bundle/SchemaBundle": "androidx/room/migration/bundle/SchemaBundle",
"android/support/design/widget/AppBarLayout": "android/support/design/widget/AppBarLayout",
"android/support/v4/view/OnApplyWindowInsetsListener": "androidx/core/view/OnApplyWindowInsetsListener",
"android/support/v4/view/WindowInsetsCompat": "androidx/core/view/WindowInsetsCompat",
@@ -2390,9 +2525,55 @@
"android/support/v4/view/animation/FastOutLinearInInterpolator": "androidx/interpolator/view/animation/FastOutLinearInInterpolator",
"android/support/v4/view/animation/LookupTableInterpolator": "androidx/interpolator/view/animation/LookupTableInterpolator",
"android/support/v4/view/animation/LinearOutSlowInInterpolator": "androidx/interpolator/view/animation/LinearOutSlowInInterpolator",
+ "android/arch/lifecycle/MediatorLiveData": "androidx/lifecycle/MediatorLiveData",
+ "android/arch/lifecycle/Transformations": "androidx/lifecycle/Transformations",
+ "android/arch/core/util/Function": "androidx/arch/core/util/Function",
+ "android/databinding/adapters/AbsListViewBindingAdapter": "androidx/databinding/adapters/AbsListViewBindingAdapter",
+ "android/databinding/adapters/AbsSeekBarBindingAdapter": "androidx/databinding/adapters/AbsSeekBarBindingAdapter",
+ "android/databinding/adapters/AbsSpinnerBindingAdapter": "androidx/databinding/adapters/AbsSpinnerBindingAdapter",
+ "android/databinding/adapters/ObservableListAdapter": "androidx/databinding/adapters/ObservableListAdapter",
+ "android/databinding/adapters/ActionMenuViewBindingAdapter": "androidx/databinding/adapters/ActionMenuViewBindingAdapter",
+ "android/databinding/adapters/AdapterViewBindingAdapter": "androidx/databinding/adapters/AdapterViewBindingAdapter",
+ "android/databinding/adapters/AutoCompleteTextViewBindingAdapter": "androidx/databinding/adapters/AutoCompleteTextViewBindingAdapter",
+ "android/databinding/adapters/CalendarViewBindingAdapter": "androidx/databinding/adapters/CalendarViewBindingAdapter",
+ "android/databinding/adapters/CardViewBindingAdapter": "androidx/databinding/adapters/CardViewBindingAdapter",
+ "android/databinding/adapters/CheckedTextViewBindingAdapter": "androidx/databinding/adapters/CheckedTextViewBindingAdapter",
+ "android/databinding/adapters/ChronometerBindingAdapter": "androidx/databinding/adapters/ChronometerBindingAdapter",
+ "android/databinding/adapters/CompoundButtonBindingAdapter": "androidx/databinding/adapters/CompoundButtonBindingAdapter",
+ "android/databinding/adapters/Converters": "androidx/databinding/adapters/Converters",
+ "android/databinding/adapters/DatePickerBindingAdapter": "androidx/databinding/adapters/DatePickerBindingAdapter",
+ "android/databinding/adapters/ListenerUtil": "androidx/databinding/adapters/ListenerUtil",
+ "android/databinding/adapters/ExpandableListViewBindingAdapter": "androidx/databinding/adapters/ExpandableListViewBindingAdapter",
+ "android/databinding/adapters/FrameLayoutBindingAdapter": "androidx/databinding/adapters/FrameLayoutBindingAdapter",
+ "android/databinding/adapters/ImageViewBindingAdapter": "androidx/databinding/adapters/ImageViewBindingAdapter",
+ "android/databinding/adapters/LinearLayoutBindingAdapter": "androidx/databinding/adapters/LinearLayoutBindingAdapter",
+ "android/databinding/adapters/NumberPickerBindingAdapter": "androidx/databinding/adapters/NumberPickerBindingAdapter",
+ "android/databinding/adapters/ProgressBarBindingAdapter": "androidx/databinding/adapters/ProgressBarBindingAdapter",
+ "android/databinding/adapters/RadioGroupBindingAdapter": "androidx/databinding/adapters/RadioGroupBindingAdapter",
+ "android/databinding/adapters/RatingBarBindingAdapter": "androidx/databinding/adapters/RatingBarBindingAdapter",
+ "android/databinding/adapters/SearchViewBindingAdapter": "androidx/databinding/adapters/SearchViewBindingAdapter",
+ "android/databinding/adapters/SeekBarBindingAdapter": "androidx/databinding/adapters/SeekBarBindingAdapter",
+ "android/databinding/adapters/SpinnerBindingAdapter": "androidx/databinding/adapters/SpinnerBindingAdapter",
+ "android/databinding/adapters/SwitchBindingAdapter": "androidx/databinding/adapters/SwitchBindingAdapter",
+ "android/databinding/adapters/SwitchCompatBindingAdapter": "androidx/databinding/adapters/SwitchCompatBindingAdapter",
+ "android/support/v7/widget/SwitchCompat": "androidx/appcompat/widget/SwitchCompat",
+ "android/databinding/adapters/TabHostBindingAdapter": "androidx/databinding/adapters/TabHostBindingAdapter",
+ "android/databinding/adapters/TabWidgetBindingAdapter": "androidx/databinding/adapters/TabWidgetBindingAdapter",
+ "android/databinding/adapters/TableLayoutBindingAdapter": "androidx/databinding/adapters/TableLayoutBindingAdapter",
+ "android/databinding/adapters/TextViewBindingAdapter": "androidx/databinding/adapters/TextViewBindingAdapter",
+ "android/databinding/adapters/TimePickerBindingAdapter": "androidx/databinding/adapters/TimePickerBindingAdapter",
+ "android/databinding/adapters/ToolbarBindingAdapter": "androidx/databinding/adapters/ToolbarBindingAdapter",
+ "android/databinding/adapters/VideoViewBindingAdapter": "androidx/databinding/adapters/VideoViewBindingAdapter",
+ "android/databinding/adapters/ViewBindingAdapter": "androidx/databinding/adapters/ViewBindingAdapter",
+ "android/databinding/adapters/ViewGroupBindingAdapter": "androidx/databinding/adapters/ViewGroupBindingAdapter",
+ "android/databinding/adapters/ViewStubBindingAdapter": "androidx/databinding/adapters/ViewStubBindingAdapter",
+ "android/databinding/ViewStubProxy": "androidx/databinding/ViewStubProxy",
+ "android/databinding/adapters/ZoomControlsBindingAdapter": "androidx/databinding/adapters/ZoomControlsBindingAdapter",
+ "android/databinding/DataBinderMapper": "androidx/databinding/DataBinderMapper",
+ "android/databinding/DataBindingComponent": "androidx/databinding/DataBindingComponent",
+ "android/databinding/ViewDataBinding": "androidx/databinding/ViewDataBinding",
"android/support/text/emoji/EmojiProcessor": "androidx/emoji/text/EmojiProcessor",
"android/support/text/emoji/EmojiMetadata": "androidx/emoji/text/EmojiMetadata",
- "android/support/v4/util/ArraySet": "androidx/collection/ArraySet",
"android/support/text/emoji/EmojiSpan": "androidx/emoji/text/EmojiSpan",
"android/support/text/emoji/TypefaceEmojiSpan": "androidx/emoji/text/TypefaceEmojiSpan",
"android/support/v4/graphics/PaintCompat": "androidx/core/graphics/PaintCompat",
@@ -2418,6 +2599,7 @@
"android/support/text/emoji/widget/EmojiInputFilter": "androidx/emoji/widget/EmojiInputFilter",
"android/support/text/emoji/widget/EmojiTextView": "androidx/emoji/widget/EmojiTextView",
"android/support/text/emoji/widget/EmojiTransformationMethod": "androidx/emoji/widget/EmojiTransformationMethod",
+ "android/arch/lifecycle/GenericLifecycleObserver": "androidx/lifecycle/GenericLifecycleObserver",
"android/support/v13/view/DragAndDropPermissionsCompat": "androidx/core/view/DragAndDropPermissionsCompat",
"android/support/v13/view/DragStartHelper": "androidx/core/view/DragStartHelper",
"android/support/v4/view/MotionEventCompat": "androidx/core/view/MotionEventCompat",
@@ -2427,7 +2609,6 @@
"android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat": "androidx/core/accessibilityservice/AccessibilityServiceInfoCompat",
"android/support/v4/app/ActivityCompat": "androidx/core/app/ActivityCompat",
"android/support/v4/app/SharedElementCallback": "androidx/core/app/SharedElementCallback",
- "android/support/v4/app/ActivityManagerCompat": "androidx/core/app/ActivityManagerCompat",
"android/support/v4/app/ActivityOptionsCompat": "androidx/core/app/ActivityOptionsCompat",
"android/support/v4/app/AlarmManagerCompat": "androidx/core/app/AlarmManagerCompat",
"android/support/v4/app/AppLaunchChecker": "androidx/core/app/AppLaunchChecker",
@@ -2445,6 +2626,8 @@
"android/support/v4/app/NotificationManagerCompat": "androidx/core/app/NotificationManagerCompat",
"android/support/v4/app/ServiceCompat": "androidx/core/app/ServiceCompat",
"android/support/v4/app/ShareCompat": "androidx/core/app/ShareCompat",
+ "android/arch/lifecycle/LifecycleRegistry": "androidx/lifecycle/LifecycleRegistry",
+ "android/arch/lifecycle/ReportFragment": "androidx/lifecycle/ReportFragment",
"android/support/v4/app/TaskStackBuilder": "androidx/core/app/TaskStackBuilder",
"android/support/v4/content/FileProvider": "androidx/core/content/FileProvider",
"android/support/v4/content/IntentCompat": "androidx/core/content/IntentCompat",
@@ -2543,6 +2726,8 @@
"android/support/v4/widget/PopupMenuCompat": "androidx/core/widget/PopupMenuCompat",
"android/support/v4/widget/PopupWindowCompat": "androidx/core/widget/PopupWindowCompat",
"android/support/v4/widget/ScrollerCompat": "androidx/core/widget/ScrollerCompat",
+ "android/arch/core/internal/FastSafeIterableMap": "androidx/arch/core/internal/FastSafeIterableMap",
+ "android/arch/lifecycle/LifecycleRegistryOwner": "androidx/lifecycle/LifecycleRegistryOwner",
"android/support/design/transformation/ExpandableBehavior": "android/support/design/transformation/ExpandableBehavior",
"android/support/design/transformation/ExpandableTransformationBehavior": "android/support/design/transformation/ExpandableTransformationBehavior",
"android/support/design/transformation/FabTransformationBehavior": "android/support/design/transformation/FabTransformationBehavior",
@@ -2567,6 +2752,28 @@
"android/support/v4/widget/SimpleCursorAdapter": "androidx/cursoradapter/widget/SimpleCursorAdapter",
"android/support/design/theme/MaterialComponentsViewInflater": "android/support/design/theme/MaterialComponentsViewInflater",
"android/support/v7/app/AppCompatViewInflater": "androidx/appcompat/app/AppCompatViewInflater",
+ "android/databinding/BaseObservable": "androidx/databinding/BaseObservable",
+ "android/databinding/PropertyChangeRegistry": "androidx/databinding/PropertyChangeRegistry",
+ "android/databinding/BaseObservableField": "androidx/databinding/BaseObservableField",
+ "android/databinding/DataBindingUtil": "androidx/databinding/DataBindingUtil",
+ "android/databinding/DataBinderMapperImpl": "androidx/databinding/DataBinderMapperImpl",
+ "android/databinding/ListChangeRegistry": "androidx/databinding/ListChangeRegistry",
+ "android/databinding/MapChangeRegistry": "androidx/databinding/MapChangeRegistry",
+ "android/databinding/MergedDataBinderMapper": "androidx/databinding/MergedDataBinderMapper",
+ "android/databinding/ObservableArrayList": "androidx/databinding/ObservableArrayList",
+ "android/databinding/ObservableArrayMap": "androidx/databinding/ObservableArrayMap",
+ "android/databinding/ObservableBoolean": "androidx/databinding/ObservableBoolean",
+ "android/databinding/ObservableByte": "androidx/databinding/ObservableByte",
+ "android/databinding/ObservableChar": "androidx/databinding/ObservableChar",
+ "android/databinding/ObservableDouble": "androidx/databinding/ObservableDouble",
+ "android/databinding/ObservableField": "androidx/databinding/ObservableField",
+ "android/databinding/ObservableFloat": "androidx/databinding/ObservableFloat",
+ "android/databinding/ObservableInt": "androidx/databinding/ObservableInt",
+ "android/databinding/ObservableLong": "androidx/databinding/ObservableLong",
+ "android/databinding/ObservableParcelable": "androidx/databinding/ObservableParcelable",
+ "android/databinding/ObservableShort": "androidx/databinding/ObservableShort",
+ "android/databinding/OnRebindCallback": "androidx/databinding/OnRebindCallback",
+ "android/support/v4/util/LongSparseArray": "androidx/collection/LongSparseArray",
"android/support/v4/app/BackStackRecord": "androidx/fragment/app/BackStackRecord",
"android/support/v4/app/Fragment": "androidx/fragment/app/Fragment",
"android/support/v4/app/FragmentTransaction": "androidx/fragment/app/FragmentTransaction",
@@ -2742,8 +2949,6 @@
"android/support/v17/leanback/widget/MediaItemActionPresenter": "androidx/leanback/widget/MediaItemActionPresenter",
"android/support/v17/leanback/widget/AbstractMediaListHeaderPresenter": "androidx/leanback/widget/AbstractMediaListHeaderPresenter",
"android/support/v17/leanback/widget/ActionPresenterSelector": "androidx/leanback/widget/ActionPresenterSelector",
- "android/support/v7/util/DiffUtil": "androidx/recyclerview/widget/DiffUtil",
- "android/support/v7/util/ListUpdateCallback": "androidx/recyclerview/widget/ListUpdateCallback",
"android/support/v17/leanback/widget/BaseCardView": "androidx/leanback/widget/BaseCardView",
"android/support/v17/leanback/widget/GridLayoutManager": "androidx/leanback/widget/GridLayoutManager",
"android/support/v17/leanback/widget/WindowAlignment": "androidx/leanback/widget/WindowAlignment",
@@ -2830,6 +3035,16 @@
"android/support/v4/provider/SingleDocumentFile": "androidx/documentfile/provider/SingleDocumentFile",
"android/support/v4/provider/TreeDocumentFile": "androidx/documentfile/provider/TreeDocumentFile",
"android/support/v4/provider/DocumentsContractApi19": "androidx/documentfile/provider/DocumentsContractApi19",
+ "android/arch/lifecycle/EmptyActivityLifecycleCallbacks": "androidx/lifecycle/EmptyActivityLifecycleCallbacks",
+ "android/arch/lifecycle/HolderFragment": "androidx/lifecycle/HolderFragment",
+ "android/arch/lifecycle/LifecycleDispatcher": "androidx/lifecycle/LifecycleDispatcher",
+ "android/arch/lifecycle/LifecycleService": "androidx/lifecycle/LifecycleService",
+ "android/arch/lifecycle/ServiceLifecycleDispatcher": "androidx/lifecycle/ServiceLifecycleDispatcher",
+ "android/arch/lifecycle/ProcessLifecycleOwner": "androidx/lifecycle/ProcessLifecycleOwner",
+ "android/arch/lifecycle/ProcessLifecycleOwnerInitializer": "androidx/lifecycle/ProcessLifecycleOwnerInitializer",
+ "android/arch/lifecycle/ViewModelProviders": "androidx/lifecycle/ViewModelProviders",
+ "android/arch/lifecycle/ViewModelStores": "androidx/lifecycle/ViewModelStores",
+ "android/arch/persistence/room/testing/MigrationTestHelper": "androidx/room/testing/MigrationTestHelper",
"android/support/wear/ambient/AmbientDelegate": "androidx/wear/ambient/AmbientDelegate",
"android/support/wear/ambient/WearableControllerProvider": "androidx/wear/ambient/WearableControllerProvider",
"android/support/wear/ambient/AmbientMode": "androidx/wear/ambient/AmbientMode",
@@ -2871,8 +3086,6 @@
"android/support/wear/widget/drawer/WearableDrawerLayout": "androidx/wear/widget/drawer/WearableDrawerLayout",
"android/support/v4/content/LocalBroadcastManager": "androidx/localbroadcastmanager/content/LocalBroadcastManager",
"android/support/v4/print/PrintHelper": "androidx/print/PrintHelper",
- "android/support/v7/recyclerview/extensions/AsyncDifferConfig": "androidx/recyclerview/widget/AsyncDifferConfig",
- "android/support/v7/util/AdapterListUpdateCallback": "androidx/recyclerview/widget/AdapterListUpdateCallback",
"android/support/media/ExifInterface": "androidx/exifinterface/media/ExifInterface",
"android/support/v7/app/MediaRouteActionProvider": "androidx/mediarouter/app/MediaRouteActionProvider",
"android/support/v7/media/MediaRouter": "androidx/mediarouter/media/MediaRouter",
@@ -2994,7 +3207,6 @@
"android/support/transition/Slide": "androidx/transition/Slide",
"android/support/transition/WindowIdImpl": "androidx/transition/WindowIdImpl",
"android/support/transition/TransitionValuesMaps": "androidx/transition/TransitionValuesMaps",
- "android/support/v4/util/LongSparseArray": "androidx/collection/LongSparseArray",
"android/support/transition/TransitionInflater": "androidx/transition/TransitionInflater",
"android/support/transition/ViewGroupOverlayApi14": "androidx/transition/ViewGroupOverlayApi14",
"android/support/transition/ViewOverlayApi14": "androidx/transition/ViewOverlayApi14",
@@ -3040,7 +3252,6 @@
"android/support/v7/preference/PreferenceInflater": "androidx/preference/PreferenceInflater",
"android/support/v7/preference/SeekBarPreference": "androidx/preference/SeekBarPreference",
"android/support/v7/preference/SwitchPreferenceCompat": "androidx/preference/SwitchPreferenceCompat",
- "android/support/v7/widget/SwitchCompat": "androidx/appcompat/widget/SwitchCompat",
"android/support/v7/preference/UnPressableLinearLayout": "androidx/preference/UnPressableLinearLayout",
"android/support/v7/view/menu/SubMenuBuilder": "androidx/appcompat/view/menu/SubMenuBuilder",
"android/support/v7/widget/LinearLayoutCompat": "androidx/appcompat/widget/LinearLayoutCompat",
@@ -3082,6 +3293,182 @@
"android/support/content/Query": "androidx/contentpager/content/Query",
"android/support/content/InMemoryCursor": "androidx/contentpager/content/InMemoryCursor",
"android/support/content/LoaderQueryRunner": "androidx/contentpager/content/LoaderQueryRunner",
+ "android/arch/persistence/room/parser/SQLiteParser": "androidx/room/parser/SQLiteParser",
+ "android/arch/persistence/room/parser/SQLiteListener": "androidx/room/parser/SQLiteListener",
+ "android/arch/persistence/room/parser/SQLiteVisitor": "androidx/room/parser/SQLiteVisitor",
+ "android/arch/persistence/room/parser/SQLiteLexer": "androidx/room/parser/SQLiteLexer",
+ "android/arch/persistence/room/parser/SQLiteBaseVisitor": "androidx/room/parser/SQLiteBaseVisitor",
+ "android/arch/persistence/room/parser/SQLiteBaseListener": "androidx/room/parser/SQLiteBaseListener",
+ "android/arch/persistence/room/parser/SQLTypeAffinity": "androidx/room/parser/SQLTypeAffinity",
+ "android/arch/persistence/room/verifier/ColumnInfo": "androidx/room/verifier/ColumnInfo",
+ "android/arch/persistence/room/parser/QueryVisitor": "androidx/room/parser/QueryVisitor",
+ "android/arch/persistence/room/parser/ParsedQuery": "androidx/room/parser/ParsedQuery",
+ "android/arch/persistence/room/parser/ParserErrors": "androidx/room/parser/ParserErrors",
+ "android/arch/persistence/room/parser/QueryType": "androidx/room/parser/QueryType",
+ "android/arch/persistence/room/parser/SqlParser": "androidx/room/parser/SqlParser",
+ "android/arch/persistence/room/parser/Table": "androidx/room/parser/Table",
+ "android/arch/persistence/room/parser/Section": "androidx/room/parser/Section",
+ "android/arch/persistence/room/parser/SectionType": "androidx/room/parser/SectionType",
+ "android/arch/persistence/room/verifier/QueryResultInfo": "androidx/room/verifier/QueryResultInfo",
+ "android/arch/persistence/room/parser/Collate": "androidx/room/parser/Collate",
+ "android/arch/persistence/room/verifier/DatabaseVerifier": "androidx/room/verifier/DatabaseVerifier",
+ "android/arch/persistence/room/processor/Context": "androidx/room/processor/Context",
+ "android/arch/persistence/room/vo/Entity": "androidx/room/vo/Entity",
+ "android/arch/persistence/room/log/RLog": "androidx/room/log/RLog",
+ "android/arch/persistence/room/vo/Warning": "androidx/room/vo/Warning",
+ "android/arch/persistence/room/verifier/DatabaseVerificaitonErrors": "androidx/room/verifier/DatabaseVerificaitonErrors",
+ "android/arch/persistence/room/solver/types/BoxedBooleanToBoxedIntConverter": "androidx/room/solver/types/BoxedBooleanToBoxedIntConverter",
+ "android/arch/persistence/room/solver/types/TypeConverter": "androidx/room/solver/types/TypeConverter",
+ "android/arch/persistence/room/solver/CodeGenScope": "androidx/room/solver/CodeGenScope",
+ "android/arch/persistence/room/ext/Javapoet_extKt": "androidx/room/ext/Javapoet_extKt",
+ "android/arch/persistence/room/solver/types/PrimitiveColumnTypeAdapter": "androidx/room/solver/types/PrimitiveColumnTypeAdapter",
+ "android/arch/persistence/room/solver/types/ColumnTypeAdapter": "androidx/room/solver/types/ColumnTypeAdapter",
+ "android/arch/persistence/room/solver/types/BoxedPrimitiveColumnTypeAdapter": "androidx/room/solver/types/BoxedPrimitiveColumnTypeAdapter",
+ "android/arch/persistence/room/solver/types/PrimitiveBooleanToIntConverter": "androidx/room/solver/types/PrimitiveBooleanToIntConverter",
+ "android/arch/persistence/room/solver/types/CompositeAdapter": "androidx/room/solver/types/CompositeAdapter",
+ "android/arch/persistence/room/solver/types/NoOpConverter": "androidx/room/solver/types/NoOpConverter",
+ "android/arch/persistence/room/solver/types/StringColumnTypeAdapter": "androidx/room/solver/types/StringColumnTypeAdapter",
+ "android/arch/persistence/room/solver/types/StatementValueBinder": "androidx/room/solver/types/StatementValueBinder",
+ "android/arch/persistence/room/solver/types/CursorValueReader": "androidx/room/solver/types/CursorValueReader",
+ "android/arch/persistence/room/solver/types/CustomTypeConverterWrapper": "androidx/room/solver/types/CustomTypeConverterWrapper",
+ "android/arch/persistence/room/vo/CustomTypeConverter": "androidx/room/vo/CustomTypeConverter",
+ "android/arch/persistence/room/writer/ClassWriter": "androidx/room/writer/ClassWriter",
+ "android/arch/persistence/room/solver/types/ByteArrayColumnTypeAdapter": "androidx/room/solver/types/ByteArrayColumnTypeAdapter",
+ "android/arch/persistence/room/solver/types/CompositeTypeConverter": "androidx/room/solver/types/CompositeTypeConverter",
+ "android/arch/persistence/room/solver/TypeAdapterStore": "androidx/room/solver/TypeAdapterStore",
+ "android/arch/persistence/room/solver/binderprovider/LiveDataQueryResultBinderProvider": "androidx/room/solver/binderprovider/LiveDataQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/ObservableQueryResultBinderProvider": "androidx/room/solver/ObservableQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/QueryResultAdapter": "androidx/room/solver/query/result/QueryResultAdapter",
+ "android/arch/persistence/room/solver/query/result/QueryResultBinder": "androidx/room/solver/query/result/QueryResultBinder",
+ "android/arch/persistence/room/solver/query/result/LiveDataQueryResultBinder": "androidx/room/solver/query/result/LiveDataQueryResultBinder",
+ "android/arch/persistence/room/solver/binderprovider/DataSourceQueryResultBinderProvider": "androidx/room/solver/binderprovider/DataSourceQueryResultBinderProvider",
+ "android/arch/persistence/room/ext/PagingTypeNames": "androidx/room/ext/PagingTypeNames",
+ "android/arch/persistence/room/solver/QueryResultBinderProvider": "androidx/room/solver/QueryResultBinderProvider",
+ "android/arch/persistence/room/processor/ProcessorErrors": "androidx/room/processor/ProcessorErrors",
+ "android/arch/persistence/room/solver/query/result/RowAdapter": "androidx/room/solver/query/result/RowAdapter",
+ "android/arch/persistence/room/solver/query/result/ListQueryResultAdapter": "androidx/room/solver/query/result/ListQueryResultAdapter",
+ "android/arch/persistence/room/solver/query/result/PositionalDataSourceQueryResultBinder": "androidx/room/solver/query/result/PositionalDataSourceQueryResultBinder",
+ "android/arch/persistence/room/ext/LifecyclesTypeNames": "androidx/room/ext/LifecyclesTypeNames",
+ "android/arch/persistence/room/solver/binderprovider/RxMaybeQueryResultBinderProvider": "androidx/room/solver/binderprovider/RxMaybeQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/binderprovider/RxCallableQueryResultBinderProvider": "androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/RxCallableQueryResultBinder": "androidx/room/solver/query/result/RxCallableQueryResultBinder",
+ "android/arch/persistence/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider": "androidx/room/solver/binderprovider/GuavaListenableFutureQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/GuavaListenableFutureQueryResultBinder": "androidx/room/solver/query/result/GuavaListenableFutureQueryResultBinder",
+ "android/arch/persistence/room/ext/GuavaUtilConcurrentTypeNames": "androidx/room/ext/GuavaUtilConcurrentTypeNames",
+ "android/arch/persistence/room/solver/binderprovider/FlowableQueryResultBinderProvider": "androidx/room/solver/binderprovider/FlowableQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/FlowableQueryResultBinder": "androidx/room/solver/query/result/FlowableQueryResultBinder",
+ "android/arch/persistence/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider": "androidx/room/solver/binderprovider/DataSourceFactoryQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/DataSourceFactoryQueryResultBinder": "androidx/room/solver/query/result/DataSourceFactoryQueryResultBinder",
+ "android/arch/persistence/room/ext/RoomRxJava2TypeNames": "androidx/room/ext/RoomRxJava2TypeNames",
+ "android/arch/persistence/room/ext/RoomGuavaTypeNames": "androidx/room/ext/RoomGuavaTypeNames",
+ "android/arch/persistence/room/solver/binderprovider/InstantQueryResultBinderProvider": "androidx/room/solver/binderprovider/InstantQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/InstantQueryResultBinder": "androidx/room/solver/query/result/InstantQueryResultBinder",
+ "android/arch/persistence/room/ext/RxJava2TypeNames": "androidx/room/ext/RxJava2TypeNames",
+ "android/arch/persistence/room/solver/binderprovider/CursorQueryResultBinderProvider": "androidx/room/solver/binderprovider/CursorQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/CursorQueryResultBinder": "androidx/room/solver/query/result/CursorQueryResultBinder",
+ "android/arch/persistence/room/ext/AndroidTypeNames": "androidx/room/ext/AndroidTypeNames",
+ "android/arch/persistence/room/solver/binderprovider/RxSingleQueryResultBinderProvider": "androidx/room/solver/binderprovider/RxSingleQueryResultBinderProvider",
+ "android/arch/persistence/room/solver/query/result/SingleEntityQueryResultAdapter": "androidx/room/solver/query/result/SingleEntityQueryResultAdapter",
+ "android/arch/persistence/room/ext/GuavaBaseTypeNames": "androidx/room/ext/GuavaBaseTypeNames",
+ "android/arch/persistence/room/solver/query/result/GuavaOptionalQueryResultAdapter": "androidx/room/solver/query/result/GuavaOptionalQueryResultAdapter",
+ "android/arch/persistence/room/ext/CommonTypeNames": "androidx/room/ext/CommonTypeNames",
+ "android/arch/persistence/room/solver/query/result/OptionalQueryResultAdapter": "androidx/room/solver/query/result/OptionalQueryResultAdapter",
+ "android/arch/persistence/room/solver/query/result/ArrayQueryResultAdapter": "androidx/room/solver/query/result/ArrayQueryResultAdapter",
+ "android/arch/persistence/room/solver/query/result/PojoRowAdapter": "androidx/room/solver/query/result/PojoRowAdapter",
+ "android/arch/persistence/room/Entity": "androidx/room/Entity",
+ "android/arch/persistence/room/ext/Element_extKt": "androidx/room/ext/Element_extKt",
+ "android/arch/persistence/room/solver/query/result/EntityRowAdapter": "androidx/room/solver/query/result/EntityRowAdapter",
+ "android/arch/persistence/room/processor/EntityProcessor": "androidx/room/processor/EntityProcessor",
+ "android/arch/persistence/room/solver/query/result/SingleColumnRowAdapter": "androidx/room/solver/query/result/SingleColumnRowAdapter",
+ "android/arch/persistence/room/processor/PojoProcessor": "androidx/room/processor/PojoProcessor",
+ "android/arch/persistence/room/processor/FieldProcessor": "androidx/room/processor/FieldProcessor",
+ "android/arch/persistence/room/vo/EmbeddedField": "androidx/room/vo/EmbeddedField",
+ "android/arch/persistence/room/vo/Pojo": "androidx/room/vo/Pojo",
+ "android/arch/persistence/room/solver/query/parameter/QueryParameterAdapter": "androidx/room/solver/query/parameter/QueryParameterAdapter",
+ "android/arch/persistence/room/solver/query/parameter/CollectionQueryParameterAdapter": "androidx/room/solver/query/parameter/CollectionQueryParameterAdapter",
+ "android/arch/persistence/room/solver/query/parameter/BasicQueryParameterAdapter": "androidx/room/solver/query/parameter/BasicQueryParameterAdapter",
+ "android/arch/persistence/room/solver/query/parameter/ArrayQueryParameterAdapter": "androidx/room/solver/query/parameter/ArrayQueryParameterAdapter",
+ "android/arch/persistence/room/solver/query/result/BaseObservableQueryResultBinder": "androidx/room/solver/query/result/BaseObservableQueryResultBinder",
+ "android/arch/persistence/room/solver/query/result/TransactionWrapperKt": "androidx/room/solver/query/result/TransactionWrapperKt",
+ "android/arch/persistence/room/solver/query/result/TransactionWrapper": "androidx/room/solver/query/result/TransactionWrapper",
+ "android/arch/persistence/room/writer/DaoWriter": "androidx/room/writer/DaoWriter",
+ "android/arch/persistence/room/writer/EntityCursorConverterWriter": "androidx/room/writer/EntityCursorConverterWriter",
+ "android/arch/persistence/room/vo/RelationCollector": "androidx/room/vo/RelationCollector",
+ "android/arch/persistence/room/vo/Field": "androidx/room/vo/Field",
+ "android/arch/persistence/room/vo/FieldWithIndex": "androidx/room/vo/FieldWithIndex",
+ "android/arch/persistence/room/writer/FieldReadWriteWriter": "androidx/room/writer/FieldReadWriteWriter",
+ "android/arch/persistence/room/ext/RoomTypeNames": "androidx/room/ext/RoomTypeNames",
+ "android/arch/persistence/room/vo/Dao": "androidx/room/vo/Dao",
+ "android/arch/persistence/room/vo/Constructor": "androidx/room/vo/Constructor",
+ "android/arch/persistence/room/vo/Database": "androidx/room/vo/Database",
+ "android/arch/persistence/room/vo/Index": "androidx/room/vo/Index",
+ "android/arch/persistence/room/vo/SchemaIdentityKey": "androidx/room/vo/SchemaIdentityKey",
+ "android/arch/persistence/room/vo/DeletionMethod": "androidx/room/vo/DeletionMethod",
+ "android/arch/persistence/room/vo/ShortcutMethod": "androidx/room/vo/ShortcutMethod",
+ "android/arch/persistence/room/vo/ShortcutQueryParameter": "androidx/room/vo/ShortcutQueryParameter",
+ "android/arch/persistence/room/vo/HasSchemaIdentity": "androidx/room/vo/HasSchemaIdentity",
+ "android/arch/persistence/room/vo/PrimaryKey": "androidx/room/vo/PrimaryKey",
+ "android/arch/persistence/room/vo/PojoMethod": "androidx/room/vo/PojoMethod",
+ "android/arch/persistence/room/vo/TransactionMethod": "androidx/room/vo/TransactionMethod",
+ "android/arch/persistence/room/vo/QueryMethod": "androidx/room/vo/QueryMethod",
+ "android/arch/persistence/room/vo/FieldGetter": "androidx/room/vo/FieldGetter",
+ "android/arch/persistence/room/vo/CallType": "androidx/room/vo/CallType",
+ "android/arch/persistence/room/vo/ForeignKeyAction": "androidx/room/vo/ForeignKeyAction",
+ "android/arch/persistence/room/vo/ForeignKey": "androidx/room/vo/ForeignKey",
+ "android/arch/persistence/room/vo/Relation": "androidx/room/vo/Relation",
+ "android/arch/persistence/room/preconditions/Checks": "androidx/room/preconditions/Checks",
+ "android/arch/persistence/room/vo/QueryParameter": "androidx/room/vo/QueryParameter",
+ "android/arch/persistence/room/writer/RelationCollectorMethodWriter": "androidx/room/writer/RelationCollectorMethodWriter",
+ "android/arch/persistence/room/writer/QueryWriter": "androidx/room/writer/QueryWriter",
+ "android/arch/persistence/room/vo/RawQueryMethod": "androidx/room/vo/RawQueryMethod",
+ "android/arch/persistence/room/vo/UpdateMethod": "androidx/room/vo/UpdateMethod",
+ "android/arch/persistence/room/vo/FieldSetter": "androidx/room/vo/FieldSetter",
+ "android/arch/persistence/room/vo/InsertionMethod": "androidx/room/vo/InsertionMethod",
+ "android/arch/persistence/room/vo/DaoMethod": "androidx/room/vo/DaoMethod",
+ "android/arch/persistence/room/ext/SupportDbTypeNames": "androidx/room/ext/SupportDbTypeNames",
+ "android/arch/persistence/room/RoomProcessor": "androidx/room/RoomProcessor",
+ "android/arch/persistence/room/writer/EntityInsertionAdapterWriter": "androidx/room/writer/EntityInsertionAdapterWriter",
+ "android/arch/persistence/room/writer/TableInfoValidationWriter": "androidx/room/writer/TableInfoValidationWriter",
+ "android/arch/persistence/room/writer/DatabaseWriter": "androidx/room/writer/DatabaseWriter",
+ "android/arch/persistence/room/writer/EntityDeleteComparator": "androidx/room/writer/EntityDeleteComparator",
+ "android/arch/persistence/room/writer/EntityDeletionAdapterWriter": "androidx/room/writer/EntityDeletionAdapterWriter",
+ "android/arch/persistence/room/writer/EntityUpdateAdapterWriter": "androidx/room/writer/EntityUpdateAdapterWriter",
+ "android/arch/persistence/room/writer/SQLiteOpenHelperWriter": "androidx/room/writer/SQLiteOpenHelperWriter",
+ "android/arch/persistence/room/processor/OnConflictProcessor": "androidx/room/processor/OnConflictProcessor",
+ "android/arch/persistence/room/writer/PreparedStatementWriter": "androidx/room/writer/PreparedStatementWriter",
+ "android/arch/persistence/room/ext/KotlinMetadataProcessor": "androidx/room/ext/KotlinMetadataProcessor",
+ "android/arch/persistence/room/ext/ArchTypeNames": "androidx/room/ext/ArchTypeNames",
+ "android/arch/persistence/room/ext/ReactiveStreamsTypeNames": "androidx/room/ext/ReactiveStreamsTypeNames",
+ "android/arch/persistence/room/Database": "androidx/room/Database",
+ "android/arch/persistence/room/processor/DatabaseProcessor": "androidx/room/processor/DatabaseProcessor",
+ "android/arch/persistence/room/Dao": "androidx/room/Dao",
+ "android/arch/persistence/room/processor/CustomConverterProcessor": "androidx/room/processor/CustomConverterProcessor",
+ "android/arch/persistence/room/processor/cache/Cache": "androidx/room/processor/cache/Cache",
+ "android/arch/persistence/room/Embedded": "androidx/room/Embedded",
+ "android/arch/persistence/room/Relation": "androidx/room/Relation",
+ "android/arch/persistence/room/Ignore": "androidx/room/Ignore",
+ "android/arch/persistence/room/processor/PojoMethodProcessor": "androidx/room/processor/PojoMethodProcessor",
+ "android/arch/persistence/room/processor/InsertionMethodProcessor": "androidx/room/processor/InsertionMethodProcessor",
+ "android/arch/persistence/room/SkipQueryVerification": "androidx/room/SkipQueryVerification",
+ "android/arch/persistence/room/processor/DaoProcessor": "androidx/room/processor/DaoProcessor",
+ "android/arch/persistence/room/processor/DeletionMethodProcessor": "androidx/room/processor/DeletionMethodProcessor",
+ "android/arch/persistence/room/processor/ShortcutMethodProcessor": "androidx/room/processor/ShortcutMethodProcessor",
+ "android/arch/persistence/room/Delete": "androidx/room/Delete",
+ "android/arch/persistence/room/processor/TransactionMethodProcessor": "androidx/room/processor/TransactionMethodProcessor",
+ "android/arch/persistence/room/processor/ShortcutParameterProcessor": "androidx/room/processor/ShortcutParameterProcessor",
+ "android/arch/persistence/room/processor/RawQueryMethodProcessor": "androidx/room/processor/RawQueryMethodProcessor",
+ "android/arch/persistence/room/RawQuery": "androidx/room/RawQuery",
+ "android/arch/persistence/room/Transaction": "androidx/room/Transaction",
+ "android/arch/persistence/room/processor/SuppressWarningProcessor": "androidx/room/processor/SuppressWarningProcessor",
+ "android/arch/persistence/room/Insert": "androidx/room/Insert",
+ "android/arch/persistence/room/processor/QueryMethodProcessor": "androidx/room/processor/QueryMethodProcessor",
+ "android/arch/persistence/room/processor/QueryParameterProcessor": "androidx/room/processor/QueryParameterProcessor",
+ "android/arch/persistence/room/processor/UpdateMethodProcessor": "androidx/room/processor/UpdateMethodProcessor",
+ "android/arch/persistence/room/Update": "androidx/room/Update",
+ "android/arch/persistence/room/Query": "androidx/room/Query",
+ "android/arch/persistence/room/TypeConverter": "androidx/room/TypeConverter",
+ "android/arch/persistence/room/TypeConverters": "androidx/room/TypeConverters",
+ "android/arch/persistence/room/PrimaryKey": "androidx/room/PrimaryKey",
"android/support/coordinatorlayout/R": "androidx/coordinatorlayout/R",
"android/support/v4/widget/DirectedAcyclicGraph": "androidx/coordinatorlayout/widget/DirectedAcyclicGraph",
"android/support/v4/widget/ViewGroupUtils": "androidx/coordinatorlayout/widget/ViewGroupUtils",
@@ -3215,12 +3602,23 @@
"android/support/v7/widget/TintResources": "androidx/appcompat/widget/TintResources",
"android/support/v7/widget/TooltipCompatHandler": "androidx/appcompat/widget/TooltipCompatHandler",
"android/support/v7/widget/TooltipPopup": "androidx/appcompat/widget/TooltipPopup",
+ "android/arch/core/executor/JunitTaskExecutorRule": "androidx/arch/core/executor/JunitTaskExecutorRule",
+ "android/arch/core/executor/TaskExecutorWithFakeMainThread": "androidx/arch/core/executor/TaskExecutorWithFakeMainThread",
+ "android/arch/core/executor/TaskExecutor": "androidx/arch/core/executor/TaskExecutor",
+ "android/arch/core/executor/testing/CountingTaskExecutorRule": "androidx/arch/core/executor/testing/CountingTaskExecutorRule",
+ "android/arch/core/executor/DefaultTaskExecutor": "androidx/arch/core/executor/DefaultTaskExecutor",
+ "android/arch/core/executor/testing/InstantTaskExecutorRule": "androidx/arch/core/executor/testing/InstantTaskExecutorRule",
"android/support/text/emoji/widget/EmojiAppCompatButton": "androidx/emoji/widget/EmojiAppCompatButton",
"android/support/text/emoji/widget/EmojiAppCompatEditText": "androidx/emoji/widget/EmojiAppCompatEditText",
"android/support/text/emoji/widget/EmojiAppCompatTextView": "androidx/emoji/widget/EmojiAppCompatTextView",
"android/support/design/card/MaterialCardView": "android/support/design/card/MaterialCardView",
"android/support/design/card/R": "android/support/design/card/R",
"android/support/design/card/MaterialCardViewHelper": "android/support/design/card/MaterialCardViewHelper",
+ "android/arch/lifecycle/ClassesInfoCache": "androidx/lifecycle/ClassesInfoCache",
+ "android/arch/lifecycle/FullLifecycleObserverAdapter": "androidx/lifecycle/FullLifecycleObserverAdapter",
+ "android/arch/lifecycle/SingleGeneratedAdapterObserver": "androidx/lifecycle/SingleGeneratedAdapterObserver",
+ "android/arch/lifecycle/CompositeGeneratedAdaptersObserver": "androidx/lifecycle/CompositeGeneratedAdaptersObserver",
+ "android/arch/lifecycle/ReflectiveGenericLifecycleObserver": "androidx/lifecycle/ReflectiveGenericLifecycleObserver",
"android/support/customtabs/CustomTabsCallback": "androidx/browser/customtabs/CustomTabsCallback",
"android/support/customtabs/CustomTabsClient": "androidx/browser/customtabs/CustomTabsClient",
"android/support/customtabs/CustomTabsServiceConnection": "androidx/browser/customtabs/CustomTabsServiceConnection",
@@ -3235,13 +3633,31 @@
"android/support/customtabs/PostMessageServiceConnection": "androidx/browser/customtabs/PostMessageServiceConnection",
"android/support/customtabs/TrustedWebUtils": "androidx/browser/customtabs/TrustedWebUtils",
"android/support/customtabs/R": "androidx/browser/R",
+ "android/arch/lifecycle/AndroidViewModel": "androidx/lifecycle/AndroidViewModel",
"android/support/design/circularreveal/coordinatorlayout/CircularRevealCoordinatorLayout": "android/support/design/circularreveal/coordinatorlayout/CircularRevealCoordinatorLayout",
"android/support/percent/PercentFrameLayout": "androidx/percentlayout/widget/PercentFrameLayout",
"android/support/percent/PercentLayoutHelper": "androidx/percentlayout/widget/PercentLayoutHelper",
"android/support/percent/R": "androidx/percentlayout/R",
"android/support/percent/PercentRelativeLayout": "androidx/percentlayout/widget/PercentRelativeLayout",
+ "android/arch/persistence/db/SupportSQLiteQueryBuilder": "androidx/sqlite/db/SupportSQLiteQueryBuilder",
"android/support/design/animation/R": "android/support/design/animation/R",
+ "android/arch/paging/PageResult": "androidx/paging/PageResult",
+ "android/arch/paging/ListDataSource": "androidx/paging/ListDataSource",
+ "android/arch/paging/WrapperItemKeyedDataSource": "androidx/paging/WrapperItemKeyedDataSource",
+ "android/arch/paging/PageKeyedDataSource": "androidx/paging/PageKeyedDataSource",
+ "android/arch/paging/ContiguousDataSource": "androidx/paging/ContiguousDataSource",
+ "android/arch/paging/WrapperPageKeyedDataSource": "androidx/paging/WrapperPageKeyedDataSource",
+ "android/arch/paging/ItemKeyedDataSource": "androidx/paging/ItemKeyedDataSource",
+ "android/arch/paging/TiledPagedList": "androidx/paging/TiledPagedList",
+ "android/arch/paging/TiledDataSource": "androidx/paging/TiledDataSource",
+ "android/arch/paging/WrapperPositionalDataSource": "androidx/paging/WrapperPositionalDataSource",
+ "android/arch/paging/ContiguousPagedList": "androidx/paging/ContiguousPagedList",
+ "android/arch/paging/SnapshotPagedList": "androidx/paging/SnapshotPagedList",
"android/support/v4/view/AsyncLayoutInflater": "androidx/asynclayoutinflater/view/AsyncLayoutInflater",
+ "android/arch/persistence/room/ForeignKey": "androidx/room/ForeignKey",
+ "android/arch/persistence/room/RoomWarnings": "androidx/room/RoomWarnings",
+ "android/arch/persistence/room/Index": "androidx/room/Index",
+ "android/arch/persistence/room/OnConflictStrategy": "androidx/room/OnConflictStrategy",
"android/support/design/circularreveal/CircularRevealGridLayout": "android/support/design/circularreveal/CircularRevealGridLayout",
"android/support/design/circularreveal/CircularRevealLinearLayout": "android/support/design/circularreveal/CircularRevealLinearLayout",
"android/support/design/circularreveal/CircularRevealRelativeLayout": "android/support/design/circularreveal/CircularRevealRelativeLayout"
@@ -3250,7 +3666,8 @@
"proGuardMap": {
"rules": {
"android/support/transition/ChangeBounds$*": "androidx/transition/ChangeBounds$*",
- "android/support/graphics/drawable/VectorDrawableCompat$*": "androidx/vectordrawable/graphics/drawable/VectorDrawableCompat$*"
+ "android/support/graphics/drawable/VectorDrawableCompat$*": "androidx/vectordrawable/graphics/drawable/VectorDrawableCompat$*",
+ "android/arch/persistence/room/paging/**": "androidx/room/paging/**"
}
}
}
\ No newline at end of file
diff --git a/jetifier/jetifier/preprocessor/scripts/processDefaultConfig.sh b/jetifier/jetifier/preprocessor/scripts/processDefaultConfig.sh
index d6f8971..19dcc7e 100755
--- a/jetifier/jetifier/preprocessor/scripts/processDefaultConfig.sh
+++ b/jetifier/jetifier/preprocessor/scripts/processDefaultConfig.sh
@@ -32,6 +32,7 @@
PREPROCESSOR_DISTRO_PATH="$BUILD_DIR/jetifier-preprocessor/build/distributions/jetifier-preprocessor.zip"
PREPROCESSOR_BIN_PATH="$OUT_DIR/jetifier-preprocessor/bin/jetifier-preprocessor"
SUPPORT_LIBS_BUILD_NUMBER="4631572"
+APP_TOOLKIT_BUILD_NUMBER="4669041"
SUPPORT_LIBS_DOWNLOADED="$OUT_DIR/supportLibs/downloaded"
SUPPORT_LIBS_UNPACKED="$OUT_DIR/supportLibs/unpacked"
@@ -65,7 +66,6 @@
echo "OUT dir is at '$OUT_DIR'"
function getPreRenamedSupportLib() {
- INPUT_FILENAME="top-of-tree-m2repository-$SUPPORT_LIBS_BUILD_NUMBER.zip"
printSectionStart "Downloading all affected support libraries"
mkdir -p "$SUPPORT_LIBS_DOWNLOADED"
@@ -79,17 +79,28 @@
fi
cd "$SUPPORT_LIBS_DOWNLOADED"
- "$FETCH_ARTIFACT" --bid "$SUPPORT_LIBS_BUILD_NUMBER" --target support_library "$INPUT_FILENAME" "$SUPPORT_LIBS_DOWNLOADED/support-lib-${SUPPORT_LIBS_BUILD_NUMBER}.zip"
- "$FETCH_ARTIFACT" --bid "$SUPPORT_LIBS_BUILD_NUMBER" --target support_library_app_toolkit "$INPUT_FILENAME" "$SUPPORT_LIBS_DOWNLOADED/arch-${SUPPORT_LIBS_BUILD_NUMBER}.zip"
+ "$FETCH_ARTIFACT" --bid "$SUPPORT_LIBS_BUILD_NUMBER" --target support_library "top-of-tree-m2repository-$SUPPORT_LIBS_BUILD_NUMBER.zip" "$SUPPORT_LIBS_DOWNLOADED/support-lib.zip"
+ "$FETCH_ARTIFACT" --bid "$APP_TOOLKIT_BUILD_NUMBER" --target support_library_app_toolkit "top-of-tree-m2repository-$APP_TOOLKIT_BUILD_NUMBER.zip" "$SUPPORT_LIBS_DOWNLOADED/arch.zip"
cd -
- unzip -oj "$SUPPORT_LIBS_DOWNLOADED/support-lib-${SUPPORT_LIBS_BUILD_NUMBER}.zip" -d "$SUPPORT_LIBS_UNPACKED"
- unzip -oj "$SUPPORT_LIBS_DOWNLOADED/arch-${SUPPORT_LIBS_BUILD_NUMBER}.zip" -d "$SUPPORT_LIBS_UNPACKED"
+ unzip -oj "$SUPPORT_LIBS_DOWNLOADED/support-lib.zip" -d "$SUPPORT_LIBS_UNPACKED"
+ unzip -oj "$SUPPORT_LIBS_DOWNLOADED/arch.zip" -d "$SUPPORT_LIBS_UNPACKED"
find "$CHECKOUT_DIR/prebuilts/maven_repo/android/com/android/support/" -type f -name "*design-*28.0.0*.aar" -exec cp '{}' -t "$SUPPORT_LIBS_UNPACKED" \;
find "$SUPPORT_LIBS_UNPACKED" -type f -name "jetifier*" -exec rm -f {} \;
}
+
+DATA_BINDING_VERSION=`curl https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/maven-metadata.xml|xmllint --format -|grep latest|awk '{split($NAME,a,"[><]"); print a[3]}'`
+function pullDataBinding() {
+ NAME=$1
+ TYPE=$2
+ curl "https://dl.google.com/dl/android/maven2/com/android/databinding/$NAME/$DATA_BINDING_VERSION/$NAME-$DATA_BINDING_VERSION.$TYPE" -o "$SUPPORT_LIBS_UNPACKED/databinding-$NAME.$TYPE"
+}
+
getPreRenamedSupportLib
+pullDataBinding "baseLibrary" "jar"
+pullDataBinding "adapters" "aar"
+pullDataBinding "library" "aar"
printSectionStart "Preparing Jetifier"
buildProjectUsingGradle $JETIFIER_DIR/../..
diff --git a/leanback/api21/androidx/leanback/transition/TransitionHelperApi21.java b/leanback/api21/androidx/leanback/transition/TransitionHelperApi21.java
deleted file mode 100644
index 57d7476..0000000
--- a/leanback/api21/androidx/leanback/transition/TransitionHelperApi21.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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 androidx.leanback.transition;
-
-import android.R;
-import android.content.Context;
-import android.graphics.Rect;
-import android.transition.ChangeTransform;
-import android.transition.Transition;
-import android.transition.TransitionManager;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.animation.AnimationUtils;
-
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(21)
-final class TransitionHelperApi21 {
-
- TransitionHelperApi21() {
- }
-
- public static void setEnterTransition(android.app.Fragment fragment, Object transition) {
- fragment.setEnterTransition((Transition)transition);
- }
-
- public static void setExitTransition(android.app.Fragment fragment, Object transition) {
- fragment.setExitTransition((Transition)transition);
- }
-
- public static void setSharedElementEnterTransition(android.app.Fragment fragment,
- Object transition) {
- fragment.setSharedElementEnterTransition((Transition)transition);
- }
-
- public static void addSharedElement(android.app.FragmentTransaction ft,
- View view, String transitionName) {
- ft.addSharedElement(view, transitionName);
- }
-
- public static Object getSharedElementEnterTransition(Window window) {
- return window.getSharedElementEnterTransition();
- }
-
- public static void setSharedElementEnterTransition(Window window, Object transition) {
- window.setSharedElementEnterTransition((Transition) transition);
- }
-
- public static Object getSharedElementReturnTransition(Window window) {
- return window.getSharedElementReturnTransition();
- }
-
- public static void setSharedElementReturnTransition(Window window, Object transition) {
- window.setSharedElementReturnTransition((Transition) transition);
- }
-
- public static Object getSharedElementExitTransition(Window window) {
- return window.getSharedElementExitTransition();
- }
-
- public static Object getSharedElementReenterTransition(Window window) {
- return window.getSharedElementReenterTransition();
- }
-
- public static Object getEnterTransition(Window window) {
- return window.getEnterTransition();
- }
-
- public static void setEnterTransition(Window window, Object transition) {
- window.setEnterTransition((Transition) transition);
- }
-
- public static Object getReturnTransition(Window window) {
- return window.getReturnTransition();
- }
-
- public static void setReturnTransition(Window window, Object transition) {
- window.setReturnTransition((Transition) transition);
- }
-
- public static Object getExitTransition(Window window) {
- return window.getExitTransition();
- }
-
- public static Object getReenterTransition(Window window) {
- return window.getReenterTransition();
- }
-
- public static Object createScale() {
- return new ChangeTransform();
- }
-
- public static Object createDefaultInterpolator(Context context) {
- return AnimationUtils.loadInterpolator(context, R.interpolator.fast_out_linear_in);
- }
-
- public static Object createChangeTransform() {
- return new ChangeTransform();
- }
-
- public static Object createFadeAndShortSlide(int edge) {
- return new FadeAndShortSlide(edge);
- }
-
- public static Object createFadeAndShortSlide(int edge, float distance) {
- FadeAndShortSlide slide = new FadeAndShortSlide(edge);
- slide.setDistance(distance);
- return slide;
- }
-
- public static void beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject) {
- Transition transition = (Transition) transitionObject;
- TransitionManager.beginDelayedTransition(sceneRoot, transition);
- }
-
- public static void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
- viewGroup.setTransitionGroup(transitionGroup);
- }
-
- public static void setEpicenterCallback(Object transitionObject,
- final TransitionEpicenterCallback callback) {
- Transition transition = (Transition) transitionObject;
- if (callback == null) {
- transition.setEpicenterCallback(null);
- } else {
- transition.setEpicenterCallback(new Transition.EpicenterCallback() {
- @Override
- public Rect onGetEpicenter(Transition transition) {
- return callback.onGetEpicenter(transition);
- }
- });
- }
- }
-}
diff --git a/leanback/build.gradle b/leanback/build.gradle
index fe04a8a..56b7fc5 100644
--- a/leanback/build.gradle
+++ b/leanback/build.gradle
@@ -23,7 +23,6 @@
sourceSets {
main.java.srcDirs += [
'common',
- 'jbmr2',
'kitkat',
'api21',
]
diff --git a/leanback/jbmr2/androidx/leanback/widget/ShadowHelperJbmr2.java b/leanback/jbmr2/androidx/leanback/widget/ShadowHelperJbmr2.java
deleted file mode 100644
index 49e5532..0000000
--- a/leanback/jbmr2/androidx/leanback/widget/ShadowHelperJbmr2.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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 androidx.leanback.widget;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.RequiresApi;
-import androidx.leanback.R;
-
-@RequiresApi(18)
-class ShadowHelperJbmr2 {
-
- static class ShadowImpl {
- View mNormalShadow;
- View mFocusShadow;
- }
-
- /* prepare parent for allowing shadows of a child */
- public static void prepareParent(ViewGroup parent) {
- parent.setLayoutMode(ViewGroup.LAYOUT_MODE_OPTICAL_BOUNDS);
- }
-
- /* add shadows and return a implementation detail object */
- public static Object addShadow(ViewGroup shadowContainer) {
- shadowContainer.setLayoutMode(ViewGroup.LAYOUT_MODE_OPTICAL_BOUNDS);
- LayoutInflater inflater = LayoutInflater.from(shadowContainer.getContext());
- inflater.inflate(R.layout.lb_shadow, shadowContainer, true);
- ShadowImpl impl = new ShadowImpl();
- impl.mNormalShadow = shadowContainer.findViewById(R.id.lb_shadow_normal);
- impl.mFocusShadow = shadowContainer.findViewById(R.id.lb_shadow_focused);
- return impl;
- }
-
- /* set shadow focus level 0 for unfocused 1 for fully focused */
- public static void setShadowFocusLevel(Object impl, float level) {
- ShadowImpl shadowImpl = (ShadowImpl) impl;
- shadowImpl.mNormalShadow.setAlpha(1 - level);
- shadowImpl.mFocusShadow.setAlpha(level);
- }
-}
diff --git a/leanback/kitkat/androidx/leanback/transition/CustomChangeBounds.java b/leanback/kitkat/androidx/leanback/transition/CustomChangeBounds.java
new file mode 100644
index 0000000..0331b50
--- /dev/null
+++ b/leanback/kitkat/androidx/leanback/transition/CustomChangeBounds.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.leanback.transition;
+
+import android.animation.Animator;
+import android.transition.ChangeBounds;
+import android.transition.TransitionValues;
+import android.util.SparseIntArray;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.RequiresApi;
+
+import java.util.HashMap;
+
+/**
+ * change bounds that support customized start delay.
+ */
+@RequiresApi(19)
+class CustomChangeBounds extends ChangeBounds {
+
+ int mDefaultStartDelay;
+ // View -> delay
+ final HashMap<View, Integer> mViewStartDelays = new HashMap<View, Integer>();
+ // id -> delay
+ final SparseIntArray mIdStartDelays = new SparseIntArray();
+ // Class.getName() -> delay
+ final HashMap<String, Integer> mClassStartDelays = new HashMap<String, Integer>();
+
+ private int getDelay(View view) {
+ Integer delay = mViewStartDelays.get(view);
+ if (delay != null) {
+ return delay;
+ }
+ int idStartDelay = mIdStartDelays.get(view.getId(), -1);
+ if (idStartDelay != -1) {
+ return idStartDelay;
+ }
+ delay = mClassStartDelays.get(view.getClass().getName());
+ if (delay != null) {
+ return delay;
+ }
+ return mDefaultStartDelay;
+ }
+
+ @Override
+ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+ TransitionValues endValues) {
+ Animator animator = super.createAnimator(sceneRoot, startValues, endValues);
+ if (animator != null && endValues != null && endValues.view != null) {
+ animator.setStartDelay(getDelay(endValues.view));
+ }
+ return animator;
+ }
+
+ public void setStartDelay(View view, int startDelay) {
+ mViewStartDelays.put(view, startDelay);
+ }
+
+ public void setStartDelay(int viewId, int startDelay) {
+ mIdStartDelays.put(viewId, startDelay);
+ }
+
+ public void setStartDelay(String className, int startDelay) {
+ mClassStartDelays.put(className, startDelay);
+ }
+
+ public void setDefaultStartDelay(int startDelay) {
+ mDefaultStartDelay = startDelay;
+ }
+}
diff --git a/leanback/kitkat/androidx/leanback/transition/LeanbackTransitionHelperKitKat.java b/leanback/kitkat/androidx/leanback/transition/LeanbackTransitionHelperKitKat.java
deleted file mode 100644
index 49e16b1..0000000
--- a/leanback/kitkat/androidx/leanback/transition/LeanbackTransitionHelperKitKat.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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 androidx.leanback.transition;
-
-import android.content.Context;
-import android.view.Gravity;
-import android.view.animation.AnimationUtils;
-
-import androidx.annotation.RequiresApi;
-import androidx.leanback.R;
-
-@RequiresApi(19)
-class LeanbackTransitionHelperKitKat {
-
- static public Object loadTitleInTransition(Context context) {
- SlideKitkat slide = new SlideKitkat();
- slide.setSlideEdge(Gravity.TOP);
- slide.setInterpolator(AnimationUtils.loadInterpolator(context,
- android.R.anim.decelerate_interpolator));
- slide.addTarget(R.id.browse_title_group);
- return slide;
- }
-
- static public Object loadTitleOutTransition(Context context) {
- SlideKitkat slide = new SlideKitkat();
- slide.setSlideEdge(Gravity.TOP);
- slide.setInterpolator(AnimationUtils.loadInterpolator(context,
- R.anim.lb_decelerator_4));
- slide.addTarget(R.id.browse_title_group);
- return slide;
- }
-
-}
diff --git a/leanback/kitkat/androidx/leanback/transition/TransitionHelperKitkat.java b/leanback/kitkat/androidx/leanback/transition/TransitionHelperKitkat.java
deleted file mode 100644
index ae1ca02..0000000
--- a/leanback/kitkat/androidx/leanback/transition/TransitionHelperKitkat.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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 androidx.leanback.transition;
-
-import android.animation.Animator;
-import android.animation.TimeInterpolator;
-import android.content.Context;
-import android.transition.AutoTransition;
-import android.transition.ChangeBounds;
-import android.transition.Fade;
-import android.transition.Scene;
-import android.transition.Transition;
-import android.transition.TransitionInflater;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
-import android.transition.TransitionValues;
-import android.util.SparseIntArray;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.RequiresApi;
-
-import java.util.HashMap;
-
-@RequiresApi(19)
-final class TransitionHelperKitkat {
-
- TransitionHelperKitkat() {
- }
-
- static Object createScene(ViewGroup sceneRoot, Runnable enterAction) {
- Scene scene = new Scene(sceneRoot);
- scene.setEnterAction(enterAction);
- return scene;
- }
-
- static Object createTransitionSet(boolean sequential) {
- TransitionSet set = new TransitionSet();
- set.setOrdering(sequential ? TransitionSet.ORDERING_SEQUENTIAL :
- TransitionSet.ORDERING_TOGETHER);
- return set;
- }
-
- static void addTransition(Object transitionSet, Object transition) {
- ((TransitionSet) transitionSet).addTransition((Transition) transition);
- }
-
- static Object createAutoTransition() {
- return new AutoTransition();
- }
-
- static Object createSlide(int slideEdge) {
- SlideKitkat slide = new SlideKitkat();
- slide.setSlideEdge(slideEdge);
- return slide;
- }
-
- static Object createScale() {
- Scale scale = new Scale();
- return scale;
- }
-
- static Object createFadeTransition(int fadingMode) {
- Fade fade = new Fade(fadingMode);
- return fade;
- }
-
- /**
- * change bounds that support customized start delay.
- */
- static class CustomChangeBounds extends ChangeBounds {
-
- int mDefaultStartDelay;
- // View -> delay
- final HashMap<View, Integer> mViewStartDelays = new HashMap<View, Integer>();
- // id -> delay
- final SparseIntArray mIdStartDelays = new SparseIntArray();
- // Class.getName() -> delay
- final HashMap<String, Integer> mClassStartDelays = new HashMap<String, Integer>();
-
- private int getDelay(View view) {
- Integer delay = mViewStartDelays.get(view);
- if (delay != null) {
- return delay;
- }
- int idStartDelay = mIdStartDelays.get(view.getId(), -1);
- if (idStartDelay != -1) {
- return idStartDelay;
- }
- delay = mClassStartDelays.get(view.getClass().getName());
- if (delay != null) {
- return delay;
- }
- return mDefaultStartDelay;
- }
-
- @Override
- public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
- TransitionValues endValues) {
- Animator animator = super.createAnimator(sceneRoot, startValues, endValues);
- if (animator != null && endValues != null && endValues.view != null) {
- animator.setStartDelay(getDelay(endValues.view));
- }
- return animator;
- }
-
- public void setStartDelay(View view, int startDelay) {
- mViewStartDelays.put(view, startDelay);
- }
-
- public void setStartDelay(int viewId, int startDelay) {
- mIdStartDelays.put(viewId, startDelay);
- }
-
- public void setStartDelay(String className, int startDelay) {
- mClassStartDelays.put(className, startDelay);
- }
-
- public void setDefaultStartDelay(int startDelay) {
- mDefaultStartDelay = startDelay;
- }
- }
-
- static Object createChangeBounds(boolean reparent) {
- CustomChangeBounds changeBounds = new CustomChangeBounds();
- changeBounds.setReparent(reparent);
- return changeBounds;
- }
-
- static void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
- ((CustomChangeBounds) changeBounds).setStartDelay(viewId, startDelay);
- }
-
- static void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
- ((CustomChangeBounds) changeBounds).setStartDelay(view, startDelay);
- }
-
- static void setChangeBoundsStartDelay(Object changeBounds, String className, int startDelay) {
- ((CustomChangeBounds) changeBounds).setStartDelay(className, startDelay);
- }
-
- static void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
- ((CustomChangeBounds) changeBounds).setDefaultStartDelay(startDelay);
- }
-
- static void setStartDelay(Object transition, long startDelay) {
- ((Transition)transition).setStartDelay(startDelay);
- }
-
- static void setDuration(Object transition, long duration) {
- ((Transition)transition).setDuration(duration);
- }
-
- static void exclude(Object transition, int targetId, boolean exclude) {
- ((Transition) transition).excludeTarget(targetId, exclude);
- }
-
- static void exclude(Object transition, View targetView, boolean exclude) {
- ((Transition) transition).excludeTarget(targetView, exclude);
- }
-
- static void excludeChildren(Object transition, int targetId, boolean exclude) {
- ((Transition) transition).excludeChildren(targetId, exclude);
- }
-
- static void excludeChildren(Object transition, View targetView, boolean exclude) {
- ((Transition) transition).excludeChildren(targetView, exclude);
- }
-
- static void include(Object transition, int targetId) {
- ((Transition) transition).addTarget(targetId);
- }
-
- static void include(Object transition, View targetView) {
- ((Transition) transition).addTarget(targetView);
- }
-
- static void addTransitionListener(Object transition, final TransitionListener listener) {
- if (listener == null) {
- return;
- }
- Transition t = (Transition) transition;
- listener.mImpl = new Transition.TransitionListener() {
-
- @Override
- public void onTransitionStart(Transition transition) {
- listener.onTransitionStart(transition);
- }
-
- @Override
- public void onTransitionResume(Transition transition) {
- listener.onTransitionResume(transition);
- }
-
- @Override
- public void onTransitionPause(Transition transition) {
- listener.onTransitionPause(transition);
- }
-
- @Override
- public void onTransitionEnd(Transition transition) {
- listener.onTransitionEnd(transition);
- }
-
- @Override
- public void onTransitionCancel(Transition transition) {
- listener.onTransitionCancel(transition);
- }
- };
- t.addListener((Transition.TransitionListener) listener.mImpl);
- }
-
- static void removeTransitionListener(Object transition, final TransitionListener listener) {
- if (listener == null || listener.mImpl == null) {
- return;
- }
- Transition t = (Transition) transition;
- t.removeListener((Transition.TransitionListener) listener.mImpl);
- listener.mImpl = null;
- }
-
- static void runTransition(Object scene, Object transition) {
- TransitionManager.go((Scene) scene, (Transition) transition);
- }
-
- static void setInterpolator(Object transition, Object timeInterpolator) {
- ((Transition) transition).setInterpolator((TimeInterpolator) timeInterpolator);
- }
-
- static void addTarget(Object transition, View view) {
- ((Transition) transition).addTarget(view);
- }
-
- static Object loadTransition(Context context, int resId) {
- return TransitionInflater.from(context).inflateTransition(resId);
- }
-}
diff --git a/leanback/src/main/java/androidx/leanback/app/FragmentUtil.java b/leanback/src/main/java/androidx/leanback/app/FragmentUtil.java
index 84ff0b7..8d042e8 100644
--- a/leanback/src/main/java/androidx/leanback/app/FragmentUtil.java
+++ b/leanback/src/main/java/androidx/leanback/app/FragmentUtil.java
@@ -19,20 +19,11 @@
import android.content.Context;
import android.os.Build;
-import androidx.annotation.RequiresApi;
-
class FragmentUtil {
-
- @RequiresApi(23)
- private static Context getContextNew(Fragment fragment) {
- return fragment.getContext();
- }
-
- public static Context getContext(Fragment fragment) {
+ static Context getContext(Fragment fragment) {
if (Build.VERSION.SDK_INT >= 23) {
- return getContextNew(fragment);
- } else {
- return fragment.getActivity();
+ return fragment.getContext();
}
+ return fragment.getActivity();
}
}
diff --git a/leanback/src/main/java/androidx/leanback/app/GuidedStepSupportFragment.java b/leanback/src/main/java/androidx/leanback/app/GuidedStepSupportFragment.java
index 4ea8986..3215c98 100644
--- a/leanback/src/main/java/androidx/leanback/app/GuidedStepSupportFragment.java
+++ b/leanback/src/main/java/androidx/leanback/app/GuidedStepSupportFragment.java
@@ -556,7 +556,7 @@
String transitionName)
{
if (subView != null)
- TransitionHelper.addSharedElement(ft, subView, transitionName);
+ ft.addSharedElement(subView, transitionName);
}
/**
@@ -897,7 +897,7 @@
TransitionHelper.exclude(enterTransition, R.id.guidedstep_background, true);
TransitionHelper.exclude(enterTransition, R.id.guidedactions_sub_list_background,
true);
- TransitionHelper.setEnterTransition(this, enterTransition);
+ setEnterTransition(enterTransition);
Object fade = TransitionHelper.createFadeTransition(
TransitionHelper.FADE_IN | TransitionHelper.FADE_OUT);
@@ -906,7 +906,7 @@
Object sharedElementTransition = TransitionHelper.createTransitionSet(false);
TransitionHelper.addTransition(sharedElementTransition, fade);
TransitionHelper.addTransition(sharedElementTransition, changeBounds);
- TransitionHelper.setSharedElementEnterTransition(this, sharedElementTransition);
+ setSharedElementEnterTransition(sharedElementTransition);
} else if (uiStyle == UI_STYLE_ENTRANCE) {
if (entranceTransitionType == SLIDE_FROM_SIDE) {
Object fade = TransitionHelper.createFadeTransition(
@@ -919,29 +919,29 @@
Object enterTransition = TransitionHelper.createTransitionSet(false);
TransitionHelper.addTransition(enterTransition, fade);
TransitionHelper.addTransition(enterTransition, slideFromSide);
- TransitionHelper.setEnterTransition(this, enterTransition);
+ setEnterTransition(enterTransition);
} else {
Object slideFromBottom = TransitionHelper.createFadeAndShortSlide(
Gravity.BOTTOM);
TransitionHelper.include(slideFromBottom, R.id.guidedstep_background_view_root);
Object enterTransition = TransitionHelper.createTransitionSet(false);
TransitionHelper.addTransition(enterTransition, slideFromBottom);
- TransitionHelper.setEnterTransition(this, enterTransition);
+ setEnterTransition(enterTransition);
}
// No shared element transition
- TransitionHelper.setSharedElementEnterTransition(this, null);
+ setSharedElementEnterTransition(null);
} else if (uiStyle == UI_STYLE_ACTIVITY_ROOT) {
// for Activity root, we don't need enter transition, use activity transition
- TransitionHelper.setEnterTransition(this, null);
+ setEnterTransition(null);
// No shared element transition
- TransitionHelper.setSharedElementEnterTransition(this, null);
+ setSharedElementEnterTransition(null);
}
// exitTransition is same for all style
Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
TransitionHelper.exclude(exitTransition, R.id.guidedstep_background, true);
TransitionHelper.exclude(exitTransition, R.id.guidedactions_sub_list_background,
true);
- TransitionHelper.setExitTransition(this, exitTransition);
+ setExitTransition(exitTransition);
}
}
diff --git a/leanback/src/main/java/androidx/leanback/app/PermissionHelper.java b/leanback/src/main/java/androidx/leanback/app/PermissionHelper.java
index 7ee619e..73d1a05 100644
--- a/leanback/src/main/java/androidx/leanback/app/PermissionHelper.java
+++ b/leanback/src/main/java/androidx/leanback/app/PermissionHelper.java
@@ -18,7 +18,6 @@
import android.os.Build;
import androidx.annotation.RestrictTo;
-import androidx.fragment.app.Fragment;
/**
* @hide
@@ -33,9 +32,4 @@
}
}
- public static void requestPermissions(Fragment fragment,
- String[] permissions, int requestCode) {
- fragment.requestPermissions(permissions, requestCode);
- }
-
}
diff --git a/leanback/src/main/java/androidx/leanback/app/SearchSupportFragment.java b/leanback/src/main/java/androidx/leanback/app/SearchSupportFragment.java
index 60c0db8..2d1d29e 100644
--- a/leanback/src/main/java/androidx/leanback/app/SearchSupportFragment.java
+++ b/leanback/src/main/java/androidx/leanback/app/SearchSupportFragment.java
@@ -232,8 +232,8 @@
new SearchBar.SearchBarPermissionListener() {
@Override
public void requestAudioPermission() {
- PermissionHelper.requestPermissions(SearchSupportFragment.this,
- new String[]{Manifest.permission.RECORD_AUDIO}, AUDIO_PERMISSION_REQUEST_CODE);
+ requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},
+ AUDIO_PERMISSION_REQUEST_CODE);
}
};
diff --git a/leanback/src/main/java/androidx/leanback/transition/LeanbackTransitionHelper.java b/leanback/src/main/java/androidx/leanback/transition/LeanbackTransitionHelper.java
index 7b373be..a259050 100644
--- a/leanback/src/main/java/androidx/leanback/transition/LeanbackTransitionHelper.java
+++ b/leanback/src/main/java/androidx/leanback/transition/LeanbackTransitionHelper.java
@@ -17,8 +17,9 @@
import android.content.Context;
import android.os.Build;
+import android.view.Gravity;
+import android.view.animation.AnimationUtils;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.leanback.R;
@@ -29,63 +30,29 @@
@RestrictTo(LIBRARY_GROUP)
public class LeanbackTransitionHelper {
- interface LeanbackTransitionHelperVersion {
- Object loadTitleInTransition(Context context);
- Object loadTitleOutTransition(Context context);
- }
-
- /*
- * Kitkat does not allow load custom transition from resource, calling
- * LeanbackTransitionHelperKitKat to build custom transition in code.
- */
- @RequiresApi(19)
- static class LeanbackTransitionHelperKitKatImpl implements LeanbackTransitionHelperVersion {
-
- @Override
- public Object loadTitleInTransition(Context context) {
- return LeanbackTransitionHelperKitKat.loadTitleInTransition(context);
- }
-
- @Override
- public Object loadTitleOutTransition(Context context) {
- return LeanbackTransitionHelperKitKat.loadTitleOutTransition(context);
- }
- }
-
- /*
- * Load transition from resource or just return stub for API17.
- */
- static class LeanbackTransitionHelperDefault implements LeanbackTransitionHelperVersion {
-
- @Override
- public Object loadTitleInTransition(Context context) {
+ public static Object loadTitleInTransition(Context context) {
+ if (Build.VERSION.SDK_INT < 19 || Build.VERSION.SDK_INT >= 21) {
return TransitionHelper.loadTransition(context, R.transition.lb_title_in);
}
- @Override
- public Object loadTitleOutTransition(Context context) {
+ SlideKitkat slide = new SlideKitkat();
+ slide.setSlideEdge(Gravity.TOP);
+ slide.setInterpolator(AnimationUtils.loadInterpolator(context,
+ android.R.anim.decelerate_interpolator));
+ slide.addTarget(R.id.browse_title_group);
+ return slide;
+ }
+
+ public static Object loadTitleOutTransition(Context context) {
+ if (Build.VERSION.SDK_INT < 19 || Build.VERSION.SDK_INT >= 21) {
return TransitionHelper.loadTransition(context, R.transition.lb_title_out);
}
- }
- static LeanbackTransitionHelperVersion sImpl;
-
- static {
- if (Build.VERSION.SDK_INT >= 21) {
- sImpl = new LeanbackTransitionHelperDefault();
- } else if (Build.VERSION.SDK_INT >= 19) {
- sImpl = new LeanbackTransitionHelperKitKatImpl();
- } else {
- // Helper will create a stub object for transition in this case.
- sImpl = new LeanbackTransitionHelperDefault();
- }
- }
-
- static public Object loadTitleInTransition(Context context) {
- return sImpl.loadTitleInTransition(context);
- }
-
- static public Object loadTitleOutTransition(Context context) {
- return sImpl.loadTitleOutTransition(context);
+ SlideKitkat slide = new SlideKitkat();
+ slide.setSlideEdge(Gravity.TOP);
+ slide.setInterpolator(AnimationUtils.loadInterpolator(context,
+ R.anim.lb_decelerator_4));
+ slide.addTarget(R.id.browse_title_group);
+ return slide;
}
}
diff --git a/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java b/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java
index b829587..084e1e7 100644
--- a/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java
+++ b/leanback/src/main/java/androidx/leanback/transition/TransitionHelper.java
@@ -15,17 +15,24 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import android.animation.TimeInterpolator;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Build;
-import android.view.Gravity;
+import android.transition.AutoTransition;
+import android.transition.ChangeTransform;
+import android.transition.Fade;
+import android.transition.Scene;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.view.animation.AnimationUtils;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentTransaction;
import java.util.ArrayList;
@@ -39,23 +46,6 @@
public static final int FADE_IN = 0x1;
public static final int FADE_OUT = 0x2;
- public static final int SLIDE_LEFT = Gravity.LEFT;
- public static final int SLIDE_TOP = Gravity.TOP;
- public static final int SLIDE_RIGHT = Gravity.RIGHT;
- public static final int SLIDE_BOTTOM = Gravity.BOTTOM;
-
- private static TransitionHelperVersionImpl sImpl;
-
- /**
- * Gets whether the system supports Transition animations.
- *
- * @return True if Transition animations are supported.
- */
- public static boolean systemSupportsTransitions() {
- // Supported on Android 4.4 or later.
- return Build.VERSION.SDK_INT >= 19;
- }
-
/**
* Returns true if system supports entrance Transition animations.
*/
@@ -63,322 +53,302 @@
return Build.VERSION.SDK_INT >= 21;
}
- /**
- * Interface implemented by classes that support Transition animations.
- */
- interface TransitionHelperVersionImpl {
+ private static class TransitionStub {
+ ArrayList<TransitionListener> mTransitionListeners;
- void setEnterTransition(android.app.Fragment fragment, Object transition);
-
- void setExitTransition(android.app.Fragment fragment, Object transition);
-
- void setSharedElementEnterTransition(android.app.Fragment fragment,
- Object transition);
-
- void addSharedElement(android.app.FragmentTransaction ft,
- View view, String transitionName);
-
- Object getSharedElementEnterTransition(Window window);
-
- void setSharedElementEnterTransition(Window window, Object transition);
-
- Object getSharedElementReturnTransition(Window window);
-
- void setSharedElementReturnTransition(Window window, Object transition);
-
- Object getSharedElementExitTransition(Window window);
-
- Object getSharedElementReenterTransition(Window window);
-
- Object getEnterTransition(Window window);
-
- void setEnterTransition(Window window, Object transition);
-
- Object getReturnTransition(Window window);
-
- void setReturnTransition(Window window, Object transition);
-
- Object getExitTransition(Window window);
-
- Object getReenterTransition(Window window);
-
- Object createScene(ViewGroup sceneRoot, Runnable r);
-
- Object createAutoTransition();
-
- Object createSlide(int slideEdge);
-
- Object createScale();
-
- Object createFadeTransition(int fadingMode);
-
- Object createChangeTransform();
-
- Object createChangeBounds(boolean reparent);
-
- Object createFadeAndShortSlide(int edge);
-
- Object createFadeAndShortSlide(int edge, float distance);
-
- void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay);
-
- void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay);
-
- void setChangeBoundsStartDelay(Object changeBounds, String className,
- int startDelay);
-
- void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay);
-
- Object createTransitionSet(boolean sequential);
-
- void addTransition(Object transitionSet, Object transition);
-
- void addTransitionListener(Object transition, TransitionListener listener);
-
- void removeTransitionListener(Object transition, TransitionListener listener);
-
- void runTransition(Object scene, Object transition);
-
- void exclude(Object transition, int targetId, boolean exclude);
-
- void exclude(Object transition, View targetView, boolean exclude);
-
- void excludeChildren(Object transition, int targetId, boolean exclude);
-
- void excludeChildren(Object transition, View target, boolean exclude);
-
- void include(Object transition, int targetId);
-
- void include(Object transition, View targetView);
-
- void setStartDelay(Object transition, long startDelay);
-
- void setDuration(Object transition, long duration);
-
- void setInterpolator(Object transition, Object timeInterpolator);
-
- void addTarget(Object transition, View view);
-
- Object createDefaultInterpolator(Context context);
-
- Object loadTransition(Context context, int resId);
-
- void beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject);
-
- void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup);
-
- void setEpicenterCallback(Object transitionObject,
- TransitionEpicenterCallback callback);
+ TransitionStub() {
+ }
}
- /**
- * Interface used when we do not support Transition animations.
- */
- static class TransitionHelperStubImpl implements TransitionHelperVersionImpl {
-
- private static class TransitionStub {
- ArrayList<TransitionListener> mTransitionListeners;
-
- TransitionStub() {
- }
+ public static Object getSharedElementEnterTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getSharedElementEnterTransition();
}
+ return null;
+ }
- @Override
- public void setEnterTransition(android.app.Fragment fragment, Object transition) {
+ public static void setSharedElementEnterTransition(Window window, Object transition) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ window.setSharedElementEnterTransition((Transition) transition);
}
+ }
- @Override
- public void setExitTransition(android.app.Fragment fragment, Object transition) {
+ public static Object getSharedElementReturnTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getSharedElementReturnTransition();
}
+ return null;
+ }
- @Override
- public void setSharedElementEnterTransition(android.app.Fragment fragment,
- Object transition) {
+ public static void setSharedElementReturnTransition(Window window, Object transition) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ window.setSharedElementReturnTransition((Transition) transition);
}
+ }
- @Override
- public void addSharedElement(android.app.FragmentTransaction ft,
- View view, String transitionName) {
+ public static Object getSharedElementExitTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getSharedElementExitTransition();
}
+ return null;
+ }
- @Override
- public Object getSharedElementEnterTransition(Window window) {
- return null;
+ public static Object getSharedElementReenterTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getSharedElementReenterTransition();
}
+ return null;
+ }
- @Override
- public void setSharedElementEnterTransition(Window window, Object object) {
+ public static Object getEnterTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getEnterTransition();
}
+ return null;
+ }
- @Override
- public Object getSharedElementReturnTransition(Window window) {
- return null;
+ public static void setEnterTransition(Window window, Object transition) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ window.setEnterTransition((Transition) transition);
}
+ }
- @Override
- public void setSharedElementReturnTransition(Window window, Object transition) {
+ public static Object getReturnTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getReturnTransition();
}
+ return null;
+ }
- @Override
- public Object getSharedElementExitTransition(Window window) {
- return null;
+ public static void setReturnTransition(Window window, Object transition) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ window.setReturnTransition((Transition) transition);
}
+ }
- @Override
- public Object getSharedElementReenterTransition(Window window) {
- return null;
+ public static Object getExitTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getExitTransition();
}
+ return null;
+ }
- @Override
- public Object getEnterTransition(Window window) {
- return null;
+ public static Object getReenterTransition(Window window) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return window.getReenterTransition();
}
+ return null;
+ }
- @Override
- public void setEnterTransition(Window window, Object transition) {
+ public static Object createScene(ViewGroup sceneRoot, Runnable r) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ Scene scene = new Scene(sceneRoot);
+ scene.setEnterAction(r);
+ return scene;
}
+ return r;
+ }
- @Override
- public Object getReturnTransition(Window window) {
- return null;
+ public static Object createChangeBounds(boolean reparent) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ CustomChangeBounds changeBounds = new CustomChangeBounds();
+ changeBounds.setReparent(reparent);
+ return changeBounds;
}
+ return new TransitionStub();
+ }
- @Override
- public void setReturnTransition(Window window, Object transition) {
+ public static Object createChangeTransform() {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return new ChangeTransform();
}
+ return new TransitionStub();
+ }
- @Override
- public Object getExitTransition(Window window) {
- return null;
+ public static void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((CustomChangeBounds) changeBounds).setStartDelay(view, startDelay);
}
+ }
- @Override
- public Object getReenterTransition(Window window) {
- return null;
+ public static void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((CustomChangeBounds) changeBounds).setStartDelay(viewId, startDelay);
}
+ }
- @Override
- public Object createScene(ViewGroup sceneRoot, Runnable r) {
- return r;
+ public static void setChangeBoundsStartDelay(Object changeBounds, String className,
+ int startDelay) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((CustomChangeBounds) changeBounds).setStartDelay(className, startDelay);
}
+ }
- @Override
- public Object createAutoTransition() {
- return new TransitionStub();
+ public static void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((CustomChangeBounds) changeBounds).setDefaultStartDelay(startDelay);
}
+ }
- @Override
- public Object createFadeTransition(int fadingMode) {
- return new TransitionStub();
+ public static Object createTransitionSet(boolean sequential) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ TransitionSet set = new TransitionSet();
+ set.setOrdering(sequential ? TransitionSet.ORDERING_SEQUENTIAL
+ : TransitionSet.ORDERING_TOGETHER);
+ return set;
}
+ return new TransitionStub();
+ }
- @Override
- public Object createChangeBounds(boolean reparent) {
- return new TransitionStub();
+ public static Object createSlide(int slideEdge) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ SlideKitkat slide = new SlideKitkat();
+ slide.setSlideEdge(slideEdge);
+ return slide;
}
+ return new TransitionStub();
+ }
- @Override
- public Object createChangeTransform() {
- return new TransitionStub();
+ public static Object createScale() {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return new ChangeTransform();
}
-
- @Override
- public Object createFadeAndShortSlide(int edge) {
- return new TransitionStub();
+ if (Build.VERSION.SDK_INT >= 19) {
+ return new Scale();
}
+ return new TransitionStub();
+ }
- @Override
- public Object createFadeAndShortSlide(int edge, float distance) {
- return new TransitionStub();
+ public static void addTransition(Object transitionSet, Object transition) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((TransitionSet) transitionSet).addTransition((Transition) transition);
}
+ }
- @Override
- public Object createSlide(int slideEdge) {
- return new TransitionStub();
+ public static void exclude(Object transition, int targetId, boolean exclude) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).excludeTarget(targetId, exclude);
}
+ }
- @Override
- public Object createScale() {
- return new TransitionStub();
+ public static void exclude(Object transition, View targetView, boolean exclude) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).excludeTarget(targetView, exclude);
}
+ }
- @Override
- public void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
+ public static void excludeChildren(Object transition, int targetId, boolean exclude) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).excludeChildren(targetId, exclude);
}
+ }
- @Override
- public void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
+ public static void excludeChildren(Object transition, View targetView, boolean exclude) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).excludeChildren(targetView, exclude);
}
+ }
- @Override
- public void setChangeBoundsStartDelay(Object changeBounds, String className,
- int startDelay) {
+ public static void include(Object transition, int targetId) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).addTarget(targetId);
}
+ }
- @Override
- public void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
+ public static void include(Object transition, View targetView) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).addTarget(targetView);
}
+ }
- @Override
- public Object createTransitionSet(boolean sequential) {
- return new TransitionStub();
+ public static void setStartDelay(Object transition, long startDelay) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).setStartDelay(startDelay);
}
+ }
- @Override
- public void addTransition(Object transitionSet, Object transition) {
+ public static void setDuration(Object transition, long duration) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).setDuration(duration);
}
+ }
- @Override
- public void exclude(Object transition, int targetId, boolean exclude) {
+ public static Object createAutoTransition() {
+ if (Build.VERSION.SDK_INT >= 19) {
+ return new AutoTransition();
}
+ return new TransitionStub();
+ }
- @Override
- public void exclude(Object transition, View targetView, boolean exclude) {
+ public static Object createFadeTransition(int fadeMode) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ return new Fade(fadeMode);
}
+ return new TransitionStub();
+ }
- @Override
- public void excludeChildren(Object transition, int targetId, boolean exclude) {
+ public static void addTransitionListener(Object transition, final TransitionListener listener) {
+ if (listener == null) {
+ return;
}
+ if (Build.VERSION.SDK_INT >= 19) {
+ Transition t = (Transition) transition;
+ listener.mImpl = new Transition.TransitionListener() {
+ @Override
+ public void onTransitionStart(Transition transition11) {
+ listener.onTransitionStart(transition11);
+ }
- @Override
- public void excludeChildren(Object transition, View targetView, boolean exclude) {
- }
+ @Override
+ public void onTransitionResume(Transition transition11) {
+ listener.onTransitionResume(transition11);
+ }
- @Override
- public void include(Object transition, int targetId) {
- }
+ @Override
+ public void onTransitionPause(Transition transition11) {
+ listener.onTransitionPause(transition11);
+ }
- @Override
- public void include(Object transition, View targetView) {
- }
+ @Override
+ public void onTransitionEnd(Transition transition11) {
+ listener.onTransitionEnd(transition11);
+ }
- @Override
- public void setStartDelay(Object transition, long startDelay) {
- }
-
- @Override
- public void setDuration(Object transition, long duration) {
- }
-
- @Override
- public void addTransitionListener(Object transition, TransitionListener listener) {
+ @Override
+ public void onTransitionCancel(Transition transition11) {
+ listener.onTransitionCancel(transition11);
+ }
+ };
+ t.addListener((Transition.TransitionListener) listener.mImpl);
+ } else {
TransitionStub stub = (TransitionStub) transition;
if (stub.mTransitionListeners == null) {
- stub.mTransitionListeners = new ArrayList<TransitionListener>();
+ stub.mTransitionListeners = new ArrayList<>();
}
stub.mTransitionListeners.add(listener);
}
+ }
- @Override
- public void removeTransitionListener(Object transition, TransitionListener listener) {
+ public static void removeTransitionListener(Object transition, TransitionListener listener) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ if (listener == null || listener.mImpl == null) {
+ return;
+ }
+ Transition t = (Transition) transition;
+ t.removeListener((Transition.TransitionListener) listener.mImpl);
+ listener.mImpl = null;
+ } else {
TransitionStub stub = (TransitionStub) transition;
if (stub.mTransitionListeners != null) {
stub.mTransitionListeners.remove(listener);
}
}
+ }
- @Override
- public void runTransition(Object scene, Object transition) {
+ public static void runTransition(Object scene, Object transition) {
+ if (Build.VERSION.SDK_INT >= 19) {
+ TransitionManager.go((Scene) scene, (Transition) transition);
+ } else {
TransitionStub transitionStub = (TransitionStub) transition;
if (transitionStub != null && transitionStub.mTransitionListeners != null) {
for (int i = 0, size = transitionStub.mTransitionListeners.size(); i < size; i++) {
@@ -395,552 +365,103 @@
}
}
}
-
- @Override
- public void setInterpolator(Object transition, Object timeInterpolator) {
- }
-
- @Override
- public void addTarget(Object transition, View view) {
- }
-
- @Override
- public Object createDefaultInterpolator(Context context) {
- return null;
- }
-
- @Override
- public Object loadTransition(Context context, int resId) {
- return new TransitionStub();
- }
-
- @Override
- public void beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject) {
- }
-
- @Override
- public void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
- }
-
- @Override
- public void setEpicenterCallback(Object transitionObject,
- TransitionEpicenterCallback callback) {
- }
- }
-
- /**
- * Implementation used on KitKat (and above).
- */
- @RequiresApi(19)
- static class TransitionHelperKitkatImpl extends TransitionHelperStubImpl {
-
- @Override
- public Object createScene(ViewGroup sceneRoot, Runnable r) {
- return TransitionHelperKitkat.createScene(sceneRoot, r);
- }
-
- @Override
- public Object createAutoTransition() {
- return TransitionHelperKitkat.createAutoTransition();
- }
-
- @Override
- public Object createFadeTransition(int fadingMode) {
- return TransitionHelperKitkat.createFadeTransition(fadingMode);
- }
-
- @Override
- public Object createChangeBounds(boolean reparent) {
- return TransitionHelperKitkat.createChangeBounds(reparent);
- }
-
- @Override
- public Object createSlide(int slideEdge) {
- return TransitionHelperKitkat.createSlide(slideEdge);
- }
-
- @Override
- public Object createScale() {
- return TransitionHelperKitkat.createScale();
- }
-
- @Override
- public void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
- TransitionHelperKitkat.setChangeBoundsStartDelay(changeBounds, view, startDelay);
- }
-
- @Override
- public void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
- TransitionHelperKitkat.setChangeBoundsStartDelay(changeBounds, viewId, startDelay);
- }
-
- @Override
- public void setChangeBoundsStartDelay(Object changeBounds, String className,
- int startDelay) {
- TransitionHelperKitkat.setChangeBoundsStartDelay(changeBounds, className, startDelay);
- }
-
- @Override
- public void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
- TransitionHelperKitkat.setChangeBoundsDefaultStartDelay(changeBounds, startDelay);
- }
-
- @Override
- public Object createTransitionSet(boolean sequential) {
- return TransitionHelperKitkat.createTransitionSet(sequential);
- }
-
- @Override
- public void addTransition(Object transitionSet, Object transition) {
- TransitionHelperKitkat.addTransition(transitionSet, transition);
- }
-
- @Override
- public void exclude(Object transition, int targetId, boolean exclude) {
- TransitionHelperKitkat.exclude(transition, targetId, exclude);
- }
-
- @Override
- public void exclude(Object transition, View targetView, boolean exclude) {
- TransitionHelperKitkat.exclude(transition, targetView, exclude);
- }
-
- @Override
- public void excludeChildren(Object transition, int targetId, boolean exclude) {
- TransitionHelperKitkat.excludeChildren(transition, targetId, exclude);
- }
-
- @Override
- public void excludeChildren(Object transition, View targetView, boolean exclude) {
- TransitionHelperKitkat.excludeChildren(transition, targetView, exclude);
- }
-
- @Override
- public void include(Object transition, int targetId) {
- TransitionHelperKitkat.include(transition, targetId);
- }
-
- @Override
- public void include(Object transition, View targetView) {
- TransitionHelperKitkat.include(transition, targetView);
- }
-
- @Override
- public void setStartDelay(Object transition, long startDelay) {
- TransitionHelperKitkat.setStartDelay(transition, startDelay);
- }
-
- @Override
- public void setDuration(Object transition, long duration) {
- TransitionHelperKitkat.setDuration(transition, duration);
- }
-
- @Override
- public void addTransitionListener(Object transition, TransitionListener listener) {
- TransitionHelperKitkat.addTransitionListener(transition, listener);
- }
-
- @Override
- public void removeTransitionListener(Object transition, TransitionListener listener) {
- TransitionHelperKitkat.removeTransitionListener(transition, listener);
- }
-
- @Override
- public void runTransition(Object scene, Object transition) {
- TransitionHelperKitkat.runTransition(scene, transition);
- }
-
- @Override
- public void setInterpolator(Object transition, Object timeInterpolator) {
- TransitionHelperKitkat.setInterpolator(transition, timeInterpolator);
- }
-
- @Override
- public void addTarget(Object transition, View view) {
- TransitionHelperKitkat.addTarget(transition, view);
- }
-
- @Override
- public Object createDefaultInterpolator(Context context) {
- return null;
- }
-
- @Override
- public Object loadTransition(Context context, int resId) {
- return TransitionHelperKitkat.loadTransition(context, resId);
- }
- }
-
- @RequiresApi(21)
- static final class TransitionHelperApi21Impl extends TransitionHelperKitkatImpl {
-
- @Override
- public void setEnterTransition(android.app.Fragment fragment, Object transition) {
- TransitionHelperApi21.setEnterTransition(fragment, transition);
- }
-
- @Override
- public void setExitTransition(android.app.Fragment fragment, Object transition) {
- TransitionHelperApi21.setExitTransition(fragment, transition);
- }
-
- @Override
- public void setSharedElementEnterTransition(android.app.Fragment fragment,
- Object transition) {
- TransitionHelperApi21.setSharedElementEnterTransition(fragment, transition);
- }
-
- @Override
- public void addSharedElement(android.app.FragmentTransaction ft,
- View view, String transitionName) {
- TransitionHelperApi21.addSharedElement(ft, view, transitionName);
- }
-
- @Override
- public Object getSharedElementEnterTransition(Window window) {
- return TransitionHelperApi21.getSharedElementEnterTransition(window);
- }
-
- @Override
- public void setSharedElementEnterTransition(Window window, Object object) {
- TransitionHelperApi21.setSharedElementEnterTransition(window, object);
- }
-
- @Override
- public Object getSharedElementReturnTransition(Window window) {
- return TransitionHelperApi21.getSharedElementReturnTransition(window);
- }
-
- @Override
- public void setSharedElementReturnTransition(Window window, Object transition) {
- TransitionHelperApi21.setSharedElementReturnTransition(window, transition);
- }
-
- @Override
- public Object getSharedElementExitTransition(Window window) {
- return TransitionHelperApi21.getSharedElementExitTransition(window);
- }
-
- @Override
- public Object getSharedElementReenterTransition(Window window) {
- return TransitionHelperApi21.getSharedElementReenterTransition(window);
- }
-
- @Override
- public Object createFadeAndShortSlide(int edge) {
- return TransitionHelperApi21.createFadeAndShortSlide(edge);
- }
-
- @Override
- public Object createFadeAndShortSlide(int edge, float distance) {
- return TransitionHelperApi21.createFadeAndShortSlide(edge, distance);
- }
-
- @Override
- public void beginDelayedTransition(ViewGroup sceneRoot, Object transition) {
- TransitionHelperApi21.beginDelayedTransition(sceneRoot, transition);
- }
-
- @Override
- public Object getEnterTransition(Window window) {
- return TransitionHelperApi21.getEnterTransition(window);
- }
-
- @Override
- public void setEnterTransition(Window window, Object transition) {
- TransitionHelperApi21.setEnterTransition(window, transition);
- }
-
- @Override
- public Object getReturnTransition(Window window) {
- return TransitionHelperApi21.getReturnTransition(window);
- }
-
- @Override
- public void setReturnTransition(Window window, Object transition) {
- TransitionHelperApi21.setReturnTransition(window, transition);
- }
-
- @Override
- public Object getExitTransition(Window window) {
- return TransitionHelperApi21.getExitTransition(window);
- }
-
- @Override
- public Object getReenterTransition(Window window) {
- return TransitionHelperApi21.getReenterTransition(window);
- }
-
- @Override
- public Object createScale() {
- return TransitionHelperApi21.createScale();
- }
-
- @Override
- public Object createDefaultInterpolator(Context context) {
- return TransitionHelperApi21.createDefaultInterpolator(context);
- }
-
- @Override
- public void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
- TransitionHelperApi21.setTransitionGroup(viewGroup, transitionGroup);
- }
-
- @Override
- public Object createChangeTransform() {
- return TransitionHelperApi21.createChangeTransform();
- }
-
- @Override
- public void setEpicenterCallback(Object transitionObject,
- TransitionEpicenterCallback callback) {
- TransitionHelperApi21.setEpicenterCallback(transitionObject, callback);
- }
- }
-
- static {
- if (Build.VERSION.SDK_INT >= 21) {
- sImpl = new TransitionHelperApi21Impl();
- } else if (systemSupportsTransitions()) {
- sImpl = new TransitionHelperKitkatImpl();
- } else {
- sImpl = new TransitionHelperStubImpl();
- }
- }
-
- public static Object getSharedElementEnterTransition(Window window) {
- return sImpl.getSharedElementEnterTransition(window);
- }
-
- public static void setSharedElementEnterTransition(Window window, Object transition) {
- sImpl.setSharedElementEnterTransition(window, transition);
- }
-
- public static Object getSharedElementReturnTransition(Window window) {
- return sImpl.getSharedElementReturnTransition(window);
- }
-
- public static void setSharedElementReturnTransition(Window window, Object transition) {
- sImpl.setSharedElementReturnTransition(window, transition);
- }
-
- public static Object getSharedElementExitTransition(Window window) {
- return sImpl.getSharedElementExitTransition(window);
- }
-
- public static Object getSharedElementReenterTransition(Window window) {
- return sImpl.getSharedElementReenterTransition(window);
- }
-
- public static Object getEnterTransition(Window window) {
- return sImpl.getEnterTransition(window);
- }
-
- public static void setEnterTransition(Window window, Object transition) {
- sImpl.setEnterTransition(window, transition);
- }
-
- public static Object getReturnTransition(Window window) {
- return sImpl.getReturnTransition(window);
- }
-
- public static void setReturnTransition(Window window, Object transition) {
- sImpl.setReturnTransition(window, transition);
- }
-
- public static Object getExitTransition(Window window) {
- return sImpl.getExitTransition(window);
- }
-
- public static Object getReenterTransition(Window window) {
- return sImpl.getReenterTransition(window);
- }
-
- public static Object createScene(ViewGroup sceneRoot, Runnable r) {
- return sImpl.createScene(sceneRoot, r);
- }
-
- public static Object createChangeBounds(boolean reparent) {
- return sImpl.createChangeBounds(reparent);
- }
-
- public static Object createChangeTransform() {
- return sImpl.createChangeTransform();
- }
-
- public static void setChangeBoundsStartDelay(Object changeBounds, View view, int startDelay) {
- sImpl.setChangeBoundsStartDelay(changeBounds, view, startDelay);
- }
-
- public static void setChangeBoundsStartDelay(Object changeBounds, int viewId, int startDelay) {
- sImpl.setChangeBoundsStartDelay(changeBounds, viewId, startDelay);
- }
-
- public static void setChangeBoundsStartDelay(Object changeBounds, String className,
- int startDelay) {
- sImpl.setChangeBoundsStartDelay(changeBounds, className, startDelay);
- }
-
- public static void setChangeBoundsDefaultStartDelay(Object changeBounds, int startDelay) {
- sImpl.setChangeBoundsDefaultStartDelay(changeBounds, startDelay);
- }
-
- public static Object createTransitionSet(boolean sequential) {
- return sImpl.createTransitionSet(sequential);
- }
-
- public static Object createSlide(int slideEdge) {
- return sImpl.createSlide(slideEdge);
- }
-
- public static Object createScale() {
- return sImpl.createScale();
- }
-
- public static void addTransition(Object transitionSet, Object transition) {
- sImpl.addTransition(transitionSet, transition);
- }
-
- public static void exclude(Object transition, int targetId, boolean exclude) {
- sImpl.exclude(transition, targetId, exclude);
- }
-
- public static void exclude(Object transition, View targetView, boolean exclude) {
- sImpl.exclude(transition, targetView, exclude);
- }
-
- public static void excludeChildren(Object transition, int targetId, boolean exclude) {
- sImpl.excludeChildren(transition, targetId, exclude);
- }
-
- public static void excludeChildren(Object transition, View targetView, boolean exclude) {
- sImpl.excludeChildren(transition, targetView, exclude);
- }
-
- public static void include(Object transition, int targetId) {
- sImpl.include(transition, targetId);
- }
-
- public static void include(Object transition, View targetView) {
- sImpl.include(transition, targetView);
- }
-
- public static void setStartDelay(Object transition, long startDelay) {
- sImpl.setStartDelay(transition, startDelay);
- }
-
- public static void setDuration(Object transition, long duration) {
- sImpl.setDuration(transition, duration);
- }
-
- public static Object createAutoTransition() {
- return sImpl.createAutoTransition();
- }
-
- public static Object createFadeTransition(int fadeMode) {
- return sImpl.createFadeTransition(fadeMode);
- }
-
- public static void addTransitionListener(Object transition, TransitionListener listener) {
- sImpl.addTransitionListener(transition, listener);
- }
-
- public static void removeTransitionListener(Object transition, TransitionListener listener) {
- sImpl.removeTransitionListener(transition, listener);
- }
-
- public static void runTransition(Object scene, Object transition) {
- sImpl.runTransition(scene, transition);
}
public static void setInterpolator(Object transition, Object timeInterpolator) {
- sImpl.setInterpolator(transition, timeInterpolator);
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).setInterpolator((TimeInterpolator) timeInterpolator);
+ }
}
public static void addTarget(Object transition, View view) {
- sImpl.addTarget(transition, view);
+ if (Build.VERSION.SDK_INT >= 19) {
+ ((Transition) transition).addTarget(view);
+ }
}
public static Object createDefaultInterpolator(Context context) {
- return sImpl.createDefaultInterpolator(context);
+ if (Build.VERSION.SDK_INT >= 21) {
+ return AnimationUtils.loadInterpolator(context,
+ android.R.interpolator.fast_out_linear_in);
+ }
+ return null;
}
public static Object loadTransition(Context context, int resId) {
- return sImpl.loadTransition(context, resId);
+ if (Build.VERSION.SDK_INT >= 19) {
+ return TransitionInflater.from(context).inflateTransition(resId);
+ }
+ return new TransitionStub();
}
public static void setEnterTransition(android.app.Fragment fragment, Object transition) {
- sImpl.setEnterTransition(fragment, transition);
+ if (Build.VERSION.SDK_INT >= 21) {
+ fragment.setEnterTransition((Transition) transition);
+ }
}
public static void setExitTransition(android.app.Fragment fragment, Object transition) {
- sImpl.setExitTransition(fragment, transition);
+ if (Build.VERSION.SDK_INT >= 21) {
+ fragment.setExitTransition((Transition) transition);
+ }
}
public static void setSharedElementEnterTransition(android.app.Fragment fragment,
Object transition) {
- sImpl.setSharedElementEnterTransition(fragment, transition);
+ if (Build.VERSION.SDK_INT >= 21) {
+ fragment.setSharedElementEnterTransition((Transition) transition);
+ }
}
public static void addSharedElement(android.app.FragmentTransaction ft,
View view, String transitionName) {
- sImpl.addSharedElement(ft, view, transitionName);
- }
-
- public static void setEnterTransition(Fragment fragment,
- Object transition) {
- fragment.setEnterTransition(transition);
- }
-
- public static void setExitTransition(Fragment fragment,
- Object transition) {
- fragment.setExitTransition(transition);
- }
-
- public static void setSharedElementEnterTransition(Fragment fragment,
- Object transition) {
- fragment.setSharedElementEnterTransition(transition);
- }
-
- public static void addSharedElement(FragmentTransaction ft,
- View view, String transitionName) {
- ft.addSharedElement(view, transitionName);
+ if (Build.VERSION.SDK_INT >= 21) {
+ ft.addSharedElement(view, transitionName);
+ }
}
public static Object createFadeAndShortSlide(int edge) {
- return sImpl.createFadeAndShortSlide(edge);
+ if (Build.VERSION.SDK_INT >= 21) {
+ return new FadeAndShortSlide(edge);
+ }
+ return new TransitionStub();
}
public static Object createFadeAndShortSlide(int edge, float distance) {
- return sImpl.createFadeAndShortSlide(edge, distance);
+ if (Build.VERSION.SDK_INT >= 21) {
+ FadeAndShortSlide slide = new FadeAndShortSlide(edge);
+ slide.setDistance(distance);
+ return slide;
+ }
+ return new TransitionStub();
}
public static void beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject) {
- sImpl.beginDelayedTransition(sceneRoot, transitionObject);
+ if (Build.VERSION.SDK_INT >= 21) {
+ Transition transition = (Transition) transitionObject;
+ TransitionManager.beginDelayedTransition(sceneRoot, transition);
+ }
}
public static void setTransitionGroup(ViewGroup viewGroup, boolean transitionGroup) {
- sImpl.setTransitionGroup(viewGroup, transitionGroup);
+ if (Build.VERSION.SDK_INT >= 21) {
+ viewGroup.setTransitionGroup(transitionGroup);
+ }
}
public static void setEpicenterCallback(Object transition,
- TransitionEpicenterCallback callback) {
- sImpl.setEpicenterCallback(transition, callback);
- }
-
- /**
- * @deprecated Use static calls.
- */
- @Deprecated
- public static TransitionHelper getInstance() {
- return new TransitionHelper();
- }
-
- /**
- * @deprecated Use {@link #addTransitionListener(Object, TransitionListener)}
- */
- @Deprecated
- public static void setTransitionListener(Object transition, TransitionListener listener) {
- sImpl.addTransitionListener(transition, listener);
+ final TransitionEpicenterCallback callback) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ if (callback == null) {
+ ((Transition) transition).setEpicenterCallback(null);
+ } else {
+ ((Transition) transition).setEpicenterCallback(new Transition.EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition11) {
+ return callback.onGetEpicenter(transition11);
+ }
+ });
+ }
+ }
}
}
diff --git a/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayContainer.java b/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayContainer.java
index 20abd7f..b0b45de 100644
--- a/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayContainer.java
+++ b/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayContainer.java
@@ -119,7 +119,7 @@
* Return true if the platform sdk supports shadow.
*/
public static boolean supportsShadow() {
- return StaticShadowHelper.getInstance().supportsShadow();
+ return StaticShadowHelper.supportsShadow();
}
/**
@@ -135,7 +135,7 @@
* to parent.
*/
public static void prepareParentForShadow(ViewGroup parent) {
- StaticShadowHelper.getInstance().prepareParent(parent);
+ StaticShadowHelper.prepareParent(parent);
}
/**
@@ -226,7 +226,7 @@
this, mUnfocusedZ, mFocusedZ, mRoundedCornerRadius);
break;
case SHADOW_STATIC:
- mShadowImpl = StaticShadowHelper.getInstance().addStaticShadow(this);
+ mShadowImpl = StaticShadowHelper.addStaticShadow(this);
break;
}
if (hasColorDimOverlay) {
diff --git a/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayHelper.java b/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayHelper.java
index 0299142..1dfd653 100644
--- a/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayHelper.java
+++ b/leanback/src/main/java/androidx/leanback/widget/ShadowOverlayHelper.java
@@ -280,7 +280,7 @@
* Return true if the platform sdk supports shadow.
*/
public static boolean supportsShadow() {
- return StaticShadowHelper.getInstance().supportsShadow();
+ return StaticShadowHelper.supportsShadow();
}
/**
@@ -316,7 +316,7 @@
*/
public void prepareParentForShadow(ViewGroup parent) {
if (mShadowType == SHADOW_STATIC) {
- StaticShadowHelper.getInstance().prepareParent(parent);
+ StaticShadowHelper.prepareParent(parent);
}
}
@@ -458,7 +458,7 @@
ShadowHelper.setShadowFocusLevel(impl, level);
break;
case SHADOW_STATIC:
- StaticShadowHelper.getInstance().setShadowFocusLevel(impl, level);
+ StaticShadowHelper.setShadowFocusLevel(impl, level);
break;
}
}
diff --git a/leanback/src/main/java/androidx/leanback/widget/StaticShadowHelper.java b/leanback/src/main/java/androidx/leanback/widget/StaticShadowHelper.java
index 5b3ff45..5ab0c61 100644
--- a/leanback/src/main/java/androidx/leanback/widget/StaticShadowHelper.java
+++ b/leanback/src/main/java/androidx/leanback/widget/StaticShadowHelper.java
@@ -16,107 +16,52 @@
package androidx.leanback.widget;
import android.os.Build;
+import android.view.LayoutInflater;
+import android.view.View;
import android.view.ViewGroup;
-import androidx.annotation.RequiresApi;
-
+import androidx.leanback.R;
/**
* Helper for static (nine patch) shadows.
*/
final class StaticShadowHelper {
-
- final static StaticShadowHelper sInstance = new StaticShadowHelper();
- boolean mSupportsShadow;
- ShadowHelperVersionImpl mImpl;
-
- /**
- * Interface implemented by classes that support Shadow.
- */
- static interface ShadowHelperVersionImpl {
- public void prepareParent(ViewGroup parent);
- public Object addStaticShadow(ViewGroup shadowContainer);
- public void setShadowFocusLevel(Object impl, float level);
- }
-
- /**
- * Interface used when we do not support Shadow animations.
- */
- private static final class ShadowHelperStubImpl implements ShadowHelperVersionImpl {
- ShadowHelperStubImpl() {
- }
-
- @Override
- public void prepareParent(ViewGroup parent) {
- // do nothing
- }
-
- @Override
- public Object addStaticShadow(ViewGroup shadowContainer) {
- // do nothing
- return null;
- }
-
- @Override
- public void setShadowFocusLevel(Object impl, float level) {
- // do nothing
- }
- }
-
- /**
- * Implementation used on JBMR2 (and above).
- */
- @RequiresApi(19)
- private static final class ShadowHelperJbmr2Impl implements ShadowHelperVersionImpl {
- ShadowHelperJbmr2Impl() {
- }
-
- @Override
- public void prepareParent(ViewGroup parent) {
- ShadowHelperJbmr2.prepareParent(parent);
- }
-
- @Override
- public Object addStaticShadow(ViewGroup shadowContainer) {
- return ShadowHelperJbmr2.addShadow(shadowContainer);
- }
-
- @Override
- public void setShadowFocusLevel(Object impl, float level) {
- ShadowHelperJbmr2.setShadowFocusLevel(impl, level);
- }
- }
-
- /**
- * Returns the StaticShadowHelper.
- */
private StaticShadowHelper() {
+ }
+
+ static boolean supportsShadow() {
+ return Build.VERSION.SDK_INT >= 21;
+ }
+
+ static void prepareParent(ViewGroup parent) {
if (Build.VERSION.SDK_INT >= 21) {
- mSupportsShadow = true;
- mImpl = new ShadowHelperJbmr2Impl();
- } else {
- mSupportsShadow = false;
- mImpl = new ShadowHelperStubImpl();
+ parent.setLayoutMode(ViewGroup.LAYOUT_MODE_OPTICAL_BOUNDS);
}
}
- public static StaticShadowHelper getInstance() {
- return sInstance;
+ static Object addStaticShadow(ViewGroup shadowContainer) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ shadowContainer.setLayoutMode(ViewGroup.LAYOUT_MODE_OPTICAL_BOUNDS);
+ LayoutInflater inflater = LayoutInflater.from(shadowContainer.getContext());
+ inflater.inflate(R.layout.lb_shadow, shadowContainer, true);
+ ShadowImpl impl = new ShadowImpl();
+ impl.mNormalShadow = shadowContainer.findViewById(R.id.lb_shadow_normal);
+ impl.mFocusShadow = shadowContainer.findViewById(R.id.lb_shadow_focused);
+ return impl;
+ }
+ return null;
}
- public boolean supportsShadow() {
- return mSupportsShadow;
+ static void setShadowFocusLevel(Object impl, float level) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ ShadowImpl shadowImpl = (ShadowImpl) impl;
+ shadowImpl.mNormalShadow.setAlpha(1 - level);
+ shadowImpl.mFocusShadow.setAlpha(level);
+ }
}
- public void prepareParent(ViewGroup parent) {
- mImpl.prepareParent(parent);
- }
-
- public Object addStaticShadow(ViewGroup shadowContainer) {
- return mImpl.addStaticShadow(shadowContainer);
- }
-
- public void setShadowFocusLevel(Object impl, float level) {
- mImpl.setShadowFocusLevel(impl, level);
+ static class ShadowImpl {
+ View mNormalShadow;
+ View mFocusShadow;
}
}
diff --git a/lifecycle/common-java8/api/current.txt b/lifecycle/common-java8/api/current.txt
new file mode 100644
index 0000000..07ed08c
--- /dev/null
+++ b/lifecycle/common-java8/api/current.txt
@@ -0,0 +1,13 @@
+package androidx.lifecycle {
+
+ public abstract interface DefaultLifecycleObserver implements androidx.lifecycle.LifecycleObserver {
+ method public default void onCreate(androidx.lifecycle.LifecycleOwner);
+ method public default void onDestroy(androidx.lifecycle.LifecycleOwner);
+ method public default void onPause(androidx.lifecycle.LifecycleOwner);
+ method public default void onResume(androidx.lifecycle.LifecycleOwner);
+ method public default void onStart(androidx.lifecycle.LifecycleOwner);
+ method public default void onStop(androidx.lifecycle.LifecycleOwner);
+ }
+
+}
+
diff --git a/lifecycle/common/api/current.txt b/lifecycle/common/api/current.txt
new file mode 100644
index 0000000..370089b
--- /dev/null
+++ b/lifecycle/common/api/current.txt
@@ -0,0 +1,44 @@
+package androidx.lifecycle {
+
+ public abstract class Lifecycle {
+ ctor public Lifecycle();
+ method public abstract void addObserver(androidx.lifecycle.LifecycleObserver);
+ method public abstract androidx.lifecycle.Lifecycle.State getCurrentState();
+ method public abstract void removeObserver(androidx.lifecycle.LifecycleObserver);
+ }
+
+ public static final class Lifecycle.Event extends java.lang.Enum {
+ method public static androidx.lifecycle.Lifecycle.Event valueOf(java.lang.String);
+ method public static final androidx.lifecycle.Lifecycle.Event[] values();
+ enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
+ enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
+ enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
+ enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_PAUSE;
+ enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_RESUME;
+ enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_START;
+ enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_STOP;
+ }
+
+ public static final class Lifecycle.State extends java.lang.Enum {
+ method public boolean isAtLeast(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.State valueOf(java.lang.String);
+ method public static final androidx.lifecycle.Lifecycle.State[] values();
+ enum_constant public static final androidx.lifecycle.Lifecycle.State CREATED;
+ enum_constant public static final androidx.lifecycle.Lifecycle.State DESTROYED;
+ enum_constant public static final androidx.lifecycle.Lifecycle.State INITIALIZED;
+ enum_constant public static final androidx.lifecycle.Lifecycle.State RESUMED;
+ enum_constant public static final androidx.lifecycle.Lifecycle.State STARTED;
+ }
+
+ public abstract interface LifecycleObserver {
+ }
+
+ public abstract interface LifecycleOwner {
+ method public abstract androidx.lifecycle.Lifecycle getLifecycle();
+ }
+
+ public abstract class OnLifecycleEvent implements java.lang.annotation.Annotation {
+ }
+
+}
+
diff --git a/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java b/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java
index 33f4eba..8c94a95 100644
--- a/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java
+++ b/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java
@@ -23,7 +23,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.arch.core.internal.SafeIterableMap;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import java.util.Iterator;
import java.util.Map;
diff --git a/lifecycle/livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java b/lifecycle/livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java
index 9b78ed0..741ee66 100644
--- a/lifecycle/livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java
+++ b/lifecycle/livedata-core/src/test/java/androidx/lifecycle/LiveDataTest.java
@@ -38,8 +38,8 @@
import static org.mockito.Mockito.when;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.testing.InstantTaskExecutorRule;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
import org.junit.After;
import org.junit.Before;
diff --git a/lifecycle/livedata-core/src/test/java/androidx/lifecycle/ThreadedLiveDataTest.java b/lifecycle/livedata-core/src/test/java/androidx/lifecycle/ThreadedLiveDataTest.java
index e4eb869..19dcd21 100644
--- a/lifecycle/livedata-core/src/test/java/androidx/lifecycle/ThreadedLiveDataTest.java
+++ b/lifecycle/livedata-core/src/test/java/androidx/lifecycle/ThreadedLiveDataTest.java
@@ -24,8 +24,8 @@
import static org.mockito.Mockito.when;
import androidx.annotation.Nullable;
-import androidx.executor.JunitTaskExecutorRule;
-import androidx.executor.TaskExecutor;
+import androidx.arch.core.executor.JunitTaskExecutorRule;
+import androidx.arch.core.executor.TaskExecutor;
import org.junit.Before;
import org.junit.Rule;
diff --git a/lifecycle/livedata/src/main/java/androidx/lifecycle/ComputableLiveData.java b/lifecycle/livedata/src/main/java/androidx/lifecycle/ComputableLiveData.java
index 2c91427..e2e2a1b 100644
--- a/lifecycle/livedata/src/main/java/androidx/lifecycle/ComputableLiveData.java
+++ b/lifecycle/livedata/src/main/java/androidx/lifecycle/ComputableLiveData.java
@@ -21,7 +21,7 @@
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/lifecycle/livedata/src/test/java/androidx/lifecycle/ComputableLiveDataTest.java b/lifecycle/livedata/src/test/java/androidx/lifecycle/ComputableLiveDataTest.java
index e84eb42..2b9d37e 100644
--- a/lifecycle/livedata/src/test/java/androidx/lifecycle/ComputableLiveDataTest.java
+++ b/lifecycle/livedata/src/test/java/androidx/lifecycle/ComputableLiveDataTest.java
@@ -29,9 +29,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.TaskExecutor;
-import androidx.executor.TaskExecutorWithFakeMainThread;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.TaskExecutor;
+import androidx.arch.core.executor.TaskExecutorWithFakeMainThread;
import androidx.lifecycle.util.InstantTaskExecutor;
import org.junit.After;
diff --git a/lifecycle/livedata/src/test/java/androidx/lifecycle/MediatorLiveDataTest.java b/lifecycle/livedata/src/test/java/androidx/lifecycle/MediatorLiveDataTest.java
index ac065fb..a90c343 100644
--- a/lifecycle/livedata/src/test/java/androidx/lifecycle/MediatorLiveDataTest.java
+++ b/lifecycle/livedata/src/test/java/androidx/lifecycle/MediatorLiveDataTest.java
@@ -26,8 +26,8 @@
import static org.mockito.Mockito.when;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.testing.InstantTaskExecutorRule;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
import androidx.lifecycle.util.InstantTaskExecutor;
import org.junit.Before;
diff --git a/lifecycle/livedata/src/test/java/androidx/lifecycle/TransformationsTest.java b/lifecycle/livedata/src/test/java/androidx/lifecycle/TransformationsTest.java
index 7bb37ec..4994523 100644
--- a/lifecycle/livedata/src/test/java/androidx/lifecycle/TransformationsTest.java
+++ b/lifecycle/livedata/src/test/java/androidx/lifecycle/TransformationsTest.java
@@ -27,7 +27,7 @@
import static org.mockito.Mockito.when;
import androidx.arch.core.util.Function;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.lifecycle.util.InstantTaskExecutor;
import org.junit.Before;
diff --git a/lifecycle/livedata/src/test/java/androidx/lifecycle/util/InstantTaskExecutor.java b/lifecycle/livedata/src/test/java/androidx/lifecycle/util/InstantTaskExecutor.java
index 56facd3..60d703f 100644
--- a/lifecycle/livedata/src/test/java/androidx/lifecycle/util/InstantTaskExecutor.java
+++ b/lifecycle/livedata/src/test/java/androidx/lifecycle/util/InstantTaskExecutor.java
@@ -16,7 +16,7 @@
package androidx.lifecycle.util;
-import androidx.executor.TaskExecutor;
+import androidx.arch.core.executor.TaskExecutor;
public class InstantTaskExecutor extends TaskExecutor {
@Override
diff --git a/lifecycle/reactivestreams/build.gradle b/lifecycle/reactivestreams/build.gradle
index 34390b7..649c526 100644
--- a/lifecycle/reactivestreams/build.gradle
+++ b/lifecycle/reactivestreams/build.gradle
@@ -35,9 +35,7 @@
testImplementation(JUNIT)
testImplementation(RX_JAVA)
- testImplementation(TEST_RUNNER)
-
- androidTestImplementation(SUPPORT_APPCOMPAT, libs.support_exclude_config)
+ testImplementation(project(":arch:core-testing"))
}
supportLibrary {
@@ -48,4 +46,4 @@
inceptionYear = "2017"
description = "Android Lifecycle Reactivestreams"
url = SupportLibraryExtension.ARCHITECTURE_URL
-}
\ No newline at end of file
+}
diff --git a/collection-ktx/OWNERS b/lifecycle/reactivestreams/ktx/OWNERS
similarity index 100%
copy from collection-ktx/OWNERS
copy to lifecycle/reactivestreams/ktx/OWNERS
diff --git a/lifecycle/reactivestreams/ktx/build.gradle b/lifecycle/reactivestreams/ktx/build.gradle
new file mode 100644
index 0000000..2604a8e
--- /dev/null
+++ b/lifecycle/reactivestreams/ktx/build.gradle
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static androidx.build.dependencies.DependenciesKt.*
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.SupportLibraryExtension
+
+plugins {
+ id("SupportAndroidLibraryPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ api(project(":lifecycle:lifecycle-reactivestreams"))
+ api(KOTLIN_STDLIB)
+
+ testImplementation(JUNIT)
+ testImplementation(RX_JAVA)
+ testImplementation(TRUTH)
+ testImplementation(project(":arch:core-testing"))
+}
+
+supportLibrary {
+ name = "Android Lifecycle ReactiveStreams KTX"
+ publish = true
+ mavenVersion = LibraryVersions.LIFECYCLES_EXT
+ mavenGroup = LibraryGroups.LIFECYCLE
+ inceptionYear = "2018"
+ description = "Kotlin extensions for Lifecycle ReactiveStreams"
+ url = SupportLibraryExtension.ARCHITECTURE_URL
+}
diff --git a/lifecycle/reactivestreams/ktx/src/main/AndroidManifest.xml b/lifecycle/reactivestreams/ktx/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d2c150c
--- /dev/null
+++ b/lifecycle/reactivestreams/ktx/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest package="androidx.lifecycle.reactivestreams.ktx"/>
diff --git a/lifecycle/reactivestreams/ktx/src/main/java/androidx/lifecycle/LiveDataReactiveSteams.kt b/lifecycle/reactivestreams/ktx/src/main/java/androidx/lifecycle/LiveDataReactiveSteams.kt
new file mode 100644
index 0000000..e4a95e7
--- /dev/null
+++ b/lifecycle/reactivestreams/ktx/src/main/java/androidx/lifecycle/LiveDataReactiveSteams.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:Suppress("NOTHING_TO_INLINE") // Aliases to public API.
+
+package androidx.lifecycle
+
+import org.reactivestreams.Publisher
+
+/**
+ * Adapts the given [LiveData] stream to a ReactiveStreams [Publisher].
+ *
+ * @see LiveDataReactiveStreams.toPublisher
+ */
+inline fun <T> LiveData<T>.toPublisher(lifecycle: LifecycleOwner): Publisher<T> =
+ LiveDataReactiveStreams.toPublisher(lifecycle, this)
+
+/**
+ * Creates an observable [LiveData] stream from a ReactiveStreams [Publisher].
+ *
+ * @see LiveDataReactiveStreams.fromPublisher
+ */
+inline fun <T> Publisher<T>.toLiveData(): LiveData<T> =
+ LiveDataReactiveStreams.fromPublisher(this)
diff --git a/lifecycle/reactivestreams/ktx/src/test/java/androidx/lifecycle/LiveDataReactiveStreamsTest.kt b/lifecycle/reactivestreams/ktx/src/test/java/androidx/lifecycle/LiveDataReactiveStreamsTest.kt
new file mode 100644
index 0000000..ad3bdb2
--- /dev/null
+++ b/lifecycle/reactivestreams/ktx/src/test/java/androidx/lifecycle/LiveDataReactiveStreamsTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import com.google.common.truth.Truth.assertThat
+import io.reactivex.processors.PublishProcessor
+import io.reactivex.processors.ReplayProcessor
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+class LiveDataReactiveStreamsTest {
+ @get:Rule val rule = InstantTaskExecutorRule()
+
+ private lateinit var lifecycleOwner: LifecycleOwner
+
+ @Before fun init() {
+ lifecycleOwner = object : LifecycleOwner {
+ internal var registry = LifecycleRegistry(this)
+
+ init {
+ registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
+ }
+
+ override fun getLifecycle(): Lifecycle {
+ return registry
+ }
+ }
+ }
+
+ @Test fun convertsFromPublisher() {
+ val processor = PublishProcessor.create<String>()
+ val liveData = processor.toLiveData()
+
+ val output = mutableListOf<String?>()
+ liveData.observe(lifecycleOwner, Observer { output.add(it) })
+
+ processor.onNext("foo")
+ processor.onNext("bar")
+ processor.onNext("baz")
+
+ assertThat(output).containsExactly("foo", "bar", "baz")
+ }
+
+ @Test fun convertsToPublisherWithSyncData() {
+ val liveData = MutableLiveData<String>()
+ liveData.value = "foo"
+
+ val outputProcessor = ReplayProcessor.create<String>()
+ liveData.toPublisher(lifecycleOwner).subscribe(outputProcessor)
+
+ liveData.value = "bar"
+ liveData.value = "baz"
+
+ assertThat(outputProcessor.values).asList().containsExactly("foo", "bar", "baz")
+ }
+}
diff --git a/lifecycle/reactivestreams/src/androidTest/AndroidManifest.xml b/lifecycle/reactivestreams/src/androidTest/AndroidManifest.xml
deleted file mode 100644
index 304fd93..0000000
--- a/lifecycle/reactivestreams/src/androidTest/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2017 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.lifecycle.reactivestreams.test">
- <uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
-
- <application>
- <activity android:name="androidx.lifecycle.viewmodeltest.ViewModelActivity"
- android:theme="@style/Base.Theme.AppCompat">
- </activity>
- </application>
-
-</manifest>
diff --git a/lifecycle/reactivestreams/src/main/java/androidx/lifecycle/LiveDataReactiveStreams.java b/lifecycle/reactivestreams/src/main/java/androidx/lifecycle/LiveDataReactiveStreams.java
index 250f50d..711e71e 100644
--- a/lifecycle/reactivestreams/src/main/java/androidx/lifecycle/LiveDataReactiveStreams.java
+++ b/lifecycle/reactivestreams/src/main/java/androidx/lifecycle/LiveDataReactiveStreams.java
@@ -18,7 +18,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
@@ -165,7 +165,7 @@
}
/**
- * Creates an Observable {@link LiveData} stream from a ReactiveStreams publisher.
+ * Creates an observable {@link LiveData} stream from a ReactiveStreams {@link Publisher}}.
*
* <p>
* When the LiveData becomes active, it subscribes to the emissions from the Publisher.
diff --git a/lifecycle/reactivestreams/src/test/java/androidx/lifecycle/LiveDataReactiveStreamsTest.java b/lifecycle/reactivestreams/src/test/java/androidx/lifecycle/LiveDataReactiveStreamsTest.java
index decb189..ed792d2 100644
--- a/lifecycle/reactivestreams/src/test/java/androidx/lifecycle/LiveDataReactiveStreamsTest.java
+++ b/lifecycle/reactivestreams/src/test/java/androidx/lifecycle/LiveDataReactiveStreamsTest.java
@@ -21,15 +21,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import android.support.test.filters.SmallTest;
-
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.TaskExecutor;
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
-import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
@@ -47,8 +45,9 @@
import io.reactivex.schedulers.TestScheduler;
import io.reactivex.subjects.AsyncSubject;
-@SmallTest
public class LiveDataReactiveStreamsTest {
+ @Rule public final TestRule instantTaskExecutorRule = new InstantTaskExecutorRule();
+
private LifecycleOwner mLifecycleOwner;
private final List<String> mLiveDataOutput = new ArrayList<>();
@@ -62,7 +61,6 @@
private final ReplayProcessor<String> mOutputProcessor = ReplayProcessor.create();
private static final TestScheduler sBackgroundScheduler = new TestScheduler();
- private Thread mTestThread;
@Before
public void init() {
@@ -77,31 +75,6 @@
return mRegistry;
}
};
- mTestThread = Thread.currentThread();
- ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
-
- @Override
- public void executeOnDiskIO(Runnable runnable) {
- throw new IllegalStateException();
- }
-
- @Override
- public void postToMainThread(Runnable runnable) {
- // Wrong implementation, but it is fine for test
- runnable.run();
- }
-
- @Override
- public boolean isMainThread() {
- return Thread.currentThread() == mTestThread;
- }
-
- });
- }
-
- @After
- public void removeExecutorDelegate() {
- ArchTaskExecutor.getInstance().setDelegate(null);
}
@Test
diff --git a/loader/api/current.txt b/loader/api/current.txt
index 2d00efb..275582d 100644
--- a/loader/api/current.txt
+++ b/loader/api/current.txt
@@ -5,7 +5,7 @@
method public abstract void destroyLoader(int);
method public abstract void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public static void enableDebugLogging(boolean);
- method public static <T extends android.arch.lifecycle.LifecycleOwner & android.arch.lifecycle.ViewModelStoreOwner> androidx.loader.app.LoaderManager getInstance(T);
+ method public static <T extends androidx.lifecycle.LifecycleOwner & androidx.lifecycle.ViewModelStoreOwner> androidx.loader.app.LoaderManager getInstance(T);
method public abstract <D> androidx.loader.content.Loader<D> getLoader(int);
method public boolean hasRunningLoaders();
method public abstract <D> androidx.loader.content.Loader<D> initLoader(int, android.os.Bundle, androidx.loader.app.LoaderManager.LoaderCallbacks<D>);
diff --git a/loader/src/androidTest/AndroidManifest.xml b/loader/src/androidTest/AndroidManifest.xml
index 641063e..5115c15 100644
--- a/loader/src/androidTest/AndroidManifest.xml
+++ b/loader/src/androidTest/AndroidManifest.xml
@@ -17,10 +17,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.support.loader.test">
<uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
-
- <application>
- <activity android:name="androidx.loader.app.test.EmptyActivity" />
- </application>
-
</manifest>
diff --git a/loader/src/androidTest/java/androidx/loader/app/LoaderInfoTest.java b/loader/src/androidTest/java/androidx/loader/app/LoaderInfoTest.java
index ecdf44f..963d390 100644
--- a/loader/src/androidTest/java/androidx/loader/app/LoaderInfoTest.java
+++ b/loader/src/androidTest/java/androidx/loader/app/LoaderInfoTest.java
@@ -22,9 +22,9 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
-import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import androidx.lifecycle.Lifecycle;
@@ -32,11 +32,9 @@
import androidx.lifecycle.LifecycleRegistry;
import androidx.loader.app.test.DelayLoader;
import androidx.loader.app.test.DummyLoaderCallbacks;
-import androidx.loader.app.test.EmptyActivity;
import androidx.loader.content.Loader;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,25 +57,21 @@
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
- @Rule
- public ActivityTestRule<EmptyActivity> mActivityRule =
- new ActivityTestRule<>(EmptyActivity.class);
-
@Test
public void testIsCallbackWaitingForData() throws Throwable {
final DummyLoaderCallbacks loaderCallback = new DummyLoaderCallbacks(mock(Context.class));
final CountDownLatch deliverResultLatch = new CountDownLatch(1);
- Loader<Boolean> delayLoader = new DelayLoader(mActivityRule.getActivity(),
+ Loader<Boolean> delayLoader = new DelayLoader(mock(Context.class),
deliverResultLatch);
final LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
0, null, delayLoader, null);
assertFalse("isCallbackWaitingForData should be false before setCallback",
loaderInfo.isCallbackWaitingForData());
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderInfo.setCallback(mActivityRule.getActivity(), loaderCallback);
+ loaderInfo.setCallback(mOwner, loaderCallback);
}
});
assertTrue("isCallbackWaitingForData should be true immediately after setCallback",
@@ -86,7 +80,7 @@
assertTrue("Loader timed out delivering results",
deliverResultLatch.await(1, TimeUnit.SECONDS));
// Results are posted to the UI thread, so we wait for them there
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
assertTrue("onLoadFinished should be called after setCallback",
@@ -107,7 +101,7 @@
assertFalse("onLoadFinished shouldn't be called before setCallback",
loaderCallback.mOnLoadFinished);
- loaderInfo.setCallback(mActivityRule.getActivity(), loaderCallback);
+ loaderInfo.setCallback(mOwner, loaderCallback);
assertTrue("onLoadFinished should be called after setCallback",
loaderCallback.mOnLoadFinished);
}
@@ -122,15 +116,15 @@
assertFalse("onLoadFinished for initial shouldn't be called before setCallback initial",
initialCallback.mOnLoadFinished);
- loaderInfo.setCallback(mActivityRule.getActivity(), initialCallback);
+ loaderInfo.setCallback(mOwner, initialCallback);
assertTrue("onLoadFinished for initial should be called after setCallback initial",
initialCallback.mOnLoadFinished);
final DummyLoaderCallbacks replacementCallback =
- new DummyLoaderCallbacks(mActivityRule.getActivity());
+ new DummyLoaderCallbacks(mock(Context.class));
initialCallback.mOnLoadFinished = false;
- loaderInfo.setCallback(mActivityRule.getActivity(), replacementCallback);
+ loaderInfo.setCallback(mOwner, replacementCallback);
assertFalse("onLoadFinished for initial should not be called "
+ "after setCallback replacement",
initialCallback.mOnLoadFinished);
@@ -202,7 +196,7 @@
final LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
0, null, loader, null);
- loaderInfo.setCallback(mActivityRule.getActivity(), loaderCallback);
+ loaderInfo.setCallback(mOwner, loaderCallback);
assertTrue("Loader should be started after setCallback", loader.isStarted());
loaderInfo.destroy(true);
assertFalse("Loader should not be started after destroy", loader.isStarted());
diff --git a/loader/src/androidTest/java/androidx/loader/app/LoaderManagerTest.java b/loader/src/androidTest/java/androidx/loader/app/LoaderManagerTest.java
index cd60ee8..bbe7e52 100644
--- a/loader/src/androidTest/java/androidx/loader/app/LoaderManagerTest.java
+++ b/loader/src/androidTest/java/androidx/loader/app/LoaderManagerTest.java
@@ -23,8 +23,9 @@
import android.content.Context;
import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
-import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import androidx.annotation.NonNull;
@@ -35,10 +36,9 @@
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.loader.app.test.DelayLoaderCallbacks;
import androidx.loader.app.test.DummyLoaderCallbacks;
-import androidx.loader.app.test.EmptyActivity;
import androidx.loader.content.Loader;
-import org.junit.Rule;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,24 +49,26 @@
@SmallTest
public class LoaderManagerTest {
- @Rule
- public ActivityTestRule<EmptyActivity> mActivityRule =
- new ActivityTestRule<>(EmptyActivity.class);
+ private LoaderManager mLoaderManager;
+
+ @Before
+ public void setup() {
+ mLoaderManager = LoaderManager.getInstance(new LoaderOwner());
+ }
@Test
public void testDestroyFromOnCreateLoader() throws Throwable {
- final LoaderOwner loaderOwner = new LoaderOwner();
final CountDownLatch onCreateLoaderLatch = new CountDownLatch(1);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- LoaderManager.getInstance(loaderOwner).initLoader(65, null,
+ mLoaderManager.initLoader(65, null,
new DummyLoaderCallbacks(mock(Context.class)) {
@NonNull
@Override
public Loader<Boolean> onCreateLoader(int id, Bundle args) {
try {
- LoaderManager.getInstance(loaderOwner).destroyLoader(65);
+ mLoaderManager.destroyLoader(65);
fail("Calling destroyLoader in onCreateLoader should throw an "
+ "IllegalStateException");
} catch (IllegalStateException e) {
@@ -87,18 +89,17 @@
*/
@Test
public void testDestroyFromOnLoadFinished() throws Throwable {
- final LoaderOwner loaderOwner = new LoaderOwner();
final CountDownLatch onLoadFinishedLatch = new CountDownLatch(1);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- LoaderManager.getInstance(loaderOwner).initLoader(43, null,
+ mLoaderManager.initLoader(43, null,
new DummyLoaderCallbacks(mock(Context.class)) {
@Override
public void onLoadFinished(@NonNull Loader<Boolean> loader,
Boolean data) {
super.onLoadFinished(loader, data);
- LoaderManager.getInstance(loaderOwner).destroyLoader(43);
+ mLoaderManager.destroyLoader(43);
}
});
}
@@ -108,16 +109,14 @@
@Test
public void testDestroyLoaderBeforeDeliverData() throws Throwable {
- final LoaderOwner loaderOwner = new LoaderOwner();
- final LoaderManager loaderManager = LoaderManager.getInstance(loaderOwner);
final DelayLoaderCallbacks callback =
new DelayLoaderCallbacks(mock(Context.class), new CountDownLatch(1));
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.initLoader(37, null, callback);
+ mLoaderManager.initLoader(37, null, callback);
// Immediately destroy it before it has a chance to deliver data
- loaderManager.destroyLoader(37);
+ mLoaderManager.destroyLoader(37);
}
});
assertFalse("LoaderCallbacks should not be reset if they never received data",
@@ -128,23 +127,21 @@
@Test
public void testDestroyLoaderAfterDeliverData() throws Throwable {
- final LoaderOwner loaderOwner = new LoaderOwner();
- final LoaderManager loaderManager = LoaderManager.getInstance(loaderOwner);
CountDownLatch countDownLatch = new CountDownLatch(1);
final DelayLoaderCallbacks callback =
new DelayLoaderCallbacks(mock(Context.class), countDownLatch);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.initLoader(38, null, callback);
+ mLoaderManager.initLoader(38, null, callback);
}
});
// Wait for the Loader to return data
countDownLatch.await(1, TimeUnit.SECONDS);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.destroyLoader(38);
+ mLoaderManager.destroyLoader(38);
}
});
assertTrue("LoaderCallbacks should be reset after destroyLoader()",
@@ -156,19 +153,17 @@
@Test
public void testRestartLoaderBeforeDeliverData() throws Throwable {
- final LoaderOwner loaderOwner = new LoaderOwner();
- final LoaderManager loaderManager = LoaderManager.getInstance(loaderOwner);
final DelayLoaderCallbacks initialCallback =
new DelayLoaderCallbacks(mock(Context.class), new CountDownLatch(1));
CountDownLatch restartCountDownLatch = new CountDownLatch(1);
final DelayLoaderCallbacks restartCallback =
new DelayLoaderCallbacks(mock(Context.class), restartCountDownLatch);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.initLoader(44, null, initialCallback);
+ mLoaderManager.initLoader(44, null, initialCallback);
// Immediately restart it before it has a chance to deliver data
- loaderManager.restartLoader(44, null, restartCallback);
+ mLoaderManager.restartLoader(44, null, restartCallback);
}
});
assertFalse("Initial LoaderCallbacks should not be reset after restartLoader()",
@@ -180,15 +175,13 @@
@Test
public void testRestartLoaderAfterDeliverData() throws Throwable {
- final LoaderOwner loaderOwner = new LoaderOwner();
- final LoaderManager loaderManager = LoaderManager.getInstance(loaderOwner);
CountDownLatch initialCountDownLatch = new CountDownLatch(1);
final DelayLoaderCallbacks initialCallback =
new DelayLoaderCallbacks(mock(Context.class), initialCountDownLatch);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.initLoader(45, null, initialCallback);
+ mLoaderManager.initLoader(45, null, initialCallback);
}
});
// Wait for the first Loader to return data
@@ -196,10 +189,10 @@
CountDownLatch restartCountDownLatch = new CountDownLatch(1);
final DelayLoaderCallbacks restartCallback =
new DelayLoaderCallbacks(mock(Context.class), restartCountDownLatch);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.restartLoader(45, null, restartCallback);
+ mLoaderManager.restartLoader(45, null, restartCallback);
}
});
assertFalse("Initial LoaderCallbacks should not be reset after restartLoader()",
@@ -213,15 +206,13 @@
@Test
public void testRestartLoaderMultiple() throws Throwable {
- final LoaderOwner loaderOwner = new LoaderOwner();
- final LoaderManager loaderManager = LoaderManager.getInstance(loaderOwner);
CountDownLatch initialCountDownLatch = new CountDownLatch(1);
final DelayLoaderCallbacks initialCallback =
new DelayLoaderCallbacks(mock(Context.class), initialCountDownLatch);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.initLoader(46, null, initialCallback);
+ mLoaderManager.initLoader(46, null, initialCallback);
}
});
// Wait for the first Loader to return data
@@ -231,12 +222,12 @@
CountDownLatch restartCountDownLatch = new CountDownLatch(1);
final DelayLoaderCallbacks restartCallback =
new DelayLoaderCallbacks(mock(Context.class), restartCountDownLatch);
- mActivityRule.runOnUiThread(new Runnable() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- loaderManager.restartLoader(46, null, intermediateCallback);
+ mLoaderManager.restartLoader(46, null, intermediateCallback);
// Immediately replace the restarted Loader with yet another Loader
- loaderManager.restartLoader(46, null, restartCallback);
+ mLoaderManager.restartLoader(46, null, restartCallback);
}
});
assertFalse("Initial LoaderCallbacks should not be reset after restartLoader()",
@@ -250,24 +241,40 @@
initialCallback.mLoader.isReset());
}
+ @UiThreadTest
+ @Test(expected = IllegalArgumentException.class)
+ public void enforceNonNullLoader() {
+ mLoaderManager.initLoader(-1, null, new LoaderManager.LoaderCallbacks<Object>() {
+ @Override
+ public Loader<Object> onCreateLoader(int id, Bundle args) {
+ return null;
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Object> loader, Object data) {
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Object> loader) {
+ }
+ });
+ }
+
@Test(expected = IllegalStateException.class)
public void enforceOnMainThread_initLoader() {
- LoaderOwner loaderOwner = new LoaderOwner();
- LoaderManager.getInstance(loaderOwner).initLoader(-1, null,
+ mLoaderManager.initLoader(-1, null,
new DummyLoaderCallbacks(mock(Context.class)));
}
@Test(expected = IllegalStateException.class)
public void enforceOnMainThread_restartLoader() {
- LoaderOwner loaderOwner = new LoaderOwner();
- LoaderManager.getInstance(loaderOwner).restartLoader(-1, null,
+ mLoaderManager.restartLoader(-1, null,
new DummyLoaderCallbacks(mock(Context.class)));
}
@Test(expected = IllegalStateException.class)
public void enforceOnMainThread_destroyLoader() {
- LoaderOwner loaderOwner = new LoaderOwner();
- LoaderManager.getInstance(loaderOwner).destroyLoader(-1);
+ mLoaderManager.destroyLoader(-1);
}
class LoaderOwner implements LifecycleOwner, ViewModelStoreOwner {
diff --git a/loader/src/main/java/androidx/loader/app/LoaderManagerImpl.java b/loader/src/main/java/androidx/loader/app/LoaderManagerImpl.java
index 770779d..7a2bae6 100644
--- a/loader/src/main/java/androidx/loader/app/LoaderManagerImpl.java
+++ b/loader/src/main/java/androidx/loader/app/LoaderManagerImpl.java
@@ -380,6 +380,10 @@
try {
mLoaderViewModel.startCreatingLoader();
Loader<D> loader = callback.onCreateLoader(id, args);
+ if (loader == null) {
+ throw new IllegalArgumentException("Object returned from onCreateLoader "
+ + "must not be null");
+ }
if (loader.getClass().isMemberClass()
&& !Modifier.isStatic(loader.getClass().getModifiers())) {
throw new IllegalArgumentException("Object returned from onCreateLoader "
diff --git a/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java b/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
index c73c01a..66ca559 100644
--- a/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
+++ b/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
@@ -43,6 +43,7 @@
import androidx.annotation.RestrictTo;
import androidx.core.app.ActivityManagerCompat;
import androidx.core.hardware.display.DisplayManagerCompat;
+import androidx.core.util.ObjectsCompat;
import androidx.core.util.Pair;
import androidx.media.VolumeProviderCompat;
import androidx.mediarouter.app.MediaRouteDiscoveryFragment;
@@ -783,10 +784,6 @@
}
}
- static <T> boolean equal(T a, T b) {
- return a == b || (a != null && b != null && a.equals(b));
- }
-
/**
* Provides information about a media route.
* <p>
@@ -1490,15 +1487,15 @@
int changes = 0;
mDescriptor = descriptor;
if (descriptor != null) {
- if (!equal(mName, descriptor.getName())) {
+ if (!ObjectsCompat.equals(mName, descriptor.getName())) {
mName = descriptor.getName();
changes |= CHANGE_GENERAL;
}
- if (!equal(mDescription, descriptor.getDescription())) {
+ if (!ObjectsCompat.equals(mDescription, descriptor.getDescription())) {
mDescription = descriptor.getDescription();
changes |= CHANGE_GENERAL;
}
- if (!equal(mIconUri, descriptor.getIconUri())) {
+ if (!ObjectsCompat.equals(mIconUri, descriptor.getIconUri())) {
mIconUri = descriptor.getIconUri();
changes |= CHANGE_GENERAL;
}
@@ -1548,11 +1545,11 @@
mPresentationDisplay = null;
changes |= CHANGE_GENERAL | CHANGE_PRESENTATION_DISPLAY;
}
- if (!equal(mExtras, descriptor.getExtras())) {
+ if (!ObjectsCompat.equals(mExtras, descriptor.getExtras())) {
mExtras = descriptor.getExtras();
changes |= CHANGE_GENERAL;
}
- if (!equal(mSettingsIntent, descriptor.getSettingsActivity())) {
+ if (!ObjectsCompat.equals(mSettingsIntent, descriptor.getSettingsActivity())) {
mSettingsIntent = descriptor.getSettingsActivity();
changes |= CHANGE_GENERAL;
}
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagedListDifferTest.kt b/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagedListDifferTest.kt
index 7686132..169779d 100644
--- a/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagedListDifferTest.kt
+++ b/paging/runtime/src/androidTest/java/androidx/paging/AsyncPagedListDifferTest.kt
@@ -17,7 +17,7 @@
package androidx.paging
import android.support.test.filters.SmallTest
-import androidx.executor.ArchTaskExecutor
+import androidx.arch.core.executor.ArchTaskExecutor
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListUpdateCallback
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
new file mode 100644
index 0000000..54955a0
--- /dev/null
+++ b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.paging
+
+import android.support.test.filters.SmallTest
+import androidx.arch.core.executor.ArchTaskExecutor
+import androidx.arch.core.executor.TaskExecutor
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
+import androidx.lifecycle.Observer
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class LivePagedListBuilderTest {
+ private val backgroundExecutor = TestExecutor()
+ private val lifecycleOwner = object : LifecycleOwner {
+ private val lifecycle = LifecycleRegistry(this)
+
+ override fun getLifecycle(): Lifecycle {
+ return lifecycle
+ }
+
+ fun handleEvent(event: Lifecycle.Event) {
+ lifecycle.handleLifecycleEvent(event)
+ }
+ }
+
+ @Before
+ fun setup() {
+ ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() {
+ override fun executeOnDiskIO(runnable: Runnable) {
+ fail("IO executor should be overwritten")
+ }
+
+ override fun postToMainThread(runnable: Runnable) {
+ runnable.run()
+ }
+
+ override fun isMainThread(): Boolean {
+ return true
+ }
+ })
+ lifecycleOwner.handleEvent(Lifecycle.Event.ON_START)
+ }
+
+ @After
+ fun teardown() {
+ lifecycleOwner.handleEvent(Lifecycle.Event.ON_STOP)
+ ArchTaskExecutor.getInstance().setDelegate(null)
+ }
+
+ private class MockDataSource : PositionalDataSource<String>() {
+ override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<String>) {
+ assertEquals(2, params.pageSize)
+ callback.onResult(listOf("a", "b"), 0, 4)
+ }
+
+ override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<String>) {
+ callback.onResult(listOf("c", "d"))
+ }
+
+ class Factory : DataSource.Factory<Int, String>() {
+ override fun create(): DataSource<Int, String> {
+ return MockDataSource()
+ }
+ }
+ }
+
+ @Test
+ fun executorBehavior() {
+ // specify a background executor via builder, and verify it gets used for all loads,
+ // overriding default arch IO executor
+ val livePagedList = LivePagedListBuilder(
+ MockDataSource.Factory(), 2)
+ .setBackgroundThreadExecutor(backgroundExecutor)
+ .build()
+
+ val pagedListHolder: Array<PagedList<String>?> = arrayOfNulls(1)
+
+ livePagedList.observe(lifecycleOwner, Observer<PagedList<String>> { newList ->
+ pagedListHolder[0] = newList
+ })
+
+ // won't compute until we flush...
+ assertNull(pagedListHolder[0])
+
+ // flush loadInitial, done with passed executor
+ backgroundExecutor.executeAll()
+
+ val pagedList = pagedListHolder[0]
+ assertNotNull(pagedList)
+ assertEquals(listOf("a", "b", null, null), pagedList)
+
+ // flush loadRange
+ pagedList!!.loadAround(2)
+ backgroundExecutor.executeAll()
+
+ assertEquals(listOf("a", "b", "c", "d"), pagedList)
+ }
+}
diff --git a/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java b/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
index f37ac5d..f30163d 100644
--- a/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
+++ b/paging/runtime/src/main/java/androidx/paging/AsyncPagedListDiffer.java
@@ -18,7 +18,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.lifecycle.LiveData;
import androidx.recyclerview.widget.AdapterListUpdateCallback;
import androidx.recyclerview.widget.AsyncDifferConfig;
diff --git a/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.java b/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.java
index 5d758cb..75c632f 100644
--- a/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.java
+++ b/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.java
@@ -19,7 +19,7 @@
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.lifecycle.ComputableLiveData;
import androidx.lifecycle.LiveData;
@@ -167,7 +167,7 @@
@NonNull final DataSource.Factory<Key, Value> dataSourceFactory,
@NonNull final Executor mainThreadExecutor,
@NonNull final Executor backgroundThreadExecutor) {
- return new ComputableLiveData<PagedList<Value>>() {
+ return new ComputableLiveData<PagedList<Value>>(backgroundThreadExecutor) {
@Nullable
private PagedList<Value> mList;
@Nullable
diff --git a/palette/build.gradle b/palette/build.gradle
index b1ab9e7..4037bf5 100644
--- a/palette/build.gradle
+++ b/palette/build.gradle
@@ -10,6 +10,8 @@
api(project(":core"))
api(project(":legacy-support-core-utils"))
+ annotationProcessor(NULLAWAY)
+
androidTestImplementation(TEST_RUNNER_TMP, libs.exclude_for_espresso)
}
diff --git a/palette-ktx/OWNERS b/palette/ktx/OWNERS
similarity index 100%
rename from palette-ktx/OWNERS
rename to palette/ktx/OWNERS
diff --git a/palette-ktx/build.gradle b/palette/ktx/build.gradle
similarity index 100%
rename from palette-ktx/build.gradle
rename to palette/ktx/build.gradle
diff --git a/palette-ktx/src/androidTest/java/androidx/palette/graphics/PaletteTest.kt b/palette/ktx/src/androidTest/java/androidx/palette/graphics/PaletteTest.kt
similarity index 100%
rename from palette-ktx/src/androidTest/java/androidx/palette/graphics/PaletteTest.kt
rename to palette/ktx/src/androidTest/java/androidx/palette/graphics/PaletteTest.kt
diff --git a/palette-ktx/src/main/AndroidManifest.xml b/palette/ktx/src/main/AndroidManifest.xml
similarity index 100%
rename from palette-ktx/src/main/AndroidManifest.xml
rename to palette/ktx/src/main/AndroidManifest.xml
diff --git a/palette-ktx/src/main/java/androidx/palette/graphics/Palette.kt b/palette/ktx/src/main/java/androidx/palette/graphics/Palette.kt
similarity index 100%
rename from palette-ktx/src/main/java/androidx/palette/graphics/Palette.kt
rename to palette/ktx/src/main/java/androidx/palette/graphics/Palette.kt
diff --git a/palette/src/main/java/androidx/palette/graphics/ColorCutQuantizer.java b/palette/src/main/java/androidx/palette/graphics/ColorCutQuantizer.java
index 5c304f8..58e3643 100644
--- a/palette/src/main/java/androidx/palette/graphics/ColorCutQuantizer.java
+++ b/palette/src/main/java/androidx/palette/graphics/ColorCutQuantizer.java
@@ -19,6 +19,7 @@
import android.graphics.Color;
import android.util.TimingLogger;
+import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import java.util.ArrayList;
@@ -56,7 +57,7 @@
final int[] mColors;
final int[] mHistogram;
final List<Palette.Swatch> mQuantizedColors;
- final TimingLogger mTimingLogger;
+ @Nullable final TimingLogger mTimingLogger;
final Palette.Filter[] mFilters;
private final float[] mTempHsl = new float[3];
@@ -68,6 +69,7 @@
* @param maxColors The maximum number of colors that should be in the result palette.
* @param filters Set of filters to use in the quantization stage
*/
+ @SuppressWarnings("NullAway") // mTimingLogger initialization and access guarded by LOG_TIMINGS.
ColorCutQuantizer(final int[] pixels, final int maxColors, final Palette.Filter[] filters) {
mTimingLogger = LOG_TIMINGS ? new TimingLogger(LOG_TAG, "Creation") : null;
mFilters = filters;
@@ -169,6 +171,7 @@
* @param queue {@link java.util.PriorityQueue} to poll for boxes
* @param maxSize Maximum amount of boxes to split
*/
+ @SuppressWarnings("NullAway") // mTimingLogger initialization and access guarded by LOG_TIMINGS.
private void splitBoxes(final PriorityQueue<Vbox> queue, final int maxSize) {
while (queue.size() < maxSize) {
final Vbox vbox = queue.poll();
diff --git a/palette/src/main/java/androidx/palette/graphics/Palette.java b/palette/src/main/java/androidx/palette/graphics/Palette.java
index 503149c..6f062ac 100644
--- a/palette/src/main/java/androidx/palette/graphics/Palette.java
+++ b/palette/src/main/java/androidx/palette/graphics/Palette.java
@@ -80,9 +80,10 @@
public interface PaletteAsyncListener {
/**
- * Called when the {@link Palette} has been generated.
+ * Called when the {@link Palette} has been generated. {@code null} will be passed when an
+ * error occurred during generation.
*/
- void onGenerated(@NonNull Palette palette);
+ void onGenerated(@Nullable Palette palette);
}
static final int DEFAULT_RESIZE_BITMAP_AREA = 112 * 112;
@@ -152,7 +153,7 @@
private final Map<Target, Swatch> mSelectedSwatches;
private final SparseBooleanArray mUsedColors;
- private final Swatch mDominantSwatch;
+ @Nullable private final Swatch mDominantSwatch;
Palette(List<Swatch> swatches, List<Target> targets) {
mSwatches = swatches;
@@ -360,6 +361,7 @@
mUsedColors.clear();
}
+ @Nullable
private Swatch generateScoredTarget(final Target target) {
final Swatch maxScoreSwatch = getMaxScoredSwatchForTarget(target);
if (maxScoreSwatch != null && target.isExclusive()) {
@@ -369,6 +371,7 @@
return maxScoreSwatch;
}
+ @Nullable
private Swatch getMaxScoredSwatchForTarget(final Target target) {
float maxScore = 0;
Swatch maxScoreSwatch = null;
@@ -419,6 +422,7 @@
return saturationScore + luminanceScore + populationScore;
}
+ @Nullable
private Swatch findDominantSwatch() {
int maxPop = Integer.MIN_VALUE;
Swatch maxSwatch = null;
@@ -432,12 +436,6 @@
return maxSwatch;
}
- private static float[] copyHslValues(Swatch color) {
- final float[] newHsl = new float[3];
- System.arraycopy(color.getHsl(), 0, newHsl, 0, 3);
- return newHsl;
- }
-
/**
* Represents a color swatch generated from an image's palette. The RGB color can be retrieved
* by calling {@link #getRgb()}.
@@ -451,7 +449,7 @@
private int mTitleTextColor;
private int mBodyTextColor;
- private float[] mHsl;
+ @Nullable private float[] mHsl;
public Swatch(@ColorInt int color, int population) {
mRed = Color.red(color);
@@ -600,8 +598,8 @@
* Builder class for generating {@link Palette} instances.
*/
public static final class Builder {
- private final List<Swatch> mSwatches;
- private final Bitmap mBitmap;
+ @Nullable private final List<Swatch> mSwatches;
+ @Nullable private final Bitmap mBitmap;
private final List<Target> mTargets = new ArrayList<>();
@@ -610,7 +608,7 @@
private int mResizeMaxDimension = -1;
private final List<Filter> mFilters = new ArrayList<>();
- private Rect mRegion;
+ @Nullable private Rect mRegion;
/**
* Construct a new {@link Builder} using a source {@link Bitmap}
@@ -831,9 +829,12 @@
if (logger != null) {
logger.addSplit("Color quantization completed");
}
- } else {
+ } else if (mSwatches != null) {
// Else we're using the provided swatches
swatches = mSwatches;
+ } else {
+ // The constructors enforce either a bitmap or swatches are present.
+ throw new AssertionError();
}
// Now create a Palette instance
@@ -863,6 +864,7 @@
return new AsyncTask<Bitmap, Void, Palette>() {
@Override
+ @Nullable
protected Palette doInBackground(Bitmap... params) {
try {
return generate();
@@ -873,7 +875,7 @@
}
@Override
- protected void onPostExecute(Palette colorExtractor) {
+ protected void onPostExecute(@Nullable Palette colorExtractor) {
listener.onGenerated(colorExtractor);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mBitmap);
diff --git a/palette-ktx/OWNERS b/persistence/db/ktx/OWNERS
similarity index 100%
copy from palette-ktx/OWNERS
copy to persistence/db/ktx/OWNERS
diff --git a/persistence/db/ktx/build.gradle b/persistence/db/ktx/build.gradle
new file mode 100644
index 0000000..676445b
--- /dev/null
+++ b/persistence/db/ktx/build.gradle
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static androidx.build.dependencies.DependenciesKt.*
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.SupportLibraryExtension
+
+plugins {
+ id("SupportAndroidLibraryPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ api(project(":sqlite:sqlite"))
+ api(KOTLIN_STDLIB)
+
+ testImplementation(JUNIT)
+ testImplementation(MOCKITO_CORE)
+}
+
+supportLibrary {
+ name = "Android DB KTX"
+ publish = true
+ mavenVersion = LibraryVersions.ROOM
+ mavenGroup = LibraryGroups.PERSISTENCE
+ inceptionYear = "2018"
+ description = "Kotlin extensions for DB"
+ url = SupportLibraryExtension.ARCHITECTURE_URL
+}
diff --git a/persistence/db/ktx/src/main/AndroidManifest.xml b/persistence/db/ktx/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f4d66ba
--- /dev/null
+++ b/persistence/db/ktx/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest package="androidx.sqlite.db.ktx"/>
diff --git a/persistence/db/ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabase.kt b/persistence/db/ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabase.kt
new file mode 100644
index 0000000..ba7b338
--- /dev/null
+++ b/persistence/db/ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabase.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.sqlite.db
+
+/**
+ * Run [body] in a transaction marking it as successful if it completes without exception.
+ *
+ * @param exclusive Run in `EXCLUSIVE` mode when true, `IMMEDIATE` mode otherwise.
+ */
+inline fun <T> SupportSQLiteDatabase.transaction(
+ exclusive: Boolean = true,
+ body: SupportSQLiteDatabase.() -> T
+): T {
+ if (exclusive) {
+ beginTransaction()
+ } else {
+ beginTransactionNonExclusive()
+ }
+ try {
+ val result = body()
+ setTransactionSuccessful()
+ return result
+ } finally {
+ endTransaction()
+ }
+}
diff --git a/persistence/db/ktx/src/test/java/androidx/sqlite/db/SupportSQLiteDatabaseTest.kt b/persistence/db/ktx/src/test/java/androidx/sqlite/db/SupportSQLiteDatabaseTest.kt
new file mode 100644
index 0000000..76698d3
--- /dev/null
+++ b/persistence/db/ktx/src/test/java/androidx/sqlite/db/SupportSQLiteDatabaseTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.sqlite.db
+
+import org.junit.Assert.fail
+import org.junit.Test
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+class SupportSQLiteDatabaseTest {
+ @Test fun exclusiveDefault() {
+ val db = mock(SupportSQLiteDatabase::class.java)
+ db.transaction {}
+ verify(db).beginTransaction()
+ }
+
+ @Test fun exclusiveFalse() {
+ val db = mock(SupportSQLiteDatabase::class.java)
+ db.transaction(exclusive = false) {}
+ verify(db).beginTransactionNonExclusive()
+ }
+
+ @Test fun exclusiveTrue() {
+ val db = mock(SupportSQLiteDatabase::class.java)
+ db.transaction(exclusive = true) {}
+ verify(db).beginTransaction()
+ }
+
+ @Test fun bodyNormalCallsSuccessAndEnd() {
+ val db = mock(SupportSQLiteDatabase::class.java)
+ db.transaction {}
+ verify(db).setTransactionSuccessful()
+ verify(db).endTransaction()
+ }
+
+ @Suppress("UNREACHABLE_CODE") // A programming error might not invoke the lambda.
+ @Test fun bodyThrowsDoesNotCallSuccess() {
+ val db = mock(SupportSQLiteDatabase::class.java)
+ try {
+ db.transaction {
+ throw IllegalStateException()
+ }
+ fail()
+ } catch (e: IllegalStateException) {
+ }
+ verify(db, times(0)).setTransactionSuccessful()
+ verify(db).endTransaction()
+ }
+}
diff --git a/preference/src/main/java/androidx/preference/EditTextPreferenceDialogFragment.java b/preference/src/main/java/androidx/preference/EditTextPreferenceDialogFragment.java
index 2fa0e1b..f25710b 100644
--- a/preference/src/main/java/androidx/preference/EditTextPreferenceDialogFragment.java
+++ b/preference/src/main/java/androidx/preference/EditTextPreferenceDialogFragment.java
@@ -63,6 +63,7 @@
super.onBindDialogView(view);
mEditText = view.findViewById(android.R.id.edit);
+ mEditText.requestFocus();
if (mEditText == null) {
throw new IllegalStateException("Dialog view must contain an EditText with id"
@@ -71,7 +72,7 @@
mEditText.setText(mText);
// Place cursor at the end
- mEditText.setSelection(mText.length());
+ mEditText.setSelection(mEditText.getText().length());
}
private EditTextPreference getEditTextPreference() {
diff --git a/preference/src/main/java/androidx/preference/PreferenceDialogFragment.java b/preference/src/main/java/androidx/preference/PreferenceDialogFragment.java
index a4123fe..2b911a1 100644
--- a/preference/src/main/java/androidx/preference/PreferenceDialogFragment.java
+++ b/preference/src/main/java/androidx/preference/PreferenceDialogFragment.java
@@ -193,6 +193,11 @@
* Returns whether the preference needs to display a soft input method when the dialog
* is displayed. Default is false. Subclasses should override this method if they need
* the soft input method brought up automatically.
+ *
+ * <p>Note: If your application targets P or above, ensure your subclass manually requests
+ * focus (ideally in {@link #onBindDialogView(View)}) for the input field in order to
+ * correctly attach the input method to the field.
+ *
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
diff --git a/print/src/main/java/androidx/print/PrintHelper.java b/print/src/main/java/androidx/print/PrintHelper.java
index f32eb23..2630940 100644
--- a/print/src/main/java/androidx/print/PrintHelper.java
+++ b/print/src/main/java/androidx/print/PrintHelper.java
@@ -56,6 +56,24 @@
* Helper for printing bitmaps.
*/
public final class PrintHelper {
+ private static final String LOG_TAG = "PrintHelper";
+ // will be <= 300 dpi on A4 (8.3×11.7) paper (worst case of 150 dpi)
+ private static final int MAX_PRINT_SIZE = 3500;
+
+ /**
+ * Whether the PrintActivity respects the suggested orientation.
+ *
+ * There is a bug in the PrintActivity that causes it to ignore the orientation
+ */
+ private static final boolean PRINT_ACTIVITY_RESPECTS_ORIENTATION =
+ Build.VERSION.SDK_INT < 20 || Build.VERSION.SDK_INT > 23;
+
+ /**
+ * Whether the print subsystem handles min margins correctly. If not the print helper needs
+ * to fake this.
+ */
+ private static final boolean IS_MIN_MARGINS_HANDLING_CORRECT = Build.VERSION.SDK_INT != 23;
+
/**
* image will be scaled but leave white space
*/
@@ -110,7 +128,14 @@
@Retention(RetentionPolicy.SOURCE)
private @interface Orientation {}
- private final PrintHelperVersionImpl mImpl;
+ private final Context mContext;
+
+ BitmapFactory.Options mDecodeOptions = null;
+ private final Object mLock = new Object();
+
+ @ScaleMode int mScaleMode = SCALE_MODE_FILL;
+ @ColorMode int mColorMode = COLOR_MODE_COLOR;
+ @Orientation int mOrientation = ORIENTATION_LANDSCAPE;
/**
* Gets whether the system supports printing.
@@ -123,786 +148,12 @@
}
/**
- * Interface implemented by classes that support printing
- */
- interface PrintHelperVersionImpl {
-
- void setScaleMode(int scaleMode);
-
- int getScaleMode();
-
- void setColorMode(int colorMode);
-
- int getColorMode();
-
- void setOrientation(int orientation);
-
- int getOrientation();
-
- void printBitmap(@NonNull String jobName, @NonNull Bitmap bitmap,
- @Nullable OnPrintFinishCallback callback);
-
- void printBitmap(@NonNull String jobName, @NonNull Uri imageFile,
- @Nullable OnPrintFinishCallback callback)
- throws FileNotFoundException;
- }
-
- /**
- * Implementation used when we do not support printing
- */
- private static final class PrintHelperStub implements PrintHelperVersionImpl {
- @ScaleMode int mScaleMode = SCALE_MODE_FILL;
- @ColorMode int mColorMode = COLOR_MODE_COLOR;
- @Orientation int mOrientation = ORIENTATION_LANDSCAPE;
-
- @Override
- public void setScaleMode(@ScaleMode int scaleMode) {
- mScaleMode = scaleMode;
- }
-
- @ScaleMode
- @Override
- public int getScaleMode() {
- return mScaleMode;
- }
-
- @ColorMode
- @Override
- public int getColorMode() {
- return mColorMode;
- }
-
- @Override
- public void setColorMode(@ColorMode int colorMode) {
- mColorMode = colorMode;
- }
-
- @Override
- public void setOrientation(@Orientation int orientation) {
- mOrientation = orientation;
- }
-
- @Orientation
- @Override
- public int getOrientation() {
- return mOrientation;
- }
-
- @Override
- public void printBitmap(String jobName, Bitmap bitmap, OnPrintFinishCallback callback) {
- }
-
- @Override
- public void printBitmap(String jobName, Uri imageFile, OnPrintFinishCallback callback) {
- }
- }
-
- /**
- * Kitkat specific PrintManager API implementation.
- */
- @RequiresApi(19)
- private static class PrintHelperApi19 implements PrintHelperVersionImpl{
- private static final String LOG_TAG = "PrintHelperApi19";
- // will be <= 300 dpi on A4 (8.3×11.7) paper (worst case of 150 dpi)
- private static final int MAX_PRINT_SIZE = 3500;
- final Context mContext;
- BitmapFactory.Options mDecodeOptions = null;
- private final Object mLock = new Object();
-
- /**
- * Whether the PrintActivity respects the suggested orientation
- */
- protected boolean mPrintActivityRespectsOrientation;
-
- /**
- * Whether the print subsystem handles min margins correctly. If not the print helper needs
- * to fake this.
- */
- protected boolean mIsMinMarginsHandlingCorrect;
-
- @ScaleMode int mScaleMode = SCALE_MODE_FILL;
-
- @ColorMode int mColorMode = COLOR_MODE_COLOR;
-
- @Orientation int mOrientation;
-
- PrintHelperApi19(Context context) {
- mPrintActivityRespectsOrientation = true;
- mIsMinMarginsHandlingCorrect = true;
-
- mContext = context;
- }
-
- /**
- * Selects whether the image will fill the paper and be cropped
- * <p/>
- * {@link #SCALE_MODE_FIT}
- * or whether the image will be scaled but leave white space
- * {@link #SCALE_MODE_FILL}.
- *
- * @param scaleMode {@link #SCALE_MODE_FIT} or
- * {@link #SCALE_MODE_FILL}
- */
- @Override
- public void setScaleMode(@ScaleMode int scaleMode) {
- mScaleMode = scaleMode;
- }
-
- /**
- * Returns the scale mode with which the image will fill the paper.
- *
- * @return The scale Mode: {@link #SCALE_MODE_FIT} or
- * {@link #SCALE_MODE_FILL}
- */
- @ScaleMode
- @Override
- public int getScaleMode() {
- return mScaleMode;
- }
-
- /**
- * Sets whether the image will be printed in color (default)
- * {@link #COLOR_MODE_COLOR} or in back and white
- * {@link #COLOR_MODE_MONOCHROME}.
- *
- * @param colorMode The color mode which is one of
- * {@link #COLOR_MODE_COLOR} and {@link #COLOR_MODE_MONOCHROME}.
- */
- @Override
- public void setColorMode(@ColorMode int colorMode) {
- mColorMode = colorMode;
- }
-
- /**
- * Sets whether to select landscape (default), {@link #ORIENTATION_LANDSCAPE}
- * or portrait {@link #ORIENTATION_PORTRAIT}
- * @param orientation The page orientation which is one of
- * {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
- */
- @Override
- public void setOrientation(@Orientation int orientation) {
- mOrientation = orientation;
- }
-
- /**
- * Gets the page orientation with which the image will be printed.
- *
- * @return The preferred orientation which is one of
- * {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}
- */
- @Orientation
- @Override
- public int getOrientation() {
- /// Unset defaults to landscape but might turn image
- if (mOrientation == 0) {
- return ORIENTATION_LANDSCAPE;
- }
- return mOrientation;
- }
-
- /**
- * Gets the color mode with which the image will be printed.
- *
- * @return The color mode which is one of {@link #COLOR_MODE_COLOR}
- * and {@link #COLOR_MODE_MONOCHROME}.
- */
- @ColorMode
- @Override
- public int getColorMode() {
- return mColorMode;
- }
-
- /**
- * Check if the supplied bitmap should best be printed on a portrait orientation paper.
- *
- * @param bitmap The bitmap to be printed.
- * @return true iff the picture should best be printed on a portrait orientation paper.
- */
- private static boolean isPortrait(Bitmap bitmap) {
- return bitmap.getWidth() <= bitmap.getHeight();
- }
-
- /**
- * Create a build with a copy from the other print attributes.
- *
- * @param other The other print attributes
- *
- * @return A builder that will build print attributes that match the other attributes
- */
- protected PrintAttributes.Builder copyAttributes(PrintAttributes other) {
- PrintAttributes.Builder b = (new PrintAttributes.Builder())
- .setMediaSize(other.getMediaSize())
- .setResolution(other.getResolution())
- .setMinMargins(other.getMinMargins());
-
- if (other.getColorMode() != 0) {
- b.setColorMode(other.getColorMode());
- }
-
- return b;
- }
-
- /**
- * Prints a bitmap.
- *
- * @param jobName The print job name.
- * @param bitmap The bitmap to print.
- * @param callback Optional callback to observe when printing is finished.
- */
- @Override
- public void printBitmap(final String jobName, final Bitmap bitmap,
- final OnPrintFinishCallback callback) {
- if (bitmap == null) {
- return;
- }
-
- final int fittingMode = mScaleMode; // grab the fitting mode at time of call
- PrintManager printManager =
- (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
- PrintAttributes.MediaSize mediaSize;
- if (isPortrait(bitmap)) {
- mediaSize = PrintAttributes.MediaSize.UNKNOWN_PORTRAIT;
- } else {
- mediaSize = PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE;
- }
- PrintAttributes attr = new PrintAttributes.Builder()
- .setMediaSize(mediaSize)
- .setColorMode(mColorMode)
- .build();
-
- printManager.print(jobName,
- new PrintDocumentAdapter() {
- private PrintAttributes mAttributes;
-
- @Override
- public void onLayout(PrintAttributes oldPrintAttributes,
- PrintAttributes newPrintAttributes,
- CancellationSignal cancellationSignal,
- LayoutResultCallback layoutResultCallback,
- Bundle bundle) {
-
- mAttributes = newPrintAttributes;
-
- PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
- .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
- .setPageCount(1)
- .build();
- boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
- layoutResultCallback.onLayoutFinished(info, changed);
- }
-
- @Override
- public void onWrite(PageRange[] pageRanges,
- ParcelFileDescriptor fileDescriptor,
- CancellationSignal cancellationSignal,
- WriteResultCallback writeResultCallback) {
- writeBitmap(mAttributes, fittingMode, bitmap, fileDescriptor,
- cancellationSignal, writeResultCallback);
- }
-
- @Override
- public void onFinish() {
- if (callback != null) {
- callback.onFinish();
- }
- }
- }, attr);
- }
-
- /**
- * Calculates the transform the print an Image to fill the page
- *
- * @param imageWidth with of bitmap
- * @param imageHeight height of bitmap
- * @param content The output page dimensions
- * @param fittingMode The mode of fitting {@link #SCALE_MODE_FILL} vs
- * {@link #SCALE_MODE_FIT}
- * @return Matrix to be used in canvas.drawBitmap(bitmap, matrix, null) call
- */
- private Matrix getMatrix(int imageWidth, int imageHeight, RectF content,
- @ScaleMode int fittingMode) {
- Matrix matrix = new Matrix();
-
- // Compute and apply scale to fill the page.
- float scale = content.width() / imageWidth;
- if (fittingMode == SCALE_MODE_FILL) {
- scale = Math.max(scale, content.height() / imageHeight);
- } else {
- scale = Math.min(scale, content.height() / imageHeight);
- }
- matrix.postScale(scale, scale);
-
- // Center the content.
- final float translateX = (content.width()
- - imageWidth * scale) / 2;
- final float translateY = (content.height()
- - imageHeight * scale) / 2;
- matrix.postTranslate(translateX, translateY);
- return matrix;
- }
-
- /**
- * Write a bitmap for a PDF document.
- *
- * @param attributes The print attributes
- * @param fittingMode How to fit the bitmap
- * @param bitmap The bitmap to write
- * @param fileDescriptor The file to write to
- * @param cancellationSignal Signal cancelling operation
- * @param writeResultCallback Callback to call once written
- */
- private void writeBitmap(final PrintAttributes attributes, final int fittingMode,
- final Bitmap bitmap, final ParcelFileDescriptor fileDescriptor,
- final CancellationSignal cancellationSignal,
- final PrintDocumentAdapter.WriteResultCallback writeResultCallback) {
- final PrintAttributes pdfAttributes;
- if (mIsMinMarginsHandlingCorrect) {
- pdfAttributes = attributes;
- } else {
- // If the handling of any margin != 0 is broken, strip the margins and add them to
- // the bitmap later
- pdfAttributes = copyAttributes(attributes)
- .setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0)).build();
- }
-
- (new AsyncTask<Void, Void, Throwable>() {
- @Override
- protected Throwable doInBackground(Void... params) {
- try {
- if (cancellationSignal.isCanceled()) {
- return null;
- }
-
- PrintedPdfDocument pdfDocument = new PrintedPdfDocument(mContext,
- pdfAttributes);
-
- Bitmap maybeGrayscale = convertBitmapForColorMode(bitmap,
- pdfAttributes.getColorMode());
-
- if (cancellationSignal.isCanceled()) {
- return null;
- }
-
- try {
- PdfDocument.Page page = pdfDocument.startPage(1);
-
- RectF contentRect;
- if (mIsMinMarginsHandlingCorrect) {
- contentRect = new RectF(page.getInfo().getContentRect());
- } else {
- // Create dummy doc that has the margins to compute correctly sized
- // content rectangle
- PrintedPdfDocument dummyDocument = new PrintedPdfDocument(mContext,
- attributes);
- PdfDocument.Page dummyPage = dummyDocument.startPage(1);
- contentRect = new RectF(dummyPage.getInfo().getContentRect());
- dummyDocument.finishPage(dummyPage);
- dummyDocument.close();
- }
-
- // Resize bitmap
- Matrix matrix = getMatrix(
- maybeGrayscale.getWidth(), maybeGrayscale.getHeight(),
- contentRect, fittingMode);
-
- if (mIsMinMarginsHandlingCorrect) {
- // The pdfDocument takes care of the positioning and margins
- } else {
- // Move it to the correct position.
- matrix.postTranslate(contentRect.left, contentRect.top);
-
- // Cut off margins
- page.getCanvas().clipRect(contentRect);
- }
-
- // Draw the bitmap.
- page.getCanvas().drawBitmap(maybeGrayscale, matrix, null);
-
- // Finish the page.
- pdfDocument.finishPage(page);
-
- if (cancellationSignal.isCanceled()) {
- return null;
- }
-
- // Write the document.
- pdfDocument.writeTo(
- new FileOutputStream(fileDescriptor.getFileDescriptor()));
- return null;
- } finally {
- pdfDocument.close();
-
- if (fileDescriptor != null) {
- try {
- fileDescriptor.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
- // If we created a new instance for grayscaling, then recycle it here.
- if (maybeGrayscale != bitmap) {
- maybeGrayscale.recycle();
- }
- }
- } catch (Throwable t) {
- return t;
- }
- }
-
- @Override
- protected void onPostExecute(Throwable throwable) {
- if (cancellationSignal.isCanceled()) {
- // Cancelled.
- writeResultCallback.onWriteCancelled();
- } else if (throwable == null) {
- // Done.
- writeResultCallback.onWriteFinished(
- new PageRange[] { PageRange.ALL_PAGES });
- } else {
- // Failed.
- Log.e(LOG_TAG, "Error writing printed content", throwable);
- writeResultCallback.onWriteFailed(null);
- }
- }
- }).execute();
- }
-
- /**
- * Prints an image located at the Uri. Image types supported are those of
- * <code>BitmapFactory.decodeStream</code> (JPEG, GIF, PNG, BMP, WEBP)
- *
- * @param jobName The print job name.
- * @param imageFile The <code>Uri</code> pointing to an image to print.
- * @param callback Optional callback to observe when printing is finished.
- * @throws FileNotFoundException if <code>Uri</code> is not pointing to a valid image.
- */
- @Override
- public void printBitmap(final String jobName, final Uri imageFile,
- final OnPrintFinishCallback callback)
- throws FileNotFoundException {
- final int fittingMode = mScaleMode;
-
- PrintDocumentAdapter printDocumentAdapter = new PrintDocumentAdapter() {
- private PrintAttributes mAttributes;
- AsyncTask<Uri, Boolean, Bitmap> mLoadBitmap;
- Bitmap mBitmap = null;
-
- @Override
- public void onLayout(final PrintAttributes oldPrintAttributes,
- final PrintAttributes newPrintAttributes,
- final CancellationSignal cancellationSignal,
- final LayoutResultCallback layoutResultCallback,
- Bundle bundle) {
-
- synchronized (this) {
- mAttributes = newPrintAttributes;
- }
-
- if (cancellationSignal.isCanceled()) {
- layoutResultCallback.onLayoutCancelled();
- return;
- }
- // we finished the load
- if (mBitmap != null) {
- PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
- .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
- .setPageCount(1)
- .build();
- boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
- layoutResultCallback.onLayoutFinished(info, changed);
- return;
- }
-
- mLoadBitmap = new AsyncTask<Uri, Boolean, Bitmap>() {
- @Override
- protected void onPreExecute() {
- // First register for cancellation requests.
- cancellationSignal.setOnCancelListener(
- new CancellationSignal.OnCancelListener() {
- @Override
- public void onCancel() { // on different thread
- cancelLoad();
- cancel(false);
- }
- });
- }
-
- @Override
- protected Bitmap doInBackground(Uri... uris) {
- try {
- return loadConstrainedBitmap(imageFile);
- } catch (FileNotFoundException e) {
- /* ignore */
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- super.onPostExecute(bitmap);
-
- // If orientation was not set by the caller, try to fit the bitmap on
- // the current paper by potentially rotating the bitmap by 90 degrees.
- if (bitmap != null
- && (!mPrintActivityRespectsOrientation || mOrientation == 0)) {
- PrintAttributes.MediaSize mediaSize;
-
- synchronized (this) {
- mediaSize = mAttributes.getMediaSize();
- }
-
- if (mediaSize != null) {
- if (mediaSize.isPortrait() != isPortrait(bitmap)) {
- Matrix rotation = new Matrix();
-
- rotation.postRotate(90);
- bitmap = Bitmap.createBitmap(bitmap, 0, 0,
- bitmap.getWidth(), bitmap.getHeight(), rotation,
- true);
- }
- }
- }
-
- mBitmap = bitmap;
- if (bitmap != null) {
- PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
- .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
- .setPageCount(1)
- .build();
-
- boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
-
- layoutResultCallback.onLayoutFinished(info, changed);
-
- } else {
- layoutResultCallback.onLayoutFailed(null);
- }
- mLoadBitmap = null;
- }
-
- @Override
- protected void onCancelled(Bitmap result) {
- // Task was cancelled, report that.
- layoutResultCallback.onLayoutCancelled();
- mLoadBitmap = null;
- }
- }.execute();
- }
-
- private void cancelLoad() {
- synchronized (mLock) { // prevent race with set null below
- if (mDecodeOptions != null) {
- mDecodeOptions.requestCancelDecode();
- mDecodeOptions = null;
- }
- }
- }
-
- @Override
- public void onFinish() {
- super.onFinish();
- cancelLoad();
- if (mLoadBitmap != null) {
- mLoadBitmap.cancel(true);
- }
- if (callback != null) {
- callback.onFinish();
- }
- if (mBitmap != null) {
- mBitmap.recycle();
- mBitmap = null;
- }
- }
-
- @Override
- public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor fileDescriptor,
- CancellationSignal cancellationSignal,
- WriteResultCallback writeResultCallback) {
- writeBitmap(mAttributes, fittingMode, mBitmap, fileDescriptor,
- cancellationSignal, writeResultCallback);
- }
- };
-
- PrintManager printManager =
- (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
- PrintAttributes.Builder builder = new PrintAttributes.Builder();
- builder.setColorMode(mColorMode);
-
- if (mOrientation == ORIENTATION_LANDSCAPE || mOrientation == 0) {
- builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE);
- } else if (mOrientation == ORIENTATION_PORTRAIT) {
- builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_PORTRAIT);
- }
- PrintAttributes attr = builder.build();
-
- printManager.print(jobName, printDocumentAdapter, attr);
- }
-
- /**
- * Loads a bitmap while limiting its size
- *
- * @param uri location of a valid image
- * @return the Bitmap
- * @throws FileNotFoundException if the Uri does not point to an image
- */
- private Bitmap loadConstrainedBitmap(Uri uri)
- throws FileNotFoundException {
- if (uri == null || mContext == null) {
- throw new IllegalArgumentException("bad argument to getScaledBitmap");
- }
- // Get width and height of stored bitmap
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inJustDecodeBounds = true;
- loadBitmap(uri, opt);
-
- int w = opt.outWidth;
- int h = opt.outHeight;
-
- // If bitmap cannot be decoded, return null
- if (w <= 0 || h <= 0) {
- return null;
- }
-
- // Find best downsampling size
- int imageSide = Math.max(w, h);
-
- int sampleSize = 1;
- while (imageSide > MAX_PRINT_SIZE) {
- imageSide >>>= 1;
- sampleSize <<= 1;
- }
-
- // Make sure sample size is reasonable
- if (sampleSize <= 0 || 0 >= (Math.min(w, h) / sampleSize)) {
- return null;
- }
- BitmapFactory.Options decodeOptions;
- synchronized (mLock) { // prevent race with set null below
- mDecodeOptions = new BitmapFactory.Options();
- mDecodeOptions.inMutable = true;
- mDecodeOptions.inSampleSize = sampleSize;
- decodeOptions = mDecodeOptions;
- }
- try {
- return loadBitmap(uri, decodeOptions);
- } finally {
- synchronized (mLock) {
- mDecodeOptions = null;
- }
- }
- }
-
- /**
- * Returns the bitmap from the given uri loaded using the given options.
- * Returns null on failure.
- */
- private Bitmap loadBitmap(Uri uri, BitmapFactory.Options o) throws FileNotFoundException {
- if (uri == null || mContext == null) {
- throw new IllegalArgumentException("bad argument to loadBitmap");
- }
- InputStream is = null;
- try {
- is = mContext.getContentResolver().openInputStream(uri);
- return BitmapFactory.decodeStream(is, null, o);
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException t) {
- Log.w(LOG_TAG, "close fail ", t);
- }
- }
- }
- }
-
- private Bitmap convertBitmapForColorMode(Bitmap original, @ColorMode int colorMode) {
- if (colorMode != COLOR_MODE_MONOCHROME) {
- return original;
- }
- // Create a grayscale bitmap
- Bitmap grayscale = Bitmap.createBitmap(original.getWidth(), original.getHeight(),
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(grayscale);
- Paint p = new Paint();
- ColorMatrix cm = new ColorMatrix();
- cm.setSaturation(0);
- ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
- p.setColorFilter(f);
- c.drawBitmap(original, 0, 0, p);
- c.setBitmap(null);
-
- return grayscale;
- }
- }
-
- /**
- * Api20 specific PrintManager API implementation.
- */
- @RequiresApi(20)
- private static class PrintHelperApi20 extends PrintHelperApi19 {
- PrintHelperApi20(Context context) {
- super(context);
-
-
- // There is a bug in the PrintActivity that causes it to ignore the orientation
- mPrintActivityRespectsOrientation = false;
- }
- }
-
- /**
- * Api23 specific PrintManager API implementation.
- */
- @RequiresApi(23)
- private static class PrintHelperApi23 extends PrintHelperApi20 {
- @Override
- protected PrintAttributes.Builder copyAttributes(PrintAttributes other) {
- PrintAttributes.Builder b = super.copyAttributes(other);
-
- if (other.getDuplexMode() != 0) {
- b.setDuplexMode(other.getDuplexMode());
- }
-
- return b;
- }
-
- PrintHelperApi23(Context context) {
- super(context);
-
- mIsMinMarginsHandlingCorrect = false;
- }
- }
-
- /**
- * Api24 specific PrintManager API implementation.
- */
- @RequiresApi(24)
- private static class PrintHelperApi24 extends PrintHelperApi23 {
- PrintHelperApi24(Context context) {
- super(context);
-
- mIsMinMarginsHandlingCorrect = true;
- mPrintActivityRespectsOrientation = true;
- }
- }
-
- /**
* Constructs the PrintHelper that can be used to print images.
*
* @param context A context for accessing system resources.
*/
public PrintHelper(@NonNull Context context) {
- if (Build.VERSION.SDK_INT >= 24) {
- mImpl = new PrintHelperApi24(context);
- } else if (Build.VERSION.SDK_INT >= 23) {
- mImpl = new PrintHelperApi23(context);
- } else if (Build.VERSION.SDK_INT >= 20) {
- mImpl = new PrintHelperApi20(context);
- } else if (Build.VERSION.SDK_INT >= 19) {
- mImpl = new PrintHelperApi19(context);
- } else {
- // System does not support printing.
- mImpl = new PrintHelperStub();
- }
+ mContext = context;
}
/**
@@ -915,7 +166,7 @@
* {@link #SCALE_MODE_FILL}
*/
public void setScaleMode(@ScaleMode int scaleMode) {
- mImpl.setScaleMode(scaleMode);
+ mScaleMode = scaleMode;
}
/**
@@ -926,7 +177,7 @@
*/
@ScaleMode
public int getScaleMode() {
- return mImpl.getScaleMode();
+ return mScaleMode;
}
/**
@@ -938,7 +189,7 @@
* {@link #COLOR_MODE_COLOR} and {@link #COLOR_MODE_MONOCHROME}.
*/
public void setColorMode(@ColorMode int colorMode) {
- mImpl.setColorMode(colorMode);
+ mColorMode = colorMode;
}
/**
@@ -949,7 +200,7 @@
*/
@ColorMode
public int getColorMode() {
- return mImpl.getColorMode();
+ return mColorMode;
}
/**
@@ -960,7 +211,7 @@
* {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
*/
public void setOrientation(int orientation) {
- mImpl.setOrientation(orientation);
+ mOrientation = orientation;
}
/**
@@ -970,7 +221,11 @@
* {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
*/
public int getOrientation() {
- return mImpl.getOrientation();
+ // Unset defaults to landscape but might turn image
+ if (Build.VERSION.SDK_INT >= 19 && mOrientation == 0) {
+ return ORIENTATION_LANDSCAPE;
+ }
+ return mOrientation;
}
@@ -981,7 +236,7 @@
* @param bitmap The bitmap to print.
*/
public void printBitmap(@NonNull String jobName, @NonNull Bitmap bitmap) {
- mImpl.printBitmap(jobName, bitmap, null);
+ printBitmap(jobName, bitmap, null);
}
/**
@@ -991,9 +246,63 @@
* @param bitmap The bitmap to print.
* @param callback Optional callback to observe when printing is finished.
*/
- public void printBitmap(@NonNull String jobName, @NonNull Bitmap bitmap,
- @Nullable OnPrintFinishCallback callback) {
- mImpl.printBitmap(jobName, bitmap, callback);
+ public void printBitmap(@NonNull final String jobName, @NonNull final Bitmap bitmap,
+ @Nullable final OnPrintFinishCallback callback) {
+ if (Build.VERSION.SDK_INT < 19 || bitmap == null) {
+ return;
+ }
+
+ final int fittingMode = mScaleMode; // grab the fitting mode at time of call
+ PrintManager printManager =
+ (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
+ PrintAttributes.MediaSize mediaSize;
+ if (isPortrait(bitmap)) {
+ mediaSize = PrintAttributes.MediaSize.UNKNOWN_PORTRAIT;
+ } else {
+ mediaSize = PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE;
+ }
+ PrintAttributes attr = new PrintAttributes.Builder()
+ .setMediaSize(mediaSize)
+ .setColorMode(mColorMode)
+ .build();
+
+ printManager.print(jobName,
+ new PrintDocumentAdapter() {
+ private PrintAttributes mAttributes;
+
+ @Override
+ public void onLayout(PrintAttributes oldPrintAttributes,
+ PrintAttributes newPrintAttributes,
+ CancellationSignal cancellationSignal,
+ LayoutResultCallback layoutResultCallback,
+ Bundle bundle) {
+
+ mAttributes = newPrintAttributes;
+
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
+ .setPageCount(1)
+ .build();
+ boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
+ layoutResultCallback.onLayoutFinished(info, changed);
+ }
+
+ @Override
+ public void onWrite(PageRange[] pageRanges,
+ ParcelFileDescriptor fileDescriptor,
+ CancellationSignal cancellationSignal,
+ WriteResultCallback writeResultCallback) {
+ writeBitmap(mAttributes, fittingMode, bitmap, fileDescriptor,
+ cancellationSignal, writeResultCallback);
+ }
+
+ @Override
+ public void onFinish() {
+ if (callback != null) {
+ callback.onFinish();
+ }
+ }
+ }, attr);
}
/**
@@ -1007,7 +316,7 @@
*/
public void printBitmap(@NonNull String jobName, @NonNull Uri imageFile)
throws FileNotFoundException {
- mImpl.printBitmap(jobName, imageFile, null);
+ printBitmap(jobName, imageFile, null);
}
/**
@@ -1020,9 +329,460 @@
* @throws FileNotFoundException if <code>Uri</code> is not pointing to a valid image.
* @param callback Optional callback to observe when printing is finished.
*/
- public void printBitmap(@NonNull String jobName, @NonNull Uri imageFile,
- @Nullable OnPrintFinishCallback callback)
+ public void printBitmap(@NonNull final String jobName, @NonNull final Uri imageFile,
+ @Nullable final OnPrintFinishCallback callback)
throws FileNotFoundException {
- mImpl.printBitmap(jobName, imageFile, callback);
+ if (Build.VERSION.SDK_INT < 19) {
+ return;
+ }
+
+ final int fittingMode = mScaleMode;
+
+ PrintDocumentAdapter printDocumentAdapter = new PrintDocumentAdapter() {
+ private PrintAttributes mAttributes;
+ AsyncTask<Uri, Boolean, Bitmap> mLoadBitmap;
+ Bitmap mBitmap = null;
+
+ @Override
+ public void onLayout(final PrintAttributes oldPrintAttributes,
+ final PrintAttributes newPrintAttributes,
+ final CancellationSignal cancellationSignal,
+ final LayoutResultCallback layoutResultCallback,
+ Bundle bundle) {
+
+ synchronized (this) {
+ mAttributes = newPrintAttributes;
+ }
+
+ if (cancellationSignal.isCanceled()) {
+ layoutResultCallback.onLayoutCancelled();
+ return;
+ }
+ // we finished the load
+ if (mBitmap != null) {
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
+ .setPageCount(1)
+ .build();
+ boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
+ layoutResultCallback.onLayoutFinished(info, changed);
+ return;
+ }
+
+ mLoadBitmap = new AsyncTask<Uri, Boolean, Bitmap>() {
+ @Override
+ protected void onPreExecute() {
+ // First register for cancellation requests.
+ cancellationSignal.setOnCancelListener(
+ new CancellationSignal.OnCancelListener() {
+ @Override
+ public void onCancel() { // on different thread
+ cancelLoad();
+ cancel(false);
+ }
+ });
+ }
+
+ @Override
+ protected Bitmap doInBackground(Uri... uris) {
+ try {
+ return loadConstrainedBitmap(imageFile);
+ } catch (FileNotFoundException e) {
+ /* ignore */
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap bitmap) {
+ super.onPostExecute(bitmap);
+
+ // If orientation was not set by the caller, try to fit the bitmap on
+ // the current paper by potentially rotating the bitmap by 90 degrees.
+ if (bitmap != null
+ && (!PRINT_ACTIVITY_RESPECTS_ORIENTATION || mOrientation == 0)) {
+ PrintAttributes.MediaSize mediaSize;
+
+ synchronized (this) {
+ mediaSize = mAttributes.getMediaSize();
+ }
+
+ if (mediaSize != null) {
+ if (mediaSize.isPortrait() != isPortrait(bitmap)) {
+ Matrix rotation = new Matrix();
+
+ rotation.postRotate(90);
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), rotation,
+ true);
+ }
+ }
+ }
+
+ mBitmap = bitmap;
+ if (bitmap != null) {
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
+ .setPageCount(1)
+ .build();
+
+ boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
+
+ layoutResultCallback.onLayoutFinished(info, changed);
+
+ } else {
+ layoutResultCallback.onLayoutFailed(null);
+ }
+ mLoadBitmap = null;
+ }
+
+ @Override
+ protected void onCancelled(Bitmap result) {
+ // Task was cancelled, report that.
+ layoutResultCallback.onLayoutCancelled();
+ mLoadBitmap = null;
+ }
+ }.execute();
+ }
+
+ private void cancelLoad() {
+ synchronized (mLock) { // prevent race with set null below
+ if (mDecodeOptions != null) {
+ mDecodeOptions.requestCancelDecode();
+ mDecodeOptions = null;
+ }
+ }
+ }
+
+ @Override
+ public void onFinish() {
+ super.onFinish();
+ cancelLoad();
+ if (mLoadBitmap != null) {
+ mLoadBitmap.cancel(true);
+ }
+ if (callback != null) {
+ callback.onFinish();
+ }
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ mBitmap = null;
+ }
+ }
+
+ @Override
+ public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor fileDescriptor,
+ CancellationSignal cancellationSignal,
+ WriteResultCallback writeResultCallback) {
+ writeBitmap(mAttributes, fittingMode, mBitmap, fileDescriptor,
+ cancellationSignal, writeResultCallback);
+ }
+ };
+
+ PrintManager printManager =
+ (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
+ PrintAttributes.Builder builder = new PrintAttributes.Builder();
+ builder.setColorMode(mColorMode);
+
+ if (mOrientation == ORIENTATION_LANDSCAPE || mOrientation == 0) {
+ builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE);
+ } else if (mOrientation == ORIENTATION_PORTRAIT) {
+ builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_PORTRAIT);
+ }
+ PrintAttributes attr = builder.build();
+
+ printManager.print(jobName, printDocumentAdapter, attr);
+ }
+
+ /**
+ * Check if the supplied bitmap should best be printed on a portrait orientation paper.
+ *
+ * @param bitmap The bitmap to be printed.
+ * @return true iff the picture should best be printed on a portrait orientation paper.
+ */
+ private static boolean isPortrait(Bitmap bitmap) {
+ return bitmap.getWidth() <= bitmap.getHeight();
+ }
+
+ /**
+ * Create a build with a copy from the other print attributes.
+ *
+ * @param other The other print attributes
+ *
+ * @return A builder that will build print attributes that match the other attributes
+ */
+ @RequiresApi(19)
+ private static PrintAttributes.Builder copyAttributes(PrintAttributes other) {
+ PrintAttributes.Builder b = (new PrintAttributes.Builder())
+ .setMediaSize(other.getMediaSize())
+ .setResolution(other.getResolution())
+ .setMinMargins(other.getMinMargins());
+
+ if (other.getColorMode() != 0) {
+ b.setColorMode(other.getColorMode());
+ }
+
+ if (Build.VERSION.SDK_INT >= 23) {
+ if (other.getDuplexMode() != 0) {
+ b.setDuplexMode(other.getDuplexMode());
+ }
+ }
+
+ return b;
+ }
+
+ /**
+ * Calculates the transform the print an Image to fill the page
+ *
+ * @param imageWidth with of bitmap
+ * @param imageHeight height of bitmap
+ * @param content The output page dimensions
+ * @param fittingMode The mode of fitting {@link #SCALE_MODE_FILL} vs
+ * {@link #SCALE_MODE_FIT}
+ * @return Matrix to be used in canvas.drawBitmap(bitmap, matrix, null) call
+ */
+ private static Matrix getMatrix(int imageWidth, int imageHeight, RectF content,
+ @ScaleMode int fittingMode) {
+ Matrix matrix = new Matrix();
+
+ // Compute and apply scale to fill the page.
+ float scale = content.width() / imageWidth;
+ if (fittingMode == SCALE_MODE_FILL) {
+ scale = Math.max(scale, content.height() / imageHeight);
+ } else {
+ scale = Math.min(scale, content.height() / imageHeight);
+ }
+ matrix.postScale(scale, scale);
+
+ // Center the content.
+ final float translateX = (content.width()
+ - imageWidth * scale) / 2;
+ final float translateY = (content.height()
+ - imageHeight * scale) / 2;
+ matrix.postTranslate(translateX, translateY);
+ return matrix;
+ }
+
+ /**
+ * Write a bitmap for a PDF document.
+ *
+ * @param attributes The print attributes
+ * @param fittingMode How to fit the bitmap
+ * @param bitmap The bitmap to write
+ * @param fileDescriptor The file to write to
+ * @param cancellationSignal Signal cancelling operation
+ * @param writeResultCallback Callback to call once written
+ */
+ @RequiresApi(19)
+ private void writeBitmap(final PrintAttributes attributes, final int fittingMode,
+ final Bitmap bitmap, final ParcelFileDescriptor fileDescriptor,
+ final CancellationSignal cancellationSignal,
+ final PrintDocumentAdapter.WriteResultCallback writeResultCallback) {
+ final PrintAttributes pdfAttributes;
+ if (IS_MIN_MARGINS_HANDLING_CORRECT) {
+ pdfAttributes = attributes;
+ } else {
+ // If the handling of any margin != 0 is broken, strip the margins and add them to
+ // the bitmap later
+ pdfAttributes = copyAttributes(attributes)
+ .setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0)).build();
+ }
+
+ (new AsyncTask<Void, Void, Throwable>() {
+ @Override
+ protected Throwable doInBackground(Void... params) {
+ try {
+ if (cancellationSignal.isCanceled()) {
+ return null;
+ }
+
+ PrintedPdfDocument pdfDocument = new PrintedPdfDocument(mContext,
+ pdfAttributes);
+
+ Bitmap maybeGrayscale = convertBitmapForColorMode(bitmap,
+ pdfAttributes.getColorMode());
+
+ if (cancellationSignal.isCanceled()) {
+ return null;
+ }
+
+ try {
+ PdfDocument.Page page = pdfDocument.startPage(1);
+
+ RectF contentRect;
+ if (IS_MIN_MARGINS_HANDLING_CORRECT) {
+ contentRect = new RectF(page.getInfo().getContentRect());
+ } else {
+ // Create dummy doc that has the margins to compute correctly sized
+ // content rectangle
+ PrintedPdfDocument dummyDocument = new PrintedPdfDocument(mContext,
+ attributes);
+ PdfDocument.Page dummyPage = dummyDocument.startPage(1);
+ contentRect = new RectF(dummyPage.getInfo().getContentRect());
+ dummyDocument.finishPage(dummyPage);
+ dummyDocument.close();
+ }
+
+ // Resize bitmap
+ Matrix matrix = getMatrix(
+ maybeGrayscale.getWidth(), maybeGrayscale.getHeight(),
+ contentRect, fittingMode);
+
+ if (IS_MIN_MARGINS_HANDLING_CORRECT) {
+ // The pdfDocument takes care of the positioning and margins
+ } else {
+ // Move it to the correct position.
+ matrix.postTranslate(contentRect.left, contentRect.top);
+
+ // Cut off margins
+ page.getCanvas().clipRect(contentRect);
+ }
+
+ // Draw the bitmap.
+ page.getCanvas().drawBitmap(maybeGrayscale, matrix, null);
+
+ // Finish the page.
+ pdfDocument.finishPage(page);
+
+ if (cancellationSignal.isCanceled()) {
+ return null;
+ }
+
+ // Write the document.
+ pdfDocument.writeTo(
+ new FileOutputStream(fileDescriptor.getFileDescriptor()));
+ return null;
+ } finally {
+ pdfDocument.close();
+
+ if (fileDescriptor != null) {
+ try {
+ fileDescriptor.close();
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+ // If we created a new instance for grayscaling, then recycle it here.
+ if (maybeGrayscale != bitmap) {
+ maybeGrayscale.recycle();
+ }
+ }
+ } catch (Throwable t) {
+ return t;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable throwable) {
+ if (cancellationSignal.isCanceled()) {
+ // Cancelled.
+ writeResultCallback.onWriteCancelled();
+ } else if (throwable == null) {
+ // Done.
+ writeResultCallback.onWriteFinished(
+ new PageRange[] { PageRange.ALL_PAGES });
+ } else {
+ // Failed.
+ Log.e(LOG_TAG, "Error writing printed content", throwable);
+ writeResultCallback.onWriteFailed(null);
+ }
+ }
+ }).execute();
+ }
+
+ /**
+ * Loads a bitmap while limiting its size
+ *
+ * @param uri location of a valid image
+ * @return the Bitmap
+ * @throws FileNotFoundException if the Uri does not point to an image
+ */
+ private Bitmap loadConstrainedBitmap(Uri uri)
+ throws FileNotFoundException {
+ if (uri == null || mContext == null) {
+ throw new IllegalArgumentException("bad argument to getScaledBitmap");
+ }
+ // Get width and height of stored bitmap
+ BitmapFactory.Options opt = new BitmapFactory.Options();
+ opt.inJustDecodeBounds = true;
+ loadBitmap(uri, opt);
+
+ int w = opt.outWidth;
+ int h = opt.outHeight;
+
+ // If bitmap cannot be decoded, return null
+ if (w <= 0 || h <= 0) {
+ return null;
+ }
+
+ // Find best downsampling size
+ int imageSide = Math.max(w, h);
+
+ int sampleSize = 1;
+ while (imageSide > MAX_PRINT_SIZE) {
+ imageSide >>>= 1;
+ sampleSize <<= 1;
+ }
+
+ // Make sure sample size is reasonable
+ if (sampleSize <= 0 || 0 >= (Math.min(w, h) / sampleSize)) {
+ return null;
+ }
+ BitmapFactory.Options decodeOptions;
+ synchronized (mLock) { // prevent race with set null below
+ mDecodeOptions = new BitmapFactory.Options();
+ mDecodeOptions.inMutable = true;
+ mDecodeOptions.inSampleSize = sampleSize;
+ decodeOptions = mDecodeOptions;
+ }
+ try {
+ return loadBitmap(uri, decodeOptions);
+ } finally {
+ synchronized (mLock) {
+ mDecodeOptions = null;
+ }
+ }
+ }
+
+ /**
+ * Returns the bitmap from the given uri loaded using the given options.
+ * Returns null on failure.
+ */
+ private Bitmap loadBitmap(Uri uri, BitmapFactory.Options o) throws FileNotFoundException {
+ if (uri == null || mContext == null) {
+ throw new IllegalArgumentException("bad argument to loadBitmap");
+ }
+ InputStream is = null;
+ try {
+ is = mContext.getContentResolver().openInputStream(uri);
+ return BitmapFactory.decodeStream(is, null, o);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException t) {
+ Log.w(LOG_TAG, "close fail ", t);
+ }
+ }
+ }
+ }
+
+ private static Bitmap convertBitmapForColorMode(Bitmap original, @ColorMode int colorMode) {
+ if (colorMode != COLOR_MODE_MONOCHROME) {
+ return original;
+ }
+ // Create a grayscale bitmap
+ Bitmap grayscale = Bitmap.createBitmap(original.getWidth(), original.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(grayscale);
+ Paint p = new Paint();
+ ColorMatrix cm = new ColorMatrix();
+ cm.setSaturation(0);
+ ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
+ p.setColorFilter(f);
+ c.drawBitmap(original, 0, 0, p);
+ c.setBitmap(null);
+
+ return grayscale;
}
}
diff --git a/room/common/api/current.txt b/room/common/api/current.txt
new file mode 100644
index 0000000..fd32902
--- /dev/null
+++ b/room/common/api/current.txt
@@ -0,0 +1,112 @@
+package androidx.room {
+
+ public abstract class ColumnInfo implements java.lang.annotation.Annotation {
+ field public static final int BINARY = 2; // 0x2
+ field public static final int BLOB = 5; // 0x5
+ field public static final java.lang.String INHERIT_FIELD_NAME = "[field-name]";
+ field public static final int INTEGER = 3; // 0x3
+ field public static final int LOCALIZED = 5; // 0x5
+ field public static final int NOCASE = 3; // 0x3
+ field public static final int REAL = 4; // 0x4
+ field public static final int RTRIM = 4; // 0x4
+ field public static final int TEXT = 2; // 0x2
+ field public static final int UNDEFINED = 1; // 0x1
+ field public static final int UNICODE = 6; // 0x6
+ field public static final int UNSPECIFIED = 1; // 0x1
+ }
+
+ public static abstract class ColumnInfo.Collate implements java.lang.annotation.Annotation {
+ }
+
+ public static abstract class ColumnInfo.SQLiteTypeAffinity implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Dao implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Database implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Delete implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Embedded implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Entity implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class ForeignKey implements java.lang.annotation.Annotation {
+ field public static final int CASCADE = 5; // 0x5
+ field public static final int NO_ACTION = 1; // 0x1
+ field public static final int RESTRICT = 2; // 0x2
+ field public static final int SET_DEFAULT = 4; // 0x4
+ field public static final int SET_NULL = 3; // 0x3
+ }
+
+ public static abstract class ForeignKey.Action implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Ignore implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Index implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Insert implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class OnConflictStrategy implements java.lang.annotation.Annotation {
+ field public static final int ABORT = 3; // 0x3
+ field public static final int FAIL = 4; // 0x4
+ field public static final int IGNORE = 5; // 0x5
+ field public static final int REPLACE = 1; // 0x1
+ field public static final int ROLLBACK = 2; // 0x2
+ }
+
+ public abstract class PrimaryKey implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Query implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class RawQuery implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Relation implements java.lang.annotation.Annotation {
+ }
+
+ public class RoomWarnings {
+ ctor public RoomWarnings();
+ field public static final java.lang.String CANNOT_CREATE_VERIFICATION_DATABASE = "ROOM_CANNOT_CREATE_VERIFICATION_DATABASE";
+ field public static final java.lang.String CURSOR_MISMATCH = "ROOM_CURSOR_MISMATCH";
+ field public static final java.lang.String DEFAULT_CONSTRUCTOR = "ROOM_DEFAULT_CONSTRUCTOR";
+ field public static final java.lang.String INDEX_FROM_EMBEDDED_ENTITY_IS_DROPPED = "ROOM_EMBEDDED_ENTITY_INDEX_IS_DROPPED";
+ field public static final java.lang.String INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED = "ROOM_EMBEDDED_INDEX_IS_DROPPED";
+ field public static final java.lang.String INDEX_FROM_PARENT_FIELD_IS_DROPPED = "ROOM_PARENT_FIELD_INDEX_IS_DROPPED";
+ field public static final java.lang.String INDEX_FROM_PARENT_IS_DROPPED = "ROOM_PARENT_INDEX_IS_DROPPED";
+ field public static final java.lang.String MISSING_INDEX_ON_FOREIGN_KEY_CHILD = "ROOM_MISSING_FOREIGN_KEY_CHILD_INDEX";
+ field public static final java.lang.String MISSING_JAVA_TMP_DIR = "ROOM_MISSING_JAVA_TMP_DIR";
+ field public static final java.lang.String MISSING_SCHEMA_LOCATION = "ROOM_MISSING_SCHEMA_LOCATION";
+ field public static final java.lang.String PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED = "ROOM_EMBEDDED_PRIMARY_KEY_IS_DROPPED";
+ field public static final java.lang.String RELATION_QUERY_WITHOUT_TRANSACTION = "ROOM_RELATION_QUERY_WITHOUT_TRANSACTION";
+ field public static final java.lang.String RELATION_TYPE_MISMATCH = "ROOM_RELATION_TYPE_MISMATCH";
+ }
+
+ public abstract class SkipQueryVerification implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Transaction implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class TypeConverter implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class TypeConverters implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class Update implements java.lang.annotation.Annotation {
+ }
+
+}
+
diff --git a/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt b/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
index 8ff200b..5cf3476 100644
--- a/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/ext/javapoet_ext.kt
@@ -88,7 +88,7 @@
object ArchTypeNames {
val APP_EXECUTOR: ClassName =
- ClassName.get("androidx.executor", "ArchTaskExecutor")
+ ClassName.get("androidx.arch.core.executor", "ArchTaskExecutor")
}
object PagingTypeNames {
diff --git a/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt b/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
index 5c11114..345f94a 100644
--- a/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/testing/test_util.kt
@@ -134,7 +134,7 @@
/**
* Create mocks of [Element] and [TypeMirror] so that they can be used for instantiating a fake
- * [android.arch.persistence.room.vo.Field].
+ * [androidx.room.vo.Field].
*/
fun mockElementAndType(): Pair<Element, TypeMirror> {
val element = mock(Element::class.java)
diff --git a/room/guava/src/main/java/androidx/room/guava/GuavaRoom.java b/room/guava/src/main/java/androidx/room/guava/GuavaRoom.java
index 2f9c078..be483aa 100644
--- a/room/guava/src/main/java/androidx/room/guava/GuavaRoom.java
+++ b/room/guava/src/main/java/androidx/room/guava/GuavaRoom.java
@@ -18,7 +18,7 @@
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import androidx.annotation.RestrictTo;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.room.RoomSQLiteQuery;
import com.google.common.util.concurrent.FutureCallback;
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt
index d49f6f9..d73bc96 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/BooksDaoTest.kt
@@ -18,7 +18,7 @@
import android.database.sqlite.SQLiteConstraintException
import android.support.test.filters.SmallTest
-import androidx.executor.ArchTaskExecutor
+import androidx.arch.core.executor.ArchTaskExecutor
import androidx.room.integration.kotlintestapp.vo.Author
import androidx.room.integration.kotlintestapp.vo.Book
import androidx.room.integration.kotlintestapp.vo.BookWithPublisher
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt
index 1751992..0f213188 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestDatabaseTest.kt
@@ -17,7 +17,7 @@
package androidx.room.integration.kotlintestapp.test
import android.support.test.InstrumentationRegistry
-import androidx.executor.testing.InstantTaskExecutorRule
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.room.integration.kotlintestapp.TestDatabase
import androidx.room.integration.kotlintestapp.dao.BooksDao
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
index f30b5b4..92a43b7 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
@@ -26,8 +26,8 @@
import android.support.test.runner.AndroidJUnit4;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.testing.CountingTaskExecutorRule;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.testing.CountingTaskExecutorRule;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/FunnyNamedDaoTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/FunnyNamedDaoTest.java
index 0583cff..9d0da7f 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/FunnyNamedDaoTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/FunnyNamedDaoTest.java
@@ -25,7 +25,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import androidx.executor.testing.CountingTaskExecutorRule;
+import androidx.arch.core.executor.testing.CountingTaskExecutorRule;
import androidx.room.integration.testapp.vo.FunnyNamedEntity;
import org.junit.Rule;
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTest.java
index ef53250..fe66855 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/InvalidationTest.java
@@ -27,7 +27,7 @@
import android.support.test.runner.AndroidJUnit4;
import androidx.annotation.NonNull;
-import androidx.executor.testing.CountingTaskExecutorRule;
+import androidx.arch.core.executor.testing.CountingTaskExecutorRule;
import androidx.room.InvalidationTracker;
import androidx.room.Room;
import androidx.room.integration.testapp.TestDatabase;
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java
index 9e59962..2b32a62 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/LiveDataQueryTest.java
@@ -29,8 +29,8 @@
import android.support.test.runner.AndroidJUnit4;
import androidx.annotation.Nullable;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.testing.CountingTaskExecutorRule;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.testing.CountingTaskExecutorRule;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
index cb8f81f..152141d 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
@@ -24,8 +24,8 @@
import android.support.test.filters.SmallTest;
import androidx.annotation.NonNull;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.testing.CountingTaskExecutorRule;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.testing.CountingTaskExecutorRule;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java
index 76d4bfc..e577c5b 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java
@@ -26,7 +26,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import androidx.executor.testing.CountingTaskExecutorRule;
+import androidx.arch.core.executor.testing.CountingTaskExecutorRule;
import androidx.lifecycle.LiveData;
import androidx.room.integration.testapp.dao.RawDao;
import androidx.room.integration.testapp.vo.NameAndLastName;
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
index 3d7b4e4..9878cd2 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
@@ -23,8 +23,8 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import androidx.executor.ArchTaskExecutor;
-import androidx.executor.TaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.TaskExecutor;
import androidx.room.EmptyResultSetException;
import androidx.room.integration.testapp.vo.Pet;
import androidx.room.integration.testapp.vo.User;
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
index d9b8f9c..992d8f8 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
@@ -20,7 +20,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import androidx.executor.testing.InstantTaskExecutorRule;
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
import androidx.room.Room;
import androidx.room.integration.testapp.TestDatabase;
import androidx.room.integration.testapp.vo.User;
diff --git a/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/CustomerViewModel.java b/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/CustomerViewModel.java
index a8f3a68..eca2552 100644
--- a/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/CustomerViewModel.java
+++ b/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/CustomerViewModel.java
@@ -19,7 +19,7 @@
import android.app.Application;
import androidx.annotation.WorkerThread;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
diff --git a/room/runtime/src/main/java/androidx/room/InvalidationTracker.java b/room/runtime/src/main/java/androidx/room/InvalidationTracker.java
index bec0999..801f5a3 100644
--- a/room/runtime/src/main/java/androidx/room/InvalidationTracker.java
+++ b/room/runtime/src/main/java/androidx/room/InvalidationTracker.java
@@ -28,7 +28,7 @@
import androidx.arch.core.internal.SafeIterableMap;
import androidx.collection.ArrayMap;
import androidx.collection.ArraySet;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteStatement;
diff --git a/room/runtime/src/main/java/androidx/room/RoomDatabase.java b/room/runtime/src/main/java/androidx/room/RoomDatabase.java
index 457c112..d89cf00 100644
--- a/room/runtime/src/main/java/androidx/room/RoomDatabase.java
+++ b/room/runtime/src/main/java/androidx/room/RoomDatabase.java
@@ -31,7 +31,7 @@
import androidx.annotation.WorkerThread;
import androidx.collection.SparseArrayCompat;
import androidx.core.app.ActivityManagerCompat;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteDatabase;
diff --git a/room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java b/room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java
index 22599b1..f4ffd24 100644
--- a/room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java
+++ b/room/runtime/src/test/java/androidx/room/InvalidationTrackerTest.java
@@ -35,7 +35,7 @@
import android.database.sqlite.SQLiteException;
import androidx.annotation.NonNull;
-import androidx.executor.JunitTaskExecutorRule;
+import androidx.arch.core.executor.JunitTaskExecutorRule;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
import androidx.sqlite.db.SupportSQLiteStatement;
diff --git a/room/rxjava2/src/main/java/androidx/room/RxRoom.java b/room/rxjava2/src/main/java/androidx/room/RxRoom.java
index b13e774..d2ba8bf 100644
--- a/room/rxjava2/src/main/java/androidx/room/RxRoom.java
+++ b/room/rxjava2/src/main/java/androidx/room/RxRoom.java
@@ -18,7 +18,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
-import androidx.executor.ArchTaskExecutor;
+import androidx.arch.core.executor.ArchTaskExecutor;
import java.util.Set;
import java.util.concurrent.Callable;
diff --git a/room/rxjava2/src/test/java/androidx/room/RxRoomTest.java b/room/rxjava2/src/test/java/androidx/room/RxRoomTest.java
index abf16d9..15a89bf 100644
--- a/room/rxjava2/src/test/java/androidx/room/RxRoomTest.java
+++ b/room/rxjava2/src/test/java/androidx/room/RxRoomTest.java
@@ -25,7 +25,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import androidx.executor.JunitTaskExecutorRule;
+import androidx.arch.core.executor.JunitTaskExecutorRule;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
diff --git a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
index 379b991..8f94bb9 100644
--- a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
+++ b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
@@ -19,6 +19,7 @@
import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.INFINITY;
import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
@@ -26,17 +27,18 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.provider.Settings;
import android.text.SpannableString;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
import android.util.SparseArray;
import androidx.annotation.NonNull;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
import androidx.slice.builders.GridRowBuilder;
@@ -46,6 +48,7 @@
import java.util.Arrays;
import java.util.Calendar;
+import java.util.concurrent.TimeUnit;
/**
* Examples of using slice template builders.
@@ -139,86 +142,100 @@
private Slice createWeather(Uri sliceUri) {
SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST,
- "open weather app"), Icon.createWithResource(getContext(), R.drawable.weather_1),
+ "open weather app"),
+ IconCompat.createWithResource(getContext(), R.drawable.weather_1),
"Weather is happening!");
- return new ListBuilder(getContext(), sliceUri).addGrid(gb -> gb
- .setPrimaryAction(primaryAction)
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
- SMALL_IMAGE)
- .addText("MON")
- .addTitleText("69\u00B0"))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_2),
- SMALL_IMAGE)
- .addText("TUE")
- .addTitleText("71\u00B0"))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_3),
- SMALL_IMAGE)
- .addText("WED")
- .addTitleText("76\u00B0"))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_4),
- SMALL_IMAGE)
- .addText("THU")
- .addTitleText("72\u00B0"))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
- SMALL_IMAGE)
- .addText("FRI")
- .addTitleText("68\u00B0")))
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
+ .addGrid(gb -> gb
+ .setPrimaryAction(primaryAction)
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.weather_1),
+ SMALL_IMAGE)
+ .addText("MON")
+ .addTitleText("69\u00B0"))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.weather_2),
+ SMALL_IMAGE)
+ .addText("TUE")
+ .addTitleText("71\u00B0"))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.weather_3),
+ SMALL_IMAGE)
+ .addText("WED")
+ .addTitleText("76\u00B0"))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.weather_4),
+ SMALL_IMAGE)
+ .addText("THU")
+ .addTitleText("72\u00B0"))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.weather_1),
+ SMALL_IMAGE)
+ .addText("FRI")
+ .addTitleText("68\u00B0")))
.build();
}
private Slice createGallery(Uri sliceUri) {
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xff4285F4)
.addRow(b -> b
- .setTitle("Family trip to Hawaii")
- .setSubtitle("Sep 30, 2017 - Oct 2, 2017"))
+ .setTitle("Family trip to Hawaii")
+ .setSubtitle("Sep 30, 2017 - Oct 2, 2017"))
.addAction(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "cast photo album"),
- Icon.createWithResource(getContext(), R.drawable.ic_cast),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_cast),
"Cast photo album"))
.addAction(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "share photo album"),
- Icon.createWithResource(getContext(), R.drawable.ic_share),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_share),
"Share photo album"))
.addGrid(b -> b
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_1),
- LARGE_IMAGE))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_2),
- LARGE_IMAGE))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_3),
- LARGE_IMAGE))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_4),
- LARGE_IMAGE))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_2),
- LARGE_IMAGE))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_3),
- LARGE_IMAGE))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_4),
- LARGE_IMAGE))
- .addSeeMoreAction(getBroadcastIntent(ACTION_TOAST, "see your gallery"))
- .setContentDescription("Images from your trip to Hawaii"))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.slices_1),
+ LARGE_IMAGE))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.slices_2),
+ LARGE_IMAGE))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.slices_3),
+ LARGE_IMAGE))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.slices_4),
+ LARGE_IMAGE))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.slices_2),
+ LARGE_IMAGE))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.slices_3),
+ LARGE_IMAGE))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.slices_4),
+ LARGE_IMAGE))
+ .addSeeMoreAction(getBroadcastIntent(ACTION_TOAST, "see your gallery"))
+ .setContentDescription("Images from your trip to Hawaii"))
.build();
}
private Slice createCatSlice(Uri sliceUri, boolean customSeeMore) {
- ListBuilder b = new ListBuilder(getContext(), sliceUri);
+ ListBuilder b = new ListBuilder(getContext(), sliceUri, INFINITY);
GridRowBuilder gb = new GridRowBuilder(b);
PendingIntent pi = getBroadcastIntent(ACTION_TOAST, "See cats you follow");
if (customSeeMore) {
GridRowBuilder.CellBuilder cb = new GridRowBuilder.CellBuilder(gb);
- cb.addImage(Icon.createWithResource(getContext(), R.drawable.ic_right_caret),
+ cb.addImage(IconCompat.createWithResource(getContext(), R.drawable.ic_right_caret),
ICON_IMAGE);
cb.setContentIntent(pi);
cb.addTitleText("All cats");
@@ -227,59 +244,62 @@
gb.addSeeMoreAction(pi);
}
gb.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_1), SMALL_IMAGE)
- .addTitleText("Oreo"))
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_1),
+ SMALL_IMAGE)
+ .addTitleText("Oreo"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_2),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_2),
SMALL_IMAGE)
.addTitleText("Silver"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_3),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_3),
SMALL_IMAGE)
.addTitleText("Drake"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_5),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_5),
SMALL_IMAGE)
.addTitleText("Olive"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_4),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_4),
SMALL_IMAGE)
.addTitleText("Lady Marmalade"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_6),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_6),
SMALL_IMAGE)
.addTitleText("Grapefruit"));
return b.addGridRow(gb).build();
}
private Slice createContact2(Uri sliceUri) {
- ListBuilder b = new ListBuilder(getContext(), sliceUri);
+ ListBuilder b = new ListBuilder(getContext(), sliceUri, INFINITY);
ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(b);
GridRowBuilder gb = new GridRowBuilder(b);
return b.setColor(0xff3949ab)
.addRow(rb
.setTitle("Mady Pitza")
.setSubtitle("Frequently contacted contact")
- .addEndItem(Icon.createWithResource(getContext(), R.drawable.mady),
+ .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.mady),
SMALL_IMAGE))
.addGridRow(gb
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_call),
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_call),
ICON_IMAGE)
.addText("Call")
.setContentIntent(getBroadcastIntent(ACTION_TOAST, "call")))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_text),
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_text),
ICON_IMAGE)
.addText("Text")
.setContentIntent(getBroadcastIntent(ACTION_TOAST, "text")))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(),
+ .addImage(IconCompat.createWithResource(getContext(),
R.drawable.ic_video), ICON_IMAGE)
.setContentIntent(getBroadcastIntent(ACTION_TOAST, "video"))
.addText("Video"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(),
+ .addImage(IconCompat.createWithResource(getContext(),
R.drawable.ic_email), ICON_IMAGE)
.addText("Email")
.setContentIntent(getBroadcastIntent(ACTION_TOAST, "email"))))
@@ -292,35 +312,40 @@
Calendar.getInstance().getTimeInMillis(),
DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE);
SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST,
- "See contact info"), Icon.createWithResource(getContext(),
+ "See contact info"), IconCompat.createWithResource(getContext(),
R.drawable.mady), SMALL_IMAGE, "Mady");
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xff3949ab)
.setHeader(b -> b
.setTitle("Mady Pitza")
.setSummarySubtitle("Called " + lastCalledString)
.setPrimaryAction(primaryAction))
.addRow(b -> b
- .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_call),
+ .setTitleItem(
+ IconCompat.createWithResource(getContext(), R.drawable.ic_call),
ICON_IMAGE)
.setTitle("314-259-2653")
.setSubtitle("Call lasted 1 hr 17 min")
.addEndItem(lastCalled))
.addRow(b -> b
- .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_text),
+ .setTitleItem(
+ IconCompat.createWithResource(getContext(), R.drawable.ic_text),
ICON_IMAGE)
.setTitle("You: Coooooool see you then")
.addEndItem(System.currentTimeMillis() - 40 * DateUtils.MINUTE_IN_MILLIS))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "call"),
- Icon.createWithResource(getContext(), R.drawable.ic_call), "Call mady"))
+ IconCompat.createWithResource(getContext(), R.drawable.ic_call),
+ "Call mady"))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "text"),
- Icon.createWithResource(getContext(), R.drawable.ic_text), "Text mady"))
+ IconCompat.createWithResource(getContext(), R.drawable.ic_text),
+ "Text mady"))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "video"),
- Icon.createWithResource(getContext(), R.drawable.ic_video),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_video),
"Video call mady"))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "email"),
- Icon.createWithResource(getContext(), R.drawable.ic_email), "Email mady"))
+ IconCompat.createWithResource(getContext(), R.drawable.ic_email),
+ "Email mady"))
.build();
}
@@ -330,7 +355,7 @@
.add(b -> b
.addText("yo home \uD83C\uDF55, I emailed you the info")
.addTimestamp(System.currentTimeMillis() - 20 * DateUtils.MINUTE_IN_MILLIS)
- .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+ .addSource(IconCompat.createWithResource(getContext(), R.drawable.mady)))
.add(b -> b
.addText("just bought my tickets")
.addTimestamp(System.currentTimeMillis() - 10 * DateUtils.MINUTE_IN_MILLIS))
@@ -338,53 +363,54 @@
.addText("yay! can't wait for getContext() weekend!\n"
+ "\uD83D\uDE00")
.addTimestamp(System.currentTimeMillis() - 5 * DateUtils.MINUTE_IN_MILLIS)
- .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+ .addSource(IconCompat.createWithResource(getContext(), R.drawable.mady)))
.build();
}
private Slice createNoteSlice(Uri sliceUri) {
// TODO: Remote input.
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xfff4b400)
.addRow(b -> b.setTitle("Create new note"))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "create note"),
- Icon.createWithResource(getContext(), R.drawable.ic_create),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_create),
"Create note"))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "voice note"),
- Icon.createWithResource(getContext(), R.drawable.ic_voice),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_voice),
"Voice note"))
.addAction(new SliceAction(getIntent("android.media.action.IMAGE_CAPTURE"),
- Icon.createWithResource(getContext(), R.drawable.ic_camera),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_camera),
"Photo note"))
.build();
}
private Slice createReservationSlice(Uri sliceUri) {
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xffFF5252)
.setHeader(b -> b
- .setTitle("Upcoming trip to Seattle")
- .setSubtitle("Feb 1 - 19 | 2 guests"))
+ .setTitle("Upcoming trip to Seattle")
+ .setSubtitle("Feb 1 - 19 | 2 guests"))
.addAction(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "show location on map"),
- Icon.createWithResource(getContext(), R.drawable.ic_location),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_location),
"Show reservation location"))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "contact host"),
- Icon.createWithResource(getContext(), R.drawable.ic_text),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_text),
"Contact host"))
.addGrid(b -> b
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.reservation),
- LARGE_IMAGE)
- .setContentDescription("Image of your reservation in Seattle")))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.reservation),
+ LARGE_IMAGE)
+ .setContentDescription("Image of your reservation in Seattle")))
.addGrid(b -> b
- .addCell(cb -> cb
- .addTitleText("Check In")
- .addText("12:00 PM, Feb 1"))
- .addCell(cb -> cb
- .addTitleText("Check Out")
- .addText("11:00 AM, Feb 19")))
+ .addCell(cb -> cb
+ .addTitleText("Check In")
+ .addText("12:00 PM, Feb 1"))
+ .addCell(cb -> cb
+ .addTitleText("Check Out")
+ .addText("11:00 AM, Feb 19")))
.build();
}
@@ -398,55 +424,55 @@
workSubtitle.setSpan(colorSpan, 27, workSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST, "get ride"),
- Icon.createWithResource(getContext(), R.drawable.ic_car), "Get Ride");
- return new ListBuilder(getContext(), sliceUri)
+ IconCompat.createWithResource(getContext(), R.drawable.ic_car), "Get Ride");
+ return new ListBuilder(getContext(), sliceUri, -TimeUnit.MINUTES.toMillis(2))
.setColor(0xff0F9D58)
.setHeader(b -> b
- .setTitle("Get ride")
- .setSubtitle(headerSubtitle)
- .setSummarySubtitle("Ride to work in 12 min | Ride home in 1 hour 45 min")
- .setPrimaryAction(primaryAction))
+ .setTitle("Get ride")
+ .setSubtitle(headerSubtitle)
+ .setSummarySubtitle("Ride to work in 12 min | Ride home in 1 hour 45 min")
+ .setPrimaryAction(primaryAction))
.addRow(b -> b
- .setTitle("Work")
- .setSubtitle(workSubtitle)
- .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "work"),
- Icon.createWithResource(getContext(), R.drawable.ic_work),
- "Get ride to work")))
+ .setTitle("Work")
+ .setSubtitle(workSubtitle)
+ .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "work"),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_work),
+ "Get ride to work")))
.addRow(b -> b
- .setTitle("Home")
- .setSubtitle(homeSubtitle)
- .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "home"),
- Icon.createWithResource(getContext(), R.drawable.ic_home),
- "Get ride home")))
+ .setTitle("Home")
+ .setSubtitle(homeSubtitle)
+ .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "home"),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_home),
+ "Get ride home")))
.build();
}
private Slice createCustomToggleSlice(Uri sliceUri) {
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xffff4081)
.addRow(b -> b
- .setTitle("Custom toggle")
- .setSubtitle("It can support two states")
- .setPrimaryAction(new SliceAction(getBroadcastIntent(ACTION_TOAST,
- "star toggled"),
- Icon.createWithResource(getContext(), R.drawable.toggle_star),
- "Toggle star", true /* isChecked */)))
+ .setTitle("Custom toggle")
+ .setSubtitle("It can support two states")
+ .setPrimaryAction(new SliceAction(getBroadcastIntent(ACTION_TOAST,
+ "star toggled"),
+ IconCompat.createWithResource(getContext(), R.drawable.toggle_star),
+ "Toggle star", true /* isChecked */)))
.build();
}
private Slice createTwoCustomToggleSlices(Uri sliceUri) {
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xffff4081)
.addRow(b -> b
.setTitle("2 toggles")
.setSubtitle("each supports two states")
.addEndItem(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "first star toggled"),
- Icon.createWithResource(getContext(), R.drawable.toggle_star),
+ IconCompat.createWithResource(getContext(), R.drawable.toggle_star),
"Toggle star", true /* isChecked */))
.addEndItem(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "second star toggled"),
- Icon.createWithResource(getContext(), R.drawable.toggle_star),
+ IconCompat.createWithResource(getContext(), R.drawable.toggle_star),
"Toggle star", false /* isChecked */)))
.build();
}
@@ -476,32 +502,32 @@
// Set the first row as a toggle
boolean finalWifiEnabled = wifiEnabled;
SliceAction primaryAction = new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS),
- Icon.createWithResource(getContext(), R.drawable.ic_wifi), "Wi-fi Settings");
+ IconCompat.createWithResource(getContext(), R.drawable.ic_wifi), "Wi-fi Settings");
String toggleCDString = wifiEnabled ? "Turn wifi off" : "Turn wifi on";
String sliceCDString = wifiEnabled ? "Wifi connected to " + state
: "Wifi disconnected, 10 networks available";
- ListBuilder lb = new ListBuilder(getContext(), sliceUri)
+ ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xff4285f4)
.setHeader(b -> b
- .setTitle("Wi-fi")
- .setSubtitle(state)
- .setContentDescription(sliceCDString)
- .setPrimaryAction(primaryAction))
+ .setTitle("Wi-fi")
+ .setSubtitle(state)
+ .setContentDescription(sliceCDString)
+ .setPrimaryAction(primaryAction))
.addAction((new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED, null),
toggleCDString, finalWifiEnabled)));
// Add fake wifi networks
- int[] wifiIcons = new int[] {R.drawable.ic_wifi_full, R.drawable.ic_wifi_low,
+ int[] wifiIcons = new int[]{R.drawable.ic_wifi_full, R.drawable.ic_wifi_low,
R.drawable.ic_wifi_fair};
for (int i = 0; i < 10; i++) {
final int iconId = wifiIcons[i % wifiIcons.length];
- Icon icon = Icon.createWithResource(getContext(), iconId);
+ IconCompat icon = IconCompat.createWithResource(getContext(), iconId);
final String networkName = "Network" + i;
ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(lb);
rb.setTitleItem(icon, ICON_IMAGE).setTitle(networkName);
boolean locked = i % 3 == 0;
if (locked) {
- rb.addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_lock),
+ rb.addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_lock),
ICON_IMAGE);
rb.setContentDescription("Connect to " + networkName + ", password needed");
} else {
@@ -514,14 +540,15 @@
}
// Add keywords
- String[] keywords = new String[] {"internet", "wifi", "data", "network"};
+ String[] keywords = new String[]{"internet", "wifi", "data", "network"};
lb.setKeywords(Arrays.asList(keywords));
// Add see more intent
if (TEST_CUSTOM_SEE_MORE) {
lb.addSeeMoreRow(rb -> rb
.setTitle("See all available networks")
- .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_right_caret),
+ .addEndItem(
+ IconCompat.createWithResource(getContext(), R.drawable.ic_right_caret),
SMALL_IMAGE)
.setPrimaryAction(primaryAction));
} else {
@@ -531,11 +558,12 @@
}
private Slice createStarRatingInputRange(Uri sliceUri) {
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xffff4081)
.addInputRange(c -> c
.setTitle("Star rating")
- .setThumb(Icon.createWithResource(getContext(), R.drawable.ic_star_on))
+ .setThumb(
+ IconCompat.createWithResource(getContext(), R.drawable.ic_star_on))
.setAction(getBroadcastIntent(ACTION_TOAST_RANGE_VALUE, null))
.setMax(5)
.setValue(3)
@@ -544,7 +572,7 @@
}
private Slice createDownloadProgressRange(Uri sliceUri) {
- return new ListBuilder(getContext(), sliceUri)
+ return new ListBuilder(getContext(), sliceUri, INFINITY)
.setColor(0xffff4081)
.addRange(c -> c
.setTitle("Download progress")
@@ -577,27 +605,35 @@
update(1500, mListSummaries, 1, "12 miles | 12 min | $9.00", sliceUri, r);
update(1700, mListSummaries, 2, "5 miles | 10 min | $8.00", sliceUri, r);
}
- Slice s = new ListBuilder(getContext(), sliceUri)
+ CharSequence work = mListSummaries.get(0, "");
+ CharSequence home = mListSummaries.get(1, "");
+ CharSequence school = mListSummaries.get(2, "");
+ Slice s = new ListBuilder(getContext(), sliceUri, -TimeUnit.MINUTES.toMillis(50))
.addRow(b -> b
.setTitle("Work")
- .setSubtitle(mListSummaries.get(0, ""), updating)
- .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_work),
+ .setSubtitle(work,
+ updating || TextUtils.isEmpty(work))
+ .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_work),
ICON_IMAGE))
.addRow(b -> b
.setTitle("Home")
- .setSubtitle(mListSummaries.get(1, ""), updating)
+ .setSubtitle(mListSummaries.get(1, ""),
+ updating || TextUtils.isEmpty(home))
.addEndItem(
- Icon.createWithResource(getContext(), R.drawable.ic_home),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_home),
ICON_IMAGE))
.addRow(b -> b
.setTitle("School")
- .setSubtitle(mListSummaries.get(2, ""), updating)
- .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_school),
+ .setSubtitle(mListSummaries.get(2, ""),
+ updating || TextUtils.isEmpty(school))
+ .addEndItem(
+ IconCompat.createWithResource(getContext(), R.drawable.ic_school),
ICON_IMAGE))
.build();
return s;
}
+ // TODO: Should test large image grids
private Slice createLoadingGridSlice(Uri sliceUri) {
boolean updating = mGridLastUpdate == 0
|| mGridLastUpdate < (System.currentTimeMillis() - 10 * System.currentTimeMillis());
@@ -610,27 +646,40 @@
update(1500, mGridSummaries, 3, "33 min", sliceUri, r);
update(1000, mGridSummaries, 4, "12 min", sliceUri, r);
}
- Slice s = new ListBuilder(getContext(), sliceUri)
+ CharSequence title = mGridSummaries.get(0, "");
+ CharSequence subtitle = mGridSummaries.get(1, "");
+ CharSequence home = mGridSummaries.get(2, "");
+ CharSequence work = mGridSummaries.get(3, "");
+ CharSequence school = mGridSummaries.get(4, "");
+ Slice s = new ListBuilder(getContext(), sliceUri, INFINITY)
.setHeader(hb -> hb
- .setTitle(mGridSummaries.get(0, ""), updating)
- .setSubtitle(mGridSummaries.get(1, ""), updating))
+ .setTitle(title,
+ updating || TextUtils.isEmpty(title))
+ .setSubtitle(subtitle,
+ updating || TextUtils.isEmpty(subtitle)))
.addGrid(gb -> gb
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_home),
- ICON_IMAGE)
- .addTitleText("Home")
- .addText(mGridSummaries.get(2, ""), updating))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_work),
- ICON_IMAGE)
- .addTitleText("Work")
- .addText(mGridSummaries.get(3, ""), updating))
- .addCell(cb -> cb
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_school),
- ICON_IMAGE)
- .addTitleText("School")
- .addText(mGridSummaries.get(4, ""), updating)))
- .build();
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_home),
+ ICON_IMAGE)
+ .addTitleText("Home")
+ .addText(home,
+ updating || TextUtils.isEmpty(home)))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_work),
+ ICON_IMAGE)
+ .addTitleText("Work")
+ .addText(work,
+ updating || TextUtils.isEmpty(work)))
+ .addCell(cb -> cb
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_school),
+ ICON_IMAGE)
+ .addTitleText("School")
+ .addText(school,
+ updating || TextUtils.isEmpty(school))))
+ .build();
return s;
}
diff --git a/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/CardFragmentActivity.java b/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/CardFragmentActivity.java
index 666f7d2..bdf0b49 100644
--- a/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/CardFragmentActivity.java
+++ b/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/CardFragmentActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/cards/CardView.java b/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/cards/CardView.java
index 02b52f8..563f73d 100644
--- a/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/cards/CardView.java
+++ b/samples/ViewPager2Demos/src/main/java/com/example/androidx/viewpager2/cards/CardView.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/settings.gradle b/settings.gradle
index 3e6c4c7..581897d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -40,7 +40,7 @@
includeProject(":car", "car")
includeProject(":cardview", "cardview")
includeProject(":collection", "collection")
-includeProject(":collection-ktx", "collection-ktx")
+includeProject(":collection-ktx", "collection/ktx")
includeProject(":contentpaging", "content")
includeProject(":coordinatorlayout", "coordinatorlayout")
includeProject(":core", "compat")
@@ -68,7 +68,7 @@
includeProject(":media", "media")
includeProject(":mediarouter", "mediarouter")
includeProject(":palette", "palette")
-includeProject(":palette-ktx", "palette-ktx")
+includeProject(":palette-ktx", "palette/ktx")
includeProject(":percentlayout", "percent")
includeProject(":preference", "preference")
includeProject(":print", "print")
diff --git a/slices/builders/api/current.txt b/slices/builders/api/current.txt
index ed3d684..3ff195a 100644
--- a/slices/builders/api/current.txt
+++ b/slices/builders/api/current.txt
@@ -19,8 +19,10 @@
ctor public GridBuilder.CellBuilder(androidx.slice.builders.GridBuilder, android.net.Uri);
method public deprecated androidx.slice.builders.GridBuilder.CellBuilder addImage(android.graphics.drawable.Icon);
method public deprecated androidx.slice.builders.GridBuilder.CellBuilder addImage(android.graphics.drawable.Icon, boolean);
- method public androidx.slice.builders.GridBuilder.CellBuilder addImage(android.graphics.drawable.Icon, int);
- method public androidx.slice.builders.GridBuilder.CellBuilder addImage(android.graphics.drawable.Icon, int, boolean);
+ method public deprecated androidx.slice.builders.GridBuilder.CellBuilder addImage(android.graphics.drawable.Icon, int);
+ method public deprecated androidx.slice.builders.GridBuilder.CellBuilder addImage(android.graphics.drawable.Icon, int, boolean);
+ method public androidx.slice.builders.GridBuilder.CellBuilder addImage(androidx.core.graphics.drawable.IconCompat, int);
+ method public androidx.slice.builders.GridBuilder.CellBuilder addImage(androidx.core.graphics.drawable.IconCompat, int, boolean);
method public deprecated androidx.slice.builders.GridBuilder.CellBuilder addLargeImage(android.graphics.drawable.Icon);
method public deprecated androidx.slice.builders.GridBuilder.CellBuilder addLargeImage(android.graphics.drawable.Icon, boolean);
method public androidx.slice.builders.GridBuilder.CellBuilder addText(java.lang.CharSequence);
@@ -45,8 +47,8 @@
public static final class GridRowBuilder.CellBuilder extends androidx.slice.builders.TemplateSliceBuilder {
ctor public GridRowBuilder.CellBuilder(androidx.slice.builders.GridRowBuilder);
ctor public GridRowBuilder.CellBuilder(androidx.slice.builders.GridRowBuilder, android.net.Uri);
- method public androidx.slice.builders.GridRowBuilder.CellBuilder addImage(android.graphics.drawable.Icon, int);
- method public androidx.slice.builders.GridRowBuilder.CellBuilder addImage(android.graphics.drawable.Icon, int, boolean);
+ method public androidx.slice.builders.GridRowBuilder.CellBuilder addImage(androidx.core.graphics.drawable.IconCompat, int);
+ method public androidx.slice.builders.GridRowBuilder.CellBuilder addImage(androidx.core.graphics.drawable.IconCompat, int, boolean);
method public androidx.slice.builders.GridRowBuilder.CellBuilder addText(java.lang.CharSequence);
method public androidx.slice.builders.GridRowBuilder.CellBuilder addText(java.lang.CharSequence, boolean);
method public androidx.slice.builders.GridRowBuilder.CellBuilder addTitleText(java.lang.CharSequence);
@@ -56,7 +58,8 @@
}
public class ListBuilder extends androidx.slice.builders.TemplateSliceBuilder {
- ctor public ListBuilder(android.content.Context, android.net.Uri);
+ ctor public deprecated ListBuilder(android.content.Context, android.net.Uri);
+ ctor public ListBuilder(android.content.Context, android.net.Uri, long);
method public androidx.slice.builders.ListBuilder addAction(androidx.slice.builders.SliceAction);
method public deprecated androidx.slice.builders.ListBuilder addGrid(androidx.slice.builders.GridBuilder);
method public deprecated androidx.slice.builders.ListBuilder addGrid(java.util.function.Consumer<androidx.slice.builders.GridBuilder>);
@@ -71,12 +74,15 @@
method public androidx.slice.builders.ListBuilder addSeeMoreAction(android.app.PendingIntent);
method public androidx.slice.builders.ListBuilder addSeeMoreRow(androidx.slice.builders.ListBuilder.RowBuilder);
method public androidx.slice.builders.ListBuilder addSeeMoreRow(java.util.function.Consumer<androidx.slice.builders.ListBuilder.RowBuilder>);
+ method public androidx.slice.builders.ListBuilder setColor(int);
method public androidx.slice.builders.ListBuilder setHeader(androidx.slice.builders.ListBuilder.HeaderBuilder);
method public androidx.slice.builders.ListBuilder setHeader(java.util.function.Consumer<androidx.slice.builders.ListBuilder.HeaderBuilder>);
method public androidx.slice.builders.ListBuilder setKeywords(java.util.List<java.lang.String>);
field public static final int ICON_IMAGE = 0; // 0x0
+ field public static final long INFINITY = -1L; // 0xffffffffffffffffL
field public static final int LARGE_IMAGE = 2; // 0x2
field public static final int SMALL_IMAGE = 1; // 0x1
+ field public static final int UNKNOWN_IMAGE = 3; // 0x3
}
public static class ListBuilder.HeaderBuilder extends androidx.slice.builders.TemplateSliceBuilder {
@@ -96,7 +102,8 @@
method public androidx.slice.builders.ListBuilder.InputRangeBuilder setAction(android.app.PendingIntent);
method public androidx.slice.builders.ListBuilder.InputRangeBuilder setContentDescription(java.lang.CharSequence);
method public androidx.slice.builders.ListBuilder.InputRangeBuilder setMax(int);
- method public androidx.slice.builders.ListBuilder.InputRangeBuilder setThumb(android.graphics.drawable.Icon);
+ method public deprecated androidx.slice.builders.ListBuilder.InputRangeBuilder setThumb(android.graphics.drawable.Icon);
+ method public androidx.slice.builders.ListBuilder.InputRangeBuilder setThumb(androidx.core.graphics.drawable.IconCompat);
method public androidx.slice.builders.ListBuilder.InputRangeBuilder setTitle(java.lang.CharSequence);
method public androidx.slice.builders.ListBuilder.InputRangeBuilder setValue(int);
}
@@ -116,8 +123,12 @@
method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(long);
method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon);
method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, boolean);
- method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, int);
- method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, int, boolean);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, int);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, int, boolean);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.core.graphics.drawable.IconCompat);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.core.graphics.drawable.IconCompat, boolean);
+ method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.core.graphics.drawable.IconCompat, int);
+ method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.core.graphics.drawable.IconCompat, int, boolean);
method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction);
method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction, boolean);
method public androidx.slice.builders.ListBuilder.RowBuilder setContentDescription(java.lang.CharSequence);
@@ -129,23 +140,32 @@
method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(long);
method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon);
method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, boolean);
- method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, int);
- method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, int, boolean);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, int);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, int, boolean);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.core.graphics.drawable.IconCompat);
+ method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.core.graphics.drawable.IconCompat, boolean);
+ method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.core.graphics.drawable.IconCompat, int);
+ method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.core.graphics.drawable.IconCompat, int, boolean);
method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.slice.builders.SliceAction);
method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.slice.builders.SliceAction, boolean);
}
- public class SliceAction {
- ctor public SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, java.lang.CharSequence);
- ctor public SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, int, java.lang.CharSequence);
- ctor public SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, java.lang.CharSequence, boolean);
+ public class SliceAction implements androidx.slice.core.SliceAction {
+ ctor public deprecated SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, java.lang.CharSequence);
+ ctor public deprecated SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, int, java.lang.CharSequence);
+ ctor public deprecated SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, java.lang.CharSequence, boolean);
+ ctor public SliceAction(android.app.PendingIntent, androidx.core.graphics.drawable.IconCompat, java.lang.CharSequence);
+ ctor public SliceAction(android.app.PendingIntent, androidx.core.graphics.drawable.IconCompat, int, java.lang.CharSequence);
+ ctor public SliceAction(android.app.PendingIntent, androidx.core.graphics.drawable.IconCompat, java.lang.CharSequence, boolean);
ctor public SliceAction(android.app.PendingIntent, java.lang.CharSequence, boolean);
method public android.app.PendingIntent getAction();
method public java.lang.CharSequence getContentDescription();
- method public android.graphics.drawable.Icon getIcon();
+ method public androidx.core.graphics.drawable.IconCompat getIcon();
+ method public int getImageMode();
method public int getPriority();
method public java.lang.CharSequence getTitle();
method public boolean isChecked();
+ method public boolean isDefaultToggle();
method public boolean isToggle();
method public androidx.slice.builders.SliceAction setChecked(boolean);
method public androidx.slice.builders.SliceAction setContentDescription(java.lang.CharSequence);
diff --git a/slices/builders/build.gradle b/slices/builders/build.gradle
index 96c24f0..1bf4c29 100644
--- a/slices/builders/build.gradle
+++ b/slices/builders/build.gradle
@@ -25,6 +25,7 @@
dependencies {
implementation(project(":slices-core"))
implementation project(":annotation")
+ implementation project(path: ':core')
}
supportLibrary {
diff --git a/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java
index 87e7ddb..bd6dbf4 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java
@@ -27,6 +27,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.builders.impl.TemplateBuilderImpl;
import java.util.function.Consumer;
@@ -333,14 +334,7 @@
}
/**
- * Adds an image to the cell. There can be at most one image, the first one added
- * will be used, others will be ignored.
- * <p>
- * Use this method to specify content that will appear in the template once it's been
- * loaded.
- * </p>
- * @param isLoading indicates whether the app is doing work to load the added content in the
- * background or not.
+ * @deprecated TO BE REMOVED
*/
@NonNull
@Deprecated
@@ -349,6 +343,26 @@
}
/**
+ * @deprecated TO BE REMOVED
+ */
+ @NonNull
+ @Deprecated
+ public CellBuilder addImage(@NonNull Icon image, @ListBuilder.ImageMode int imageMode) {
+ return addImage(image, imageMode, false /* isLoading */);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED
+ */
+ @NonNull
+ @Deprecated
+ public CellBuilder addImage(@Nullable Icon image, @ListBuilder.ImageMode int imageMode,
+ boolean isLoading) {
+ mImpl.addImage(IconCompat.createFromIcon(image), imageMode, isLoading);
+ return this;
+ }
+
+ /**
* Adds an image to the cell. There can be at most one image, the first one added will be
* used, others will be ignored.
*
@@ -360,7 +374,8 @@
* @see ListBuilder#LARGE_IMAGE
*/
@NonNull
- public CellBuilder addImage(@NonNull Icon image, @ListBuilder.ImageMode int imageMode) {
+ public CellBuilder addImage(@NonNull IconCompat image,
+ @ListBuilder.ImageMode int imageMode) {
return addImage(image, imageMode, false /* isLoading */);
}
@@ -381,7 +396,8 @@
* @see ListBuilder#LARGE_IMAGE
*/
@NonNull
- public CellBuilder addImage(@Nullable Icon image, @ListBuilder.ImageMode int imageMode,
+ public CellBuilder addImage(@Nullable IconCompat image,
+ @ListBuilder.ImageMode int imageMode,
boolean isLoading) {
mImpl.addImage(image, imageMode, isLoading);
return this;
diff --git a/slices/builders/src/main/java/androidx/slice/builders/GridRowBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/GridRowBuilder.java
index e8b8836..6213a4f 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/GridRowBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/GridRowBuilder.java
@@ -19,7 +19,6 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import android.app.PendingIntent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build;
@@ -27,6 +26,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.builders.impl.TemplateBuilderImpl;
import java.util.function.Consumer;
@@ -277,7 +277,8 @@
* @see ListBuilder#LARGE_IMAGE
*/
@NonNull
- public CellBuilder addImage(@NonNull Icon image, @ListBuilder.ImageMode int imageMode) {
+ public CellBuilder addImage(@NonNull IconCompat image,
+ @ListBuilder.ImageMode int imageMode) {
return addImage(image, imageMode, false /* isLoading */);
}
@@ -298,8 +299,8 @@
* @see ListBuilder#LARGE_IMAGE
*/
@NonNull
- public CellBuilder addImage(@Nullable Icon image, @ListBuilder.ImageMode int imageMode,
- boolean isLoading) {
+ public CellBuilder addImage(@Nullable IconCompat image,
+ @ListBuilder.ImageMode int imageMode, boolean isLoading) {
mImpl.addImage(image, imageMode, isLoading);
return this;
}
diff --git a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
index bec2af9..29d43ac 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
@@ -31,10 +31,12 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.SliceSpecs;
import androidx.slice.builders.impl.ListBuilderBasicImpl;
import androidx.slice.builders.impl.ListBuilderV1Impl;
import androidx.slice.builders.impl.TemplateBuilderImpl;
+import androidx.slice.core.SliceHints;
import java.util.List;
import java.util.function.Consumer;
@@ -68,31 +70,58 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@IntDef({
- LARGE_IMAGE, SMALL_IMAGE, ICON_IMAGE
+ LARGE_IMAGE, SMALL_IMAGE, ICON_IMAGE, UNKNOWN_IMAGE
})
public @interface ImageMode{}
/**
* Indicates that an image should be presented as an icon and it can be tinted.
*/
- public static final int ICON_IMAGE = 0;
+ public static final int ICON_IMAGE = SliceHints.ICON_IMAGE;
/**
* Indicates that an image should be presented in a smaller size and it shouldn't be tinted.
*/
- public static final int SMALL_IMAGE = 1;
+ public static final int SMALL_IMAGE = SliceHints.SMALL_IMAGE;
/**
* Indicates that an image presented in a larger size and it shouldn't be tinted.
*/
- public static final int LARGE_IMAGE = 2;
+ public static final int LARGE_IMAGE = SliceHints.LARGE_IMAGE;
+ /**
+ * Indicates that an image mode is unknown.
+ */
+ public static final int UNKNOWN_IMAGE = SliceHints.UNKNOWN_IMAGE;
+
+ /**
+ * Constant representing infinity.
+ */
+ public static final long INFINITY = SliceHints.INFINITY;
/**
* Create a builder which will construct a slice that will display rows of content.
* @param uri Uri to tag for this slice.
+ *
+ * @deprecated TO BE REMOVED; use {@link #ListBuilder(Context, Uri, long)}.
*/
+ @Deprecated
public ListBuilder(@NonNull Context context, @NonNull Uri uri) {
super(context, uri);
}
+ /**
+ * Create a builder which will construct a slice that will display rows of content.
+ * <p>
+ * A slice requires an associated time-to-live, i.e. how long the data contained in the slice
+ * can remain fresh. If your slice has content that is not time sensitive, set a TTL of
+ * {@link #INFINITY}.
+ *
+ * @param uri Uri to tag for this slice.
+ * @param ttl the length in milliseconds that the content in this slice can live for.
+ */
+ public ListBuilder(@NonNull Context context, @NonNull Uri uri, long ttl) {
+ super(context, uri);
+ mImpl.setTtl(ttl);
+ }
+
@Override
void setImpl(TemplateBuilderImpl impl) {
mImpl = (androidx.slice.builders.impl.ListBuilder) impl;
@@ -206,10 +235,17 @@
}
/**
- * Sets the color to tint items displayed by this template (e.g. icons).
- * @hide
+ * Sets the color to use on tintable items within the list builder.
+ * Things that might be tinted are:
+ * <ul>
+ * <li>Any {@link SliceAction}s within your slice.
+ * </li>
+ * <li>UI controls such as {@link android.widget.Switch}s or {@link android.widget.SeekBar}s
+ * </li>
+ * <li>Tinting the {@link androidx.slice.widget.SliceView#MODE_SHORTCUT} representation
+ * </li>
+ * </ul>
*/
- @RestrictTo(LIBRARY_GROUP)
@NonNull
public ListBuilder setColor(@ColorInt int color) {
mImpl.setColor(color);
@@ -455,10 +491,18 @@
}
/**
- * Set the {@link Icon} to be displayed as the thumb on the input range.
+ * @deprecated TO BE REMOVED
*/
@NonNull
public InputRangeBuilder setThumb(@NonNull Icon thumb) {
+ return setThumb(IconCompat.createFromIcon(thumb));
+ }
+
+ /**
+ * Set the {@link Icon} to be displayed as the thumb on the input range.
+ */
+ @NonNull
+ public InputRangeBuilder setThumb(@NonNull IconCompat thumb) {
mImpl.setThumb(thumb);
return this;
}
@@ -550,6 +594,45 @@
}
/**
+ * @deprecated TO BE REMOVED.
+ */
+ @Deprecated
+ @NonNull
+ public RowBuilder setTitleItem(@NonNull Icon icon) {
+ return setTitleItem(icon, ICON_IMAGE);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED.
+ */
+ @Deprecated
+ @NonNull
+ public RowBuilder setTitleItem(@Nullable Icon icon, boolean isLoading) {
+ return setTitleItem(icon, ICON_IMAGE, isLoading);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED.
+ */
+ @Deprecated
+ public RowBuilder setTitleItem(@NonNull Icon icon, @ImageMode int imageMode) {
+ mImpl.setTitleItem(IconCompat.createFromIcon(icon), imageMode, false /* isLoading */);
+ return this;
+ }
+
+ /**
+ * @deprecated TO BE REMOVED.
+ */
+ @Deprecated
+ @NonNull
+ public RowBuilder setTitleItem(@Nullable Icon icon, @ImageMode int imageMode,
+ boolean isLoading) {
+ mImpl.setTitleItem(IconCompat.createFromIcon(icon), imageMode,
+ isLoading /* isLoading */);
+ return this;
+ }
+
+ /**
* Sets the title item to be the provided icon. There can only be one title item, this
* will replace any other title items that may have been set.
*
@@ -557,7 +640,7 @@
*/
@Deprecated
@NonNull
- public RowBuilder setTitleItem(@NonNull Icon icon) {
+ public RowBuilder setTitleItem(@NonNull IconCompat icon) {
return setTitleItem(icon, ICON_IMAGE);
}
@@ -575,7 +658,7 @@
*/
@Deprecated
@NonNull
- public RowBuilder setTitleItem(@Nullable Icon icon, boolean isLoading) {
+ public RowBuilder setTitleItem(@Nullable IconCompat icon, boolean isLoading) {
return setTitleItem(icon, ICON_IMAGE, isLoading);
}
@@ -590,7 +673,7 @@
* @see #SMALL_IMAGE
* @see #LARGE_IMAGE
*/
- public RowBuilder setTitleItem(@NonNull Icon icon, @ImageMode int imageMode) {
+ public RowBuilder setTitleItem(@NonNull IconCompat icon, @ImageMode int imageMode) {
mImpl.setTitleItem(icon, imageMode, false /* isLoading */);
return this;
}
@@ -612,7 +695,7 @@
* @see #LARGE_IMAGE
*/
@NonNull
- public RowBuilder setTitleItem(@Nullable Icon icon, @ImageMode int imageMode,
+ public RowBuilder setTitleItem(@Nullable IconCompat icon, @ImageMode int imageMode,
boolean isLoading) {
mImpl.setTitleItem(icon, imageMode, isLoading /* isLoading */);
return this;
@@ -715,6 +798,50 @@
}
/**
+ * @deprecated TO BE REMOVED
+ */
+ @Deprecated
+ @NonNull
+ public RowBuilder addEndItem(@NonNull Icon icon) {
+ return addEndItem(icon, ICON_IMAGE, false /* isLoading */);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED
+ */
+ @Deprecated
+ @NonNull
+ public RowBuilder addEndItem(@NonNull Icon icon, boolean isLoading) {
+ return addEndItem(icon, ICON_IMAGE, isLoading);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED
+ */
+ @Deprecated
+ @NonNull
+ public RowBuilder addEndItem(@NonNull Icon icon, @ImageMode int imageMode) {
+ return addEndItem(icon, imageMode, false /* isLoading */);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED
+ */
+ @Deprecated
+ @NonNull
+ public RowBuilder addEndItem(@Nullable Icon icon, @ImageMode int imageMode,
+ boolean isLoading) {
+ if (mHasEndActionOrToggle) {
+ throw new IllegalArgumentException("Trying to add an icon to end items when an"
+ + "action has already been added. End items cannot have a mixture of "
+ + "actions and icons.");
+ }
+ mImpl.addEndItem(IconCompat.createFromIcon(icon), imageMode, isLoading);
+ mHasEndImage = true;
+ return this;
+ }
+
+ /**
* Adds an icon to be displayed at the end of the row. A mixture of icons and actions
* is not permitted. If an action has already been added this will throw
* {@link IllegalArgumentException}.
@@ -723,7 +850,7 @@
*/
@Deprecated
@NonNull
- public RowBuilder addEndItem(@NonNull Icon icon) {
+ public RowBuilder addEndItem(@NonNull IconCompat icon) {
return addEndItem(icon, ICON_IMAGE, false /* isLoading */);
}
@@ -742,7 +869,7 @@
*/
@Deprecated
@NonNull
- public RowBuilder addEndItem(@NonNull Icon icon, boolean isLoading) {
+ public RowBuilder addEndItem(@NonNull IconCompat icon, boolean isLoading) {
return addEndItem(icon, ICON_IMAGE, isLoading);
}
@@ -757,7 +884,7 @@
* @see #LARGE_IMAGE
*/
@NonNull
- public RowBuilder addEndItem(@NonNull Icon icon, @ImageMode int imageMode) {
+ public RowBuilder addEndItem(@NonNull IconCompat icon, @ImageMode int imageMode) {
return addEndItem(icon, imageMode, false /* isLoading */);
}
@@ -777,7 +904,7 @@
* @see #LARGE_IMAGE
*/
@NonNull
- public RowBuilder addEndItem(@Nullable Icon icon, @ImageMode int imageMode,
+ public RowBuilder addEndItem(@Nullable IconCompat icon, @ImageMode int imageMode,
boolean isLoading) {
if (mHasEndActionOrToggle) {
throw new IllegalArgumentException("Trying to add an icon to end items when an"
@@ -823,7 +950,7 @@
+ "in a row, set a custom icon for each toggle.");
}
mImpl.addEndItem(action, isLoading);
- mHasDefaultToggle = action.isDefaultToggle();
+ mHasDefaultToggle = action.getImpl().isDefaultToggle();
mHasEndActionOrToggle = true;
return this;
}
diff --git a/slices/builders/src/main/java/androidx/slice/builders/MessagingSliceBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/MessagingSliceBuilder.java
index 32134d3..c3f1f92 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/MessagingSliceBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/MessagingSliceBuilder.java
@@ -23,12 +23,11 @@
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build;
+
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
-
-import java.util.function.Consumer;
-
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.SliceSpecs;
import androidx.slice.builders.impl.MessagingBasicImpl;
import androidx.slice.builders.impl.MessagingBuilder;
@@ -36,6 +35,8 @@
import androidx.slice.builders.impl.MessagingV1Impl;
import androidx.slice.builders.impl.TemplateBuilderImpl;
+import java.util.function.Consumer;
+
/**
* Builder to construct slice content in a messaging format.
* @hide
@@ -120,6 +121,14 @@
}
/**
+ * Add the icon used to display contact in the messaging experience
+ */
+ public MessageBuilder addSource(IconCompat source) {
+ mImpl.addSource(source.toIcon());
+ return this;
+ }
+
+ /**
* Add the text to be used for this message.
*/
public MessageBuilder addText(CharSequence text) {
diff --git a/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java b/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java
index 00adbd4..e4e28f5 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java
@@ -16,14 +16,6 @@
package androidx.slice.builders;
-import static android.app.slice.Slice.HINT_NO_TINT;
-import static android.app.slice.Slice.HINT_SELECTED;
-import static android.app.slice.Slice.HINT_SHORTCUT;
-import static android.app.slice.Slice.HINT_TITLE;
-import static android.app.slice.Slice.SUBTYPE_CONTENT_DESCRIPTION;
-import static android.app.slice.Slice.SUBTYPE_PRIORITY;
-import static android.app.slice.Slice.SUBTYPE_TOGGLE;
-
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
@@ -34,21 +26,43 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
+import androidx.slice.core.SliceActionImpl;
/**
* Class representing an action, supports tappable icons, custom toggle icons, and default toggles.
*/
-public class SliceAction {
+public class SliceAction implements androidx.slice.core.SliceAction {
- private PendingIntent mAction;
- private Icon mIcon;
- private int mImageMode;
- private CharSequence mTitle;
- private CharSequence mContentDescription;
- private boolean mIsToggle;
- private boolean mIsChecked;
- private int mPriority = -1;
+ private SliceActionImpl mSliceAction;
+
+ /**
+ * @deprecated TO BE REMOVED
+ */
+ @Deprecated
+ public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
+ @NonNull CharSequence actionTitle) {
+ this(action, actionIcon, ICON_IMAGE, actionTitle);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED
+ */
+ @Deprecated
+ public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
+ @ListBuilder.ImageMode int imageMode, @NonNull CharSequence actionTitle) {
+ this(action, IconCompat.createFromIcon(actionIcon), imageMode, actionTitle);
+ }
+
+ /**
+ * @deprecated TO BE REMOVED
+ */
+ @Deprecated
+ public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
+ @NonNull CharSequence actionTitle, boolean isChecked) {
+ this(action, IconCompat.createFromIcon(actionIcon), actionTitle, isChecked);
+ }
/**
* Construct a SliceAction representing a tappable icon.
@@ -58,7 +72,7 @@
* @param actionTitle the title for this action, also used for content description if one hasn't
* been set via {@link #setContentDescription(CharSequence)}.
*/
- public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
+ public SliceAction(@NonNull PendingIntent action, @NonNull IconCompat actionIcon,
@NonNull CharSequence actionTitle) {
this(action, actionIcon, ICON_IMAGE, actionTitle);
}
@@ -80,12 +94,9 @@
* @see ListBuilder#SMALL_IMAGE
* @see ListBuilder#LARGE_IMAGE
*/
- public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
+ public SliceAction(@NonNull PendingIntent action, @NonNull IconCompat actionIcon,
@ListBuilder.ImageMode int imageMode, @NonNull CharSequence actionTitle) {
- mAction = action;
- mIcon = actionIcon;
- mTitle = actionTitle;
- mImageMode = imageMode;
+ mSliceAction = new SliceActionImpl(action, actionIcon, imageMode, actionTitle);
}
/**
@@ -98,11 +109,9 @@
* been set via {@link #setContentDescription(CharSequence)}.
* @param isChecked the state of the toggle.
*/
- public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
+ public SliceAction(@NonNull PendingIntent action, @NonNull IconCompat actionIcon,
@NonNull CharSequence actionTitle, boolean isChecked) {
- this(action, actionIcon, ICON_IMAGE, actionTitle);
- mIsChecked = isChecked;
- mIsToggle = true;
+ mSliceAction = new SliceActionImpl(action, actionIcon, actionTitle, isChecked);
}
/**
@@ -115,19 +124,16 @@
*/
public SliceAction(@NonNull PendingIntent action, @NonNull CharSequence actionTitle,
boolean isChecked) {
- mAction = action;
- mTitle = actionTitle;
- mIsToggle = true;
- mIsChecked = isChecked;
-
+ mSliceAction = new SliceActionImpl(action, actionTitle, isChecked);
}
/**
* @param description the content description for this action.
*/
- @Nullable
+ @NonNull
+ @Override
public SliceAction setContentDescription(@NonNull CharSequence description) {
- mContentDescription = description;
+ mSliceAction.setContentDescription(description);
return this;
}
@@ -135,16 +141,20 @@
* @param isChecked whether the state of this action is checked or not; only used for toggle
* actions.
*/
+ @NonNull
+ @Override
public SliceAction setChecked(boolean isChecked) {
- mIsChecked = isChecked;
+ mSliceAction.setChecked(isChecked);
return this;
}
/**
* Sets the priority of this action, with the lowest priority having the highest ranking.
*/
+ @NonNull
+ @Override
public SliceAction setPriority(@IntRange(from = 0) int priority) {
- mPriority = priority;
+ mSliceAction.setPriority(priority);
return this;
}
@@ -152,8 +162,9 @@
* @return the {@link PendingIntent} associated with this action.
*/
@NonNull
+ @Override
public PendingIntent getAction() {
- return mAction;
+ return mSliceAction.getAction();
}
/**
@@ -161,53 +172,67 @@
* represented is a default toggle.
*/
@Nullable
- public Icon getIcon() {
- return mIcon;
+ @Override
+ public IconCompat getIcon() {
+ return mSliceAction.getIcon();
}
/**
* @return the title for this action.
*/
@NonNull
+ @Override
public CharSequence getTitle() {
- return mTitle;
+ return mSliceAction.getTitle();
}
/**
* @return the content description to use for this action.
*/
@Nullable
+ @Override
public CharSequence getContentDescription() {
- return mContentDescription;
+ return mSliceAction.getContentDescription();
}
/**
* @return the priority associated with this action, -1 if unset.
*/
+ @Override
public int getPriority() {
- return mPriority;
+ return mSliceAction.getPriority();
}
/**
* @return whether this action represents a toggle (i.e. has a checked and unchecked state).
*/
+ @Override
public boolean isToggle() {
- return mIsToggle;
+ return mSliceAction.isToggle();
}
/**
* @return whether the state of this action is checked or not; only used for toggle actions.
*/
+ @Override
public boolean isChecked() {
- return mIsChecked;
+ return mSliceAction.isChecked();
}
/**
- * @hide
+ * @return the image mode to use for this action.
*/
- @RestrictTo(LIBRARY)
+ @Override
+ public @ListBuilder.ImageMode int getImageMode() {
+ return mSliceAction.getImageMode();
+ }
+
+ /**
+ * @return whether this action is a toggle using the standard switch control.
+ */
+ @Override
public boolean isDefaultToggle() {
- return mIsToggle && mIcon == null;
+ return mSliceAction.isDefaultToggle();
}
/**
@@ -219,28 +244,15 @@
@RestrictTo(LIBRARY)
@NonNull
public Slice buildSlice(@NonNull Slice.Builder builder) {
- Slice.Builder sb = new Slice.Builder(builder);
- if (mIcon != null) {
- @Slice.SliceHint String[] hints = mImageMode == ICON_IMAGE
- ? new String[] {}
- : new String[] {HINT_NO_TINT};
- sb.addIcon(mIcon, null, hints);
- }
- if (mTitle != null) {
- sb.addText(mTitle, null, HINT_TITLE);
- }
- if (mContentDescription != null) {
- sb.addText(mContentDescription, SUBTYPE_CONTENT_DESCRIPTION);
- }
- if (mIsToggle && mIsChecked) {
- sb.addHints(HINT_SELECTED);
- }
- if (mPriority != -1) {
- sb.addInt(mPriority, SUBTYPE_PRIORITY);
- }
- String subtype = mIsToggle ? SUBTYPE_TOGGLE : null;
- builder.addHints(HINT_SHORTCUT);
- builder.addAction(mAction, sb.build(), subtype);
- return builder.build();
+ return mSliceAction.buildSlice(builder);
+ }
+
+ /**
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ @NonNull
+ public SliceActionImpl getImpl() {
+ return mSliceAction;
}
}
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilder.java
index b5eefff..9b59945 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilder.java
@@ -19,12 +19,12 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import android.app.PendingIntent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.builders.SliceAction;
/**
@@ -123,12 +123,11 @@
/**
* Adds an image to the cell. There can be at most one image, the first one added
* will be used, others will be ignored.
- *
- * @param image the image to display in the cell.
+ * @param image the image to display in the cell.
* @param imageMode the mode that image should be displayed in.
*/
@NonNull
- void addImage(@NonNull Icon image, int imageMode);
+ void addImage(@NonNull IconCompat image, int imageMode);
/**
* Adds an image to the cell. There can be at most one image, the first one added
@@ -139,7 +138,7 @@
* until updated.l.
*/
@NonNull
- void addImage(@NonNull Icon image, int imageMode, boolean isLoading);
+ void addImage(@NonNull IconCompat image, int imageMode, boolean isLoading);
/**
* Sets the action to be invoked if the user taps on this cell in the row.
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderBasicImpl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderBasicImpl.java
index dcd8791..e1a0752 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderBasicImpl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderBasicImpl.java
@@ -19,12 +19,12 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import android.app.PendingIntent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.SliceAction;
@@ -141,14 +141,14 @@
*/
@NonNull
@Override
- public void addImage(@NonNull Icon image, int imageMode) {
+ public void addImage(@NonNull IconCompat image, int imageMode) {
}
/**
*/
@NonNull
@Override
- public void addImage(@Nullable Icon image, int imageMode, boolean isLoading) {
+ public void addImage(@Nullable IconCompat image, int imageMode, boolean isLoading) {
}
/**
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
index 0c077ba..29158b4 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/GridRowBuilderListV1Impl.java
@@ -31,12 +31,12 @@
import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
import android.app.PendingIntent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.SliceAction;
@@ -193,7 +193,7 @@
*/
@NonNull
@Override
- public void addImage(@NonNull Icon image, int imageMode) {
+ public void addImage(@NonNull IconCompat image, int imageMode) {
addImage(image, imageMode, false /* isLoading */);
}
@@ -201,7 +201,7 @@
*/
@NonNull
@Override
- public void addImage(@Nullable Icon image, int imageMode, boolean isLoading) {
+ public void addImage(@Nullable IconCompat image, int imageMode, boolean isLoading) {
ArrayList<String> hints = new ArrayList<>();
if (imageMode != ICON_IMAGE) {
hints.add(HINT_NO_TINT);
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
index da4fb69..0ebd32b 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
@@ -19,12 +19,12 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import android.app.PendingIntent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.builders.SliceAction;
import java.util.List;
@@ -100,6 +100,14 @@
void setKeywords(List<String> keywords);
/**
+ * Sets the time-to-live for this slice, i.e. how long the data contained in the slice
+ * can remain fresh.
+ *
+ * @param ttl the length in milliseconds that this content can live for.
+ */
+ void setTtl(long ttl);
+
+ /**
* Create a builder that implements {@link RowBuilder}.
*/
TemplateBuilderImpl createRowBuilder();
@@ -163,9 +171,9 @@
void setAction(@NonNull PendingIntent action);
/**
- * Set the {@link Icon} to be displayed as the thumb on the input range.
+ * Set the {@link IconCompat} to be displayed as the thumb on the input range.
*/
- void setThumb(@NonNull Icon thumb);
+ void setThumb(@NonNull IconCompat thumb);
}
/**
@@ -184,11 +192,10 @@
/**
* Sets the title item to be the provided icon. There can only be one title item, this
* will replace any other title items that may have been set.
- *
- * @param icon the image to display.
+ * @param icon the image to display.
* @param imageMode the mode that image should be displayed in.
*/
- void setTitleItem(Icon icon, int imageMode);
+ void setTitleItem(IconCompat icon, int imageMode);
/**
* Sets the title item to be the provided icon. There can only be one title item, this
@@ -197,12 +204,11 @@
* When set to true, the parameter {@code isLoading} indicates that the app is doing work
* to load this content in the background, in this case the template displays a placeholder
* until updated.
- *
- * @param icon the image to display.
+ * @param icon the image to display.
* @param imageMode the mode that image should be displayed in.
* @param isLoading whether this content is being loaded in the background.
*/
- void setTitleItem(Icon icon, int imageMode, boolean isLoading);
+ void setTitleItem(IconCompat icon, int imageMode, boolean isLoading);
/**
* Sets the title item to be a tappable icon. There can only be one title item, this will
@@ -260,11 +266,10 @@
/**
* Adds an icon to be displayed at the end of the row.
- *
- * @param icon the image to display.
+ * @param icon the image to display.
* @param imageMode the mode that image should be displayed in.
*/
- void addEndItem(Icon icon, int imageMode);
+ void addEndItem(IconCompat icon, int imageMode);
/**
* Adds an icon to be displayed at the end of the row.
@@ -272,12 +277,11 @@
* When set to true, the parameter {@code isLoading} indicates that the app is doing work
* to load this content in the background, in this case the template displays a placeholder
* until updated.
- *
- * @param icon the image to display.
+ * @param icon the image to display.
* @param imageMode the mode that image should be displayed in.
* @param isLoading whether this content is being loaded in the background.
*/
- void addEndItem(Icon icon, int imageMode, boolean isLoading);
+ void addEndItem(IconCompat icon, int imageMode, boolean isLoading);
/**
* Adds a tappable icon to be displayed at the end of the row.
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
index e9a659d..204defa 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
@@ -20,12 +20,12 @@
import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
import android.app.PendingIntent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceSpec;
import androidx.slice.builders.SliceAction;
@@ -114,6 +114,12 @@
/**
*/
@Override
+ public void setTtl(long ttl) {
+ }
+
+ /**
+ */
+ @Override
public TemplateBuilderImpl createRowBuilder() {
return new RowBuilderImpl(this);
}
@@ -207,14 +213,14 @@
/**
*/
@Override
- public void setTitleItem(Icon icon, int imageMode) {
+ public void setTitleItem(IconCompat icon, int imageMode) {
}
/**
*/
@Override
- public void setTitleItem(Icon icon, int imageMode, boolean isLoading) {
+ public void setTitleItem(IconCompat icon, int imageMode, boolean isLoading) {
}
@@ -274,14 +280,14 @@
/**
*/
@Override
- public void addEndItem(Icon icon, int imageMode) {
+ public void addEndItem(IconCompat icon, int imageMode) {
}
/**
*/
@Override
- public void addEndItem(Icon icon, int imageMode, boolean isLoading) {
+ public void addEndItem(IconCompat icon, int imageMode, boolean isLoading) {
}
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
index 6671024..e85fbb1 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
@@ -31,19 +31,23 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.INFINITY;
import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
+import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
+import static androidx.slice.core.SliceHints.HINT_TTL;
import static androidx.slice.core.SliceHints.SUBTYPE_MAX;
+import static androidx.slice.core.SliceHints.SUBTYPE_MILLIS;
import static androidx.slice.core.SliceHints.SUBTYPE_RANGE;
import static androidx.slice.core.SliceHints.SUBTYPE_VALUE;
import android.app.PendingIntent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
import androidx.slice.SliceSpec;
@@ -71,6 +75,7 @@
*/
@Override
public void apply(Slice.Builder builder) {
+ builder.addTimestamp(System.currentTimeMillis(), SUBTYPE_MILLIS, HINT_LAST_UPDATED);
if (mSliceHeader != null) {
builder.addSubSlice(mSliceHeader);
}
@@ -202,7 +207,7 @@
public static class InputRangeBuilderImpl
extends RangeBuilderImpl implements InputRangeBuilder {
private PendingIntent mAction;
- private Icon mThumb;
+ private IconCompat mThumb;
public InputRangeBuilderImpl(Slice.Builder sb) {
super(sb);
@@ -214,7 +219,7 @@
}
@Override
- public void setThumb(@NonNull Icon thumb) {
+ public void setThumb(@NonNull IconCompat thumb) {
mThumb = thumb;
}
@@ -254,6 +259,14 @@
/**
*/
@Override
+ public void setTtl(long ttl) {
+ long expiry = ttl == INFINITY ? INFINITY : System.currentTimeMillis() + ttl;
+ getBuilder().addTimestamp(expiry, SUBTYPE_MILLIS, HINT_TTL);
+ }
+
+ /**
+ */
+ @Override
public TemplateBuilderImpl createRowBuilder() {
return new RowBuilderImpl(this);
}
@@ -338,7 +351,7 @@
*/
@NonNull
@Override
- public void setTitleItem(Icon icon, int imageMode) {
+ public void setTitleItem(IconCompat icon, int imageMode) {
setTitleItem(icon, imageMode, false /* isLoading */);
}
@@ -346,7 +359,7 @@
*/
@NonNull
@Override
- public void setTitleItem(Icon icon, int imageMode, boolean isLoading) {
+ public void setTitleItem(IconCompat icon, int imageMode, boolean isLoading) {
ArrayList<String> hints = new ArrayList<>();
if (imageMode != ICON_IMAGE) {
hints.add(HINT_NO_TINT);
@@ -441,7 +454,7 @@
*/
@NonNull
@Override
- public void addEndItem(Icon icon, int imageMode) {
+ public void addEndItem(IconCompat icon, int imageMode) {
addEndItem(icon, imageMode, false /* isLoading */);
}
@@ -449,7 +462,7 @@
*/
@NonNull
@Override
- public void addEndItem(Icon icon, int imageMode, boolean isLoading) {
+ public void addEndItem(IconCompat icon, int imageMode, boolean isLoading) {
ArrayList<String> hints = new ArrayList<>();
if (imageMode != ICON_IMAGE) {
hints.add(HINT_NO_TINT);
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBasicImpl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBasicImpl.java
index 8d3bf59..c999594 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBasicImpl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBasicImpl.java
@@ -19,8 +19,9 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import android.graphics.drawable.Icon;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceSpec;
@@ -44,7 +45,7 @@
public void apply(Slice.Builder builder) {
if (mLastMessage != null) {
if (mLastMessage.mIcon != null) {
- builder.addIcon(mLastMessage.mIcon, null);
+ builder.addIcon(IconCompat.createFromIcon(mLastMessage.mIcon), null);
}
if (mLastMessage.mText != null) {
builder.addText(mLastMessage.mText, null);
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java
index c1b8a85..dd66616 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingBuilder.java
@@ -19,6 +19,7 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import android.graphics.drawable.Icon;
+
import androidx.annotation.RestrictTo;
/**
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java
index b44f25b..e47871a 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java
@@ -17,12 +17,13 @@
package androidx.slice.builders.impl;
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
-
+import static androidx.slice.builders.ListBuilder.INFINITY;
import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
import android.graphics.drawable.Icon;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceSpec;
@@ -39,6 +40,7 @@
public MessagingListV1Impl(Slice.Builder b, SliceSpec spec) {
super(b, spec);
mListBuilder = new ListBuilderV1Impl(b, spec);
+ mListBuilder.setTtl(INFINITY);
}
/**
@@ -84,7 +86,7 @@
*/
@Override
public void addSource(Icon source) {
- mListBuilder.setTitleItem(source, SMALL_IMAGE);
+ mListBuilder.setTitleItem(IconCompat.createFromIcon(source), SMALL_IMAGE);
}
/**
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingV1Impl.java
index 36ecd0c..e601491 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingV1Impl.java
@@ -19,8 +19,9 @@
import static android.app.slice.Slice.SUBTYPE_MESSAGE;
import android.graphics.drawable.Icon;
-import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceSpec;
@@ -71,7 +72,8 @@
*/
@Override
public void addSource(Icon source) {
- getBuilder().addIcon(source, android.app.slice.Slice.SUBTYPE_SOURCE);
+ getBuilder().addIcon(IconCompat.createFromIcon(source),
+ android.app.slice.Slice.SUBTYPE_SOURCE);
}
/**
diff --git a/slices/core/api/current.txt b/slices/core/api/current.txt
index c1668ab..acc5cbd 100644
--- a/slices/core/api/current.txt
+++ b/slices/core/api/current.txt
@@ -16,7 +16,7 @@
method public android.app.PendingIntent getAction();
method public java.lang.String getFormat();
method public java.util.List<java.lang.String> getHints();
- method public android.graphics.drawable.Icon getIcon();
+ method public androidx.core.graphics.drawable.IconCompat getIcon();
method public int getInt();
method public androidx.slice.Slice getSlice();
method public java.lang.String getSubType();
@@ -36,3 +36,22 @@
}
+package androidx.slice.core {
+
+ public abstract interface SliceAction {
+ method public abstract android.app.PendingIntent getAction();
+ method public abstract java.lang.CharSequence getContentDescription();
+ method public abstract androidx.core.graphics.drawable.IconCompat getIcon();
+ method public abstract int getImageMode();
+ method public abstract int getPriority();
+ method public abstract java.lang.CharSequence getTitle();
+ method public abstract boolean isChecked();
+ method public abstract boolean isDefaultToggle();
+ method public abstract boolean isToggle();
+ method public abstract androidx.slice.core.SliceAction setChecked(boolean);
+ method public abstract androidx.slice.core.SliceAction setContentDescription(java.lang.CharSequence);
+ method public abstract androidx.slice.core.SliceAction setPriority(int);
+ }
+
+}
+
diff --git a/slices/core/src/androidTest/java/androidx/slice/SliceTest.java b/slices/core/src/androidTest/java/androidx/slice/SliceTest.java
index 563473a..041c8fe 100644
--- a/slices/core/src/androidTest/java/androidx/slice/SliceTest.java
+++ b/slices/core/src/androidTest/java/androidx/slice/SliceTest.java
@@ -38,12 +38,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.core.test.R;
import org.junit.Test;
@@ -120,8 +120,14 @@
SliceItem item = s.getItems().get(0);
assertEquals(FORMAT_IMAGE, item.getFormat());
- assertEquals(Icon.createWithResource(mContext, R.drawable.size_48x48).toString(),
- item.getIcon().toString());
+ assertEquivalent(IconCompat.createWithResource(mContext, R.drawable.size_48x48),
+ item.getIcon());
+ }
+
+ private void assertEquivalent(IconCompat first, IconCompat second) {
+ assertEquals(first.getType(), second.getType());
+ assertEquals(first.getResId(), second.getResId());
+ assertEquals(first.getResPackage(), second.getResPackage());
}
@Test
diff --git a/slices/core/src/androidTest/java/androidx/slice/SliceTestProvider.java b/slices/core/src/androidTest/java/androidx/slice/SliceTestProvider.java
index ab68646..d6f1628 100644
--- a/slices/core/src/androidTest/java/androidx/slice/SliceTestProvider.java
+++ b/slices/core/src/androidTest/java/androidx/slice/SliceTestProvider.java
@@ -23,9 +23,9 @@
import android.app.PendingIntent;
import android.content.Intent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice.Builder;
import androidx.slice.core.test.R;
@@ -49,7 +49,7 @@
return new Slice.Builder(sliceUri).addText("Expected text", "text").build();
case "/icon":
return new Slice.Builder(sliceUri).addIcon(
- Icon.createWithResource(getContext(), R.drawable.size_48x48),
+ IconCompat.createWithResource(getContext(), R.drawable.size_48x48),
"icon").build();
case "/action":
Builder builder = new Builder(sliceUri);
@@ -65,7 +65,7 @@
return new Slice.Builder(sliceUri)
.addHints(HINT_LIST)
.addText("Text", null, HINT_TITLE)
- .addIcon(Icon.createWithResource(getContext(), R.drawable.size_48x48),
+ .addIcon(IconCompat.createWithResource(getContext(), R.drawable.size_48x48),
null, HINT_NO_TINT, HINT_LARGE)
.build();
}
diff --git a/slices/core/src/main/java/androidx/slice/Slice.java b/slices/core/src/main/java/androidx/slice/Slice.java
index d27d246..84c7df7 100644
--- a/slices/core/src/main/java/androidx/slice/Slice.java
+++ b/slices/core/src/main/java/androidx/slice/Slice.java
@@ -38,12 +38,13 @@
import static androidx.slice.SliceConvert.unwrap;
import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
+import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
+import static androidx.slice.core.SliceHints.HINT_TTL;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.app.slice.SliceManager;
import android.content.Context;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
@@ -54,6 +55,7 @@
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.annotation.StringDef;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.core.os.BuildCompat;
import androidx.slice.compat.SliceProviderCompat;
@@ -84,7 +86,7 @@
@RestrictTo(Scope.LIBRARY)
@StringDef({HINT_TITLE, HINT_LIST, HINT_LIST_ITEM, HINT_LARGE, HINT_ACTIONS, HINT_SELECTED,
HINT_HORIZONTAL, HINT_NO_TINT, HINT_PARTIAL, HINT_SUMMARY, HINT_SEE_MORE,
- HINT_SHORTCUT, HINT_KEY_WORDS})
+ HINT_SHORTCUT, HINT_KEY_WORDS, HINT_TTL, HINT_LAST_UPDATED})
public @interface SliceHint{ }
private final SliceItem[] mItems;
@@ -292,7 +294,7 @@
* @param subType Optional template-specific type information
* @see {@link SliceItem#getSubType()}
*/
- public Builder addIcon(Icon icon, @Nullable String subType,
+ public Builder addIcon(IconCompat icon, @Nullable String subType,
@SliceHint String... hints) {
mItems.add(new SliceItem(icon, FORMAT_IMAGE, subType, hints));
return this;
@@ -303,7 +305,7 @@
* @param subType Optional template-specific type information
* @see {@link SliceItem#getSubType()}
*/
- public Builder addIcon(Icon icon, @Nullable String subType,
+ public Builder addIcon(IconCompat icon, @Nullable String subType,
@SliceHint List<String> hints) {
return addIcon(icon, subType, hints.toArray(new String[hints.size()]));
}
diff --git a/slices/core/src/main/java/androidx/slice/SliceConvert.java b/slices/core/src/main/java/androidx/slice/SliceConvert.java
index 58531fa..1d89b8e 100644
--- a/slices/core/src/main/java/androidx/slice/SliceConvert.java
+++ b/slices/core/src/main/java/androidx/slice/SliceConvert.java
@@ -27,6 +27,7 @@
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.collection.ArraySet;
+import androidx.core.graphics.drawable.IconCompat;
import java.util.List;
import java.util.Set;
@@ -51,7 +52,7 @@
builder.addSubSlice(unwrap(item.getSlice()), item.getSubType());
break;
case FORMAT_IMAGE:
- builder.addIcon(item.getIcon(), item.getSubType(), item.getHints());
+ builder.addIcon(item.getIcon().toIcon(), item.getSubType(), item.getHints());
break;
case FORMAT_REMOTE_INPUT:
builder.addRemoteInput(item.getRemoteInput(), item.getSubType(),
@@ -102,7 +103,8 @@
builder.addSubSlice(wrap(item.getSlice()), item.getSubType());
break;
case FORMAT_IMAGE:
- builder.addIcon(item.getIcon(), item.getSubType(), item.getHints());
+ builder.addIcon(IconCompat.createFromIcon(item.getIcon()),
+ item.getSubType(), item.getHints());
break;
case FORMAT_REMOTE_INPUT:
builder.addRemoteInput(item.getRemoteInput(), item.getSubType(),
diff --git a/slices/core/src/main/java/androidx/slice/SliceItem.java b/slices/core/src/main/java/androidx/slice/SliceItem.java
index e059124..067772e 100644
--- a/slices/core/src/main/java/androidx/slice/SliceItem.java
+++ b/slices/core/src/main/java/androidx/slice/SliceItem.java
@@ -26,16 +26,17 @@
import android.app.PendingIntent;
import android.app.RemoteInput;
-import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Pair;
+
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.annotation.StringDef;
-import android.text.TextUtils;
-import android.util.Pair;
+import androidx.core.graphics.drawable.IconCompat;
import java.util.Arrays;
import java.util.List;
@@ -178,9 +179,8 @@
/**
* @return The icon held by this {@link android.app.slice.SliceItem#FORMAT_IMAGE} SliceItem
*/
- @RequiresApi(23)
- public Icon getIcon() {
- return (Icon) mObj;
+ public IconCompat getIcon() {
+ return (IconCompat) mObj;
}
/**
@@ -292,6 +292,8 @@
private void writeObj(Bundle dest, Object obj, String type) {
switch (type) {
case FORMAT_IMAGE:
+ dest.putBundle(OBJ, ((IconCompat) obj).toBundle());
+ break;
case FORMAT_REMOTE_INPUT:
dest.putParcelable(OBJ, (Parcelable) obj);
break;
@@ -317,6 +319,7 @@
private static Object readObj(String type, Bundle in) {
switch (type) {
case FORMAT_IMAGE:
+ return IconCompat.createFromBundle(in.getBundle(OBJ));
case FORMAT_REMOTE_INPUT:
return in.getParcelable(OBJ);
case FORMAT_SLICE:
diff --git a/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java b/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java
index 07bce69..1e2c8f1 100644
--- a/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java
+++ b/slices/core/src/main/java/androidx/slice/compat/SliceProviderCompat.java
@@ -31,6 +31,7 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
@@ -339,7 +340,11 @@
// Manager will kill this process shortly anyway.
return null;
} finally {
- provider.close();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ provider.close();
+ } else {
+ provider.release();
+ }
}
}
diff --git a/slices/core/src/main/java/androidx/slice/core/SliceAction.java b/slices/core/src/main/java/androidx/slice/core/SliceAction.java
new file mode 100644
index 0000000..c73c6b9
--- /dev/null
+++ b/slices/core/src/main/java/androidx/slice/core/SliceAction.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.slice.core;
+
+import android.app.PendingIntent;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.graphics.drawable.IconCompat;
+
+/**
+ * Interface for a slice action, supports tappable icons, custom toggle icons, and default toggles.
+ */
+public interface SliceAction {
+
+ /**
+ * @param description the content description for this action.
+ */
+ @Nullable
+ SliceAction setContentDescription(@NonNull CharSequence description);
+
+ /**
+ * @param isChecked whether the state of this action is checked or not; only used for toggle
+ * actions.
+ */
+ SliceAction setChecked(boolean isChecked);
+
+ /**
+ * Sets the priority of this action, with the lowest priority having the highest ranking.
+ */
+ SliceAction setPriority(@IntRange(from = 0) int priority);
+
+ /**
+ * @return the {@link PendingIntent} associated with this action.
+ */
+ @NonNull
+ PendingIntent getAction();
+
+ /**
+ * @return the {@link IconCompat} to display for this action. This can be null when the action
+ * represented is a default toggle.
+ */
+ @Nullable
+ IconCompat getIcon();
+
+ /**
+ * @return the title for this action.
+ */
+ @NonNull
+ CharSequence getTitle();
+
+ /**
+ * @return the content description to use for this action.
+ */
+ @Nullable
+ CharSequence getContentDescription();
+
+ /**
+ * @return the priority associated with this action, -1 if unset.
+ */
+ int getPriority();
+
+ /**
+ * @return whether this action represents a toggle (i.e. has a checked and unchecked state).
+ */
+ boolean isToggle();
+
+ /**
+ * @return whether the state of this action is checked or not; only used for toggle actions.
+ */
+ boolean isChecked();
+
+ /**
+ * @return the image mode to use for this action.
+ */
+ @SliceHints.ImageMode int getImageMode();
+
+ /**
+ * @return whether this action is a toggle using the standard switch control.
+ */
+ boolean isDefaultToggle();
+}
diff --git a/slices/core/src/main/java/androidx/slice/core/SliceActionImpl.java b/slices/core/src/main/java/androidx/slice/core/SliceActionImpl.java
new file mode 100644
index 0000000..b5ca913
--- /dev/null
+++ b/slices/core/src/main/java/androidx/slice/core/SliceActionImpl.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.slice.core;
+
+import static android.app.slice.Slice.HINT_LARGE;
+import static android.app.slice.Slice.HINT_NO_TINT;
+import static android.app.slice.Slice.HINT_SELECTED;
+import static android.app.slice.Slice.HINT_SHORTCUT;
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.Slice.SUBTYPE_CONTENT_DESCRIPTION;
+import static android.app.slice.Slice.SUBTYPE_PRIORITY;
+import static android.app.slice.Slice.SUBTYPE_TOGGLE;
+import static android.app.slice.SliceItem.FORMAT_ACTION;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
+import static android.app.slice.SliceItem.FORMAT_INT;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import static androidx.slice.core.SliceHints.ICON_IMAGE;
+import static androidx.slice.core.SliceHints.LARGE_IMAGE;
+import static androidx.slice.core.SliceHints.SMALL_IMAGE;
+import static androidx.slice.core.SliceHints.UNKNOWN_IMAGE;
+
+import android.app.PendingIntent;
+import android.graphics.drawable.Icon;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+
+/**
+ * Class representing an action, supports tappable icons, custom toggle icons, and default toggles.
+ * @hide
+ */
+@RestrictTo(LIBRARY_GROUP)
+public class SliceActionImpl implements SliceAction {
+
+ private PendingIntent mAction;
+ private IconCompat mIcon;
+ private int mImageMode = UNKNOWN_IMAGE;
+ private CharSequence mTitle;
+ private CharSequence mContentDescription;
+ private boolean mIsToggle;
+ private boolean mIsChecked;
+ private int mPriority = -1;
+ private SliceItem mSliceItem;
+
+ /**
+ * Construct a SliceAction representing a tappable icon.
+ *
+ * @param action the pending intent to invoke for this action.
+ * @param actionIcon the icon to display for this action.
+ * @param actionTitle the title for this action, also used for content description if one hasn't
+ * been set via {@link #setContentDescription(CharSequence)}.
+ */
+ public SliceActionImpl(@NonNull PendingIntent action, @NonNull IconCompat actionIcon,
+ @NonNull CharSequence actionTitle) {
+ this(action, actionIcon, ICON_IMAGE, actionTitle);
+ }
+
+ /**
+ * Construct a SliceAction representing a tappable icon. Use this method to specify the
+ * format of the image, {@link SliceHints#ICON_IMAGE} will be presented as a tintable icon.
+ * Note that there is no difference between {@link SliceHints#SMALL_IMAGE} and
+ * {@link SliceHints#LARGE_IMAGE} for actions; these will just be represented as an
+ * non-tintable image.
+ *
+ * @param action the pending intent to invoke for this action.
+ * @param actionIcon the icon to display for this action.
+ * @param imageMode the mode this icon should be displayed in.
+ * @param actionTitle the title for this action, also used for content description if one hasn't
+ * been set via {@link #setContentDescription(CharSequence)}.
+ *
+ * @see SliceHints#ICON_IMAGE
+ * @see SliceHints#SMALL_IMAGE
+ * @see SliceHints#LARGE_IMAGE
+ */
+ public SliceActionImpl(@NonNull PendingIntent action, @NonNull IconCompat actionIcon,
+ @SliceHints.ImageMode int imageMode, @NonNull CharSequence actionTitle) {
+ mAction = action;
+ mIcon = actionIcon;
+ mTitle = actionTitle;
+ mImageMode = imageMode;
+ }
+
+ /**
+ * Construct a SliceAction representing a custom toggle icon.
+ *
+ * @param action the pending intent to invoke for this toggle.
+ * @param actionIcon the icon to display for this toggle, should have a checked and unchecked
+ * state.
+ * @param actionTitle the title for this toggle, also used for content description if one hasn't
+ * been set via {@link #setContentDescription(CharSequence)}.
+ * @param isChecked the state of the toggle.
+ */
+ public SliceActionImpl(@NonNull PendingIntent action, @NonNull IconCompat actionIcon,
+ @NonNull CharSequence actionTitle, boolean isChecked) {
+ this(action, actionIcon, ICON_IMAGE, actionTitle);
+ mIsChecked = isChecked;
+ mIsToggle = true;
+ }
+
+ /**
+ * Construct a SliceAction representing a default toggle.
+ *
+ * @param action the pending intent to invoke for this toggle.
+ * @param actionTitle the title for this toggle, also used for content description if one hasn't
+ * been set via {@link #setContentDescription(CharSequence)}.
+ * @param isChecked the state of the toggle.
+ */
+ public SliceActionImpl(@NonNull PendingIntent action, @NonNull CharSequence actionTitle,
+ boolean isChecked) {
+ mAction = action;
+ mTitle = actionTitle;
+ mIsToggle = true;
+ mIsChecked = isChecked;
+ }
+
+ /**
+ * Constructs a SliceAction based off of a {@link SliceItem}. Expects a specific format
+ * for the item.
+ *
+ * @param slice the slice item to construct the action out of.
+ *
+ * @hide
+ */
+ @RestrictTo(LIBRARY)
+ public SliceActionImpl(SliceItem slice) {
+ mSliceItem = slice;
+ if (slice.hasHint(HINT_SHORTCUT) && FORMAT_SLICE.equals(slice.getFormat())) {
+ SliceItem actionItem = SliceQuery.find(slice, FORMAT_ACTION);
+ if (actionItem == null) {
+ // Can't have action slice without action
+ return;
+ }
+ mAction = actionItem.getAction();
+ SliceItem iconItem = SliceQuery.find(actionItem.getSlice(), FORMAT_IMAGE);
+ if (iconItem != null) {
+ mIcon = iconItem.getIcon();
+ mImageMode = iconItem.hasHint(HINT_NO_TINT)
+ ? iconItem.hasHint(HINT_LARGE) ? LARGE_IMAGE : SMALL_IMAGE
+ : ICON_IMAGE;
+ }
+ SliceItem titleItem = SliceQuery.find(actionItem.getSlice(), FORMAT_TEXT, HINT_TITLE,
+ null /* nonHints */);
+ if (titleItem != null) {
+ mTitle = titleItem.getText();
+ }
+ SliceItem cdItem = SliceQuery.findSubtype(actionItem.getSlice(), FORMAT_TEXT,
+ SUBTYPE_CONTENT_DESCRIPTION);
+ if (cdItem != null) {
+ mContentDescription = cdItem.getText();
+ }
+ mIsToggle = SUBTYPE_TOGGLE.equals(actionItem.getSubType());
+ if (mIsToggle) {
+ mIsChecked = actionItem.hasHint(HINT_SELECTED);
+ }
+ SliceItem priority = SliceQuery.findSubtype(actionItem.getSlice(), FORMAT_INT,
+ SUBTYPE_PRIORITY);
+ mPriority = priority != null ? priority.getInt() : -1;
+ } else if (FORMAT_ACTION.equals(slice.getFormat())) {
+ mAction = slice.getAction();
+ }
+ }
+
+ /**
+ * @param description the content description for this action.
+ */
+ @Nullable
+ @Override
+ public SliceActionImpl setContentDescription(@NonNull CharSequence description) {
+ mContentDescription = description;
+ return this;
+ }
+
+ /**
+ * @param isChecked whether the state of this action is checked or not; only used for toggle
+ * actions.
+ */
+ @Override
+ public SliceActionImpl setChecked(boolean isChecked) {
+ mIsChecked = isChecked;
+ return this;
+ }
+
+ /**
+ * Sets the priority of this action, with the lowest priority having the highest ranking.
+ */
+ @Override
+ public SliceActionImpl setPriority(@IntRange(from = 0) int priority) {
+ mPriority = priority;
+ return this;
+ }
+
+ /**
+ * @return the {@link PendingIntent} associated with this action.
+ */
+ @NonNull
+ @Override
+ public PendingIntent getAction() {
+ return mAction;
+ }
+
+ /**
+ * @return the {@link Icon} to display for this action. This can be null when the action
+ * represented is a default toggle.
+ */
+ @Nullable
+ @Override
+ public IconCompat getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * @return the title for this action.
+ */
+ @NonNull
+ @Override
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * @return the content description to use for this action.
+ */
+ @Nullable
+ @Override
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ /**
+ * @return the priority associated with this action, -1 if unset.
+ */
+ @Override
+ public int getPriority() {
+ return mPriority;
+ }
+
+ /**
+ * @return whether this action represents a toggle (i.e. has a checked and unchecked state).
+ */
+ @Override
+ public boolean isToggle() {
+ return mIsToggle;
+ }
+
+ /**
+ * @return whether the state of this action is checked or not; only used for toggle actions.
+ */
+ @Override
+ public boolean isChecked() {
+ return mIsChecked;
+ }
+
+ /**
+ * @return the image mode to use for this action.
+ */
+ @Override
+ public @SliceHints.ImageMode int getImageMode() {
+ return mImageMode;
+ }
+
+ /**
+ * @return whether this action is a toggle using the standard switch control.
+ */
+ @Override
+ public boolean isDefaultToggle() {
+ return mIsToggle && mIcon == null;
+ }
+
+ /**
+ * @return the SliceItem used to construct this action, this is only populated if the action was
+ * constructed with {@link #SliceActionImpl(SliceItem)}.
+ */
+ @Nullable
+ public SliceItem getSliceItem() {
+ return mSliceItem;
+ }
+
+ /**
+ * @param builder this should be a new builder that has any additional hints the action might
+ * need.
+ * @return the slice representation of this action.
+ */
+ @NonNull
+ public Slice buildSlice(@NonNull Slice.Builder builder) {
+ Slice.Builder sb = new Slice.Builder(builder);
+ if (mIcon != null) {
+ @Slice.SliceHint String[] hints = mImageMode == ICON_IMAGE
+ ? new String[] {}
+ : new String[] {HINT_NO_TINT};
+ sb.addIcon(mIcon, null, hints);
+ }
+ if (mTitle != null) {
+ sb.addText(mTitle, null, HINT_TITLE);
+ }
+ if (mContentDescription != null) {
+ sb.addText(mContentDescription, SUBTYPE_CONTENT_DESCRIPTION);
+ }
+ if (mIsToggle && mIsChecked) {
+ sb.addHints(HINT_SELECTED);
+ }
+ if (mPriority != -1) {
+ sb.addInt(mPriority, SUBTYPE_PRIORITY);
+ }
+ String subtype = mIsToggle ? SUBTYPE_TOGGLE : null;
+ builder.addHints(HINT_SHORTCUT);
+ builder.addAction(mAction, sb.build(), subtype);
+ return builder.build();
+ }
+}
diff --git a/slices/core/src/main/java/androidx/slice/core/SliceHints.java b/slices/core/src/main/java/androidx/slice/core/SliceHints.java
index a1ffb42..acbdfc6 100644
--- a/slices/core/src/main/java/androidx/slice/core/SliceHints.java
+++ b/slices/core/src/main/java/androidx/slice/core/SliceHints.java
@@ -18,6 +18,7 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import androidx.annotation.IntDef;
import androidx.annotation.RestrictTo;
/**
@@ -61,4 +62,46 @@
*/
public static final String HINT_KEY_WORDS = "key_words";
+ /**
+ * Hint indicating an item representing a time-to-live for the content.
+ */
+ public static final String HINT_TTL = "ttl";
+
+ /**
+ * Hint indicating an item representing when the content was created or last updated.
+ */
+ public static final String HINT_LAST_UPDATED = "last_updated";
+
+ /**
+ * Subtype to tag an item as representing a time in milliseconds since midnight,
+ * January 1, 1970 UTC.
+ */
+ public static final String SUBTYPE_MILLIS = "millis";
+
+ @IntDef({
+ LARGE_IMAGE, SMALL_IMAGE, ICON_IMAGE, UNKNOWN_IMAGE
+ })
+ public @interface ImageMode{}
+
+ /**
+ * Indicates that an image should be presented as an icon and it can be tinted.
+ */
+ public static final int ICON_IMAGE = 0;
+ /**
+ * Indicates that an image should be presented in a smaller size and it shouldn't be tinted.
+ */
+ public static final int SMALL_IMAGE = 1;
+ /**
+ * Indicates that an image presented in a larger size and it shouldn't be tinted.
+ */
+ public static final int LARGE_IMAGE = 2;
+ /**
+ * Indicates that an image mode is unknown.
+ */
+ public static final int UNKNOWN_IMAGE = 3;
+
+ /**
+ * Constant representing infinity.
+ */
+ public static final long INFINITY = -1;
}
diff --git a/slices/view/api/current.txt b/slices/view/api/current.txt
index c176d3e..0936bbf 100644
--- a/slices/view/api/current.txt
+++ b/slices/view/api/current.txt
@@ -16,15 +16,27 @@
method public abstract void onSliceUpdated(androidx.slice.Slice);
}
+ public class SliceMetadata {
+ method public static androidx.slice.SliceMetadata from(android.content.Context, androidx.slice.Slice);
+ method public long getExpiry();
+ method public long getLastUpdatedTime();
+ method public int getLoadingState();
+ method public java.util.List<androidx.slice.SliceItem> getSliceActions();
+ method public java.util.List<java.lang.String> getSliceKeywords();
+ field public static final int LOADED_ALL = 2; // 0x2
+ field public static final int LOADED_NONE = 0; // 0x0
+ field public static final int LOADED_PARTIAL = 1; // 0x1
+ }
+
public class SliceUtils {
- method public static int getLoadingState(androidx.slice.Slice);
- method public static java.util.List<androidx.slice.SliceItem> getSliceActions(androidx.slice.Slice);
- method public static java.util.List<java.lang.String> getSliceKeywords(androidx.slice.Slice);
+ method public static deprecated int getLoadingState(androidx.slice.Slice);
+ method public static deprecated java.util.List<androidx.slice.SliceItem> getSliceActions(androidx.slice.Slice);
+ method public static deprecated java.util.List<java.lang.String> getSliceKeywords(androidx.slice.Slice);
method public static androidx.slice.Slice parseSlice(java.io.InputStream, java.lang.String) throws java.io.IOException;
method public static void serializeSlice(androidx.slice.Slice, android.content.Context, java.io.OutputStream, java.lang.String, androidx.slice.SliceUtils.SerializeOptions) throws java.io.IOException;
- field public static final int LOADING_ALL = 0; // 0x0
- field public static final int LOADING_COMPLETE = 2; // 0x2
- field public static final int LOADING_PARTIAL = 1; // 0x1
+ field public static final deprecated int LOADING_ALL = 0; // 0x0
+ field public static final deprecated int LOADING_COMPLETE = 2; // 0x2
+ field public static final deprecated int LOADING_PARTIAL = 1; // 0x1
}
public static class SliceUtils.SerializeOptions {
diff --git a/slices/view/src/androidTest/java/androidx/slice/SliceMetadataTest.java b/slices/view/src/androidTest/java/androidx/slice/SliceMetadataTest.java
new file mode 100644
index 0000000..c416b30
--- /dev/null
+++ b/slices/view/src/androidTest/java/androidx/slice/SliceMetadataTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.slice;
+
+import static android.app.slice.Slice.HINT_PARTIAL;
+import static android.app.slice.Slice.HINT_TITLE;
+
+import static androidx.slice.SliceMetadata.LOADED_ALL;
+import static androidx.slice.SliceMetadata.LOADED_NONE;
+import static androidx.slice.SliceMetadata.LOADED_PARTIAL;
+import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.net.Uri;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import androidx.slice.core.SliceHints;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for {@link SliceMetadata}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SliceMetadataTest {
+
+ private final Context mContext = InstrumentationRegistry.getContext();
+
+ @Test
+ public void testKeywords() {
+ Uri uri = Uri.parse("content://pkg/slice");
+ Slice keywordSlice = new Slice.Builder(uri)
+ .addHints(HINT_KEY_WORDS)
+ .addText("keyword1", null)
+ .addText("keyword2", null)
+ .addText("keyword3", null).build();
+ Slice slice = new Slice.Builder(uri)
+ .addText("Some text", null, HINT_TITLE)
+ .addText("Some other text", null)
+ .addSubSlice(keywordSlice)
+ .build();
+
+ SliceMetadata sliceInfo1 = SliceMetadata.from(mContext, slice);
+ List<String> sliceKeywords = sliceInfo1.getSliceKeywords();
+ String[] expectedList = new String[] {"keyword1", "keyword2", "keyword3"};
+ assertArrayEquals(expectedList, sliceKeywords.toArray());
+
+ // Make sure it doesn't find keywords that aren't there
+ Slice slice2 = new Slice.Builder(uri)
+ .addText("Some text", null, HINT_TITLE)
+ .addText("Some other text", null).build();
+
+ SliceMetadata sliceInfo2 = SliceMetadata.from(mContext, slice2);
+ List<String> slice2Keywords = sliceInfo2.getSliceKeywords();
+ assertNull(slice2Keywords);
+
+ // Make sure empty list if specified to have no keywords
+ Slice noKeywordSlice = new Slice.Builder(uri).addHints(HINT_KEY_WORDS).build();
+ Slice slice3 = new Slice.Builder(uri)
+ .addText("Some text", null, HINT_TITLE)
+ .addSubSlice(noKeywordSlice)
+ .build();
+
+ SliceMetadata sliceMetadata3 = SliceMetadata.from(mContext, slice3);
+ List<String> slice3Keywords = sliceMetadata3.getSliceKeywords();
+ assertTrue(slice3Keywords.isEmpty());
+ }
+
+ @Test
+ public void testGetLoadingState() {
+ Uri uri = Uri.parse("content://pkg/slice");
+ Slice s1 = new Slice.Builder(uri).build();
+ SliceMetadata sliceInfo1 = SliceMetadata.from(mContext, s1);
+ int actualState1 = sliceInfo1.getLoadingState();
+ assertEquals(LOADED_NONE, actualState1);
+
+ Slice s2 = new Slice.Builder(uri).addText(null, null, HINT_PARTIAL).build();
+ SliceMetadata sliceInfo2 = SliceMetadata.from(mContext, s2);
+ int actualState2 = sliceInfo2.getLoadingState();
+ assertEquals(LOADED_PARTIAL, actualState2);
+
+ Slice s3 = new Slice.Builder(uri).addText("Text", null).build();
+ SliceMetadata sliceInfo3 = SliceMetadata.from(mContext, s3);
+ int actualState3 = sliceInfo3.getLoadingState();
+ assertEquals(LOADED_ALL, actualState3);
+ }
+
+ @Test
+ public void testGetExpiry() {
+ Uri uri = Uri.parse("content://pkg/slice");
+ long timestamp = System.currentTimeMillis();
+ long ttl = TimeUnit.DAYS.toMillis(1);
+ Slice ttlSlice = new Slice.Builder(uri)
+ .addText("Some text", null)
+ .addTimestamp(timestamp, null)
+ .addTimestamp(timestamp, null, SliceHints.HINT_LAST_UPDATED)
+ .addTimestamp(ttl, null, SliceHints.HINT_TTL)
+ .build();
+
+ SliceMetadata si1 = SliceMetadata.from(mContext, ttlSlice);
+ long retrievedTtl = si1.getExpiry();
+ assertEquals(ttl, retrievedTtl);
+
+ Slice noTtlSlice = new Slice.Builder(uri)
+ .addText("Some text", null)
+ .addTimestamp(timestamp, null).build();
+ SliceMetadata si2 = SliceMetadata.from(mContext, noTtlSlice);
+ long retrievedTtl2 = si2.getExpiry();
+ assertEquals(0, retrievedTtl2);
+ }
+
+ @Test
+ public void testGetLastUpdated() {
+ Uri uri = Uri.parse("content://pkg/slice");
+ long timestamp = System.currentTimeMillis();
+ long ttl = TimeUnit.DAYS.toMillis(1);
+ Slice ttlSlice = new Slice.Builder(uri)
+ .addText("Some text", null)
+ .addTimestamp(timestamp - 20, null)
+ .addTimestamp(timestamp, null, SliceHints.HINT_LAST_UPDATED)
+ .addTimestamp(ttl, null, SliceHints.HINT_TTL)
+ .build();
+
+ SliceMetadata si1 = SliceMetadata.from(mContext, ttlSlice);
+ long retrievedLastUpdated = si1.getLastUpdatedTime();
+ assertEquals(timestamp, retrievedLastUpdated);
+
+ Slice noTtlSlice = new Slice.Builder(uri)
+ .addText("Some text", null)
+ .addTimestamp(timestamp, null).build();
+
+ SliceMetadata si2 = SliceMetadata.from(mContext, noTtlSlice);
+ long retrievedLastUpdated2 = si2.getLastUpdatedTime();
+ assertEquals(0, retrievedLastUpdated2);
+ }
+}
diff --git a/slices/view/src/androidTest/java/androidx/slice/SliceXmlTest.java b/slices/view/src/androidTest/java/androidx/slice/SliceXmlTest.java
index ec99872..298d498 100644
--- a/slices/view/src/androidTest/java/androidx/slice/SliceXmlTest.java
+++ b/slices/view/src/androidTest/java/androidx/slice/SliceXmlTest.java
@@ -17,8 +17,6 @@
package androidx.slice;
-import static android.app.slice.Slice.HINT_PARTIAL;
-import static android.app.slice.Slice.HINT_TITLE;
import static android.app.slice.SliceItem.FORMAT_ACTION;
import static android.app.slice.SliceItem.FORMAT_SLICE;
import static android.app.slice.SliceItem.FORMAT_TEXT;
@@ -26,30 +24,22 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertNull;
-
-import static androidx.slice.SliceUtils.LOADING_ALL;
-import static androidx.slice.SliceUtils.LOADING_COMPLETE;
-import static androidx.slice.SliceUtils.LOADING_PARTIAL;
-import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
-
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import androidx.core.graphics.drawable.IconCompat;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.util.List;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -126,7 +116,7 @@
.addSubSlice(new Slice.Builder(Uri.parse("content://pkg/slice/sub"))
.addTimestamp(System.currentTimeMillis(), null, "Hint")
.build())
- .addIcon(Icon.createWithBitmap(b), null)
+ .addIcon(IconCompat.createWithBitmap(b), null)
.addText("Some text", null)
.addAction(null, new Slice.Builder(Uri.parse("content://pkg/slice/sub"))
.addText("Action text", null)
@@ -148,57 +138,6 @@
assertEquivalent(before, after);
}
- @Test
- public void testKeywords() {
- Uri uri = Uri.parse("content://pkg/slice");
- Slice keywordSlice = new Slice.Builder(uri)
- .addHints(HINT_KEY_WORDS)
- .addText("keyword1", null)
- .addText("keyword2", null)
- .addText("keyword3", null).build();
- Slice slice = new Slice.Builder(uri)
- .addText("Some text", null, HINT_TITLE)
- .addText("Some other text", null)
- .addSubSlice(keywordSlice)
- .build();
-
- List<String> sliceKeywords = SliceUtils.getSliceKeywords(slice);
- String[] expectedList = new String[] {"keyword1", "keyword2", "keyword3"};
- assertArrayEquals(expectedList, sliceKeywords.toArray());
-
- // Make sure it doesn't find keywords that aren't there
- Slice slice2 = new Slice.Builder(uri)
- .addText("Some text", null, HINT_TITLE)
- .addText("Some other text", null).build();
- List<String> slice2Keywords = SliceUtils.getSliceKeywords(slice2);
- assertNull(slice2Keywords);
-
- // Make sure empty list if specified to have no keywords
- Slice noKeywordSlice = new Slice.Builder(uri).addHints(HINT_KEY_WORDS).build();
- Slice slice3 = new Slice.Builder(uri)
- .addText("Some text", null, HINT_TITLE)
- .addSubSlice(noKeywordSlice)
- .build();
- List<String> slice3Keywords = SliceUtils.getSliceKeywords(slice3);
- assertTrue(slice3Keywords.isEmpty());
- }
-
- @Test
- public void testGetLoadingState() {
- Uri uri = Uri.parse("content://pkg/slice");
- Slice s1 = new Slice.Builder(uri).build();
- int actualState1 = SliceUtils.getLoadingState(s1);
- assertEquals(LOADING_ALL, actualState1);
-
- Slice s2 = new Slice.Builder(uri).addText(null, null, HINT_PARTIAL).build();
- int actualState2 = SliceUtils.getLoadingState(s2);
- assertEquals(LOADING_PARTIAL, actualState2);
-
- Slice s3 = new Slice.Builder(uri).addText("Text", null).build();
- int actualState3 = SliceUtils.getLoadingState(s3);
- assertEquals(LOADING_COMPLETE, actualState3);
- }
-
private void assertEquivalent(Slice desired, Slice actual) {
assertEquals(desired.getUri(), actual.getUri());
assertEquals(desired.getHints(), actual.getHints());
diff --git a/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java b/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
index 2ea8071..cf524fa 100644
--- a/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
+++ b/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
@@ -19,6 +19,7 @@
import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.INFINITY;
import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
@@ -26,7 +27,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.provider.Settings;
@@ -34,6 +34,7 @@
import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.GridRowBuilder;
import androidx.slice.builders.ListBuilder;
@@ -42,6 +43,7 @@
import androidx.slice.view.test.R;
import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
/**
* Examples of using slice template builders.
@@ -54,9 +56,9 @@
"com.example.androidx.slice.action.TOAST";
public static final String EXTRA_TOAST_MESSAGE = "com.example.androidx.extra.TOAST_MESSAGE";
- public static final String[] URI_PATHS = {"message", "wifi", "wifi2", "note", "ride", "toggle",
- "toggle2", "contact", "gallery", "subscription", "subscription2", "weather",
- "reservation"};
+ public static final String[] URI_PATHS = {"message", "wifi", "wifi2", "note", "ride",
+ "ride-ttl", "toggle", "toggle2", "contact", "gallery", "subscription", "subscription2",
+ "weather", "reservation"};
private final Context mContext;
@@ -91,7 +93,9 @@
case "/note":
return createNoteSlice(sliceUri);
case "/ride":
- return createRideSlice(sliceUri);
+ return createRideSlice(sliceUri, false /* showUpdated */);
+ case "/ride-ttl":
+ return createRideSlice(sliceUri, true /* showUpdated */);
case "/toggle":
return createCustomToggleSlice(sliceUri);
case "/toggle2":
@@ -114,33 +118,34 @@
private Slice createWeather(Uri sliceUri) {
SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST,
- "open weather app"), Icon.createWithResource(getContext(), R.drawable.weather_1),
+ "open weather app"),
+ IconCompat.createWithResource(getContext(), R.drawable.weather_1),
"Weather is happening!");
- ListBuilder b = new ListBuilder(getContext(), sliceUri);
+ ListBuilder b = new ListBuilder(getContext(), sliceUri, -TimeUnit.HOURS.toMillis(8));
GridRowBuilder gb = new GridRowBuilder(b);
gb.setPrimaryAction(primaryAction);
gb.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
- SMALL_IMAGE)
- .addText("MON")
- .addTitleText("69\u00B0"))
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.weather_1),
+ SMALL_IMAGE)
+ .addText("MON")
+ .addTitleText("69\u00B0"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_2),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.weather_2),
SMALL_IMAGE)
.addText("TUE")
.addTitleText("71\u00B0"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_3),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.weather_3),
SMALL_IMAGE)
.addText("WED")
.addTitleText("76\u00B0"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_4),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.weather_4),
SMALL_IMAGE)
.addText("THU")
.addTitleText("72\u00B0"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.weather_1),
SMALL_IMAGE)
.addText("FRI")
.addTitleText("68\u00B0"));
@@ -148,41 +153,41 @@
}
private Slice createGallery(Uri sliceUri) {
- ListBuilder b = new ListBuilder(getContext(), sliceUri);
+ ListBuilder b = new ListBuilder(getContext(), sliceUri, INFINITY);
GridRowBuilder gb = new GridRowBuilder(b);
PendingIntent pi = getBroadcastIntent(ACTION_TOAST, "see more of your gallery");
gb.addSeeMoreAction(pi);
gb.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_1),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.slices_1),
LARGE_IMAGE))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_2),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.slices_2),
LARGE_IMAGE))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_3),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.slices_3),
LARGE_IMAGE))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_4),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.slices_4),
LARGE_IMAGE))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_2),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.slices_2),
LARGE_IMAGE))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_3),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.slices_3),
LARGE_IMAGE))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.slices_4),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.slices_4),
LARGE_IMAGE));
return b.addGridRow(gb).build();
}
private Slice createSubSlice(Uri sliceUri, boolean customSeeMore) {
- ListBuilder b = new ListBuilder(getContext(), sliceUri);
+ ListBuilder b = new ListBuilder(getContext(), sliceUri, INFINITY);
GridRowBuilder gb = new GridRowBuilder(b);
GridRowBuilder.CellBuilder cb = new GridRowBuilder.CellBuilder(gb);
PendingIntent pi = getBroadcastIntent(ACTION_TOAST, "See cats you follow");
if (customSeeMore) {
- cb.addImage(Icon.createWithResource(getContext(), R.drawable.ic_right_caret),
+ cb.addImage(IconCompat.createWithResource(getContext(), R.drawable.ic_right_caret),
ICON_IMAGE);
cb.setContentIntent(pi);
cb.addText("All cats");
@@ -191,37 +196,37 @@
gb.addSeeMoreAction(pi);
}
gb.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_1),
- SMALL_IMAGE)
- .addTitleText("Oreo"))
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_1),
+ SMALL_IMAGE)
+ .addTitleText("Oreo"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_2),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_2),
SMALL_IMAGE)
.addTitleText("Silver"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_3),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_3),
SMALL_IMAGE)
.addTitleText("Drake"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_5),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_5),
SMALL_IMAGE)
.addTitleText("Olive"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_4),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_4),
SMALL_IMAGE)
.addTitleText("Lady Marmalade"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.cat_6),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.cat_6),
SMALL_IMAGE)
.addTitleText("Grapefruit"));
return b.addGridRow(gb).build();
}
private Slice createContact(Uri sliceUri) {
- ListBuilder b = new ListBuilder(getContext(), sliceUri);
+ ListBuilder b = new ListBuilder(getContext(), sliceUri, INFINITY);
ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(b);
SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST,
- "See contact info"), Icon.createWithResource(getContext(),
+ "See contact info"), IconCompat.createWithResource(getContext(),
R.drawable.mady), SMALL_IMAGE, "Mady");
GridRowBuilder gb = new GridRowBuilder(b);
return b.setColor(0xff3949ab)
@@ -231,25 +236,29 @@
.addEndItem(primaryAction))
.addGridRow(gb
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_call),
- ICON_IMAGE)
- .addText("Call")
- .setContentIntent(getBroadcastIntent(ACTION_TOAST, "call")))
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_call),
+ ICON_IMAGE)
+ .addText("Call")
+ .setContentIntent(getBroadcastIntent(ACTION_TOAST, "call")))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_text),
- ICON_IMAGE)
- .addText("Text")
- .setContentIntent(getBroadcastIntent(ACTION_TOAST, "text")))
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_text),
+ ICON_IMAGE)
+ .addText("Text")
+ .setContentIntent(getBroadcastIntent(ACTION_TOAST, "text")))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_video),
- ICON_IMAGE)
- .setContentIntent(getBroadcastIntent(ACTION_TOAST, "video"))
- .addText("Video"))
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_video),
+ ICON_IMAGE)
+ .setContentIntent(getBroadcastIntent(ACTION_TOAST, "video"))
+ .addText("Video"))
.addCell(new GridRowBuilder.CellBuilder(gb)
- .addImage(Icon.createWithResource(getContext(), R.drawable.ic_email),
- ICON_IMAGE)
- .addText("Email")
- .setContentIntent(getBroadcastIntent(ACTION_TOAST, "email"))))
+ .addImage(IconCompat.createWithResource(getContext(),
+ R.drawable.ic_email),
+ ICON_IMAGE)
+ .addText("Email")
+ .setContentIntent(getBroadcastIntent(ACTION_TOAST, "email"))))
.build();
}
@@ -260,7 +269,7 @@
.add(new MessagingSliceBuilder.MessageBuilder(mb)
.addText("yo home \uD83C\uDF55, I emailed you the info")
.addTimestamp(System.currentTimeMillis() - 20 * DateUtils.MINUTE_IN_MILLIS)
- .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+ .addSource(IconCompat.createWithResource(getContext(), R.drawable.mady)))
.add(new MessagingSliceBuilder.MessageBuilder(mb)
.addText("just bought my tickets")
.addTimestamp(System.currentTimeMillis() - 10 * DateUtils.MINUTE_IN_MILLIS))
@@ -268,31 +277,31 @@
.addText("yay! can't wait for getContext() weekend!\n"
+ "\uD83D\uDE00")
.addTimestamp(System.currentTimeMillis() - 5 * DateUtils.MINUTE_IN_MILLIS)
- .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+ .addSource(IconCompat.createWithResource(getContext(), R.drawable.mady)))
.build();
}
private Slice createNoteSlice(Uri sliceUri) {
// TODO: Remote input.
- ListBuilder lb = new ListBuilder(getContext(), sliceUri);
+ ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
return lb.setColor(0xfff4b400)
.addRow(new ListBuilder.RowBuilder(lb)
- .setTitle("Create new note")
- .setSubtitle("with this note taking app")
- .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "create note"),
- Icon.createWithResource(getContext(), R.drawable.ic_create),
- "Create note"))
- .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "voice note"),
- Icon.createWithResource(getContext(), R.drawable.ic_voice),
- "Voice note"))
- .addEndItem(new SliceAction(getIntent("android.media.action.IMAGE_CAPTURE"),
- Icon.createWithResource(getContext(), R.drawable.ic_camera),
- "Photo note")))
+ .setTitle("Create new note")
+ .setSubtitle("with this note taking app")
+ .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "create note"),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_create),
+ "Create note"))
+ .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "voice note"),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_voice),
+ "Voice note"))
+ .addEndItem(new SliceAction(getIntent("android.media.action.IMAGE_CAPTURE"),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_camera),
+ "Photo note")))
.build();
}
- private Slice createRideSlice(Uri sliceUri) {
+ private Slice createRideSlice(Uri sliceUri, boolean showUpdated) {
final ForegroundColorSpan colorSpan = new ForegroundColorSpan(0xff0F9D58);
SpannableString headerSubtitle = new SpannableString("Ride in 4 min");
headerSubtitle.setSpan(colorSpan, 8, headerSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -301,8 +310,11 @@
SpannableString workSubtitle = new SpannableString("44 miles | 1 hour 45 min | $31.41");
workSubtitle.setSpan(colorSpan, 27, workSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST, "get ride"),
- Icon.createWithResource(getContext(), R.drawable.ic_car), "Get Ride");
- ListBuilder lb = new ListBuilder(getContext(), sliceUri);
+ IconCompat.createWithResource(getContext(), R.drawable.ic_car), "Get Ride");
+ Long ttl = showUpdated
+ ? -TimeUnit.MINUTES.toMillis(2) // negative for testing
+ : INFINITY;
+ ListBuilder lb = new ListBuilder(getContext(), sliceUri, ttl);
return lb.setColor(0xff0F9D58)
.setHeader(new ListBuilder.HeaderBuilder(lb)
.setTitle("Get ride")
@@ -313,42 +325,43 @@
.setTitle("Work")
.setSubtitle(workSubtitle)
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "work"),
- Icon.createWithResource(getContext(), R.drawable.ic_work),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_work),
"Get ride work")))
.addRow(new ListBuilder.RowBuilder(lb)
.setTitle("Home")
.setSubtitle(homeSubtitle)
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "home"),
- Icon.createWithResource(getContext(), R.drawable.ic_home),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_home),
"Get ride home")))
.build();
}
private Slice createCustomToggleSlice(Uri sliceUri) {
- ListBuilder b = new ListBuilder(getContext(), sliceUri);
+ ListBuilder b = new ListBuilder(getContext(), sliceUri, -TimeUnit.HOURS.toMillis(1));
return b.setColor(0xffff4081)
.addRow(new ListBuilder.RowBuilder(b)
- .setTitle("Custom toggle")
- .setSubtitle("It can support two states")
- .addEndItem(new SliceAction(getBroadcastIntent(ACTION_TOAST, "star toggled"),
- Icon.createWithResource(getContext(), R.drawable.toggle_star),
- "Toggle star", true /* isChecked */)))
+ .setTitle("Custom toggle")
+ .addEndItem(
+ new SliceAction(getBroadcastIntent(ACTION_TOAST, "star toggled"),
+ IconCompat.createWithResource(getContext(),
+ R.drawable.toggle_star),
+ "Toggle star", true /* isChecked */)))
.build();
}
private Slice createTwoCustomToggleSlices(Uri sliceUri) {
- ListBuilder lb = new ListBuilder(getContext(), sliceUri);
+ ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
return lb.setColor(0xffff4081)
.addRow(new ListBuilder.RowBuilder(lb)
.setTitle("2 toggles")
.setSubtitle("each supports two states")
.addEndItem(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "first star toggled"),
- Icon.createWithResource(getContext(), R.drawable.toggle_star),
+ IconCompat.createWithResource(getContext(), R.drawable.toggle_star),
"Toggle star", true /* isChecked */))
.addEndItem(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "second star toggled"),
- Icon.createWithResource(getContext(), R.drawable.toggle_star),
+ IconCompat.createWithResource(getContext(), R.drawable.toggle_star),
"Toggle star", false /* isChecked */)))
.build();
}
@@ -375,35 +388,36 @@
break;
}
boolean finalWifiEnabled = wifiEnabled;
- ListBuilder lb = new ListBuilder(getContext(), sliceUri);
+ ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
SliceAction primaryAction = new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS),
- Icon.createWithResource(getContext(), R.drawable.ic_wifi), "Wi-fi Settings");
+ IconCompat.createWithResource(getContext(), R.drawable.ic_wifi), "Wi-fi Settings");
lb.setColor(0xff4285f4);
lb.addRow(new ListBuilder.RowBuilder(lb)
.setTitle("Wi-fi")
- .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_wifi), ICON_IMAGE)
+ .setTitleItem(IconCompat.createWithResource(getContext(), R.drawable.ic_wifi),
+ ICON_IMAGE)
.setSubtitle(state)
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED, null),
"Toggle wifi", finalWifiEnabled))
.setPrimaryAction(primaryAction));
// Add keywords
- String[] keywords = new String[] {"internet", "wifi", "data", "network"};
+ String[] keywords = new String[]{"internet", "wifi", "data", "network"};
lb.setKeywords(Arrays.asList(keywords));
// Add fake wifi networks
- int[] wifiIcons = new int[] {R.drawable.ic_wifi_full, R.drawable.ic_wifi_low,
+ int[] wifiIcons = new int[]{R.drawable.ic_wifi_full, R.drawable.ic_wifi_low,
R.drawable.ic_wifi_fair};
for (int i = 0; i < 10; i++) {
final int iconId = wifiIcons[i % wifiIcons.length];
- Icon icon = Icon.createWithResource(getContext(), iconId);
+ IconCompat icon = IconCompat.createWithResource(getContext(), iconId);
final String networkName = "Network" + i;
ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(lb)
.setTitleItem(icon, ICON_IMAGE)
.setTitle("Network" + networkName);
boolean locked = i % 3 == 0;
if (locked) {
- rb.addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_lock));
+ rb.addEndItem(IconCompat.createWithResource(getContext(), R.drawable.ic_lock));
}
String message = locked ? "Open wifi password dialog" : "Connect to " + networkName;
rb.setPrimaryAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, message), icon,
@@ -413,7 +427,8 @@
if (customSeeMore) {
lb.addSeeMoreRow(new ListBuilder.RowBuilder(lb)
.setTitle("See all available networks")
- .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_right_caret))
+ .addEndItem(
+ IconCompat.createWithResource(getContext(), R.drawable.ic_right_caret))
.setPrimaryAction(primaryAction));
} else {
lb.addSeeMoreAction(primaryAction.getAction());
@@ -422,29 +437,29 @@
}
private Slice createReservationSlice(Uri sliceUri) {
- ListBuilder lb = new ListBuilder(getContext(), sliceUri);
+ ListBuilder lb = new ListBuilder(getContext(), sliceUri, INFINITY);
GridRowBuilder gb1 = new GridRowBuilder(lb);
gb1.addCell(new GridRowBuilder.CellBuilder(gb1)
- .addImage(Icon.createWithResource(getContext(), R.drawable.reservation),
+ .addImage(IconCompat.createWithResource(getContext(), R.drawable.reservation),
LARGE_IMAGE)
.setContentDescription("Image of your reservation in Seattle"));
GridRowBuilder gb2 = new GridRowBuilder(lb);
gb2.addCell(new GridRowBuilder.CellBuilder(gb2)
- .addTitleText("Check In")
- .addText("12:00 PM, Feb 1"))
+ .addTitleText("Check In")
+ .addText("12:00 PM, Feb 1"))
.addCell(new GridRowBuilder.CellBuilder(gb2)
- .addTitleText("Check Out")
- .addText("11:00 AM, Feb 19"));
+ .addTitleText("Check Out")
+ .addText("11:00 AM, Feb 19"));
return lb.setColor(0xffFF5252)
.setHeader(new ListBuilder.HeaderBuilder(lb)
.setTitle("Upcoming trip to Seattle")
.setSubtitle("Feb 1 - 19 | 2 guests"))
.addAction(new SliceAction(
getBroadcastIntent(ACTION_TOAST, "show location on map"),
- Icon.createWithResource(getContext(), R.drawable.ic_location),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_location),
"Show reservation location"))
.addAction(new SliceAction(getBroadcastIntent(ACTION_TOAST, "contact host"),
- Icon.createWithResource(getContext(), R.drawable.ic_text),
+ IconCompat.createWithResource(getContext(), R.drawable.ic_text),
"Contact host"))
.addGridRow(gb1)
.addGridRow(gb2)
diff --git a/slices/view/src/main/java/androidx/slice/SliceMetadata.java b/slices/view/src/main/java/androidx/slice/SliceMetadata.java
new file mode 100644
index 0000000..bf96854
--- /dev/null
+++ b/slices/view/src/main/java/androidx/slice/SliceMetadata.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.slice;
+
+import static android.app.slice.Slice.HINT_ACTIONS;
+import static android.app.slice.Slice.HINT_PARTIAL;
+import static android.app.slice.Slice.HINT_SHORTCUT;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
+
+import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
+import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
+import static androidx.slice.core.SliceHints.HINT_TTL;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.slice.core.SliceQuery;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class to parse a Slice and provide access to some information around its contents.
+ */
+public class SliceMetadata {
+
+ /**
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @IntDef({
+ LOADED_NONE, LOADED_PARTIAL, LOADED_ALL
+ })
+ public @interface SliceLoadingState{}
+
+ /**
+ * Indicates this slice is empty and waiting for content to be loaded.
+ */
+ public static final int LOADED_NONE = 0;
+ /**
+ * Indicates this slice has some content but is waiting for other content to be loaded.
+ */
+ public static final int LOADED_PARTIAL = 1;
+ /**
+ * Indicates this slice has fully loaded and is not waiting for other content.
+ */
+ public static final int LOADED_ALL = 2;
+
+ private Slice mSlice;
+ private Context mContext;
+ private long mExpiry;
+ private long mLastUpdated;
+ private List<SliceItem> mSliceActions;
+
+ /**
+ * Create a SliceMetadata object to provide access to some information around the slice and
+ * its contents.
+ *
+ * @param context the context to use for the slice.
+ * @param slice the slice to extract metadata from.
+ *
+ * @return the metadata associated with the provided slice.
+ */
+ public static SliceMetadata from(@NonNull Context context, @NonNull Slice slice) {
+ return new SliceMetadata(context, slice);
+ }
+
+ /**
+ * Create a SliceMetadata object to provide access to some information around the slice and
+ * its contents.
+ *
+ * @param context the context to use for the slice.
+ * @param slice the slice to extract metadata from.
+ */
+ private SliceMetadata(@NonNull Context context, @NonNull Slice slice) {
+ mSlice = slice;
+ mContext = context;
+ SliceItem ttlItem = SliceQuery.find(slice, FORMAT_TIMESTAMP, HINT_TTL, null);
+ if (ttlItem != null) {
+ mExpiry = ttlItem.getTimestamp();
+ }
+ SliceItem updatedItem = SliceQuery.find(slice, FORMAT_TIMESTAMP, HINT_LAST_UPDATED, null);
+ if (updatedItem != null) {
+ mLastUpdated = updatedItem.getTimestamp();
+ }
+ mSliceActions = getSliceActions(mSlice);
+ }
+
+ /**
+ * @return the group of actions associated with this slice, if they exist.
+ */
+ @Nullable
+ public List<SliceItem> getSliceActions() {
+ return mSliceActions;
+ }
+
+ /**
+ * @return the list of keywords associated with the provided slice, null if no keywords were
+ * specified or an empty list if the slice was specified to have no keywords.
+ */
+ @Nullable
+ public List<String> getSliceKeywords() {
+ SliceItem keywordGroup = SliceQuery.find(mSlice, FORMAT_SLICE, HINT_KEY_WORDS, null);
+ if (keywordGroup != null) {
+ List<SliceItem> itemList = SliceQuery.findAll(keywordGroup, FORMAT_TEXT);
+ if (itemList != null) {
+ ArrayList<String> stringList = new ArrayList<>();
+ for (int i = 0; i < itemList.size(); i++) {
+ String keyword = (String) itemList.get(i).getText();
+ if (!TextUtils.isEmpty(keyword)) {
+ stringList.add(keyword);
+ }
+ }
+ return stringList;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return the current loading state for this slice.
+ *
+ * @see #LOADED_NONE
+ * @see #LOADED_PARTIAL
+ * @see #LOADED_ALL
+ */
+ public int getLoadingState() {
+ // Check loading state
+ boolean hasHintPartial = SliceQuery.find(mSlice, null, HINT_PARTIAL, null) != null;
+ if (mSlice.getItems().size() == 0) {
+ // Empty slice
+ return LOADED_NONE;
+ } else if (hasHintPartial) {
+ // Slice with specific content to load
+ return LOADED_PARTIAL;
+ } else {
+ // Full slice
+ return LOADED_ALL;
+ }
+ }
+
+ /**
+ * A slice contains an expiry to indicate when the content in the slice might no longer be
+ * valid.
+ *
+ * @return the time, measured in milliseconds, between the expiry time of this slice and
+ * midnight, January 1, 1970 UTC, or {@link androidx.slice.builders.ListBuilder#INFINITY} if
+ * the slice is not time-sensitive.
+ */
+ public long getExpiry() {
+ return mExpiry;
+ }
+
+ /**
+ * @return the time, measured in milliseconds, between when the slice was created or last
+ * updated, and midnight, January 1, 1970 UTC.
+ */
+ public long getLastUpdatedTime() {
+ return mLastUpdated;
+ }
+
+ /**
+ * @return the group of actions associated with the provided slice, if they exist.
+ * @hide
+ */
+ @Nullable
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ public static List<SliceItem> getSliceActions(@NonNull Slice slice) {
+ SliceItem actionGroup = SliceQuery.find(slice, FORMAT_SLICE, HINT_ACTIONS, null);
+ String[] hints = new String[] {HINT_ACTIONS, HINT_SHORTCUT};
+ return (actionGroup != null)
+ ? SliceQuery.findAll(actionGroup, FORMAT_SLICE, hints, null)
+ : null;
+ }
+}
diff --git a/slices/view/src/main/java/androidx/slice/SliceUtils.java b/slices/view/src/main/java/androidx/slice/SliceUtils.java
index 62be594..40d82bc 100644
--- a/slices/view/src/main/java/androidx/slice/SliceUtils.java
+++ b/slices/view/src/main/java/androidx/slice/SliceUtils.java
@@ -25,23 +25,26 @@
import static android.app.slice.SliceItem.FORMAT_SLICE;
import static android.app.slice.SliceItem.FORMAT_TEXT;
+import static androidx.slice.SliceMetadata.LOADED_ALL;
+import static androidx.slice.SliceMetadata.LOADED_NONE;
+import static androidx.slice.SliceMetadata.LOADED_PARTIAL;
import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
import android.content.Context;
import android.text.TextUtils;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.slice.core.SliceQuery;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Utilities for dealing with slices.
*/
@@ -169,53 +172,55 @@
}
/**
- * @hide
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY)
- @IntDef({
- LOADING_ALL, LOADING_PARTIAL, LOADING_COMPLETE
- })
- public @interface SliceLoadingState{}
-
- /**
* Indicates this slice is empty and waiting for content to be loaded.
+ *
+ * @deprecated TO BE REMOVED: use {@link SliceMetadata#LOADED_NONE}
*/
+ @Deprecated
public static final int LOADING_ALL = 0;
/**
* Indicates this slice has some content but is waiting for other content to be loaded.
+ *
+ * @deprecated TO BE REMOVED: use {@link SliceMetadata#LOADED_PARTIAL}
*/
+ @Deprecated
public static final int LOADING_PARTIAL = 1;
/**
* Indicates this slice has fully loaded and is not waiting for other content.
+ *
+ * @deprecated TO BE REMOVED: use {@link SliceMetadata#LOADED_ALL}
*/
+ @Deprecated
public static final int LOADING_COMPLETE = 2;
/**
* @return the current loading state of the provided {@link Slice}.
*
- * @see #LOADING_ALL
- * @see #LOADING_PARTIAL
- * @see #LOADING_COMPLETE
+ * @deprecated TO BE REMOVED: use {@link SliceMetadata#getLoadingState()}
*/
+ @Deprecated
public static int getLoadingState(@NonNull Slice slice) {
// Check loading state
boolean hasHintPartial =
SliceQuery.find(slice, null, HINT_PARTIAL, null) != null;
if (slice.getItems().size() == 0) {
// Empty slice
- return LOADING_ALL;
+ return LOADED_NONE;
} else if (hasHintPartial) {
// Slice with specific content to load
- return LOADING_PARTIAL;
+ return LOADED_PARTIAL;
} else {
// Full slice
- return LOADING_COMPLETE;
+ return LOADED_ALL;
}
}
/**
* @return the group of actions associated with the provided slice, if they exist.
+ *
+ * @deprecated TO BE REMOVED; use {@link SliceMetadata#getSliceActions()}
*/
+ @Deprecated
@Nullable
public static List<SliceItem> getSliceActions(@NonNull Slice slice) {
SliceItem actionGroup = SliceQuery.find(slice, FORMAT_SLICE, HINT_ACTIONS, null);
@@ -228,7 +233,10 @@
/**
* @return the list of keywords associated with the provided slice, null if no keywords were
* specified or an empty list if the slice was specified to have no keywords.
+ *
+ * @deprecated TO BE REMOVED; use {@link SliceMetadata#getSliceKeywords()}
*/
+ @Deprecated
@Nullable
public static List<String> getSliceKeywords(@NonNull Slice slice) {
SliceItem keywordGroup = SliceQuery.find(slice, FORMAT_SLICE, HINT_KEY_WORDS, null);
diff --git a/slices/view/src/main/java/androidx/slice/SliceXml.java b/slices/view/src/main/java/androidx/slice/SliceXml.java
index 584ef6f..e8747be 100644
--- a/slices/view/src/main/java/androidx/slice/SliceXml.java
+++ b/slices/view/src/main/java/androidx/slice/SliceXml.java
@@ -23,13 +23,14 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
import android.net.Uri;
-import androidx.annotation.RestrictTo;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
+import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
@@ -125,7 +126,7 @@
int w = Integer.parseInt(split[0]);
int h = Integer.parseInt(split[1]);
Bitmap image = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8);
- b.addIcon(Icon.createWithBitmap(image), subtype, hints);
+ b.addIcon(IconCompat.createWithBitmap(image), subtype, hints);
}
}
break;
diff --git a/slices/view/src/main/java/androidx/slice/widget/ActionContent.java b/slices/view/src/main/java/androidx/slice/widget/ActionContent.java
deleted file mode 100644
index 877492d..0000000
--- a/slices/view/src/main/java/androidx/slice/widget/ActionContent.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.slice.widget;
-
-import static android.app.slice.Slice.HINT_SELECTED;
-import static android.app.slice.Slice.HINT_SHORTCUT;
-import static android.app.slice.Slice.HINT_TITLE;
-import static android.app.slice.Slice.SUBTYPE_CONTENT_DESCRIPTION;
-import static android.app.slice.Slice.SUBTYPE_PRIORITY;
-import static android.app.slice.Slice.SUBTYPE_TOGGLE;
-import static android.app.slice.SliceItem.FORMAT_ACTION;
-import static android.app.slice.SliceItem.FORMAT_IMAGE;
-import static android.app.slice.SliceItem.FORMAT_INT;
-import static android.app.slice.SliceItem.FORMAT_SLICE;
-import static android.app.slice.SliceItem.FORMAT_TEXT;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
-import androidx.slice.SliceItem;
-import androidx.slice.core.SliceQuery;
-
-/**
- * Extracts information required to present an action button from a slice.
- * @hide
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public class ActionContent {
- private SliceItem mSliceItem;
- private SliceItem mIconItem;
- private SliceItem mActionItem;
- private SliceItem mTitleItem;
- private SliceItem mContentDescItem;
- private boolean mIsToggle;
- private boolean mIsChecked;
- private int mPriority;
-
- public ActionContent(@NonNull SliceItem slice) {
- populate(slice);
- }
-
- /**
- * @return whether this slice is a valid action.
- */
- private boolean populate(@NonNull SliceItem slice) {
- mSliceItem = slice;
- if (slice.hasHint(HINT_SHORTCUT) && FORMAT_SLICE.equals(slice.getFormat())) {
- mActionItem = SliceQuery.find(slice, FORMAT_ACTION);
- if (mActionItem == null) {
- // Can't have action slice without action
- return false;
- }
- mIconItem = SliceQuery.find(mActionItem.getSlice(), FORMAT_IMAGE);
- mTitleItem = SliceQuery.find(mActionItem.getSlice(), FORMAT_TEXT, HINT_TITLE,
- null /* nonHints */);
- mContentDescItem = SliceQuery.findSubtype(mActionItem.getSlice(), FORMAT_TEXT,
- SUBTYPE_CONTENT_DESCRIPTION);
- mIsToggle = SUBTYPE_TOGGLE.equals(mActionItem.getSubType());
- if (mIsToggle) {
- mIsChecked = mActionItem.hasHint(HINT_SELECTED);
- }
- SliceItem priority = SliceQuery.findSubtype(mActionItem.getSlice(), FORMAT_INT,
- SUBTYPE_PRIORITY);
- mPriority = priority != null ? priority.getInt() : -1;
- return true;
- } else if (FORMAT_ACTION.equals(slice.getFormat())) {
- mActionItem = slice;
- }
- return false;
- }
-
- /**
- * @return the SliceItem used to construct this ActionContent.
- */
- @NonNull
- public SliceItem getSliceItem() {
- return mSliceItem;
- }
-
- /**
- * @return the pending intent associated with this action.
- */
- @Nullable
- public SliceItem getActionItem() {
- return mActionItem;
- }
-
- /**
- * @return the icon associated with this action.
- */
- @Nullable
- public SliceItem getIconItem() {
- return mIconItem;
- }
-
- /**
- * @return the title associated with this action.
- */
- @Nullable
- public SliceItem getTitleItem() {
- return mTitleItem;
- }
-
- /**
- * @return the content description associated with this action.
- */
- @Nullable
- public CharSequence getContentDescription() {
- return mContentDescItem != null
- ? mContentDescItem.getText()
- : mTitleItem != null ? mTitleItem.getText() : null;
- }
-
- /**
- * @return the priority associated with this action, if it exists.
- */
- public int getPriority() {
- return mPriority;
- }
-
- /**
- * @return Whether this action is toggleable.
- */
- public boolean isToggle() {
- return mIsToggle;
- }
-
- /**
- * @return Whether this action represents a custom toggle.
- */
- public boolean isCustomToggle() {
- return mIconItem != null && mIsToggle;
- }
-
- /**
- * @return Whether this action is 'checked' or not (i.e. if toggle is on).
- */
- public boolean isChecked() {
- return mIsChecked;
- }
-}
diff --git a/slices/view/src/main/java/androidx/slice/widget/ActionRow.java b/slices/view/src/main/java/androidx/slice/widget/ActionRow.java
index 78c4a3f..98ebfd2 100644
--- a/slices/view/src/main/java/androidx/slice/widget/ActionRow.java
+++ b/slices/view/src/main/java/androidx/slice/widget/ActionRow.java
@@ -20,6 +20,8 @@
import static android.app.slice.SliceItem.FORMAT_IMAGE;
import static android.app.slice.SliceItem.FORMAT_REMOTE_INPUT;
+import static androidx.slice.core.SliceHints.ICON_IMAGE;
+
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteInput;
@@ -27,9 +29,6 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
-import android.graphics.drawable.Icon;
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewParent;
@@ -39,11 +38,16 @@
import android.widget.LinearLayout;
import android.widget.TextView;
-import java.util.List;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.core.widget.ImageViewCompat;
import androidx.slice.SliceItem;
+import androidx.slice.core.SliceActionImpl;
import androidx.slice.core.SliceQuery;
+import java.util.List;
+
/**
* @hide
*/
@@ -75,25 +79,25 @@
mColor = color;
for (int i = 0; i < mActionsGroup.getChildCount(); i++) {
View view = mActionsGroup.getChildAt(i);
- SliceItem item = (SliceItem) view.getTag();
- boolean tint = !item.hasHint(HINT_NO_TINT);
+ int mode = (Integer) view.getTag();
+ boolean tint = mode == ICON_IMAGE;
if (tint) {
- ((ImageView) view).setImageTintList(ColorStateList.valueOf(mColor));
+ ImageViewCompat.setImageTintList((ImageView) view, ColorStateList.valueOf(mColor));
}
}
}
- private ImageView addAction(Icon icon, boolean allowTint, SliceItem image) {
+ private ImageView addAction(IconCompat icon, boolean allowTint) {
ImageView imageView = new ImageView(getContext());
imageView.setPadding(mIconPadding, mIconPadding, mIconPadding, mIconPadding);
imageView.setScaleType(ScaleType.FIT_CENTER);
- imageView.setImageIcon(icon);
+ imageView.setImageDrawable(icon.loadDrawable(getContext()));
if (allowTint) {
- imageView.setImageTintList(ColorStateList.valueOf(mColor));
+ ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(mColor));
}
imageView.setBackground(SliceViewUtil.getDrawable(getContext(),
android.R.attr.selectableItemBackground));
- imageView.setTag(image);
+ imageView.setTag(allowTint);
addAction(imageView);
return imageView;
}
@@ -117,7 +121,7 @@
if (input != null && image != null
&& input.getRemoteInput().getAllowFreeFormInput()) {
boolean tint = !image.hasHint(HINT_NO_TINT);
- addAction(image.getIcon(), tint, image).setOnClickListener(
+ addAction(image.getIcon(), tint).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
@@ -127,16 +131,17 @@
});
createRemoteInputView(mColor, getContext());
} else if (action.hasHint(Slice.HINT_SHORTCUT)) {
- final ActionContent ac = new ActionContent(action);
- SliceItem iconItem = ac.getIconItem();
- if (iconItem != null && ac.getActionItem() != null) {
- boolean tint = !iconItem.hasHint(HINT_NO_TINT);
- addAction(iconItem.getIcon(), tint, image).setOnClickListener(
+ final SliceActionImpl ac = new SliceActionImpl(action);
+ IconCompat iconItem = ac.getIcon();
+ if (iconItem != null && ac.getAction() != null) {
+ boolean tint = ac.getImageMode() == ICON_IMAGE;
+ addAction(iconItem, tint).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
try {
- ac.getActionItem().getAction().send();
+ // TODO - should log events here
+ ac.getAction().send();
} catch (CanceledException e) {
e.printStackTrace();
}
diff --git a/slices/view/src/main/java/androidx/slice/widget/GridContent.java b/slices/view/src/main/java/androidx/slice/widget/GridContent.java
index 64ead75..14a05aa 100644
--- a/slices/view/src/main/java/androidx/slice/widget/GridContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/GridContent.java
@@ -30,26 +30,28 @@
import static android.app.slice.SliceItem.FORMAT_TEXT;
import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
-import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
-import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
-import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
+import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
+import static androidx.slice.core.SliceHints.HINT_TTL;
+import static androidx.slice.core.SliceHints.ICON_IMAGE;
+import static androidx.slice.core.SliceHints.LARGE_IMAGE;
+import static androidx.slice.core.SliceHints.SMALL_IMAGE;
import android.app.slice.Slice;
import android.content.Context;
import android.content.res.Resources;
-import java.util.ArrayList;
-import java.util.List;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.slice.SliceItem;
-import androidx.slice.builders.ListBuilder;
+import androidx.slice.core.SliceHints;
import androidx.slice.core.SliceQuery;
import androidx.slice.view.R;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Extracts information required to present content in a grid format from a slice.
* @hide
@@ -64,7 +66,7 @@
private SliceItem mSeeMoreItem;
private int mMaxCellLineCount;
private boolean mHasImage;
- private @ListBuilder.ImageMode int mLargestImageMode;
+ private @SliceHints.ImageMode int mLargestImageMode;
private SliceItem mContentDescr;
private int mBigPicMinHeight;
@@ -195,10 +197,11 @@
List<SliceItem> filteredItems = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
SliceItem item = items.get(i);
+ boolean isNonCellContent = item.hasAnyHints(HINT_SHORTCUT, HINT_SEE_MORE,
+ HINT_KEY_WORDS, HINT_TTL, HINT_LAST_UPDATED);
if (SUBTYPE_CONTENT_DESCRIPTION.equals(item.getSubType())) {
mContentDescr = item;
- } else if (item.hasHint(HINT_LIST_ITEM) && !item.hasAnyHints(HINT_SHORTCUT,
- HINT_SEE_MORE, HINT_KEY_WORDS)) {
+ } else if (item.hasHint(HINT_LIST_ITEM) && !isNonCellContent) {
filteredItems.add(item);
}
}
@@ -333,9 +336,9 @@
*/
private boolean isValidCellContent(SliceItem cellItem) {
final String format = cellItem.getFormat();
- boolean isSpecial = SUBTYPE_CONTENT_DESCRIPTION.equals(cellItem.getSubType())
- || cellItem.hasHint(HINT_KEY_WORDS);
- return !isSpecial
+ boolean isNonCellContent = SUBTYPE_CONTENT_DESCRIPTION.equals(cellItem.getSubType())
+ || cellItem.hasAnyHints(HINT_KEY_WORDS, HINT_TTL, HINT_LAST_UPDATED);
+ return !isNonCellContent
&& (FORMAT_TEXT.equals(format)
|| FORMAT_TIMESTAMP.equals(format)
|| FORMAT_IMAGE.equals(format));
diff --git a/slices/view/src/main/java/androidx/slice/widget/GridRowView.java b/slices/view/src/main/java/androidx/slice/widget/GridRowView.java
index 54302ba..dce37e0 100644
--- a/slices/view/src/main/java/androidx/slice/widget/GridRowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/GridRowView.java
@@ -17,6 +17,7 @@
package androidx.slice.widget;
import static android.app.slice.Slice.HINT_LARGE;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
import static android.app.slice.Slice.HINT_NO_TINT;
import static android.app.slice.Slice.HINT_TITLE;
import static android.app.slice.SliceItem.FORMAT_ACTION;
@@ -46,10 +47,6 @@
import android.widget.LinearLayout;
import android.widget.TextView;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
import androidx.annotation.ColorInt;
import androidx.annotation.RestrictTo;
import androidx.slice.Slice;
@@ -57,6 +54,10 @@
import androidx.slice.core.SliceQuery;
import androidx.slice.view.R;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
/**
* @hide
*/
@@ -139,7 +140,8 @@
public void setSlice(Slice slice) {
resetView();
mRowIndex = 0;
- mGridContent = new GridContent(getContext(), slice.getItems().get(0));
+ SliceItem item = SliceQuery.find(slice, FORMAT_SLICE, HINT_LIST_ITEM, null);
+ mGridContent = new GridContent(getContext(), item);
populateViews(mGridContent);
}
@@ -325,7 +327,7 @@
addedView = tv;
} else if (FORMAT_IMAGE.equals(format)) {
ImageView iv = new ImageView(getContext());
- iv.setImageIcon(item.getIcon());
+ iv.setImageDrawable(item.getIcon().loadDrawable(getContext()));
LinearLayout.LayoutParams lp;
if (item.hasHint(HINT_LARGE)) {
iv.setScaleType(ScaleType.CENTER_CROP);
diff --git a/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java b/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java
index 48fe80b..ffa64c4 100644
--- a/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java
+++ b/slices/view/src/main/java/androidx/slice/widget/LargeSliceAdapter.java
@@ -27,8 +27,6 @@
import android.app.slice.Slice;
import android.content.Context;
-import androidx.annotation.RestrictTo;
-import androidx.recyclerview.widget.RecyclerView;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -36,14 +34,16 @@
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
+import androidx.annotation.RestrictTo;
+import androidx.recyclerview.widget.RecyclerView;
import androidx.slice.SliceItem;
import androidx.slice.core.SliceQuery;
import androidx.slice.view.R;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
/**
* @hide
*/
@@ -56,6 +56,8 @@
static final int TYPE_MESSAGE = 4;
static final int TYPE_MESSAGE_LOCAL = 5;
+ static final int HEADER_INDEX = 0;
+
private final IdGenerator mIdGen = new IdGenerator();
private final Context mContext;
private List<SliceWrapper> mSlices = new ArrayList<>();
@@ -63,6 +65,8 @@
private int mColor;
private AttributeSet mAttrs;
private List<SliceItem> mSliceActions;
+ private boolean mShowLastUpdated;
+ private long mLastUpdated;
public LargeSliceAdapter(Context context) {
mContext = context;
@@ -78,9 +82,7 @@
*/
public void setSliceActions(List<SliceItem> actions) {
mSliceActions = actions;
- if (getItemCount() > 0) {
- notifyItemChanged(0); // Header item (index 0) displays the actions
- }
+ notifyHeaderChanged();
}
/**
@@ -108,6 +110,22 @@
notifyDataSetChanged();
}
+ /**
+ * Sets whether the last updated time should be shown on the slice.
+ */
+ public void setShowLastUpdated(boolean showLastUpdated) {
+ mShowLastUpdated = showLastUpdated;
+ notifyHeaderChanged();
+ }
+
+ /**
+ * Sets when the slice was last updated.
+ */
+ public void setLastUpdated(long lastUpdated) {
+ mLastUpdated = lastUpdated;
+ notifyHeaderChanged();
+ }
+
@Override
public SliceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = inflateForType(viewType);
@@ -134,16 +152,24 @@
public void onBindViewHolder(SliceViewHolder holder, int position) {
SliceWrapper slice = mSlices.get(position);
if (holder.mSliceView != null) {
- final boolean isHeader = position == 0;
+ final boolean isHeader = position == HEADER_INDEX;
holder.mSliceView.setTint(mColor);
holder.mSliceView.setStyle(mAttrs);
holder.mSliceView.setSliceItem(slice.mItem, isHeader, position, mSliceObserver);
if (isHeader && holder.mSliceView instanceof RowView) {
holder.mSliceView.setSliceActions(mSliceActions);
+ holder.mSliceView.setLastUpdated(mLastUpdated);
+ holder.mSliceView.setShowLastUpdated(mShowLastUpdated);
}
}
}
+ private void notifyHeaderChanged() {
+ if (getItemCount() > 0) {
+ notifyItemChanged(HEADER_INDEX);
+ }
+ }
+
private View inflateForType(int viewType) {
View v = new RowView(mContext);
switch (viewType) {
diff --git a/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java b/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java
index 7b51451..36409e8 100644
--- a/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/LargeTemplateView.java
@@ -17,17 +17,17 @@
package androidx.slice.widget;
import android.content.Context;
+import android.util.AttributeSet;
+
import androidx.annotation.RestrictTo;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import android.util.AttributeSet;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
import java.util.ArrayList;
import java.util.List;
-import androidx.slice.Slice;
-import androidx.slice.SliceItem;
-
/**
* @hide
*/
@@ -102,6 +102,18 @@
mAdapter.setStyle(attrs);
}
+ @Override
+ public void setShowLastUpdated(boolean showLastUpdated) {
+ super.setShowLastUpdated(showLastUpdated);
+ mAdapter.setShowLastUpdated(showLastUpdated);
+ }
+
+ @Override
+ public void setLastUpdated(long lastUpdated) {
+ super.setLastUpdated(lastUpdated);
+ mAdapter.setLastUpdated(lastUpdated);
+ }
+
private void populate() {
if (mSlice == null) {
resetView();
diff --git a/slices/view/src/main/java/androidx/slice/widget/ListContent.java b/slices/view/src/main/java/androidx/slice/widget/ListContent.java
index 1a0f069..955144d 100644
--- a/slices/view/src/main/java/androidx/slice/widget/ListContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/ListContent.java
@@ -28,6 +28,8 @@
import static android.app.slice.SliceItem.FORMAT_TEXT;
import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
+import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
+import static androidx.slice.core.SliceHints.HINT_TTL;
import android.content.Context;
@@ -36,7 +38,7 @@
import androidx.annotation.RestrictTo;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
-import androidx.slice.SliceUtils;
+import androidx.slice.SliceMetadata;
import androidx.slice.core.SliceQuery;
import java.util.ArrayList;
@@ -62,22 +64,12 @@
}
/**
- * Resets the content.
- */
- public void reset() {
- mColorItem = null;
- mHeaderItem = null;
- mRowItems.clear();
- }
-
- /**
* @return whether this row has content that is valid to display.
*/
private boolean populate(Slice slice) {
- reset();
mColorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
// Find slice actions
- mSliceActions = SliceUtils.getSliceActions(slice);
+ mSliceActions = SliceMetadata.getSliceActions(slice);
// Find header
mHeaderItem = findHeaderItem(slice);
if (mHeaderItem != null) {
@@ -89,8 +81,9 @@
for (int i = 0; i < children.size(); i++) {
final SliceItem child = children.get(i);
final String format = child.getFormat();
- if (!child.hasAnyHints(HINT_ACTIONS, HINT_SEE_MORE, HINT_KEY_WORDS)
- && (FORMAT_ACTION.equals(format) || FORMAT_SLICE.equals(format))) {
+ boolean isNonRowContent = child.hasAnyHints(HINT_ACTIONS, HINT_SEE_MORE, HINT_KEY_WORDS,
+ HINT_TTL, HINT_LAST_UPDATED);
+ if (!isNonRowContent && (FORMAT_ACTION.equals(format) || FORMAT_SLICE.equals(format))) {
if (mHeaderItem == null && !child.hasHint(HINT_LIST_ITEM)) {
mHeaderItem = child;
mRowItems.add(0, child);
@@ -221,7 +214,7 @@
private static SliceItem findHeaderItem(@NonNull Slice slice) {
// See if header is specified
String[] nonHints = new String[] {HINT_LIST_ITEM, HINT_SHORTCUT, HINT_ACTIONS,
- HINT_KEY_WORDS};
+ HINT_KEY_WORDS, HINT_TTL, HINT_LAST_UPDATED};
SliceItem header = SliceQuery.find(slice, FORMAT_SLICE, null, nonHints);
if (header != null && isValidHeader(header)) {
return header;
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowContent.java b/slices/view/src/main/java/androidx/slice/widget/RowContent.java
index e08ceb0..7565895 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowContent.java
@@ -17,6 +17,7 @@
package androidx.slice.widget;
import static android.app.slice.Slice.HINT_ACTIONS;
+import static android.app.slice.Slice.HINT_PARTIAL;
import static android.app.slice.Slice.HINT_SEE_MORE;
import static android.app.slice.Slice.HINT_SHORTCUT;
import static android.app.slice.Slice.HINT_SUMMARY;
@@ -31,6 +32,8 @@
import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
import static androidx.slice.core.SliceHints.HINT_KEY_WORDS;
+import static androidx.slice.core.SliceHints.HINT_LAST_UPDATED;
+import static androidx.slice.core.SliceHints.HINT_TTL;
import static androidx.slice.core.SliceHints.SUBTYPE_RANGE;
import android.content.Context;
@@ -271,7 +274,9 @@
}
private static boolean hasText(SliceItem textSlice) {
- return textSlice != null && !TextUtils.isEmpty(textSlice.getText());
+ return textSlice != null
+ && (textSlice.hasHint(HINT_PARTIAL)
+ || !TextUtils.isEmpty(textSlice.getText()));
}
/**
@@ -337,11 +342,10 @@
* @return whether this item is valid content to display in a row.
*/
private static boolean isValidRowContent(SliceItem slice, SliceItem item) {
- if (item.hasHint(HINT_KEY_WORDS)) {
+ if (item.hasAnyHints(HINT_KEY_WORDS, HINT_TTL, HINT_LAST_UPDATED)) {
return false;
}
- if (FORMAT_SLICE.equals(item.getFormat())
- && !item.hasAnyHints(HINT_SHORTCUT, HINT_KEY_WORDS)) {
+ if (FORMAT_SLICE.equals(item.getFormat()) && !item.hasHint(HINT_SHORTCUT)) {
// Unpack contents of slice
item = item.getSlice().getItems().get(0);
}
@@ -367,6 +371,7 @@
final String type = item.getFormat();
return (FORMAT_ACTION.equals(type) && (SliceQuery.find(item, FORMAT_IMAGE) != null))
|| FORMAT_IMAGE.equals(type)
- || FORMAT_TIMESTAMP.equals(type);
+ || (FORMAT_TIMESTAMP.equals(type)
+ && !item.hasAnyHints(HINT_TTL, HINT_LAST_UPDATED));
}
}
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowView.java b/slices/view/src/main/java/androidx/slice/widget/RowView.java
index 18b0d54..21264f5 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowView.java
@@ -18,6 +18,7 @@
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static android.app.slice.Slice.HINT_NO_TINT;
+import static android.app.slice.Slice.HINT_PARTIAL;
import static android.app.slice.Slice.HINT_SHORTCUT;
import static android.app.slice.Slice.SUBTYPE_TOGGLE;
import static android.app.slice.SliceItem.FORMAT_ACTION;
@@ -27,6 +28,8 @@
import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
import static androidx.slice.core.SliceHints.EXTRA_RANGE_VALUE;
+import static androidx.slice.core.SliceHints.ICON_IMAGE;
+import static androidx.slice.core.SliceHints.SMALL_IMAGE;
import static androidx.slice.core.SliceHints.SUBTYPE_MAX;
import static androidx.slice.core.SliceHints.SUBTYPE_VALUE;
import static androidx.slice.widget.SliceView.MODE_SMALL;
@@ -35,7 +38,10 @@
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
-import android.graphics.drawable.Icon;
+import android.graphics.Typeface;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.style.StyleSpan;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
@@ -53,8 +59,10 @@
import androidx.annotation.ColorInt;
import androidx.annotation.RestrictTo;
+import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
+import androidx.slice.core.SliceActionImpl;
import androidx.slice.core.SliceQuery;
import androidx.slice.view.R;
@@ -79,6 +87,7 @@
private LinearLayout mContent;
private TextView mPrimaryText;
private TextView mSecondaryText;
+ private TextView mLastUpdatedText;
private View mDivider;
private ArrayList<CompoundButton> mToggles = new ArrayList<>();
private LinearLayout mEndContainer;
@@ -88,7 +97,7 @@
private int mRowIndex;
private RowContent mRowContent;
- private ActionContent mRowAction;
+ private SliceActionImpl mRowAction;
private boolean mIsHeader;
private List<SliceItem> mHeaderActions;
@@ -108,6 +117,7 @@
mContent = (LinearLayout) findViewById(android.R.id.content);
mPrimaryText = (TextView) findViewById(android.R.id.title);
mSecondaryText = (TextView) findViewById(android.R.id.summary);
+ mLastUpdatedText = (TextView) findViewById(R.id.last_updated);
mDivider = findViewById(R.id.divider);
mEndContainer = (LinearLayout) findViewById(android.R.id.widget_frame);
mSeekBar = (SeekBar) findViewById(R.id.seek_bar);
@@ -144,6 +154,14 @@
}
@Override
+ public void setShowLastUpdated(boolean showLastUpdated) {
+ super.setShowLastUpdated(showLastUpdated);
+ if (mRowContent != null) {
+ populateViews();
+ }
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = getMode() == MODE_SMALL ? getSmallHeight() : getActualHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
@@ -208,17 +226,10 @@
mPrimaryText.setTextColor(mTitleColor);
mPrimaryText.setVisibility(titleItem != null ? View.VISIBLE : View.GONE);
- final SliceItem subTitle = getMode() == MODE_SMALL
+ final SliceItem subtitleItem = getMode() == MODE_SMALL
? mRowContent.getSummaryItem()
: mRowContent.getSubtitleItem();
- if (subTitle != null) {
- mSecondaryText.setText(subTitle.getText());
- }
- mSecondaryText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mIsHeader
- ? mHeaderSubtitleSize
- : mSubtitleSize);
- mSecondaryText.setTextColor(mSubtitleColor);
- mSecondaryText.setVisibility(subTitle != null ? View.VISIBLE : View.GONE);
+ addSubtitle(subtitleItem);
final SliceItem range = mRowContent.getRange();
if (range != null) {
@@ -228,7 +239,7 @@
SliceItem primaryAction = mRowContent.getPrimaryAction();
if (primaryAction != null) {
- mRowAction = new ActionContent(primaryAction);
+ mRowAction = new SliceActionImpl(primaryAction);
if (mRowAction.isToggle()) {
// If primary action is a toggle, add it and we're done
addToggle(mRowAction, mTintColor, mEndContainer);
@@ -236,9 +247,9 @@
return;
}
}
- List<SliceItem> endItems = mRowContent.getEndItems();
- // If we're here we might be able to show end items
+ // If we're here we can can show end items; check for top level actions first
+ List<SliceItem> endItems = mRowContent.getEndItems();
String desiredFormat = FORMAT_ACTION;
if (mIsHeader && mHeaderActions != null && mHeaderActions.size() > 0) {
// Use these if we have them instead
@@ -297,13 +308,44 @@
if (mRowContent.endItemsContainAction() && itemCount == 1) {
SliceItem unwrappedActionItem = endItems.get(0).getSlice().getItems().get(0);
if (!SUBTYPE_TOGGLE.equals(unwrappedActionItem.getSubType())) {
- mRowAction = new ActionContent(endItems.get(0));
+ mRowAction = new SliceActionImpl(endItems.get(0));
}
setViewClickable(this, true);
}
}
}
+ private void addSubtitle(final SliceItem subtitleItem) {
+ CharSequence subtitleTimeString = null;
+ if (mShowLastUpdated) {
+ subtitleTimeString = getResources().getString(R.string.abc_slice_updated,
+ SliceViewUtil.getRelativeTimeString(mLastUpdated));
+ }
+ CharSequence subtitle = subtitleItem != null ? subtitleItem.getText() : null;
+ boolean subtitleExists = !TextUtils.isEmpty(subtitle)
+ || (subtitleItem != null && subtitleItem.hasHint(HINT_PARTIAL));
+ if (subtitleExists) {
+ mSecondaryText.setText(subtitle);
+ mSecondaryText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mIsHeader
+ ? mHeaderSubtitleSize
+ : mSubtitleSize);
+ mSecondaryText.setTextColor(mSubtitleColor);
+ }
+ if (subtitleTimeString != null) {
+ if (!TextUtils.isEmpty(subtitle)) {
+ subtitleTimeString = " \u00B7 " + subtitleTimeString;
+ }
+ SpannableString sp = new SpannableString(subtitleTimeString);
+ sp.setSpan(new StyleSpan(Typeface.ITALIC), 0, subtitleTimeString.length(), 0);
+ mLastUpdatedText.setText(sp);
+ mLastUpdatedText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ mIsHeader ? mHeaderSubtitleSize : mSubtitleSize);
+ mLastUpdatedText.setTextColor(mSubtitleColor);
+ }
+ mLastUpdatedText.setVisibility(TextUtils.isEmpty(subtitleTimeString) ? GONE : VISIBLE);
+ mSecondaryText.setVisibility(subtitleExists ? VISIBLE : GONE);
+ }
+
private void addRange(final SliceItem range) {
final boolean isSeekBar = FORMAT_ACTION.equals(range.getFormat());
final ProgressBar progressBar = isSeekBar ? mSeekBar : mProgressBar;
@@ -344,11 +386,11 @@
/**
* Add a toggle view to container.
*/
- private void addToggle(final ActionContent actionContent, int color, ViewGroup container) {
+ private void addToggle(final SliceActionImpl actionContent, int color, ViewGroup container) {
// Check if this is a custom toggle
final CompoundButton toggle;
- if (actionContent.isCustomToggle()) {
- Icon checkedIcon = actionContent.getIconItem().getIcon();
+ if (actionContent.isToggle() && !actionContent.isDefaultToggle()) {
+ IconCompat checkedIcon = actionContent.getIcon();
if (color != -1) {
// TODO - Should custom toggle buttons be tinted? What if the app wants diff
// colors per state?
@@ -375,7 +417,7 @@
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
try {
- PendingIntent pi = actionContent.getActionItem().getAction();
+ PendingIntent pi = actionContent.getAction();
Intent i = new Intent().putExtra(EXTRA_TOGGLE_STATE, isChecked);
pi.send(getContext(), 0, i, null, null);
if (mObserver != null) {
@@ -399,15 +441,15 @@
*/
private boolean addItem(SliceItem sliceItem, int color, boolean isStart, int padding,
final EventInfo info) {
- SliceItem image = null;
- SliceItem action = null;
+ IconCompat icon = null;
+ int imageMode = 0;
SliceItem timeStamp = null;
- ActionContent actionContent = null;
+ SliceActionImpl actionContent = null;
ViewGroup container = isStart ? mStartContainer : mEndContainer;
if (FORMAT_SLICE.equals(sliceItem.getFormat())) {
// It's an action.... let's make it so
if (sliceItem.hasHint(HINT_SHORTCUT)) {
- actionContent = new ActionContent(sliceItem);
+ actionContent = new SliceActionImpl(sliceItem);
} else {
sliceItem = sliceItem.getSlice().getItems().get(0);
}
@@ -417,20 +459,23 @@
addToggle(actionContent, color, container);
return true;
}
- action = actionContent.getActionItem();
- image = actionContent.getIconItem();
+ icon = actionContent.getIcon();
+ if (icon != null) {
+ imageMode = actionContent.getImageMode();
+ }
}
if (FORMAT_IMAGE.equals(sliceItem.getFormat())) {
- image = sliceItem;
+ icon = sliceItem.getIcon();
+ imageMode = sliceItem.hasHint(HINT_NO_TINT) ? SMALL_IMAGE : ICON_IMAGE;
} else if (FORMAT_TIMESTAMP.equals(sliceItem.getFormat())) {
timeStamp = sliceItem;
}
View addedView = null;
- if (image != null) {
+ if (icon != null) {
ImageView iv = new ImageView(getContext());
- iv.setImageIcon(image.getIcon());
+ iv.setImageDrawable(icon.loadDrawable(getContext()));
int size = mImageSize;
- if (!image.hasHint(HINT_NO_TINT)) {
+ if (imageMode == ICON_IMAGE) {
if (color != -1) {
iv.setColorFilter(color);
}
@@ -453,15 +498,15 @@
container.addView(tv);
addedView = tv;
}
- if (action != null && addedView != null) {
- final SliceItem sliceAction = action;
+ if (actionContent != null && addedView != null) {
+ final SliceActionImpl finalAction = actionContent;
addedView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
- sliceAction.getAction().send();
+ finalAction.getAction().send();
if (mObserver != null) {
- mObserver.onSliceAction(info, sliceAction);
+ mObserver.onSliceAction(info, finalAction.getSliceItem());
}
} catch (CanceledException e) {
e.printStackTrace();
@@ -501,10 +546,10 @@
@Override
public void onClick(View view) {
- if (mRowAction != null && mRowAction.getActionItem() != null && !mRowAction.isToggle()) {
+ if (mRowAction != null && mRowAction.getAction() != null && !mRowAction.isToggle()) {
// Check for a row action
try {
- mRowAction.getActionItem().getAction().send();
+ mRowAction.getAction().send();
if (mObserver != null) {
EventInfo info = new EventInfo(getMode(), EventInfo.ACTION_TYPE_CONTENT,
EventInfo.ROW_TYPE_LIST, mRowIndex);
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java b/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java
index 8250a9e..2e52246 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceChildView.java
@@ -18,19 +18,19 @@
import android.content.Context;
import android.content.res.TypedArray;
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
-import java.util.List;
-
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
import androidx.slice.view.R;
+import java.util.List;
+
/**
* Base class for children views of {@link SliceView}.
* @hide
@@ -49,6 +49,8 @@
protected int mSubtitleSize;
protected int mGridTitleSize;
protected int mGridSubtitleSize;
+ protected boolean mShowLastUpdated;
+ protected long mLastUpdated = -1;
public SliceChildView(@NonNull Context context) {
super(context);
@@ -113,6 +115,20 @@
}
/**
+ * Sets whether the last updated time should be displayed.
+ */
+ public void setShowLastUpdated(boolean showLastUpdated) {
+ mShowLastUpdated = showLastUpdated;
+ }
+
+ /**
+ * Sets when the content of this view was last updated.
+ */
+ public void setLastUpdated(long lastUpdated) {
+ mLastUpdated = lastUpdated;
+ }
+
+ /**
* Sets the observer to notify when an interaction events occur on the view.
*/
public void setSliceActionListener(SliceView.OnSliceActionListener observer) {
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceView.java b/slices/view/src/main/java/androidx/slice/widget/SliceView.java
index 9fb977e..272bbdc 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceView.java
@@ -35,7 +35,8 @@
import androidx.lifecycle.Observer;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
-import androidx.slice.SliceUtils;
+import androidx.slice.SliceMetadata;
+import androidx.slice.core.SliceHints;
import androidx.slice.core.SliceQuery;
import androidx.slice.view.R;
@@ -122,6 +123,7 @@
private boolean mShowActions = false;
private boolean mIsScrollable = true;
+ private boolean mShowLastUpdated = true;
private final int mShortcutSize;
private final int mMinLargeHeight;
@@ -261,15 +263,14 @@
*/
public void setSlice(@Nullable Slice slice) {
if (slice != null) {
- if (mCurrentSlice == null || mCurrentSlice.getUri() != slice.getUri()) {
- // New slice, new actions
- mActions = SliceUtils.getSliceActions(slice);
+ if (mCurrentSlice == null || !mCurrentSlice.getUri().equals(slice.getUri())) {
mCurrentView.resetView();
}
} else {
// No slice, no actions
mActions = null;
}
+ mActions = SliceMetadata.getSliceActions(slice);
mCurrentSlice = slice;
reinflate();
}
@@ -290,14 +291,14 @@
* It is required that the slice be set on this view before actions can be set, otherwise
* this will throw {@link IllegalStateException}. If any of the actions supplied are not
* available for the slice set on this view (i.e. the action is not returned by
- * {@link SliceUtils#getSliceActions(Slice)} this will throw {@link IllegalArgumentException}.
+ * {@link SliceMetadata#getSliceActions()} this will throw {@link IllegalArgumentException}.
*/
public void setSliceActions(@Nullable List<SliceItem> newActions) {
// Check that these actions are part of available set
if (mCurrentSlice == null) {
throw new IllegalStateException("Trying to set actions on a view without a slice");
}
- List<SliceItem> availableActions = SliceUtils.getSliceActions(mCurrentSlice);
+ List<SliceItem> availableActions = SliceMetadata.getSliceActions(mCurrentSlice);
if (availableActions != null && newActions != null) {
for (int i = 0; i < newActions.size(); i++) {
if (!availableActions.contains(newActions.get(i))) {
@@ -347,6 +348,18 @@
}
/**
+ * Sets whether this view should display when the slice was last updated.
+ *
+ * @param showLastUpdated whether the view should display when the slice was last updated.
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ public void setShowLastUpdated(boolean showLastUpdated) {
+ mShowLastUpdated = showLastUpdated;
+ mCurrentView.setShowLastUpdated(showLastUpdated);
+ }
+
+ /**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -435,6 +448,16 @@
mCurrentView.setStyle(mAttrs);
mCurrentView.setTint(getTintColor());
mCurrentView.setVisibility(lc.isValid() ? View.VISIBLE : View.GONE);
+
+ // Check if the slice content is expired and show when it was last updated
+ SliceMetadata sliceMetadata = SliceMetadata.from(getContext(), mCurrentSlice);
+ long lastUpdated = sliceMetadata.getLastUpdatedTime();
+ long expiry = sliceMetadata.getExpiry();
+ long now = System.currentTimeMillis();
+ mCurrentView.setLastUpdated(lastUpdated);
+ boolean expired = expiry != SliceHints.INFINITY && now > expiry;
+ mCurrentView.setShowLastUpdated(mShowLastUpdated && expired);
+
// Set the slice
mCurrentView.setSlice(mCurrentSlice);
updateActions();
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java b/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java
index 0c76fcf..c8e3d74 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java
@@ -29,18 +29,19 @@
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
+import android.text.format.DateUtils;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.core.content.ContextCompat;
-import android.text.format.DateUtils;
-import android.view.Gravity;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
+import androidx.core.graphics.drawable.IconCompat;
import java.util.Calendar;
@@ -139,25 +140,24 @@
/**
*/
@RequiresApi(23)
- public static Icon createIconFromDrawable(Drawable d) {
+ public static IconCompat createIconFromDrawable(Drawable d) {
if (d instanceof BitmapDrawable) {
- return Icon.createWithBitmap(((BitmapDrawable) d).getBitmap());
+ return IconCompat.createWithBitmap(((BitmapDrawable) d).getBitmap());
}
Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
d.draw(canvas);
- return Icon.createWithBitmap(b);
+ return IconCompat.createWithBitmap(b);
}
/**
*/
- @RequiresApi(23)
public static void createCircledIcon(@NonNull Context context, int iconSizePx,
- Icon icon, boolean isLarge, ViewGroup parent) {
+ IconCompat icon, boolean isLarge, ViewGroup parent) {
ImageView v = new ImageView(context);
- v.setImageIcon(icon);
+ v.setImageDrawable(icon.loadDrawable(context));
v.setScaleType(isLarge ? ImageView.ScaleType.CENTER_CROP
: ImageView.ScaleType.CENTER_INSIDE);
parent.addView(v);
diff --git a/slices/view/src/main/res/layout/abc_slice_small_template.xml b/slices/view/src/main/res/layout/abc_slice_small_template.xml
index 4a47c06..1327066 100644
--- a/slices/view/src/main/res/layout/abc_slice_small_template.xml
+++ b/slices/view/src/main/res/layout/abc_slice_small_template.xml
@@ -45,11 +45,27 @@
android:layout_height="wrap_content"
android:maxLines="1"/>
- <TextView android:id="@android:id/summary"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignStart="@android:id/title"
- android:maxLines="1" />
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:ellipsize="end"
+ android:maxLines="1" />
+
+ <TextView
+ android:id="@+id/last_updated"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1" />
+
+ </LinearLayout>
<SeekBar
android:id="@+id/seek_bar"
diff --git a/slices/view/src/main/res/values-af/strings.xml b/slices/view/src/main/res/values-af/strings.xml
index 322c8cf..812f811 100644
--- a/slices/view/src/main/res/values-af/strings.xml
+++ b/slices/view/src/main/res/values-af/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Meer"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Wys meer"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-az/strings.xml b/slices/view/src/main/res/values-az/strings.xml
index 7b0d59c..8ff3908 100644
--- a/slices/view/src/main/res/values-az/strings.xml
+++ b/slices/view/src/main/res/values-az/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Digər"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Digərinə baxın"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-be/strings.xml b/slices/view/src/main/res/values-be/strings.xml
index ae73c85..6ea856b 100644
--- a/slices/view/src/main/res/values-be/strings.xml
+++ b/slices/view/src/main/res/values-be/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"Яшчэ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Яшчэ"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Яшчэ"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-bg/strings.xml b/slices/view/src/main/res/values-bg/strings.xml
index c8efb9a..882def9 100644
--- a/slices/view/src/main/res/values-bg/strings.xml
+++ b/slices/view/src/main/res/values-bg/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Още"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Показване на още"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-bn/strings.xml b/slices/view/src/main/res/values-bn/strings.xml
index 0711d78..eb83395 100644
--- a/slices/view/src/main/res/values-bn/strings.xml
+++ b/slices/view/src/main/res/values-bn/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>টি"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"আরও"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"আরও দেখুন"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-bs/strings.xml b/slices/view/src/main/res/values-bs/strings.xml
index 1b97ec1..693f885 100644
--- a/slices/view/src/main/res/values-bs/strings.xml
+++ b/slices/view/src/main/res/values-bs/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Više"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Prikaži više"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ca/strings.xml b/slices/view/src/main/res/values-ca/strings.xml
index 9c9b13c..4ac9c6d 100644
--- a/slices/view/src/main/res/values-ca/strings.xml
+++ b/slices/view/src/main/res/values-ca/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> més"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Més"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Mostra\'n més"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-da/strings.xml b/slices/view/src/main/res/values-da/strings.xml
index c41bd9a..806a5fe 100644
--- a/slices/view/src/main/res/values-da/strings.xml
+++ b/slices/view/src/main/res/values-da/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> mere"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mere"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Se mere"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-de/strings.xml b/slices/view/src/main/res/values-de/strings.xml
index c60b528..f6a1e32 100644
--- a/slices/view/src/main/res/values-de/strings.xml
+++ b/slices/view/src/main/res/values-de/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mehr"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Mehr anzeigen"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-el/strings.xml b/slices/view/src/main/res/values-el/strings.xml
index f8cb37c..19963f2 100644
--- a/slices/view/src/main/res/values-el/strings.xml
+++ b/slices/view/src/main/res/values-el/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Περισσότ."</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Εμφάνιση περισσότερων"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-en-rAU/strings.xml b/slices/view/src/main/res/values-en-rAU/strings.xml
index 4767f88..f222ba5 100644
--- a/slices/view/src/main/res/values-en-rAU/strings.xml
+++ b/slices/view/src/main/res/values-en-rAU/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-en-rCA/strings.xml b/slices/view/src/main/res/values-en-rCA/strings.xml
index 4767f88..f222ba5 100644
--- a/slices/view/src/main/res/values-en-rCA/strings.xml
+++ b/slices/view/src/main/res/values-en-rCA/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-en-rGB/strings.xml b/slices/view/src/main/res/values-en-rGB/strings.xml
index 4767f88..f222ba5 100644
--- a/slices/view/src/main/res/values-en-rGB/strings.xml
+++ b/slices/view/src/main/res/values-en-rGB/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-en-rIN/strings.xml b/slices/view/src/main/res/values-en-rIN/strings.xml
index 4767f88..f222ba5 100644
--- a/slices/view/src/main/res/values-en-rIN/strings.xml
+++ b/slices/view/src/main/res/values-en-rIN/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-en-rXC/strings.xml b/slices/view/src/main/res/values-en-rXC/strings.xml
index 2bd9d5e..243dccb 100644
--- a/slices/view/src/main/res/values-en-rXC/strings.xml
+++ b/slices/view/src/main/res/values-en-rXC/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"More"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Show more"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-es-rUS/strings.xml b/slices/view/src/main/res/values-es-rUS/strings.xml
index 1fda757..7fc5b56 100644
--- a/slices/view/src/main/res/values-es-rUS/strings.xml
+++ b/slices/view/src/main/res/values-es-rUS/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> más"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Más"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar más"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-es/strings.xml b/slices/view/src/main/res/values-es/strings.xml
index 1920ed5..b81e23c 100644
--- a/slices/view/src/main/res/values-es/strings.xml
+++ b/slices/view/src/main/res/values-es/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> más"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Más"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Ver más"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-et/strings.xml b/slices/view/src/main/res/values-et/strings.xml
index c34dee7..80bec54 100644
--- a/slices/view/src/main/res/values-et/strings.xml
+++ b/slices/view/src/main/res/values-et/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"ja veel <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Rohkem"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Kuva rohkem"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-eu/strings.xml b/slices/view/src/main/res/values-eu/strings.xml
index ff82ef6..295f184 100644
--- a/slices/view/src/main/res/values-eu/strings.xml
+++ b/slices/view/src/main/res/values-eu/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"Beste <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Gehiago"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Erakutsi gehiago"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-fi/strings.xml b/slices/view/src/main/res/values-fi/strings.xml
index 863c2f5..0e37b9d 100644
--- a/slices/view/src/main/res/values-fi/strings.xml
+++ b/slices/view/src/main/res/values-fi/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Lisää"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Näytä lisää"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-fr/strings.xml b/slices/view/src/main/res/values-fr/strings.xml
index 9d64bc2..b4f147b 100644
--- a/slices/view/src/main/res/values-fr/strings.xml
+++ b/slices/view/src/main/res/values-fr/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> autres"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Plus"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Afficher plus"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-gl/strings.xml b/slices/view/src/main/res/values-gl/strings.xml
index 2893e44..f8686de 100644
--- a/slices/view/src/main/res/values-gl/strings.xml
+++ b/slices/view/src/main/res/values-gl/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> máis"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Máis"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Amosar máis"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-gu/strings.xml b/slices/view/src/main/res/values-gu/strings.xml
index 044a117..4cf8b47 100644
--- a/slices/view/src/main/res/values-gu/strings.xml
+++ b/slices/view/src/main/res/values-gu/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"વધુ"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"વધુ બતાવો"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-hi/strings.xml b/slices/view/src/main/res/values-hi/strings.xml
index 3f0db62..3688497 100644
--- a/slices/view/src/main/res/values-hi/strings.xml
+++ b/slices/view/src/main/res/values-hi/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"ज़्यादा देखें"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"ज़्यादा देखें"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-hr/strings.xml b/slices/view/src/main/res/values-hr/strings.xml
index 1857f12..5ec52b8 100644
--- a/slices/view/src/main/res/values-hr/strings.xml
+++ b/slices/view/src/main/res/values-hr/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"još <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Više"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Prikaži više"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-hu/strings.xml b/slices/view/src/main/res/values-hu/strings.xml
index b655dbe..957dd68 100644
--- a/slices/view/src/main/res/values-hu/strings.xml
+++ b/slices/view/src/main/res/values-hu/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Több"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Több megjelenítése"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-in/strings.xml b/slices/view/src/main/res/values-in/strings.xml
index 17da9ee..7d46931 100644
--- a/slices/view/src/main/res/values-in/strings.xml
+++ b/slices/view/src/main/res/values-in/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Lainnya"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Tampilkan lainnya"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-it/strings.xml b/slices/view/src/main/res/values-it/strings.xml
index f64fef2..8f0a761 100644
--- a/slices/view/src/main/res/values-it/strings.xml
+++ b/slices/view/src/main/res/values-it/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Altro"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Mostra altro"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ja/strings.xml b/slices/view/src/main/res/values-ja/strings.xml
index a0ed985..a18751f 100644
--- a/slices/view/src/main/res/values-ja/strings.xml
+++ b/slices/view/src/main/res/values-ja/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"他 <xliff:g id="NUMBER">%1$d</xliff:g> 件"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"もっと見る"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"もっと見る"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ka/strings.xml b/slices/view/src/main/res/values-ka/strings.xml
index 1da1a4e..8701f5d 100644
--- a/slices/view/src/main/res/values-ka/strings.xml
+++ b/slices/view/src/main/res/values-ka/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"მეტი"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"მეტის ჩვენება"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-kk/strings.xml b/slices/view/src/main/res/values-kk/strings.xml
index f95841f..1867ada 100644
--- a/slices/view/src/main/res/values-kk/strings.xml
+++ b/slices/view/src/main/res/values-kk/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Тағы"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Толығырақ көрсету"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-km/strings.xml b/slices/view/src/main/res/values-km/strings.xml
index 2d93b60..3f50a99 100644
--- a/slices/view/src/main/res/values-km/strings.xml
+++ b/slices/view/src/main/res/values-km/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"ច្រើនទៀត"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"បង្ហាញច្រើនទៀត"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-kn/strings.xml b/slices/view/src/main/res/values-kn/strings.xml
index fea51c8..e8224f3 100644
--- a/slices/view/src/main/res/values-kn/strings.xml
+++ b/slices/view/src/main/res/values-kn/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"ಇನ್ನಷ್ಟು"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"ಹೆಚ್ಚು ತೋರಿಸಿ"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ko/strings.xml b/slices/view/src/main/res/values-ko/strings.xml
index d11f21e..8e7cb24 100644
--- a/slices/view/src/main/res/values-ko/strings.xml
+++ b/slices/view/src/main/res/values-ko/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g>개 더보기"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"더보기"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"더보기"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ky/strings.xml b/slices/view/src/main/res/values-ky/strings.xml
index 8349057..910ae6d 100644
--- a/slices/view/src/main/res/values-ky/strings.xml
+++ b/slices/view/src/main/res/values-ky/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Дагы"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Дагы көрсөтүү"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-lo/strings.xml b/slices/view/src/main/res/values-lo/strings.xml
index b0185ce..d266a43 100644
--- a/slices/view/src/main/res/values-lo/strings.xml
+++ b/slices/view/src/main/res/values-lo/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"ເພີ່ມເຕີມ"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"ສະແດງເພີ່ມເຕີມ"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-mk/strings.xml b/slices/view/src/main/res/values-mk/strings.xml
index 5a243a4..b3c5da4 100644
--- a/slices/view/src/main/res/values-mk/strings.xml
+++ b/slices/view/src/main/res/values-mk/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Повеќе"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Прикажи повеќе"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ml/strings.xml b/slices/view/src/main/res/values-ml/strings.xml
index 3f77875..e2dc0b1 100644
--- a/slices/view/src/main/res/values-ml/strings.xml
+++ b/slices/view/src/main/res/values-ml/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"കൂടുതൽ"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"കൂടുതൽ കാണിക്കുക"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-mn/strings.xml b/slices/view/src/main/res/values-mn/strings.xml
index bec9ac5..740f455 100644
--- a/slices/view/src/main/res/values-mn/strings.xml
+++ b/slices/view/src/main/res/values-mn/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Бусад"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Дэлгэрэнгүй үзэх"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-mr/strings.xml b/slices/view/src/main/res/values-mr/strings.xml
index 03b0bed..ab06bea 100644
--- a/slices/view/src/main/res/values-mr/strings.xml
+++ b/slices/view/src/main/res/values-mr/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"आणखी"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"आणखी दाखवा"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ms/strings.xml b/slices/view/src/main/res/values-ms/strings.xml
index 6e276b6..03bda10 100644
--- a/slices/view/src/main/res/values-ms/strings.xml
+++ b/slices/view/src/main/res/values-ms/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Lagi"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Tunjukkan lagi"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-my/strings.xml b/slices/view/src/main/res/values-my/strings.xml
index 4c39980..754d40e 100644
--- a/slices/view/src/main/res/values-my/strings.xml
+++ b/slices/view/src/main/res/values-my/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"နောက်ထပ်"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"နောက်ထပ် ပြပါ"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-nb/strings.xml b/slices/view/src/main/res/values-nb/strings.xml
index 8713242..e977965 100644
--- a/slices/view/src/main/res/values-nb/strings.xml
+++ b/slices/view/src/main/res/values-nb/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mer"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Vis mer"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ne/strings.xml b/slices/view/src/main/res/values-ne/strings.xml
index 9d3d0c8..6a95860 100644
--- a/slices/view/src/main/res/values-ne/strings.xml
+++ b/slices/view/src/main/res/values-ne/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"थप"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"थप देखाउनुहोस्"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-nl/strings.xml b/slices/view/src/main/res/values-nl/strings.xml
index 3798fcb..ed28ef2 100644
--- a/slices/view/src/main/res/values-nl/strings.xml
+++ b/slices/view/src/main/res/values-nl/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Meer"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Meer weergeven"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-pa/strings.xml b/slices/view/src/main/res/values-pa/strings.xml
index 5c78776..cd6db9b 100644
--- a/slices/view/src/main/res/values-pa/strings.xml
+++ b/slices/view/src/main/res/values-pa/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"ਹੋਰ"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"ਹੋਰ ਦਿਖਾਓ"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-pl/strings.xml b/slices/view/src/main/res/values-pl/strings.xml
index 9a61601..5fe2d2b 100644
--- a/slices/view/src/main/res/values-pl/strings.xml
+++ b/slices/view/src/main/res/values-pl/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Więcej"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Pokaż więcej"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-pt-rBR/strings.xml b/slices/view/src/main/res/values-pt-rBR/strings.xml
index d3373a5..a163c4a 100644
--- a/slices/view/src/main/res/values-pt-rBR/strings.xml
+++ b/slices/view/src/main/res/values-pt-rBR/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"Mais <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mais"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar mais"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-pt-rPT/strings.xml b/slices/view/src/main/res/values-pt-rPT/strings.xml
index a61795f..7d4c127 100644
--- a/slices/view/src/main/res/values-pt-rPT/strings.xml
+++ b/slices/view/src/main/res/values-pt-rPT/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mais"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar mais"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-pt/strings.xml b/slices/view/src/main/res/values-pt/strings.xml
index d3373a5..a163c4a 100644
--- a/slices/view/src/main/res/values-pt/strings.xml
+++ b/slices/view/src/main/res/values-pt/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"Mais <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mais"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Mostrar mais"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ro/strings.xml b/slices/view/src/main/res/values-ro/strings.xml
index 6070e17..ed61fde 100644
--- a/slices/view/src/main/res/values-ro/strings.xml
+++ b/slices/view/src/main/res/values-ro/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mai mult"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Vedeți mai multe"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-si/strings.xml b/slices/view/src/main/res/values-si/strings.xml
index 4d5ab4a..58feb78 100644
--- a/slices/view/src/main/res/values-si/strings.xml
+++ b/slices/view/src/main/res/values-si/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"තව"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"තව පෙන්වන්න"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-sk/strings.xml b/slices/view/src/main/res/values-sk/strings.xml
index c27c533..fe77506 100644
--- a/slices/view/src/main/res/values-sk/strings.xml
+++ b/slices/view/src/main/res/values-sk/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Viac"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Zobraziť viac"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-sl/strings.xml b/slices/view/src/main/res/values-sl/strings.xml
index 3dc60a8..802caf1 100644
--- a/slices/view/src/main/res/values-sl/strings.xml
+++ b/slices/view/src/main/res/values-sl/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"in še <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Več"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Pokaži več"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-sq/strings.xml b/slices/view/src/main/res/values-sq/strings.xml
index 9b1ba91..e1cdae8 100644
--- a/slices/view/src/main/res/values-sq/strings.xml
+++ b/slices/view/src/main/res/values-sq/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Më shumë"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Shfaq më shumë"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-sv/strings.xml b/slices/view/src/main/res/values-sv/strings.xml
index d41940f..f8ed0c7 100644
--- a/slices/view/src/main/res/values-sv/strings.xml
+++ b/slices/view/src/main/res/values-sv/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"<xliff:g id="NUMBER">%1$d</xliff:g> till"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mer"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Visa mer"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-sw/strings.xml b/slices/view/src/main/res/values-sw/strings.xml
index c512c09..b23ed5e 100644
--- a/slices/view/src/main/res/values-sw/strings.xml
+++ b/slices/view/src/main/res/values-sw/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Mengine"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Onyesha mengine"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ta/strings.xml b/slices/view/src/main/res/values-ta/strings.xml
index c127c27..9f2be0e 100644
--- a/slices/view/src/main/res/values-ta/strings.xml
+++ b/slices/view/src/main/res/values-ta/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"மேலும்"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"மேலும் காட்டு"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-te/strings.xml b/slices/view/src/main/res/values-te/strings.xml
index 80d2432..0eb1da7 100644
--- a/slices/view/src/main/res/values-te/strings.xml
+++ b/slices/view/src/main/res/values-te/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"మరింత"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"మరింత చూపు"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-th/strings.xml b/slices/view/src/main/res/values-th/strings.xml
index 03c5a95..4cdd991 100644
--- a/slices/view/src/main/res/values-th/strings.xml
+++ b/slices/view/src/main/res/values-th/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"เพิ่มเติม"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"แสดงเพิ่ม"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-tr/strings.xml b/slices/view/src/main/res/values-tr/strings.xml
index 93eca82..09a589e 100644
--- a/slices/view/src/main/res/values-tr/strings.xml
+++ b/slices/view/src/main/res/values-tr/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Diğer"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Daha fazla göster"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-uk/strings.xml b/slices/view/src/main/res/values-uk/strings.xml
index c5ab87c..06c02bc 100644
--- a/slices/view/src/main/res/values-uk/strings.xml
+++ b/slices/view/src/main/res/values-uk/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Більше"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Показати більше"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-ur/strings.xml b/slices/view/src/main/res/values-ur/strings.xml
index 7b24d79..f12d6b3 100644
--- a/slices/view/src/main/res/values-ur/strings.xml
+++ b/slices/view/src/main/res/values-ur/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"مزید"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"مزید دکھائیں"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-uz/strings.xml b/slices/view/src/main/res/values-uz/strings.xml
index c600886..cbc9979 100644
--- a/slices/view/src/main/res/values-uz/strings.xml
+++ b/slices/view/src/main/res/values-uz/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Yana"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Yana"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-vi/strings.xml b/slices/view/src/main/res/values-vi/strings.xml
index 451b080..3890636 100644
--- a/slices/view/src/main/res/values-vi/strings.xml
+++ b/slices/view/src/main/res/values-vi/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Thêm"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Hiển thị thêm"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-zh-rHK/strings.xml b/slices/view/src/main/res/values-zh-rHK/strings.xml
index b21b9b9..565b565 100644
--- a/slices/view/src/main/res/values-zh-rHK/strings.xml
+++ b/slices/view/src/main/res/values-zh-rHK/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"更多"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"顯示更多"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-zh-rTW/strings.xml b/slices/view/src/main/res/values-zh-rTW/strings.xml
index b21b9b9..565b565 100644
--- a/slices/view/src/main/res/values-zh-rTW/strings.xml
+++ b/slices/view/src/main/res/values-zh-rTW/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"更多"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"顯示更多"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values-zu/strings.xml b/slices/view/src/main/res/values-zu/strings.xml
index 03e6fd1..c5ebb10 100644
--- a/slices/view/src/main/res/values-zu/strings.xml
+++ b/slices/view/src/main/res/values-zu/strings.xml
@@ -20,4 +20,8 @@
<string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
<string name="abc_slice_more" msgid="1983560225998630901">"Okuningi"</string>
<string name="abc_slice_show_more" msgid="1567717014004692768">"Bonisa okuningi"</string>
+ <!-- no translation found for abc_slice_updated (8155085405396453848) -->
+ <skip />
+ <!-- no translation found for abc_slice_error (4188371422904147368) -->
+ <skip />
</resources>
diff --git a/slices/view/src/main/res/values/strings.xml b/slices/view/src/main/res/values/strings.xml
index 8bdfa85..b959f86 100644
--- a/slices/view/src/main/res/values/strings.xml
+++ b/slices/view/src/main/res/values/strings.xml
@@ -16,10 +16,37 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Format string indicating the number of extra items that aren't being displayed. [CHAR LIMIT=none] -->
+ <!-- Format string indicating the number of extra items that aren't being displayed.
+ [CHAR LIMIT=none] -->
<string name="abc_slice_more_content">+ <xliff:g id="number" example="5">%1$d</xliff:g></string>
<!-- Text indicating there is more content available that is not displayed. [CHAR LIMIT=10] -->
<string name="abc_slice_more">More</string>
<!-- String to indicate there is more content to display in a list [CHAR LIMIT=none] -->
<string name="abc_slice_show_more">Show more</string>
+
+ <!-- Format string indicating how old the content in the template is. [CHAR LIMIT=150]-->
+ <string name="abc_slice_updated">Updated <xliff:g id="time" example="5 min ago">%1$s</xliff:g></string>
+
+ <!-- Text describing a time in the past in minutes, ideally this string should use an
+ abbreviated format of the word "minute", if available. [CHAR LIMIT=15]-->
+ <plurals name="abc_slice_duration_min">
+ <item quantity="one"><xliff:g example="1">%d</xliff:g> min ago</item>
+ <item quantity="other"><xliff:g example="2">%d</xliff:g> min ago</item>
+ </plurals>
+ <!-- Text describing a time in the past in years, ideally this string should use an
+ abbreviated format of the word "year", if available. [CHAR LIMIT=15]-->
+ <plurals name="abc_slice_duration_years">
+ <item quantity="one"><xliff:g example="1">%d</xliff:g> yr ago</item>
+ <item quantity="other"><xliff:g example="2">%d</xliff:g> yr ago</item>
+ </plurals>
+ <!-- Text describing a time in the past in days, ideally this string should use an
+ abbreviated format of the word "day", if available. [CHAR LIMIT=15]-->
+ <plurals name="abc_slice_duration_days">
+ <item quantity="one"><xliff:g example="1">%d</xliff:g> day ago</item>
+ <item quantity="other"><xliff:g example="2">%d</xliff:g> days ago</item>
+ </plurals>
+
+ <!-- Text indicating that there was a failure connecting to the app providing the slice
+ [CHAR LIMIT=none]-->
+ <string name="abc_slice_error">Couldn\'t connect</string>
</resources>
\ No newline at end of file
diff --git a/transition/src/main/java/androidx/transition/RectEvaluator.java b/transition/src/main/java/androidx/transition/RectEvaluator.java
index 26527b5..6dab422 100644
--- a/transition/src/main/java/androidx/transition/RectEvaluator.java
+++ b/transition/src/main/java/androidx/transition/RectEvaluator.java
@@ -19,12 +19,9 @@
import android.animation.TypeEvaluator;
import android.graphics.Rect;
-import androidx.annotation.RequiresApi;
-
/**
* This evaluator can be used to perform type interpolation between <code>Rect</code> values.
*/
-@RequiresApi(14)
class RectEvaluator implements TypeEvaluator<Rect> {
/**
diff --git a/transition/src/main/java/androidx/transition/TransitionValuesMaps.java b/transition/src/main/java/androidx/transition/TransitionValuesMaps.java
index 2f57769..4db4603 100644
--- a/transition/src/main/java/androidx/transition/TransitionValuesMaps.java
+++ b/transition/src/main/java/androidx/transition/TransitionValuesMaps.java
@@ -19,11 +19,9 @@
import android.util.SparseArray;
import android.view.View;
-import androidx.annotation.RequiresApi;
import androidx.collection.ArrayMap;
import androidx.collection.LongSparseArray;
-@RequiresApi(14)
class TransitionValuesMaps {
final ArrayMap<View, TransitionValues> mViewValues = new ArrayMap<>();
diff --git a/transition/src/main/java/androidx/transition/ViewGroupOverlayApi14.java b/transition/src/main/java/androidx/transition/ViewGroupOverlayApi14.java
index eda6c5a..f1bd80a 100644
--- a/transition/src/main/java/androidx/transition/ViewGroupOverlayApi14.java
+++ b/transition/src/main/java/androidx/transition/ViewGroupOverlayApi14.java
@@ -21,9 +21,7 @@
import android.view.ViewGroup;
import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-@RequiresApi(14)
class ViewGroupOverlayApi14 extends ViewOverlayApi14 implements ViewGroupOverlayImpl {
ViewGroupOverlayApi14(Context context, ViewGroup hostView, View requestingView) {
diff --git a/transition/src/main/java/androidx/transition/ViewGroupOverlayImpl.java b/transition/src/main/java/androidx/transition/ViewGroupOverlayImpl.java
index 3264a13..be009e3 100644
--- a/transition/src/main/java/androidx/transition/ViewGroupOverlayImpl.java
+++ b/transition/src/main/java/androidx/transition/ViewGroupOverlayImpl.java
@@ -19,9 +19,7 @@
import android.view.View;
import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-@RequiresApi(14)
interface ViewGroupOverlayImpl extends ViewOverlayImpl {
/**
diff --git a/transition/src/main/java/androidx/transition/ViewOverlayApi14.java b/transition/src/main/java/androidx/transition/ViewOverlayApi14.java
index 0a92736..12ebf77 100644
--- a/transition/src/main/java/androidx/transition/ViewOverlayApi14.java
+++ b/transition/src/main/java/androidx/transition/ViewOverlayApi14.java
@@ -28,7 +28,6 @@
import android.view.ViewParent;
import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.core.view.ViewCompat;
@@ -36,7 +35,6 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
-@RequiresApi(14)
class ViewOverlayApi14 implements ViewOverlayImpl {
/**
diff --git a/transition/src/main/java/androidx/transition/ViewOverlayImpl.java b/transition/src/main/java/androidx/transition/ViewOverlayImpl.java
index 68989bf..355bd06 100644
--- a/transition/src/main/java/androidx/transition/ViewOverlayImpl.java
+++ b/transition/src/main/java/androidx/transition/ViewOverlayImpl.java
@@ -19,9 +19,7 @@
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-@RequiresApi(14)
interface ViewOverlayImpl {
/**
diff --git a/transition/src/main/java/androidx/transition/WindowIdApi14.java b/transition/src/main/java/androidx/transition/WindowIdApi14.java
index d36d7c2..6a9231e 100644
--- a/transition/src/main/java/androidx/transition/WindowIdApi14.java
+++ b/transition/src/main/java/androidx/transition/WindowIdApi14.java
@@ -18,9 +18,6 @@
import android.os.IBinder;
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(14)
class WindowIdApi14 implements WindowIdImpl {
private final IBinder mToken;
diff --git a/transition/src/main/java/androidx/transition/WindowIdImpl.java b/transition/src/main/java/androidx/transition/WindowIdImpl.java
index 372694a..ca57588 100644
--- a/transition/src/main/java/androidx/transition/WindowIdImpl.java
+++ b/transition/src/main/java/androidx/transition/WindowIdImpl.java
@@ -16,8 +16,5 @@
package androidx.transition;
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(14)
interface WindowIdImpl {
}
diff --git a/v7/appcompat/src/androidTest/AndroidManifest.xml b/v7/appcompat/src/androidTest/AndroidManifest.xml
index 008e19a..945ebeb 100644
--- a/v7/appcompat/src/androidTest/AndroidManifest.xml
+++ b/v7/appcompat/src/androidTest/AndroidManifest.xml
@@ -42,6 +42,11 @@
android:theme="@style/Theme.SampleDrawerLayout"/>
<activity
+ android:name="androidx.appcompat.app.DrawerInteractionActivity"
+ android:label="@string/drawer_layout_activity"
+ android:theme="@style/Theme.SampleDrawerLayout"/>
+
+ <activity
android:name="androidx.appcompat.app.DrawerLayoutDoubleActivity"
android:label="@string/drawer_layout_activity"
android:theme="@style/Theme.SampleDrawerLayout"/>
diff --git a/loader/src/androidTest/java/androidx/loader/app/test/EmptyActivity.java b/v7/appcompat/src/androidTest/java/androidx/appcompat/app/DrawerInteractionActivity.java
similarity index 71%
rename from loader/src/androidTest/java/androidx/loader/app/test/EmptyActivity.java
rename to v7/appcompat/src/androidTest/java/androidx/appcompat/app/DrawerInteractionActivity.java
index 1b55e3b..ae7154a 100644
--- a/loader/src/androidTest/java/androidx/loader/app/test/EmptyActivity.java
+++ b/v7/appcompat/src/androidTest/java/androidx/appcompat/app/DrawerInteractionActivity.java
@@ -14,9 +14,13 @@
* limitations under the License.
*/
-package androidx.loader.app.test;
+package androidx.appcompat.app;
-import androidx.core.app.SupportActivity;
+import androidx.appcompat.testutils.BaseTestActivity;
-public class EmptyActivity extends SupportActivity {
+public class DrawerInteractionActivity extends BaseTestActivity {
+ @Override
+ protected int getContentViewLayoutResId() {
+ return 0;
+ }
}
diff --git a/v7/appcompat/src/androidTest/java/androidx/appcompat/app/DrawerInteractionTest.java b/v7/appcompat/src/androidTest/java/androidx/appcompat/app/DrawerInteractionTest.java
new file mode 100755
index 0000000..1c3f6c0
--- /dev/null
+++ b/v7/appcompat/src/androidTest/java/androidx/appcompat/app/DrawerInteractionTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.app;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
+
+import static androidx.appcompat.testutils.DrawerLayoutActions.openDrawer;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Gravity;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.core.view.GravityCompat;
+import androidx.drawerlayout.widget.DrawerLayout;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DrawerInteractionTest {
+
+ @Rule
+ public final ActivityTestRule<DrawerInteractionActivity> mActivityTestRule =
+ new ActivityTestRule<>(DrawerInteractionActivity.class);
+
+ private TestDrawerLayout mDrawerLayout;
+ private View mStartDrawer;
+ private View mContentView;
+
+ @Before
+ public void setUp() throws Throwable {
+ final Activity activity = mActivityTestRule.getActivity();
+
+ Context context = InstrumentationRegistry.getContext();
+ mDrawerLayout = new TestDrawerLayout(InstrumentationRegistry.getContext());
+ mContentView = Mockito.spy(new View(context));
+ mStartDrawer = Mockito.spy(new View(context));
+
+ mDrawerLayout.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
+ DrawerLayout.LayoutParams contentViewLayoutParams = new DrawerLayout.LayoutParams(100, 100);
+ DrawerLayout.LayoutParams drawerViewLayoutParams = new DrawerLayout.LayoutParams(50, 100);
+
+ contentViewLayoutParams.gravity = Gravity.NO_GRAVITY;
+ drawerViewLayoutParams.gravity = Gravity.START;
+
+ mContentView.setLayoutParams(contentViewLayoutParams);
+ mStartDrawer.setLayoutParams(drawerViewLayoutParams);
+ mStartDrawer.setBackgroundColor(0xFF00FF00);
+
+ mDrawerLayout.addView(mContentView);
+ mDrawerLayout.addView(mStartDrawer);
+ mDrawerLayout.setBackgroundColor(0xFFFF0000);
+
+ mDrawerLayout.expectLayouts(1);
+ mActivityTestRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.setContentView(mDrawerLayout);
+ }
+ });
+ assertThat(mDrawerLayout.waitForLayouts(2), is(true));
+ }
+
+ // Verification that DrawerLayout blocks certain pointer motion events from getting to the
+ // content view when the drawer is open.
+
+ @Test
+ @LargeTest
+ public void ui_pointerEvent_overDrawer_receivedByDrawer() throws Throwable {
+ onView(isAssignableFrom(DrawerLayout.class)).perform(openDrawer(
+ GravityCompat.START));
+ MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 25, 50, 0);
+ motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);
+
+ mDrawerLayout.dispatchGenericMotionEvent(motionEvent);
+
+ verify(mStartDrawer).dispatchGenericMotionEvent(motionEvent);
+
+ }
+
+ @Test
+ @LargeTest
+ public void ui_pointerEvent_overDrawer_notReceivedByContent() throws Throwable {
+ onView(isAssignableFrom(DrawerLayout.class)).perform(openDrawer(
+ GravityCompat.START));
+ MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 25, 50, 0);
+ motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);
+
+ mDrawerLayout.dispatchGenericMotionEvent(motionEvent);
+
+ verify(mContentView, never()).dispatchGenericMotionEvent(any(MotionEvent.class));
+ }
+
+ @Test
+ @LargeTest
+ public void ui_pointerEvent_overContentDrawerOpen_notReceivedByContent() throws Throwable {
+ onView(isAssignableFrom(DrawerLayout.class)).perform(openDrawer(
+ GravityCompat.START));
+ MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 75, 50, 0);
+ motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);
+
+ mDrawerLayout.dispatchGenericMotionEvent(motionEvent);
+
+ verify(mContentView, never()).dispatchGenericMotionEvent(any(MotionEvent.class));
+ }
+
+ @Test
+ @LargeTest
+ public void ui_pointerEvent_overContentDrawerClosed_receivedByContent() {
+ MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 75, 50, 0);
+ motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);
+
+ mDrawerLayout.dispatchGenericMotionEvent(motionEvent);
+
+ verify(mContentView).dispatchGenericMotionEvent(motionEvent);
+ }
+
+ private class TestDrawerLayout extends DrawerLayout {
+
+ CountDownLatch mLayoutCountDownLatch;
+
+ TestDrawerLayout(Context context) {
+ super(context);
+ }
+
+ public void expectLayouts(int count) {
+ mLayoutCountDownLatch = new CountDownLatch(count);
+ }
+
+ public boolean waitForLayouts(int seconds) throws InterruptedException {
+ boolean result = mLayoutCountDownLatch.await(seconds, TimeUnit.SECONDS);
+ mLayoutCountDownLatch = null;
+ return result;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (mLayoutCountDownLatch != null) {
+ mLayoutCountDownLatch.countDown();
+ }
+ }
+
+ }
+
+
+}
diff --git a/v7/appcompat/src/androidTest/java/androidx/appcompat/app/LayoutInflaterFactoryTestCase.java b/v7/appcompat/src/androidTest/java/androidx/appcompat/app/LayoutInflaterFactoryTestCase.java
index 598df4d..5bae3ef 100644
--- a/v7/appcompat/src/androidTest/java/androidx/appcompat/app/LayoutInflaterFactoryTestCase.java
+++ b/v7/appcompat/src/androidTest/java/androidx/appcompat/app/LayoutInflaterFactoryTestCase.java
@@ -23,7 +23,6 @@
import android.content.Context;
import android.content.res.Resources;
import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -34,7 +33,6 @@
import android.view.ViewGroup;
import android.widget.LinearLayout;
-import androidx.annotation.RequiresApi;
import androidx.appcompat.custom.ContextWrapperFrameLayout;
import androidx.appcompat.test.R;
import androidx.appcompat.widget.AppCompatAutoCompleteTextView;
@@ -81,8 +79,6 @@
}
// Propagation of themed context to children only works on API 11+.
- @SdkSuppress(minSdkVersion = 11)
- @RequiresApi(11)
@UiThreadTest
@Test
@SmallTest
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggle.java b/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggle.java
index d90b7bd..4941938 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggle.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggle.java
@@ -28,7 +28,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable;
import androidx.appcompat.widget.Toolbar;
@@ -208,10 +207,8 @@
});
} else if (activity instanceof DelegateProvider) { // Allow the Activity to provide an impl
mActivityImpl = ((DelegateProvider) activity).getDrawerToggleDelegate();
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- mActivityImpl = new JellybeanMr2Delegate(activity);
} else {
- mActivityImpl = new IcsDelegate(activity);
+ mActivityImpl = new FrameworkActionBarDelegate(activity);
}
mDrawerLayout = drawerLayout;
@@ -515,33 +512,34 @@
mSlider.setProgress(position);
}
- /**
- * Delegate if SDK version is between ICS and JBMR2
- */
- private static class IcsDelegate implements Delegate {
+ private static class FrameworkActionBarDelegate implements Delegate {
+ private final Activity mActivity;
+ private ActionBarDrawerToggleHoneycomb.SetIndicatorInfo mSetIndicatorInfo;
- final Activity mActivity;
- ActionBarDrawerToggleHoneycomb.SetIndicatorInfo mSetIndicatorInfo;
-
- IcsDelegate(Activity activity) {
+ FrameworkActionBarDelegate(Activity activity) {
mActivity = activity;
}
@Override
public Drawable getThemeUpIndicator() {
+ if (Build.VERSION.SDK_INT >= 18) {
+ final TypedArray a = getActionBarThemedContext().obtainStyledAttributes(null,
+ new int[] {android.R.attr.homeAsUpIndicator},
+ android.R.attr.actionBarStyle, 0);
+ final Drawable result = a.getDrawable(0);
+ a.recycle();
+ return result;
+ }
return ActionBarDrawerToggleHoneycomb.getThemeUpIndicator(mActivity);
}
@Override
public Context getActionBarThemedContext() {
final ActionBar actionBar = mActivity.getActionBar();
- final Context context;
if (actionBar != null) {
- context = actionBar.getThemedContext();
- } else {
- context = mActivity;
+ return actionBar.getThemedContext();
}
- return context;
+ return mActivity;
}
@Override
@@ -555,74 +553,28 @@
public void setActionBarUpIndicator(Drawable themeImage, int contentDescRes) {
final ActionBar actionBar = mActivity.getActionBar();
if (actionBar != null) {
- actionBar.setDisplayShowHomeEnabled(true);
- mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarUpIndicator(
+ if (Build.VERSION.SDK_INT >= 18) {
+ actionBar.setHomeAsUpIndicator(themeImage);
+ actionBar.setHomeActionContentDescription(contentDescRes);
+ } else {
+ actionBar.setDisplayShowHomeEnabled(true);
+ mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarUpIndicator(
mSetIndicatorInfo, mActivity, themeImage, contentDescRes);
- actionBar.setDisplayShowHomeEnabled(false);
+ actionBar.setDisplayShowHomeEnabled(false);
+ }
}
}
@Override
public void setActionBarDescription(int contentDescRes) {
- mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarDescription(
- mSetIndicatorInfo, mActivity, contentDescRes);
- }
- }
-
- /**
- * Delegate if SDK version is JB MR2 or newer
- */
- @RequiresApi(18)
- private static class JellybeanMr2Delegate implements Delegate {
-
- final Activity mActivity;
-
- JellybeanMr2Delegate(Activity activity) {
- mActivity = activity;
- }
-
- @Override
- public Drawable getThemeUpIndicator() {
- final TypedArray a = getActionBarThemedContext().obtainStyledAttributes(null,
- new int[]{android.R.attr.homeAsUpIndicator}, android.R.attr.actionBarStyle, 0);
- final Drawable result = a.getDrawable(0);
- a.recycle();
- return result;
- }
-
- @Override
- public Context getActionBarThemedContext() {
- final ActionBar actionBar = mActivity.getActionBar();
- final Context context;
- if (actionBar != null) {
- context = actionBar.getThemedContext();
+ if (Build.VERSION.SDK_INT >= 18) {
+ final ActionBar actionBar = mActivity.getActionBar();
+ if (actionBar != null) {
+ actionBar.setHomeActionContentDescription(contentDescRes);
+ }
} else {
- context = mActivity;
- }
- return context;
- }
-
- @Override
- public boolean isNavigationVisible() {
- final ActionBar actionBar = mActivity.getActionBar();
- return actionBar != null &&
- (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0;
- }
-
- @Override
- public void setActionBarUpIndicator(Drawable drawable, int contentDescRes) {
- final ActionBar actionBar = mActivity.getActionBar();
- if (actionBar != null) {
- actionBar.setHomeAsUpIndicator(drawable);
- actionBar.setHomeActionContentDescription(contentDescRes);
- }
- }
-
- @Override
- public void setActionBarDescription(int contentDescRes) {
- final ActionBar actionBar = mActivity.getActionBar();
- if (actionBar != null) {
- actionBar.setHomeActionContentDescription(contentDescRes);
+ mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarDescription(
+ mSetIndicatorInfo, mActivity, contentDescRes);
}
}
}
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggleHoneycomb.java b/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggleHoneycomb.java
index 9d2c718..ac02d1b 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggleHoneycomb.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/app/ActionBarDrawerToggleHoneycomb.java
@@ -28,8 +28,6 @@
import android.view.ViewGroup;
import android.widget.ImageView;
-import androidx.annotation.RequiresApi;
-
import java.lang.reflect.Method;
/**
@@ -41,7 +39,6 @@
*
* Moved from Support-v4
*/
-@RequiresApi(11)
class ActionBarDrawerToggleHoneycomb {
private static final String TAG = "ActionBarDrawerToggleHC";
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuItemWrapperICS.java b/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuItemWrapperICS.java
index 860ed18..d98acf3 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuItemWrapperICS.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuItemWrapperICS.java
@@ -30,7 +30,6 @@
import android.view.View;
import android.widget.FrameLayout;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.appcompat.view.CollapsibleActionView;
import androidx.core.internal.view.SupportMenuItem;
@@ -43,7 +42,6 @@
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
-@RequiresApi(14)
public class MenuItemWrapperICS extends BaseMenuWrapper<SupportMenuItem> implements MenuItem {
static final String LOG_TAG = "MenuItemWrapper";
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuWrapperICS.java b/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuWrapperICS.java
index 71252c9..b7e370e 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuWrapperICS.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/view/menu/MenuWrapperICS.java
@@ -24,13 +24,11 @@
import android.view.MenuItem;
import android.view.SubMenu;
-import androidx.annotation.RequiresApi;
import androidx.core.internal.view.SupportMenu;
/**
* Wraps a support {@link SupportMenu} as a framework {@link android.view.Menu}
*/
-@RequiresApi(14)
class MenuWrapperICS extends BaseMenuWrapper<SupportMenu> implements Menu {
MenuWrapperICS(Context context, SupportMenu object) {
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/view/menu/SubMenuWrapperICS.java b/v7/appcompat/src/main/java/androidx/appcompat/view/menu/SubMenuWrapperICS.java
index 5d57567..21d8a3d 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/view/menu/SubMenuWrapperICS.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/view/menu/SubMenuWrapperICS.java
@@ -24,7 +24,6 @@
import android.view.SubMenu;
import android.view.View;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.core.internal.view.SupportSubMenu;
@@ -33,7 +32,6 @@
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
-@RequiresApi(14)
class SubMenuWrapperICS extends MenuWrapperICS implements SubMenu {
SubMenuWrapperICS(Context context, SupportSubMenu subMenu) {
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarBackgroundDrawable.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarBackgroundDrawable.java
index 9e95d84..175cdb3 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarBackgroundDrawable.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarBackgroundDrawable.java
@@ -18,12 +18,12 @@
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.Outline;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.NonNull;
-@RequiresApi(9)
class ActionBarBackgroundDrawable extends Drawable {
final ActionBarContainer mContainer;
@@ -61,4 +61,17 @@
return PixelFormat.UNKNOWN;
}
+ @Override
+ public void getOutline(@NonNull Outline outline) {
+ if (mContainer.mIsSplit) {
+ if (mContainer.mSplitBackground != null) {
+ mContainer.mSplitBackground.getOutline(outline);
+ }
+ } else {
+ // ignore the stacked background for shadow casting
+ if (mContainer.mBackground != null) {
+ mContainer.mBackground.getOutline(outline);
+ }
+ }
+ }
}
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarBackgroundDrawableV21.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarBackgroundDrawableV21.java
deleted file mode 100644
index 1438004..0000000
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarBackgroundDrawableV21.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.appcompat.widget;
-
-import android.graphics.Outline;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-@RequiresApi(21)
-class ActionBarBackgroundDrawableV21 extends ActionBarBackgroundDrawable {
-
- public ActionBarBackgroundDrawableV21(ActionBarContainer container) {
- super(container);
- }
-
- @Override
- public void getOutline(@NonNull Outline outline) {
- if (mContainer.mIsSplit) {
- if (mContainer.mSplitBackground != null) {
- mContainer.mSplitBackground.getOutline(outline);
- }
- } else {
- // ignore the stacked background for shadow casting
- if (mContainer.mBackground != null) {
- mContainer.mBackground.getOutline(outline);
- }
- }
- }
-}
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarContainer.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarContainer.java
index d965ded..49e063f 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarContainer.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/ActionBarContainer.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -59,9 +58,7 @@
super(context, attrs);
// Set a transparent background so that we project appropriately.
- final Drawable bg = Build.VERSION.SDK_INT >= 21
- ? new ActionBarBackgroundDrawableV21(this)
- : new ActionBarBackgroundDrawable(this);
+ final Drawable bg = new ActionBarBackgroundDrawable(this);
ViewCompat.setBackground(this, bg);
TypedArray a = context.obtainStyledAttributes(attrs,
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java
index ec29cdb..b4dee76 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java
@@ -31,7 +31,6 @@
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.appcompat.R;
import androidx.core.view.TintableBackgroundView;
@@ -175,7 +174,6 @@
event.setClassName(Button.class.getName());
}
- @RequiresApi(14)
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatDrawableManager.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatDrawableManager.java
index 8fa121e..31d92e8 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatDrawableManager.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatDrawableManager.java
@@ -43,7 +43,6 @@
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.appcompat.R;
import androidx.collection.ArrayMap;
@@ -781,7 +780,6 @@
}
}
- @RequiresApi(11)
private static class AvdcInflateDelegate implements InflateDelegate {
AvdcInflateDelegate() {
}
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBar.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBar.java
index fcbede9..bcf37b7 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBar.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBar.java
@@ -21,7 +21,6 @@
import android.util.AttributeSet;
import android.widget.SeekBar;
-import androidx.annotation.RequiresApi;
import androidx.appcompat.R;
/**
@@ -63,7 +62,6 @@
mAppCompatSeekBarHelper.drawableStateChanged();
}
- @RequiresApi(11)
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBarHelper.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBarHelper.java
index f7560b7..9d1ffc3 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBarHelper.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatSeekBarHelper.java
@@ -24,7 +24,6 @@
import android.widget.SeekBar;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.appcompat.R;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.ViewCompat;
@@ -142,7 +141,6 @@
}
}
- @RequiresApi(11)
void jumpDrawablesToCurrentState() {
if (mTickMark != null) {
mTickMark.jumpToCurrentState();
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java
index 93f3512..bb3b5bb 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java
@@ -32,7 +32,6 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.appcompat.R;
import androidx.core.content.res.ResourcesCompat;
@@ -40,7 +39,6 @@
import java.lang.ref.WeakReference;
-@RequiresApi(9)
class AppCompatTextHelper {
// Enum for the "typeface" XML parameter.
diff --git a/v7/recyclerview/src/main/java/androidx/recyclerview/widget/PositionMap.java b/v7/recyclerview/src/main/java/androidx/recyclerview/widget/PositionMap.java
deleted file mode 100644
index b5bf5a4..0000000
--- a/v7/recyclerview/src/main/java/androidx/recyclerview/widget/PositionMap.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package androidx.recyclerview.widget;
-
-import java.util.ArrayList;
-
-/**
- * Like a SparseArray, but with the ability to offset key ranges for bulk insertions/deletions.
- */
-class PositionMap<E> implements Cloneable {
- private static final Object DELETED = new Object();
- private boolean mGarbage = false;
-
- private int[] mKeys;
- private Object[] mValues;
- private int mSize;
-
- /**
- * Creates a new SparseArray containing no mappings.
- */
- PositionMap() {
- this(10);
- }
-
- /**
- * Creates a new PositionMap containing no mappings that will not
- * require any additional memory allocation to store the specified
- * number of mappings. If you supply an initial capacity of 0, the
- * sparse array will be initialized with a light-weight representation
- * not requiring any additional array allocations.
- */
- PositionMap(int initialCapacity) {
- if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_OBJECTS;
- } else {
- initialCapacity = idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new Object[initialCapacity];
- }
- mSize = 0;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public PositionMap<E> clone() {
- PositionMap<E> clone = null;
- try {
- clone = (PositionMap<E>) super.clone();
- clone.mKeys = mKeys.clone();
- clone.mValues = mValues.clone();
- } catch (CloneNotSupportedException cnse) {
- /* ignore */
- }
- return clone;
- }
-
- /**
- * Gets the Object mapped from the specified key, or <code>null</code>
- * if no such mapping has been made.
- */
- public E get(int key) {
- return get(key, null);
- }
-
- /**
- * Gets the Object mapped from the specified key, or the specified Object
- * if no such mapping has been made.
- */
- @SuppressWarnings("unchecked")
- public E get(int key, E valueIfKeyNotFound) {
- int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
-
- if (i < 0 || mValues[i] == DELETED) {
- return valueIfKeyNotFound;
- } else {
- return (E) mValues[i];
- }
- }
-
- /**
- * Removes the mapping from the specified key, if there was any.
- */
- public void delete(int key) {
- int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
-
- if (i >= 0) {
- if (mValues[i] != DELETED) {
- mValues[i] = DELETED;
- mGarbage = true;
- }
- }
- }
-
- /**
- * Alias for {@link #delete(int)}.
- */
- public void remove(int key) {
- delete(key);
- }
-
- /**
- * Removes the mapping at the specified index.
- */
- public void removeAt(int index) {
- if (mValues[index] != DELETED) {
- mValues[index] = DELETED;
- mGarbage = true;
- }
- }
-
- /**
- * Remove a range of mappings as a batch.
- *
- * @param index Index to begin at
- * @param size Number of mappings to remove
- */
- public void removeAtRange(int index, int size) {
- final int end = Math.min(mSize, index + size);
- for (int i = index; i < end; i++) {
- removeAt(i);
- }
- }
-
- public void insertKeyRange(int keyStart, int count) {
-
- }
-
- public void removeKeyRange(ArrayList<E> removedItems, int keyStart, int count) {
-
- }
-
- private void gc() {
- // Log.e("SparseArray", "gc start with " + mSize);
-
- int n = mSize;
- int o = 0;
- int[] keys = mKeys;
- Object[] values = mValues;
-
- for (int i = 0; i < n; i++) {
- Object val = values[i];
-
- if (val != DELETED) {
- if (i != o) {
- keys[o] = keys[i];
- values[o] = val;
- values[i] = null;
- }
-
- o++;
- }
- }
-
- mGarbage = false;
- mSize = o;
-
- // Log.e("SparseArray", "gc end with " + mSize);
- }
-
- /**
- * Adds a mapping from the specified key to the specified value,
- * replacing the previous mapping from the specified key if there
- * was one.
- */
- public void put(int key, E value) {
- int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
-
- if (i >= 0) {
- mValues[i] = value;
- } else {
- i = ~i;
-
- if (i < mSize && mValues[i] == DELETED) {
- mKeys[i] = key;
- mValues[i] = value;
- return;
- }
-
- if (mGarbage && mSize >= mKeys.length) {
- gc();
-
- // Search again because indices may have changed.
- i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
- }
-
- if (mSize >= mKeys.length) {
- int n = idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
- mSize++;
- }
- }
-
- /**
- * Returns the number of key-value mappings that this SparseArray
- * currently stores.
- */
- public int size() {
- if (mGarbage) {
- gc();
- }
-
- return mSize;
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the key from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public int keyAt(int index) {
- if (mGarbage) {
- gc();
- }
-
- return mKeys[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the value from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- @SuppressWarnings("unchecked")
- public E valueAt(int index) {
- if (mGarbage) {
- gc();
- }
-
- return (E) mValues[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, sets a new
- * value for the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public void setValueAt(int index, E value) {
- if (mGarbage) {
- gc();
- }
-
- mValues[index] = value;
- }
-
- /**
- * Returns the index for which {@link #keyAt} would return the
- * specified key, or a negative number if the specified
- * key is not mapped.
- */
- public int indexOfKey(int key) {
- if (mGarbage) {
- gc();
- }
-
- return ContainerHelpers.binarySearch(mKeys, mSize, key);
- }
-
- /**
- * Returns an index for which {@link #valueAt} would return the
- * specified key, or a negative number if no keys map to the
- * specified value.
- * <p>Beware that this is a linear search, unlike lookups by key,
- * and that multiple keys can map to the same value and this will
- * find only one of them.
- * <p>Note also that unlike most collections' {@code indexOf} methods,
- * this method compares values using {@code ==} rather than {@code equals}.
- */
- public int indexOfValue(E value) {
- if (mGarbage) {
- gc();
- }
-
- for (int i = 0; i < mSize; i++) {
- if (mValues[i] == value) {
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Removes all key-value mappings from this SparseArray.
- */
- public void clear() {
- int n = mSize;
- Object[] values = mValues;
-
- for (int i = 0; i < n; i++) {
- values[i] = null;
- }
-
- mSize = 0;
- mGarbage = false;
- }
-
- /**
- * Puts a key/value pair into the array, optimizing for the case where
- * the key is greater than all existing keys in the array.
- */
- public void append(int key, E value) {
- if (mSize != 0 && key <= mKeys[mSize - 1]) {
- put(key, value);
- return;
- }
-
- if (mGarbage && mSize >= mKeys.length) {
- gc();
- }
-
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- /**
- * {@inheritDoc}
- *
- * <p>This implementation composes a string by iterating over its mappings. If
- * this map contains itself as a value, the string "(this Map)"
- * will appear in its place.
- */
- @Override
- public String toString() {
- if (size() <= 0) {
- return "{}";
- }
-
- StringBuilder buffer = new StringBuilder(mSize * 28);
- buffer.append('{');
- for (int i = 0; i < mSize; i++) {
- if (i > 0) {
- buffer.append(", ");
- }
- int key = keyAt(i);
- buffer.append(key);
- buffer.append('=');
- Object value = valueAt(i);
- if (value != this) {
- buffer.append(value);
- } else {
- buffer.append("(this Map)");
- }
- }
- buffer.append('}');
- return buffer.toString();
- }
-
- static int idealByteArraySize(int need) {
- for (int i = 4; i < 32; i++) {
- if (need <= (1 << i) - 12) {
- return (1 << i) - 12;
- }
- }
-
- return need;
- }
-
- static int idealBooleanArraySize(int need) {
- return idealByteArraySize(need);
- }
-
- static int idealShortArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
- }
-
- static int idealCharArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
- }
-
- static int idealIntArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
- }
-
- static int idealFloatArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
- }
-
- static int idealObjectArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
- }
-
- static int idealLongArraySize(int need) {
- return idealByteArraySize(need * 8) / 8;
- }
-
- static class ContainerHelpers {
- static final boolean[] EMPTY_BOOLEANS = new boolean[0];
- static final int[] EMPTY_INTS = new int[0];
- static final long[] EMPTY_LONGS = new long[0];
- static final Object[] EMPTY_OBJECTS = new Object[0];
-
- // This is Arrays.binarySearch(), but doesn't do any argument validation.
- static int binarySearch(int[] array, int size, int value) {
- int lo = 0;
- int hi = size - 1;
-
- while (lo <= hi) {
- final int mid = (lo + hi) >>> 1;
- final int midVal = array[mid];
-
- if (midVal < value) {
- lo = mid + 1;
- } else if (midVal > value) {
- hi = mid - 1;
- } else {
- return mid; // value found
- }
- }
- return ~lo; // value not present
- }
- }
-
-}
diff --git a/viewpager2/src/androidTest/AndroidManifest.xml b/viewpager2/src/androidTest/AndroidManifest.xml
index d1332fa..8e7596b 100755
--- a/viewpager2/src/androidTest/AndroidManifest.xml
+++ b/viewpager2/src/androidTest/AndroidManifest.xml
@@ -19,6 +19,7 @@
<uses-sdk android:targetSdkVersion="${target-sdk-version}"/>
<application android:supportsRtl="true">
- <activity android:name="androidx.viewpager2.widget.TestActivity"/>
+ <activity android:name="androidx.viewpager2.widget.swipe.ViewAdapterActivity"/>
+ <activity android:name="androidx.viewpager2.widget.swipe.FragmentAdapterActivity"/>
</application>
</manifest>
\ No newline at end of file
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BasicTest.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BasicTest.java
new file mode 100644
index 0000000..483317b
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/BasicTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.viewpager2.widget;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.arrayWithSize;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import java.util.UUID;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BasicTest {
+ @Rule
+ public ExpectedException mExpectedException = ExpectedException.none();
+
+ @Test
+ public void test_recyclerViewAdapter_pageFillEnforced() {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage(
+ "Item's root view must fill the whole ViewPager2 (use match_parent)");
+
+ ViewPager2 viewPager = new ViewPager2(InstrumentationRegistry.getContext());
+ viewPager.setAdapter(new RecyclerView.Adapter<RecyclerView.ViewHolder>() {
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
+ int viewType) {
+ View view = new View(parent.getContext());
+ view.setLayoutParams(new ViewGroup.LayoutParams(50, 50)); // arbitrary fixed size
+ return new RecyclerView.ViewHolder(view) {
+ };
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+ // do nothing
+ }
+
+ @Override
+ public int getItemCount() {
+ return 1;
+ }
+ });
+
+ viewPager.measure(0, 0); // equivalent of unspecified
+ }
+
+ @Test
+ public void test_childrenNotAllowed() throws Exception {
+ mExpectedException.expect(IllegalStateException.class);
+ mExpectedException.expectMessage("ViewPager2 does not support direct child views");
+
+ Context context = InstrumentationRegistry.getContext();
+ ViewPager2 viewPager = new ViewPager2(context);
+ viewPager.addView(new View(context));
+ }
+
+ @Test
+ public void test_saveStateParcel_createRestore() throws Throwable {
+ // given
+ Bundle superState = createIntBundle(42);
+ ViewPager2.SavedState state = new ViewPager2.SavedState(superState);
+ state.mRecyclerViewId = 700;
+ state.mAdapterState = new Parcelable[]{createIntBundle(1), createIntBundle(2),
+ createIntBundle(3)};
+
+ // when
+ Parcel parcel = Parcel.obtain();
+ state.writeToParcel(parcel, 0);
+ final String parcelSuffix = UUID.randomUUID().toString();
+ parcel.writeString(parcelSuffix); // to verify parcel boundaries
+ parcel.setDataPosition(0);
+ ViewPager2.SavedState recreatedState = ViewPager2.SavedState.CREATOR.createFromParcel(
+ parcel);
+
+ // then
+ assertThat("Parcel reading should not go out of bounds", parcel.readString(),
+ equalTo(parcelSuffix));
+ assertThat("All of the parcel should be read", parcel.dataAvail(), equalTo(0));
+ assertThat(recreatedState.mRecyclerViewId, equalTo(700));
+ assertThat(recreatedState.mAdapterState, arrayWithSize(3));
+ assertThat((int) ((Bundle) recreatedState.getSuperState()).get("key"), equalTo(42));
+ assertThat((int) ((Bundle) recreatedState.mAdapterState[0]).get("key"), equalTo(1));
+ assertThat((int) ((Bundle) recreatedState.mAdapterState[1]).get("key"), equalTo(2));
+ assertThat((int) ((Bundle) recreatedState.mAdapterState[2]).get("key"), equalTo(3));
+ }
+
+ private Bundle createIntBundle(int value) {
+ Bundle bundle = new Bundle(1);
+ bundle.putInt("key", value);
+ return bundle;
+ }
+}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SwipeTest.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SwipeTest.java
new file mode 100644
index 0000000..8d32543
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/SwipeTest.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.viewpager2.widget;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static android.view.View.OVER_SCROLL_NEVER;
+
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+
+import android.os.Build;
+import android.support.test.filters.LargeTest;
+import android.support.test.rule.ActivityTestRule;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.testutils.FragmentActivityUtils;
+import androidx.viewpager2.test.R;
+import androidx.viewpager2.widget.swipe.BaseActivity;
+import androidx.viewpager2.widget.swipe.FragmentAdapterActivity;
+import androidx.viewpager2.widget.swipe.PageSwiper;
+import androidx.viewpager2.widget.swipe.ViewAdapterActivity;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+@LargeTest
+@RunWith(Parameterized.class)
+public class SwipeTest {
+ private static final List<Class<? extends BaseActivity>> TEST_ACTIVITIES_ALL = asList(
+ ViewAdapterActivity.class, FragmentAdapterActivity.class);
+ private static final Set<Integer> NO_CONFIG_CHANGES = Collections.emptySet();
+ private static final List<Pair<Integer, Integer>> NO_MUTATIONS = Collections.emptyList();
+ private static final boolean RANDOM_PASS_ENABLED = false;
+
+ private final TestConfig mTestConfig;
+ private ActivityTestRule<? extends BaseActivity> mActivityTestRule;
+ private PageSwiper mSwiper;
+
+ public SwipeTest(TestConfig testConfig) {
+ mTestConfig = testConfig;
+ }
+
+ @Test
+ public void test() throws Throwable {
+ BaseActivity activity = mActivityTestRule.getActivity();
+
+ final int[] expectedValues = new int[mTestConfig.mTotalPages];
+ for (int i = 0; i < mTestConfig.mTotalPages; i++) {
+ expectedValues[i] = i;
+ }
+
+ int currentPage = 0, currentStep = 0;
+ assertStateCorrect(expectedValues[currentPage], activity);
+ for (int nextPage : mTestConfig.mPageSequence) {
+ // value change
+ if (mTestConfig.mStepToNewValue.containsKey(currentStep)) {
+ expectedValues[currentPage] = mTestConfig.mStepToNewValue.get(currentStep);
+ updatePage(currentPage, expectedValues[currentPage], activity);
+ assertStateCorrect(expectedValues[currentPage], activity);
+ }
+
+ // config change
+ if (mTestConfig.mConfigChangeSteps.contains(currentStep++)) {
+ activity = FragmentActivityUtils.recreateActivity(mActivityTestRule, activity);
+ assertStateCorrect(expectedValues[currentPage], activity);
+ }
+
+ // page swipe
+ mSwiper.swipe(currentPage, nextPage);
+ currentPage = nextPage;
+ assertStateCorrect(expectedValues[currentPage], activity);
+ }
+ }
+
+ private static void updatePage(final int pageIx, final int newValue,
+ final BaseActivity activity) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.updatePage(pageIx, newValue);
+ }
+ });
+ }
+
+ private void assertStateCorrect(int expectedValue, BaseActivity activity) {
+ onView(allOf(withId(R.id.text_view), isDisplayed())).check(
+ matches(withText(String.valueOf(expectedValue))));
+ activity.validateState();
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<TestConfig> getParams() {
+ List<TestConfig> tests = new ArrayList<>();
+
+ if (RANDOM_PASS_ENABLED) { // run locally after making larger changes
+ tests.addAll(generateRandomTests());
+ }
+
+ for (Class<? extends BaseActivity> activityClass : TEST_ACTIVITIES_ALL) {
+ tests.add(new TestConfig("full pass", asList(1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0),
+ NO_CONFIG_CHANGES, NO_MUTATIONS, 8, activityClass));
+
+ tests.add(new TestConfig("swipe beyond edge pages",
+ asList(0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0), NO_CONFIG_CHANGES, NO_MUTATIONS, 4,
+ activityClass));
+
+ tests.add(new TestConfig("config change", asList(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
+ asList(3, 5, 7), NO_MUTATIONS, 7, activityClass));
+
+ tests.add(
+ new TestConfig("regression1", asList(1, 2, 3, 2, 1, 2, 3, 4), NO_CONFIG_CHANGES,
+ NO_MUTATIONS, 10, activityClass));
+
+ tests.add(new TestConfig("regression2", asList(1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5),
+ NO_CONFIG_CHANGES, NO_MUTATIONS, 10, activityClass));
+
+ tests.add(new TestConfig("regression3", asList(1, 2, 3, 2, 1, 2, 3, 2, 1, 0),
+ NO_CONFIG_CHANGES, NO_MUTATIONS, 10, activityClass));
+ }
+
+ // mutations only apply to Fragment state persistence
+ tests.add(new TestConfig("mutations", asList(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
+ singletonList(8),
+ asList(Pair.create(0, 999), Pair.create(1, 100), Pair.create(3, 300),
+ Pair.create(5, 500)), 7, FragmentAdapterActivity.class));
+
+ return checkTestNamesUnique(tests);
+ }
+
+ private static Collection<TestConfig> generateRandomTests() {
+ List<TestConfig> result = new ArrayList<>();
+
+ int id = 0;
+ for (int i = 0; i < 10; i++) {
+ // both adapters
+ for (Class<? extends BaseActivity> adapterClass : TEST_ACTIVITIES_ALL) {
+ result.add(createRandomTest(id++, 8, 50, 0, 0, 0.875, adapterClass));
+ result.add(createRandomTest(id++, 8, 10, 0.5, 0, 0.875, adapterClass));
+ }
+
+ // fragment adapter specific
+ result.add(
+ createRandomTest(id++, 8, 50, 0, 0.125, 0.875, FragmentAdapterActivity.class));
+ result.add(createRandomTest(id++, 8, 10, 0.5, 0.125, 0.875,
+ FragmentAdapterActivity.class));
+ }
+
+ return result;
+ }
+
+ /**
+ * @param advanceProbability determines the probability of a swipe direction being towards
+ * the next edge - e.g. if we start from the left, it's the
+ * probability that the next swipe will go right. <p> Setting it to
+ * values closer to 0.5 results in a lot of back and forth, while
+ * setting it closer to 1.0 results in going edge to edge with few
+ * back-swipes.
+ */
+ @SuppressWarnings("SameParameterValue")
+ private static TestConfig createRandomTest(int id, int totalPages, int sequenceLength,
+ double configChangeProbability, double mutationProbability, double advanceProbability,
+ Class<? extends BaseActivity> activityClass) {
+ Random random = new Random();
+
+ List<Integer> pageSequence = new ArrayList<>();
+ List<Integer> configChanges = new ArrayList<>();
+ List<Pair<Integer, Integer>> stepToNewValue = new ArrayList<>();
+
+ int pageIx = 0;
+ Double goRightProbability = null;
+ for (int currentStep = 0; currentStep < sequenceLength; currentStep++) {
+ if (random.nextDouble() < configChangeProbability) {
+ configChanges.add(currentStep);
+ }
+
+ if (random.nextDouble() < mutationProbability) {
+ stepToNewValue.add(Pair.create(currentStep, random.nextInt(10_000)));
+ }
+
+ boolean goRight;
+ if (pageIx == 0) {
+ goRight = true;
+ goRightProbability = advanceProbability;
+ } else if (pageIx == totalPages - 1) { // last page
+ goRight = false;
+ goRightProbability = 1 - advanceProbability;
+ } else {
+ goRight = random.nextDouble() < goRightProbability;
+ }
+ pageSequence.add(goRight ? ++pageIx : --pageIx);
+ }
+
+ return new TestConfig("random_" + id, pageSequence, configChanges, stepToNewValue,
+ totalPages, activityClass);
+ }
+
+ private static List<TestConfig> checkTestNamesUnique(List<TestConfig> configs) {
+ Set<String> names = new HashSet<>();
+ for (TestConfig config : configs) {
+ names.add(config.toString());
+ }
+ assertThat(names.size(), is(configs.size()));
+ return configs;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ Log.i(getClass().getSimpleName(), mTestConfig.toFullSpecString());
+
+ mActivityTestRule = new ActivityTestRule<>(mTestConfig.mActivityClass, true, false);
+ mActivityTestRule.launchActivity(BaseActivity.createIntent(mTestConfig.mTotalPages));
+
+ ViewPager2 viewPager = mActivityTestRule.getActivity().findViewById(R.id.view_pager);
+ RecyclerView recyclerView = (RecyclerView) viewPager.getChildAt(0); // HACK
+ mSwiper = new PageSwiper(mTestConfig.mTotalPages, recyclerView);
+
+ // Disabling edge animations on API < 16. Espresso discourages animations altogether, but
+ // keeping them for now where they work - as closer to the real environment.
+ if (Build.VERSION.SDK_INT < 16) {
+ recyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
+ }
+
+ onView(withId(R.id.view_pager)).check(matches(isDisplayed()));
+ }
+
+ private static class TestConfig {
+ final String mMessage;
+ final List<Integer> mPageSequence;
+ final Set<Integer> mConfigChangeSteps;
+ /** {@link Map.Entry#getKey()} = step, {@link Map.Entry#getValue()} = new value */
+ final Map<Integer, Integer> mStepToNewValue;
+ final int mTotalPages;
+ final Class<? extends BaseActivity> mActivityClass;
+
+ /**
+ * @param stepToNewValue {@link Pair#first} = step, {@link Pair#second} = new value
+ */
+ TestConfig(String message, List<Integer> pageSequence,
+ Collection<Integer> configChangeSteps,
+ List<Pair<Integer, Integer>> stepToNewValue,
+ int totalPages,
+ Class<? extends BaseActivity> activityClass) {
+ mMessage = message;
+ mPageSequence = pageSequence;
+ mConfigChangeSteps = new HashSet<>(configChangeSteps);
+ mStepToNewValue = mapFromPairList(stepToNewValue);
+ mTotalPages = totalPages;
+ mActivityClass = activityClass;
+ }
+
+ private static Map<Integer, Integer> mapFromPairList(List<Pair<Integer, Integer>> list) {
+ Map<Integer, Integer> result = new HashMap<>();
+ for (Pair<Integer, Integer> pair : list) {
+ Integer prevValueAtKey = result.put(pair.first, pair.second);
+ assertThat("there should be only one value defined for a key", prevValueAtKey,
+ equalTo(null));
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return mActivityClass.getSimpleName() + ": " + mMessage;
+ }
+
+ String toFullSpecString() {
+ return String.format(
+ "Test: %s\nPage sequence: %s\nTotal pages: %s\nMutations {step1:newValue1, "
+ + "step2:newValue2, ...}: %s",
+ toString(),
+ mPageSequence,
+ mTotalPages,
+ mStepToNewValue.toString().replace('=', ':'));
+ }
+ }
+}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/TestActivity.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/TestActivity.java
deleted file mode 100644
index 74e2e4a..0000000
--- a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/TestActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.viewpager2.widget;
-
-import android.os.Bundle;
-
-import androidx.testutils.RecreatedActivity;
-import androidx.viewpager2.test.R;
-
-public class TestActivity extends RecreatedActivity {
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- setContentView(R.layout.activity_test_layout);
-
- ViewPager2Tests.sAdapterStrategy.setAdapter((ViewPager2) findViewById(R.id.view_pager));
- }
-}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/ViewPager2Tests.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/ViewPager2Tests.java
deleted file mode 100644
index 48d55f7..0000000
--- a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/ViewPager2Tests.java
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.viewpager2.widget;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-import static android.view.View.OVER_SCROLL_NEVER;
-
-import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
-
-import static org.hamcrest.CoreMatchers.allOf;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.arrayWithSize;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.lessThanOrEqualTo;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.espresso.ViewAction;
-import android.support.test.espresso.action.ViewActions;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.util.Preconditions;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-import androidx.testutils.FragmentActivityUtils;
-import androidx.viewpager2.test.R;
-
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class ViewPager2Tests {
- private static final Random RANDOM = new Random();
- private static final int[] sColors = {
- Color.parseColor("#BBA9FF00"),
- Color.parseColor("#BB00E87E"),
- Color.parseColor("#BB00C7FF"),
- Color.parseColor("#BBB30CE8"),
- Color.parseColor("#BBFF00D0")};
-
- /** mean of injecting different adapters into {@link TestActivity#onCreate(Bundle)} */
- static AdapterStrategy sAdapterStrategy;
-
- interface AdapterStrategy {
- void setAdapter(ViewPager2 viewPager);
- }
-
- @Rule
- public final ActivityTestRule<TestActivity> mActivityTestRule;
- @Rule
- public ExpectedException mExpectedException = ExpectedException.none();
-
- // allows to wait until swipe operation is finished (Smooth Scroller done)
- private CountDownLatch mStableAfterSwipe;
-
- public ViewPager2Tests() {
- mActivityTestRule = new ActivityTestRule<>(TestActivity.class, true, false);
- }
-
- private void setUpActivity(AdapterStrategy adapterStrategy) {
- sAdapterStrategy = Preconditions.checkNotNull(adapterStrategy);
- mActivityTestRule.launchActivity(null);
-
- ViewPager2 viewPager = mActivityTestRule.getActivity().findViewById(R.id.view_pager);
- viewPager.addOnScrollListener(new RecyclerView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
- // coming to idle from another state (dragging or setting) means we're stable now
- if (newState == SCROLL_STATE_IDLE) {
- mStableAfterSwipe.countDown();
- }
- }
- });
-
- if (Build.VERSION.SDK_INT < 16) { // TODO(b/71500143): remove temporary workaround
- RecyclerView mRecyclerView = (RecyclerView) viewPager.getChildAt(0);
- mRecyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
- }
-
- onView(withId(viewPager.getId())).check(matches(isDisplayed()));
- }
-
- @Before
- public void setUp() {
- sAdapterStrategy = null;
-
- final long seed = RANDOM.nextLong();
- RANDOM.setSeed(seed);
- Log.i(getClass().getName(), "Random seed: " + seed);
- }
-
- public static class PageFragment extends Fragment {
- private static final String KEY_VALUE = "value";
-
- public interface EventListener {
- void onEvent(PageFragment fragment);
-
- EventListener NO_OP = new EventListener() {
- @Override
- public void onEvent(PageFragment fragment) {
- // do nothing
- }
- };
- }
-
- private EventListener mOnAttachListener = EventListener.NO_OP;
- private EventListener mOnDestroyListener = EventListener.NO_OP;
-
- private int mPosition;
- private int mValue;
-
- public static PageFragment create(int position, int value) {
- PageFragment result = new PageFragment();
- Bundle args = new Bundle(1);
- args.putInt(KEY_VALUE, value);
- result.setArguments(args);
- result.mPosition = position;
- return result;
- }
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- mOnAttachListener.onEvent(this);
- }
-
- @NonNull
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- return inflater.inflate(R.layout.item_test_layout, container, false);
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- Bundle data = savedInstanceState != null ? savedInstanceState : getArguments();
- setValue(data.getInt(KEY_VALUE));
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mOnDestroyListener.onEvent(this);
- }
-
- @Override
- public void onSaveInstanceState(@NonNull Bundle outState) {
- outState.putInt(KEY_VALUE, mValue);
- }
-
- public void setValue(int value) {
- mValue = value;
- TextView textView = getView().findViewById(R.id.text_view);
- applyViewValue(textView, mValue);
- }
- }
-
- private static void applyViewValue(TextView textView, int value) {
- textView.setText(String.valueOf(value));
- textView.setBackgroundColor(getColor(value));
- }
-
- private static int getColor(int value) {
- return sColors[value % sColors.length];
- }
-
- @Test
- public void fragmentAdapter_fullPass() throws Throwable {
- testFragmentLifecycle(8, Arrays.asList(1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0));
- }
-
- @Test
- public void fragmentAdapter_activityRecreation() throws Throwable {
- testFragmentLifecycle(7, Arrays.asList(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
- PageMutator.NO_OP, new HashSet<>(Arrays.asList(3, 5, 7)));
- }
-
- @Test
- public void fragmentAdapter_random() throws Throwable {
- final int totalPages = 8; // increase when stress testing locally
- final int sequenceLength = 20; // increase when stress testing locally
- testFragmentLifecycle_random(totalPages, sequenceLength, PageMutator.NO_OP);
- }
-
- @Test
- public void fragmentAdapter_random_withMutations() throws Throwable {
- final int totalPages = 8; // increase when stress testing locally
- final int sequenceLength = 20; // increase when stress testing locally
- testFragmentLifecycle_random(totalPages, sequenceLength, PageMutator.RANDOM);
- }
-
- private void testFragmentLifecycle_random(int totalPages, int sequenceLength,
- PageMutator pageMutator) throws Throwable {
- List<Integer> pageSequence = generateRandomPageSequence(totalPages, sequenceLength);
-
- Log.i(getClass().getName(),
- String.format("Testing with a sequence [%s]", TextUtils.join(", ", pageSequence)));
-
- testFragmentLifecycle(totalPages, pageSequence, pageMutator,
- Collections.<Integer>emptySet());
- }
-
- @NonNull
- private List<Integer> generateRandomPageSequence(int totalPages, int sequenceLength) {
- List<Integer> pageSequence = new ArrayList<>(sequenceLength);
-
- int pageIx = 0;
- Double goRightProbability = null;
- while (pageSequence.size() != sequenceLength) {
- boolean goRight;
- if (pageIx == 0) {
- goRight = true;
- goRightProbability = 0.7;
- } else if (pageIx == totalPages - 1) { // last page
- goRight = false;
- goRightProbability = 0.3;
- } else {
- goRight = RANDOM.nextDouble() < goRightProbability;
- }
-
- pageSequence.add(goRight ? ++pageIx : --pageIx);
- }
-
- return pageSequence;
- }
-
- /**
- * Test added when caught a bug: after the last swipe: actual=6, expected=4
- * <p>
- * Bug was caused by an invalid test assumption (new Fragment value can be inferred from number
- * of instances created) - invalid in a case when we sometimes create Fragments off-screen and
- * end up scrapping them.
- **/
- @Test
- public void fragmentAdapter_regression1() throws Throwable {
- testFragmentLifecycle(10, Arrays.asList(1, 2, 3, 2, 1, 2, 3, 4));
- }
-
- /**
- * Test added when caught a bug: after the last swipe: actual=4, expected=5
- * <p>
- * Bug was caused by mSavedStates.add(position, ...) instead of mSavedStates.set(position, ...)
- **/
- @Test
- public void fragmentAdapter_regression2() throws Throwable {
- testFragmentLifecycle(10, Arrays.asList(1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5));
- }
-
- /**
- * Test added when caught a bug: after the last swipe: ArrayIndexOutOfBoundsException: length=5;
- * index=-1 at androidx.viewpager2.widget.tests.ViewPager2Tests$PageFragment.onCreateView
- * <p>
- * Bug was caused by always saving states of unattached fragments as null (even if there was a
- * valid previously saved state)
- */
- @Test
- public void fragmentAdapter_regression3() throws Throwable {
- testFragmentLifecycle(10, Arrays.asList(1, 2, 3, 2, 1, 2, 3, 2, 1, 0));
- }
-
- /** Goes left on left edge / right on right edge */
- @Test
- public void fragmentAdapter_edges() throws Throwable {
- testFragmentLifecycle(4, Arrays.asList(0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0));
- }
-
- private interface PageMutator {
- void mutate(PageFragment fragment);
-
- PageMutator NO_OP = new PageMutator() {
- @Override
- public void mutate(PageFragment fragment) {
- // do nothing
- }
- };
-
- /** At random modifies the page under Fragment */
- PageMutator RANDOM = new PageMutator() {
- @Override
- public void mutate(PageFragment fragment) {
- Random random = ViewPager2Tests.RANDOM;
- if (random.nextDouble() < 0.125) {
- int delta = (1 + random.nextInt(5)) * sColors.length;
- fragment.setValue(fragment.mValue + delta);
- }
- }
- };
- }
-
- /** @see this#testFragmentLifecycle(int, List, PageMutator, Set) */
- private void testFragmentLifecycle(final int totalPages, List<Integer> pageSequence)
- throws Throwable {
- testFragmentLifecycle(totalPages, pageSequence, PageMutator.NO_OP,
- Collections.<Integer>emptySet());
- }
-
- /**
- * Verifies:
- * <ul>
- * <li>page content / background
- * <li>maximum number of Fragments held in memory
- * <li>Fragment state saving / restoring
- * </ul>
- */
- private void testFragmentLifecycle(final int totalPages, List<Integer> pageSequence,
- final PageMutator pageMutator, Set<Integer> activityRecreateSteps) throws Throwable {
- final AtomicInteger attachCount = new AtomicInteger(0);
- final AtomicInteger destroyCount = new AtomicInteger(0);
- final boolean[] wasEverAttached = new boolean[totalPages];
- final PageFragment[] fragments = new PageFragment[totalPages];
-
- final int[] expectedValues = new int[totalPages];
- for (int i = 0; i < totalPages; i++) {
- expectedValues[i] = i;
- }
-
- setUpActivity(new AdapterStrategy() {
- @Override
- public void setAdapter(ViewPager2 viewPager) {
- viewPager.setAdapter(
- ((FragmentActivity) viewPager.getContext()).getSupportFragmentManager(),
- new ViewPager2.FragmentProvider() {
- @Override
- public Fragment getItem(final int position) {
- // if the fragment was attached in the past, it means we have
- // provided it with the correct value already; give a dummy one
- // to prove state save / restore functionality works
- int value = wasEverAttached[position] ? -1 : position;
- PageFragment fragment = PageFragment.create(position, value);
-
- fragment.mOnAttachListener = new PageFragment.EventListener() {
- @Override
- public void onEvent(PageFragment fragment) {
- attachCount.incrementAndGet();
- wasEverAttached[fragment.mPosition] = true;
- }
- };
-
- fragment.mOnDestroyListener = new PageFragment.EventListener() {
- @Override
- public void onEvent(PageFragment fragment) {
- destroyCount.incrementAndGet();
- }
- };
-
- fragments[position] = fragment;
- return fragment;
- }
-
- @Override
- public int getCount() {
- return totalPages;
- }
- }, ViewPager2.FragmentRetentionPolicy.SAVE_STATE);
- }
- });
-
- final AtomicInteger currentPage = new AtomicInteger(0);
- verifyCurrentPage(expectedValues[currentPage.get()]);
- int stepCounter = 0;
- for (int nextPage : pageSequence) {
- if (activityRecreateSteps.contains(stepCounter++)) {
- FragmentActivityUtils.recreateActivity(mActivityTestRule,
- mActivityTestRule.getActivity());
- }
- swipe(currentPage.get(), nextPage, totalPages);
- currentPage.set(nextPage);
- verifyCurrentPage(expectedValues[currentPage.get()]);
-
- // TODO: validate Fragments that are instantiated, but not attached. No destruction
- // steps are done to them - they're just left to the Garbage Collector. Maybe
- // WeakReferences could help, but the GC behaviour is not predictable. Alternatively,
- // we could only create Fragments onAttach, but there is a potential performance
- // trade-off.
- assertThat(attachCount.get() - destroyCount.get(), isBetween(1, 4));
-
- mActivityTestRule.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- final int page = currentPage.get();
- PageFragment fragment = fragments[page];
- pageMutator.mutate(fragment);
- expectedValues[page] = fragment.mValue;
- }
- });
- }
- }
-
- private void swipe(int currentPageIx, int nextPageIx, int totalPages)
- throws InterruptedException {
- if (nextPageIx >= totalPages) {
- throw new IllegalArgumentException("Invalid nextPageIx: >= totalPages.");
- }
-
- if (currentPageIx == nextPageIx) { // dedicated for testing edge behaviour
- if (nextPageIx == 0) {
- swipeRight(); // bounce off the left edge
- return;
- }
- if (nextPageIx == totalPages - 1) { // bounce off the right edge
- swipeLeft();
- return;
- }
- throw new IllegalArgumentException(
- "Invalid sequence. Not on an edge, and currentPageIx/nextPageIx pages same.");
- }
-
- if (Math.abs(nextPageIx - currentPageIx) > 1) {
- throw new IllegalArgumentException(
- "Specified nextPageIx not adjacent to the current page.");
- }
-
- if (nextPageIx > currentPageIx) {
- swipeLeft();
- } else {
- swipeRight();
- }
- }
-
- private Matcher<Integer> isBetween(int min, int max) {
- return allOf(greaterThanOrEqualTo(min), lessThanOrEqualTo(max));
- }
-
- @Test
- public void viewAdapter_edges() throws Throwable {
- testViewAdapter(4, Arrays.asList(0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0),
- Collections.<Integer>emptySet());
- }
-
- @Test
- public void viewAdapter_fullPass() throws Throwable {
- testViewAdapter(8, Arrays.asList(1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0),
- Collections.<Integer>emptySet());
- }
-
- @Test
- public void viewAdapter_activityRecreation() throws Throwable {
- testViewAdapter(7,
- Arrays.asList(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0),
- new HashSet<>(Arrays.asList(3, 5, 7)));
- }
-
- @Test
- public void saveState_parcelWriteRestore() throws Throwable {
- // given
- Bundle superState = createIntBundle(42);
- ViewPager2.SavedState state = new ViewPager2.SavedState(superState);
- state.mRecyclerViewId = 700;
- state.mAdapterState = new Parcelable[]{createIntBundle(1), createIntBundle(2),
- createIntBundle(3)};
-
- // when
- Parcel parcel = Parcel.obtain();
- state.writeToParcel(parcel, 0);
- final String parcelSuffix = UUID.randomUUID().toString();
- parcel.writeString(parcelSuffix); // to verify parcel boundaries
- parcel.setDataPosition(0);
- ViewPager2.SavedState recreatedState = ViewPager2.SavedState.CREATOR.createFromParcel(
- parcel);
-
- // then
- assertThat("Parcel reading should not go out of bounds", parcel.readString(),
- equalTo(parcelSuffix));
- assertThat("All of the parcel should be read", parcel.dataAvail(), equalTo(0));
- assertThat(recreatedState.mRecyclerViewId, equalTo(700));
- assertThat(recreatedState.mAdapterState, arrayWithSize(3));
- assertThat((int) ((Bundle) recreatedState.getSuperState()).get("key"), equalTo(42));
- assertThat((int) ((Bundle) recreatedState.mAdapterState[0]).get("key"), equalTo(1));
- assertThat((int) ((Bundle) recreatedState.mAdapterState[1]).get("key"), equalTo(2));
- assertThat((int) ((Bundle) recreatedState.mAdapterState[2]).get("key"), equalTo(3));
- }
-
- private Bundle createIntBundle(int value) {
- Bundle bundle = new Bundle(1);
- bundle.putInt("key", value);
- return bundle;
- }
-
- private void testViewAdapter(final int totalPages, List<Integer> pageSequence,
- Set<Integer> activityRecreateSteps) throws InterruptedException {
- setUpActivity(new AdapterStrategy() {
- @Override
- public void setAdapter(final ViewPager2 viewPager) {
- viewPager.setAdapter(
- new Adapter<ViewHolder>() {
- @NonNull
- @Override
- public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
- int viewType) {
- return new ViewHolder(
- LayoutInflater.from(viewPager.getContext()).inflate(
- R.layout.item_test_layout, parent, false)) {
- };
- }
-
- @Override
- public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
- TextView view = (TextView) holder.itemView;
- applyViewValue(view, position);
- }
-
- @Override
- public int getItemCount() {
- return totalPages;
- }
- });
- }
- });
-
- verifyCurrentPage(0);
- int currentPage = 0;
- int stepCounter = 0;
- for (int nextPage : pageSequence) {
- if (activityRecreateSteps.contains(stepCounter++)) {
- FragmentActivityUtils.recreateActivity(mActivityTestRule,
- mActivityTestRule.getActivity());
- }
- swipe(currentPage, nextPage, totalPages);
- currentPage = nextPage;
- verifyCurrentPage(currentPage);
- }
- }
-
- /**
- * Verifies that the current page displays the correct value and has the correct color.
- *
- * @param expectedPageValue value expected to be displayed on the page
- */
- private void verifyCurrentPage(int expectedPageValue) {
- onView(allOf(withId(R.id.text_view), isDisplayed())).check(
- matches(allOf(withText(String.valueOf(expectedPageValue)),
- new BackgroundColorMatcher(getColor(expectedPageValue)))));
- }
-
- private static class BackgroundColorMatcher extends BaseMatcher<View> {
- private final int mColor;
-
- BackgroundColorMatcher(int color) {
- mColor = color;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("should have background color: ").appendValue(mColor);
- }
-
- @Override
- public boolean matches(Object item) {
- ColorDrawable background = (ColorDrawable) ((View) item).getBackground();
- return background.getColor() == mColor;
- }
- }
-
- private void swipeLeft() throws InterruptedException {
- performSwipe(ViewActions.swipeLeft());
- }
-
- private void swipeRight() throws InterruptedException {
- performSwipe(ViewActions.swipeRight());
- }
-
- private void performSwipe(ViewAction swipeAction) throws InterruptedException {
- mStableAfterSwipe = new CountDownLatch(1);
- onView(allOf(isDisplayed(), withId(R.id.text_view))).perform(swipeAction);
- mStableAfterSwipe.await(1, TimeUnit.SECONDS);
- }
-
- @Test
- public void itemViewSizeMatchParentEnforced() {
- mExpectedException.expect(IllegalStateException.class);
- mExpectedException.expectMessage(
- "Item's root view must fill the whole ViewPager2 (use match_parent)");
-
- ViewPager2 viewPager = new ViewPager2(InstrumentationRegistry.getContext());
- viewPager.setAdapter(new Adapter<ViewHolder>() {
- @NonNull
- @Override
- public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view = new View(parent.getContext());
- view.setLayoutParams(new ViewGroup.LayoutParams(50, 50)); // arbitrary fixed size
- return new ViewHolder(view) {
- };
- }
-
- @Override
- public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
- // do nothing
- }
-
- @Override
- public int getItemCount() {
- return 1;
- }
- });
-
- viewPager.measure(0, 0); // equivalent of unspecified
- }
-
- @Test
- public void childrenNotAllowed() throws Exception {
- mExpectedException.expect(IllegalStateException.class);
- mExpectedException.expectMessage("ViewPager2 does not support direct child views");
-
- Context context = InstrumentationRegistry.getContext();
- ViewPager2 viewPager = new ViewPager2(context);
- viewPager.addView(new View(context));
- }
-
- // TODO: verify correct padding behavior
- // TODO: add test for screen orientation change
- // TODO: port some of the fragment adapter tests as view adapter tests
-}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/BaseActivity.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/BaseActivity.java
new file mode 100644
index 0000000..5e3f326
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/BaseActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.viewpager2.widget.swipe;
+
+import static androidx.core.util.Preconditions.checkNotNull;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.testutils.RecreatedActivity;
+import androidx.viewpager2.test.R;
+import androidx.viewpager2.widget.ViewPager2;
+
+public abstract class BaseActivity extends RecreatedActivity {
+ private static final String ARG_TOTAL_PAGES = "totalPages";
+
+ protected ViewPager2 mViewPager;
+ protected int mTotalPages;
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ setContentView(R.layout.activity_test_layout);
+
+ mViewPager = findViewById(R.id.view_pager);
+ mTotalPages = checkNotNull(getIntent().getExtras()).getInt(ARG_TOTAL_PAGES);
+
+ setAdapter();
+ }
+
+ protected abstract void setAdapter();
+
+ public abstract void validateState();
+
+ public abstract void updatePage(int pageIx, int newValue);
+
+ public static Intent createIntent(int totalPages) {
+ Intent intent = new Intent();
+ intent.putExtra(ARG_TOTAL_PAGES, totalPages);
+ return intent;
+ }
+}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapterActivity.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapterActivity.java
new file mode 100644
index 0000000..2d670a8
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapterActivity.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.viewpager2.widget.swipe;
+
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
+import static org.junit.Assert.assertThat;
+
+import androidx.fragment.app.Fragment;
+import androidx.viewpager2.widget.ViewPager2;
+
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class FragmentAdapterActivity extends BaseActivity {
+ private static final Random RANDOM = new Random();
+
+ private AtomicInteger mAttachCount = new AtomicInteger(0);
+ private AtomicInteger mDestroyCount = new AtomicInteger(0);
+ private PageFragment[] mFragments;
+
+ @Override
+ protected void setAdapter() {
+ mFragments = new PageFragment[mTotalPages];
+
+ ViewPager2.FragmentProvider fragmentProvider = new ViewPager2.FragmentProvider() {
+ final boolean[] mWasEverAttached = new boolean[mTotalPages];
+
+ @Override
+ public Fragment getItem(final int position) {
+ PageFragment fragment = PageFragment.create(valueForPosition(position));
+
+ fragment.mOnAttachListener = new PageFragment.EventListener() {
+ @Override
+ public void onEvent(PageFragment fragment) {
+ mAttachCount.incrementAndGet();
+ mWasEverAttached[position] = true;
+ }
+ };
+
+ fragment.mOnDestroyListener = new PageFragment.EventListener() {
+ @Override
+ public void onEvent(PageFragment fragment) {
+ mDestroyCount.incrementAndGet();
+ }
+ };
+
+ return mFragments[position] = fragment;
+ }
+
+ private int valueForPosition(int position) {
+ // only supply correct value ones; then rely on it being kept by Fragment state
+ return mWasEverAttached[position]
+ ? RANDOM.nextInt() // junk value to be overridden by state saved value
+ : position;
+ }
+
+ @Override
+ public int getCount() {
+ return mTotalPages;
+ }
+ };
+
+ mViewPager.setAdapter(getSupportFragmentManager(), fragmentProvider,
+ ViewPager2.FragmentRetentionPolicy.SAVE_STATE);
+ }
+
+ @Override
+ public void updatePage(int pageIx, int newValue) {
+ mFragments[pageIx].updateValue(newValue);
+ }
+
+ @Override
+ public void validateState() {
+ assertThat(mAttachCount.get() - mDestroyCount.get(),
+ allOf(greaterThanOrEqualTo(1), lessThanOrEqualTo(4)));
+ }
+}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageFragment.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageFragment.java
new file mode 100644
index 0000000..23132bc
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageFragment.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.viewpager2.widget.swipe;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.viewpager2.test.R;
+
+public class PageFragment extends Fragment {
+ private static final String ARG_VALUE = "value";
+
+ private int mValue;
+ EventListener mOnAttachListener = EventListener.NO_OP;
+ EventListener mOnDestroyListener = EventListener.NO_OP;
+
+ static PageFragment create(int value) {
+ PageFragment result = new PageFragment();
+ Bundle args = new Bundle(1);
+ args.putInt(ARG_VALUE, value);
+ result.setArguments(args);
+ return result;
+ }
+
+ @NonNull
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.item_test_layout, container, false);
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ Bundle data = savedInstanceState != null ? savedInstanceState : getArguments();
+ updateValue(data.getInt(ARG_VALUE));
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mOnAttachListener.onEvent(this);
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ outState.putInt(ARG_VALUE, mValue);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mOnDestroyListener.onEvent(this);
+ }
+
+ void updateValue(int newValue) {
+ mValue = newValue;
+ ((TextView) getView()).setText(String.valueOf(newValue));
+ }
+
+ public interface EventListener {
+ void onEvent(PageFragment fragment);
+
+ EventListener NO_OP = new EventListener() {
+ @Override
+ public void onEvent(PageFragment fragment) {
+ // do nothing
+ }
+ };
+ }
+}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageSwiper.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageSwiper.java
new file mode 100644
index 0000000..a17ef94
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/PageSwiper.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.viewpager2.widget.swipe;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+import static androidx.core.util.Preconditions.checkArgumentNonnegative;
+import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
+
+import static org.hamcrest.CoreMatchers.allOf;
+
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.ViewActions;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewpager2.test.R;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class PageSwiper {
+ private CountDownLatch mStableAfterSwipe;
+ private final int mLastPageIx;
+
+ public PageSwiper(int totalPages, RecyclerView recyclerView) {
+ mLastPageIx = checkArgumentNonnegative(totalPages - 1);
+
+ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ // coming to idle from another state (dragging or setting) means we're stable now
+ if (newState == SCROLL_STATE_IDLE) {
+ mStableAfterSwipe.countDown();
+ }
+ }
+ });
+ }
+
+ public void swipe(int currentPageIx, int nextPageIx) throws InterruptedException {
+ if (nextPageIx > mLastPageIx) {
+ throw new IllegalArgumentException("Invalid next page: beyond last page.");
+ }
+
+ if (currentPageIx == nextPageIx) { // dedicated for testing edge behaviour
+ if (nextPageIx == 0) {
+ swipeRight(); // bounce off the left edge
+ return;
+ }
+ if (nextPageIx == mLastPageIx) { // bounce off the right edge
+ swipeLeft();
+ return;
+ }
+ throw new IllegalArgumentException(
+ "Invalid sequence. Not on an edge, and current page = next page.");
+ }
+
+ if (Math.abs(nextPageIx - currentPageIx) > 1) {
+ throw new IllegalArgumentException(
+ "Specified next page not adjacent to the current page.");
+ }
+
+ if (nextPageIx > currentPageIx) {
+ swipeLeft();
+ } else {
+ swipeRight();
+ }
+ }
+
+ private void swipeLeft() throws InterruptedException {
+ swipe(ViewActions.swipeLeft());
+ }
+
+ private void swipeRight() throws InterruptedException {
+ swipe(ViewActions.swipeRight());
+ }
+
+ private void swipe(ViewAction swipeAction) throws InterruptedException {
+ mStableAfterSwipe = new CountDownLatch(1);
+ onView(allOf(isDisplayed(), withId(R.id.text_view))).perform(swipeAction);
+ mStableAfterSwipe.await(1, TimeUnit.SECONDS);
+ }
+}
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/ViewAdapterActivity.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/ViewAdapterActivity.java
new file mode 100644
index 0000000..8830561
--- /dev/null
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/ViewAdapterActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.viewpager2.widget.swipe;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+import androidx.viewpager2.test.R;
+
+public class ViewAdapterActivity extends BaseActivity {
+ @Override
+ protected void setAdapter() {
+ mViewPager.setAdapter(new RecyclerView.Adapter<ViewHolder>() {
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
+ int viewType) {
+ return new ViewHolder(
+ LayoutInflater.from(ViewAdapterActivity.this).inflate(
+ R.layout.item_test_layout, parent, false)) {
+ };
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ TextView view = (TextView) holder.itemView;
+ view.setText(String.valueOf(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return mTotalPages;
+ }
+ });
+ }
+
+ @Override
+ public void validateState() {
+ // do nothing
+ }
+
+ @Override
+ public void updatePage(int pageIx, int newValue) {
+ throw new IllegalStateException("not implemented");
+ }
+}
diff --git a/viewpager2/src/main/java/androidx/viewpager2/widget/ViewPager2.java b/viewpager2/src/main/java/androidx/viewpager2/widget/ViewPager2.java
index 11c73f2..29e2f40 100644
--- a/viewpager2/src/main/java/androidx/viewpager2/widget/ViewPager2.java
+++ b/viewpager2/src/main/java/androidx/viewpager2/widget/ViewPager2.java
@@ -158,7 +158,7 @@
int mRecyclerViewId;
Parcelable[] mAdapterState;
- @RequiresApi(21)
+ @RequiresApi(24)
SavedState(Parcel source, ClassLoader loader) {
super(source, loader);
readValues(source, loader);
@@ -188,7 +188,7 @@
static final Creator<SavedState> CREATOR = new ClassLoaderCreator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel source, ClassLoader loader) {
- return Build.VERSION.SDK_INT >= 21
+ return Build.VERSION.SDK_INT >= 24
? new SavedState(source, loader)
: new SavedState(source);
}
@@ -455,11 +455,6 @@
getClass().getSimpleName() + " does not support direct child views");
}
- /** @see RecyclerView#addOnScrollListener(RecyclerView.OnScrollListener) */
- public void addOnScrollListener(RecyclerView.OnScrollListener listener) {
- mRecyclerView.addOnScrollListener(listener);
- }
-
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO(b/70666622): consider margin support
diff --git a/webkit/api/current.txt b/webkit/api/current.txt
index 36bc76b..fb15e2f 100644
--- a/webkit/api/current.txt
+++ b/webkit/api/current.txt
@@ -32,6 +32,7 @@
}
public class WebViewCompat {
+ method public static android.content.pm.PackageInfo getCurrentWebViewPackage(android.content.Context);
method public static android.net.Uri getSafeBrowsingPrivacyPolicyUrl();
method public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
method public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>);
diff --git a/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java b/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
index 3c64b9c..bd77fdb 100644
--- a/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
+++ b/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -28,6 +29,7 @@
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
+import android.support.test.filters.Suppress;
import android.support.test.runner.AndroidJUnit4;
import android.webkit.SafeBrowsingResponse;
import android.webkit.ValueCallback;
@@ -83,6 +85,7 @@
assertTrue(callbackLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
}
+ @Suppress // TODO(gsennton) remove @Suppress when b/76202025 has been resolved
@Test
public void testCheckThread() {
try {
@@ -235,4 +238,22 @@
Assert.fail("The privacy policy URL should be a well-formed URL");
}
}
+
+ /**
+ * WebViewCompat.getCurrentWebViewPackage should be null on pre-L devices.
+ * On L+ devices WebViewCompat.getCurrentWebViewPackage should be null only in exceptional
+ * circumstances - like when the WebView APK is being updated, or for Wear devices. The L+
+ * devices used in support library testing should have a non-null WebView package.
+ */
+ @Test
+ public void testGetCurrentWebViewPackage() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ assertNull(WebViewCompat.getCurrentWebViewPackage(
+ InstrumentationRegistry.getTargetContext()));
+ } else {
+ assertNotNull(
+ WebViewCompat.getCurrentWebViewPackage(
+ InstrumentationRegistry.getTargetContext()));
+ }
+ }
}
diff --git a/webkit/src/main/java/androidx/webkit/WebViewCompat.java b/webkit/src/main/java/androidx/webkit/WebViewCompat.java
index 0098a82..45def2e 100644
--- a/webkit/src/main/java/androidx/webkit/WebViewCompat.java
+++ b/webkit/src/main/java/androidx/webkit/WebViewCompat.java
@@ -17,6 +17,8 @@
package androidx.webkit;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Looper;
@@ -210,6 +212,92 @@
}
}
+ /**
+ * If WebView has already been loaded into the current process this method will return the
+ * package that was used to load it. Otherwise, the package that would be used if the WebView
+ * was loaded right now will be returned; this does not cause WebView to be loaded, so this
+ * information may become outdated at any time.
+ * The WebView package changes either when the current WebView package is updated, disabled, or
+ * uninstalled. It can also be changed through a Developer Setting.
+ * If the WebView package changes, any app process that has loaded WebView will be killed. The
+ * next time the app starts and loads WebView it will use the new WebView package instead.
+ * @return the current WebView package, or {@code null} if there is none.
+ */
+ // Note that this API is not protected by a {@link androidx.webkit.WebViewFeature} since
+ // this feature is not dependent on the WebView APK.
+ @Nullable
+ public static PackageInfo getCurrentWebViewPackage(@NonNull Context context) {
+ // There was no WebView Package before Lollipop, the WebView code was part of the framework
+ // back then.
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ return null;
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ return WebView.getCurrentWebViewPackage();
+ } else { // L-N
+ try {
+ PackageInfo loadedWebViewPackageInfo = getLoadedWebViewPackageInfo();
+ if (loadedWebViewPackageInfo != null) return loadedWebViewPackageInfo;
+ } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException
+ | NoSuchMethodException e) {
+ return null;
+ }
+
+ // If WebViewFactory.getLoadedPackageInfo() returns null then WebView hasn't been loaded
+ // yet, in that case we need to fetch the name of the WebView package, and fetch the
+ // corresponding PackageInfo through the PackageManager
+ return getNotYetLoadedWebViewPackageInfo(context);
+ }
+ }
+
+ /**
+ * Return the PackageInfo of the currently loaded WebView APK. This method uses reflection and
+ * propagates any exceptions thrown, to the caller.
+ */
+ private static PackageInfo getLoadedWebViewPackageInfo()
+ throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
+ IllegalAccessException {
+ Class webViewFactoryClass = Class.forName("android.webkit.WebViewFactory");
+ PackageInfo webviewPackageInfo =
+ (PackageInfo) webViewFactoryClass.getMethod(
+ "getLoadedPackageInfo").invoke(null);
+ return webviewPackageInfo;
+ }
+
+ /**
+ * Return the PackageInfo of the WebView APK that would have been used as WebView implementation
+ * if WebView was to be loaded right now.
+ */
+ private static PackageInfo getNotYetLoadedWebViewPackageInfo(Context context) {
+ String webviewPackageName = null;
+ try {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
+ && Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
+ Class webViewFactoryClass = null;
+ webViewFactoryClass = Class.forName("android.webkit.WebViewFactory");
+
+ webviewPackageName = (String) webViewFactoryClass.getMethod(
+ "getWebViewPackageName").invoke(null);
+ } else {
+ Class webviewUpdateServiceClass =
+ Class.forName("android.webkit.WebViewUpdateService");
+ webviewPackageName = (String) webviewUpdateServiceClass.getMethod(
+ "getCurrentWebViewPackageName").invoke(null);
+ }
+ } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException
+ | NoSuchMethodException e) {
+ return null;
+ }
+ if (webviewPackageName == null) return null;
+ PackageManager pm = context.getPackageManager();
+ try {
+ return pm.getPackageInfo(webviewPackageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return null;
+ }
+ }
+
private static WebViewProviderAdapter getProvider(WebView webview) {
return new WebViewProviderAdapter(createProvider(webview));
}