diff --git a/sample/navercafesdk-sample-android-studio/app/build.gradle b/sample/navercafesdk-sample-android-studio/app/build.gradle index 3e1f990..e3f20fe 100644 --- a/sample/navercafesdk-sample-android-studio/app/build.gradle +++ b/sample/navercafesdk-sample-android-studio/app/build.gradle @@ -31,7 +31,4 @@ repositories { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.aar']) - implementation 'com.github.bumptech.glide:glide:4.9.0' - annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' - implementation project(':libraries') } diff --git a/sample/navercafesdk-sample-android-studio/app/consumer-proguard-rules.pro b/sample/navercafesdk-sample-android-studio/app/consumer-proguard-rules.pro deleted file mode 100644 index 38d797b..0000000 --- a/sample/navercafesdk-sample-android-studio/app/consumer-proguard-rules.pro +++ /dev/null @@ -1,78 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/Naver/Library/Android/sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - --ignorewarnings --keepattributes SourceFile, LineNumberTable, *Annotation*, Signature, EnclosingMethod, InnerClasses, EnclosingMethod - --keep class com.naver.cafe.** { *; } --keep interface com.naver.cafe.** { *; } --keepclassmembers class com.naver.cafe.** { - ; - ; -} - --keep class com.naver.glink.** { *; } --keep interface com.naver.glink.** { *; } - --keep class com.nhn.** { *; } --keep interface com.nhn.** { *; } - --keep class p.com.bumptech.glide.** { *; } --keep interface p.com.bumptech.glide.** { *; } - --keep class com.android.volley.** { *; } --keep interface com.android.volley.** {*;} - --keep class com.navercorp.volleyextensions.** { *; } --keep interface com.navercorp.volleyextensions.** { *; } - --keep class p.android.support.v4.util.Pair.** { *; } --keep interface p.android.support.v4.util.Pair.** { *; } - --keep class p.android.support.v4.** { *; } --keep interface p.android.support.v4.** { *; } - - --keep class com.squareup.** { *; } --keep interface com.squareup.** { *; } - --keep class com.github.clans.fab.** { *; } - --dontwarn com.nhn.android.neoid.** --dontwarn com.navercorp.volleyextensions.volleyer.response.parser.** - -##---------------Begin: proguard configuration for Gson ---------- -# Gson uses generic type information stored in a class file when working with fields. Proguard -# removes such information by default, so configure it to keep all of it. --keepattributes Signature - -# For using GSON @Expose annotation --keepattributes *Annotation* - -# Gson specific classes --keep class sun.misc.Unsafe { *; } -#-keep class com.google.gson.stream.** { *; } - -# Prevent proguard from stripping interface information from TypeAdapterFactory, -# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter) --keep class * implements com.google.gson.TypeAdapterFactory --keep class * implements com.google.gson.JsonSerializer --keep class * implements com.google.gson.JsonDeserializer - --keep class com.google.gson.Gson -##---------------End: proguard configuration for Gson ---------- diff --git a/sample/navercafesdk-sample-android-studio/app/libs/cafeSdk-4.3.0.aar b/sample/navercafesdk-sample-android-studio/app/libs/cafeSdk-4.3.0.aar index 249c519..020b482 100644 Binary files a/sample/navercafesdk-sample-android-studio/app/libs/cafeSdk-4.3.0.aar and b/sample/navercafesdk-sample-android-studio/app/libs/cafeSdk-4.3.0.aar differ diff --git a/sample/navercafesdk-sample-android-studio/app/libs/glide-3.7.0.jar b/sample/navercafesdk-sample-android-studio/app/libs/glide-3.7.0.jar new file mode 100644 index 0000000..9ef5cb6 Binary files /dev/null and b/sample/navercafesdk-sample-android-studio/app/libs/glide-3.7.0.jar differ diff --git a/sample/navercafesdk-sample-android-studio/app/libs/support-v4-23.1.0.aar b/sample/navercafesdk-sample-android-studio/app/libs/support-v4-23.1.0.aar new file mode 100644 index 0000000..f4e34ec Binary files /dev/null and b/sample/navercafesdk-sample-android-studio/app/libs/support-v4-23.1.0.aar differ diff --git a/sample/navercafesdk-sample-android-studio/app/proguard-rules.pro b/sample/navercafesdk-sample-android-studio/app/proguard-rules.pro deleted file mode 100644 index a8b5622..0000000 --- a/sample/navercafesdk-sample-android-studio/app/proguard-rules.pro +++ /dev/null @@ -1,219 +0,0 @@ -#-dump ./proguard-dump.txt -#printseeds ./proguard-seeds.txt -#-printusage ./proguard-unused.txt -#-printmapping ./proguard-mapping.txt - --dontshrink --dontoptimize --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --verbose --ignorewarnings --keepattributes SourceFile, LineNumberTable, *Annotation*, Signature, EnclosingMethod, InnerClasses, EnclosingMethod - --keep class com.nhn.** { *; } --keep class p.android.support.v7.** { *; } --keep interface p.android.support.v7.** { *; } --keep class p.android.support.** { *; } --keep interface p.android.support.** { *; } --keep class com.navercorp.volleyextensions.** { *; } --keep interface com.navercorp.volleyextensions.** { *; } --keep class google.gson.** { *; } --keep interface google.gson.** { *; } --keep enum google.gson.** { *; } --keep class p.com.bumptech.glide.** { *; } --keep interface p.com.bumptech.glide.** { *; } --keep class com.squareup.** { *; } --keep interface com.squareup.** { *; } - --keep class p.android.support.v4.** { *; } --keep interface p.android.support.v4.** { *; } - --keep class p.android.support.v4.util.Pair.** { *; } --keep interface p.android.support.v4.util.Pair.** { *; } - --keep class com.android.volley.** { *; } --keep interface com.android.volley.** {*;} - --keep class android.net.** { *; } --keep class org.** { *; } --keep interface org.** { *; } --keep class com.fasterxml.jackson.** { *; } - -#--G-LINK SDK --keep class com.naver.plug.core.api.** { - *; -} - - --keep class com.naver.plug.core.api.** {*;} - --keepclassmembers class com.naver.plug.core.api.** { - ; - ; -} - --keepclassmembers class com.naver.plug.cafe.api.** { - ; -} - - --keep class com.naver.vapp.broadcast.publisher.** {*;} --keepclassmembers class com.naver.vapp.broadcast.publisher.** { - ; -} - - - --keepparameternames --keep class com.naver.glink.android.sdk.Glink {*;} --keep interface com.naver.glink.android.sdk.Glink {*;} --keep interface com.naver.glink.android.sdk.Glink$* {*;} --keep class com.naver.plug.cafe.model.** {*;} --keepclassmembers class com.naver.plug.cafe.model.** {*;} - --keep class com.naver.plug.cafe.ui.ItemsDialogFragment {*;} --keep interface com.naver.plug.cafe.ui.ItemsDialogFragment$* {*;} --keep class com.naver.plug.cafe.ui.ItemsDialogFragment$* {*;} - --keep class com.naver.glink.android.sdk.samsung.SPlug {*;} --keep interface com.naver.glink.android.sdk.samsung.SPlug {*;} --keep interface com.naver.glink.android.sdk.samsung.SPlug$* {*;} - --keep class com.naver.plug.moot.api.response.** {*;} --keep class com.naver.plug.moot.model.** {*;} --keep class com.naver.plug.moot.ui.write.model.** {*;} --keep class com.nhncorp.nelo2.android.** {*;} -#-keep class com.naver.plug.cafe.model.WritingArticle {*;} -#-keep class com.naver.plug.cafe.model.WritingArticle$Builder {*;} - --keep public class **.R { - public *; -} --keep public class **.R$* { - public *; -} - - -##---------------Begin: proguard configuration for Common Android ---------- -# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native --keepclasseswithmembernames class * { - native ; -} - -# keep setters in Views so that animations can still work. -# see http://proguard.sourceforge.net/manual/examples.html#beans --keepclassmembers public class * extends android.view.View { - void set*(***); - *** get*(); -} - -# We want to keep methods in Activity that could be used in the XML attribute onClick --keepclassmembers class * extends android.app.Activity { - public void *(android.view.View); -} - -# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} - --keepclassmembers class **.R$* { - public static ; -} - --keep public class * extends android.view.View { - public (android.content.Context); - public (android.content.Context, android.util.AttributeSet); - public (android.content.Context, android.util.AttributeSet, int); - public void set*(...); - } - --keepclasseswithmembers public class * extends android.preference.Preference { - public (android.content.Context); - public (android.content.Context, android.util.AttributeSet); - public (android.content.Context, android.util.AttributeSet, int); - public void set*(...); -} - --keepclassmembers class * implements android.os.Parcelable { - static android.os.Parcelable$Creator CREATOR; -} - --keepclassmembers class * { - @android.webkit.JavascriptInterface *; -} - --keep class * implements java.io.Serializable { *; } - -##---------------End: proguard configuration for Common Android ---------- - - - -## Google Play Services 4.3.23 specific rules ## -## https://developer.android.com/google/play-services/setup.html#Proguard ## - --keep class * extends java.util.ListResourceBundle { - protected java.lang.Object[][] getContents(); -} - --keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { - public static final *** NULL; -} - --keepnames @com.google.android.gms.common.annotation.KeepName class * --keepclassmembernames class * { - @com.google.android.gms.common.annotation.KeepName *; -} - --keepnames class * implements android.os.Parcelable { - public static final ** CREATOR; -} - -## GSON 2.2.4 specific rules ## - -# Gson uses generic type information stored in a class file when working with fields. Proguard -# removes such information by default, so configure it to keep all of it. - -# For using GSON @Expose annotation -# Gson specific classes - --keep class sun.misc.Unsafe { *; } --keep class com.google.gson.stream.** { *; } - --keepclassmembers class com.google.gson.** { - ; - ; -} - - --keep class com.google.gson.** { *; } --keep interface com.google.gson.** { *; } - - -#--dontwarn --dontwarn org.** --dontwarn com.fasterxml.jackson.** --dontwarn com.nhn.android.login.** --dontwarn com.nhn.android.naverlogin.** --dontwarn com.nhn.android.maps.** --dontwarn roboguice.** --dontwarn net.sf.cglib.** --dontwarn com.nhncorp.** --dontwarn com.nhn.nni.** --dontwarn com.nhn.npush.** --dontwarn com.nhn.android.inappwebview.** --dontwarn android.** - --dontwarn java.lang.invoke.* --dontwarn **$$Lambda$* - --dontwarn com.google.gson.** --dontnote com.google.gson.** --dontnote org.** diff --git a/sample/navercafesdk-sample-android-studio/libraries/.gitignore b/sample/navercafesdk-sample-android-studio/libraries/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/sample/navercafesdk-sample-android-studio/libraries/build.gradle b/sample/navercafesdk-sample-android-studio/libraries/build.gradle deleted file mode 100644 index 9b73af1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 23 - - defaultConfig { - minSdkVersion 17 - targetSdkVersion 23 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - sourceSets { main { aidl.srcDirs = ['src/main/aidl/'] } } - - lintOptions { - abortOnError false - } - - buildTypes { - release { - - } - - sdkRelease { - - - } - - debug { - - } - } - - -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/proguard-rules.pro b/sample/navercafesdk-sample-android-studio/libraries/proguard-rules.pro deleted file mode 100644 index f1b4245..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/AndroidManifest.xml b/sample/navercafesdk-sample-android-studio/libraries/src/main/AndroidManifest.xml deleted file mode 100644 index d6511b6..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnimRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnimRes.java deleted file mode 100644 index 25b7162..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnimRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an anim resource reference (e.g. {@link android.R.anim#fade_in}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface AnimRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnimatorRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnimatorRes.java deleted file mode 100644 index 404fccb..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnimatorRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an animator resource reference (e.g. {@link android.R.animator#fade_in}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface AnimatorRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnyRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnyRes.java deleted file mode 100644 index 9875a13..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AnyRes.java +++ /dev/null @@ -1,38 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a resource reference of any type. If the specific type is known, use - * one of the more specific annotations instead, such as {@link StringRes} or - * {@link DrawableRes}. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface AnyRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ArrayRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ArrayRes.java deleted file mode 100644 index 2cf9ac2..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ArrayRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an array resource reference (e.g. {@link android.R.array#phoneTypes}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface ArrayRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AttrRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AttrRes.java deleted file mode 100644 index 36fffc3..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/AttrRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an attribute reference (e.g. {@link android.R.attr#action}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface AttrRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/BinderThread.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/BinderThread.java deleted file mode 100644 index ffd1f91..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/BinderThread.java +++ /dev/null @@ -1,42 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated method should only be called on the binder thread. - * If the annotated element is a class, then all methods in the class should be called - * on the binder thread. - *

- * Example: - *

{@code
- *  (@BinderThread
- *  public BeamShareData createBeamShareData() { ... }
- * }
- */ -@Documented -@Retention(CLASS) -@Target({METHOD,CONSTRUCTOR,TYPE}) -public @interface BinderThread { -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/BoolRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/BoolRes.java deleted file mode 100644 index 7396d40..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/BoolRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a boolean resource reference. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface BoolRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/CallSuper.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/CallSuper.java deleted file mode 100644 index a41d8d7..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/CallSuper.java +++ /dev/null @@ -1,38 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that any overriding methods should invoke this method as well. - *

- * Example: - *

{@code
- *  @CallSuper
- *  public abstract void onFocusLost();
- * }
- */ -@Documented -@Retention(CLASS) -@Target({METHOD}) -public @interface CallSuper { -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/CheckResult.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/CheckResult.java deleted file mode 100644 index d409f13..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/CheckResult.java +++ /dev/null @@ -1,58 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated method returns a result that it typically is - * an error to ignore. This is usually used for methods that have no side effect, - * so calling it without actually looking at the result usually means the developer - * has misunderstood what the method does. - *

- * Example: - *

{@code
- *  public @CheckResult String trim(String s) { return s.trim(); }
- *  ...
- *  s.trim(); // this is probably an error
- *  s = s.trim(); // ok
- * }
- */ -@Documented -@Retention(CLASS) -@Target({METHOD}) -public @interface CheckResult { - /** Defines the name of the suggested method to use instead, if applicable (using - * the same signature format as javadoc.) If there is more than one possibility, - * list them all separated by commas. - *

- * For example, ProcessBuilder has a method named {@code redirectErrorStream()} - * which sounds like it might redirect the error stream. It does not. It's just - * a getter which returns whether the process builder will redirect the error stream, - * and to actually set it, you must call {@code redirectErrorStream(boolean)}. - * In that case, the method should be defined like this: - *

-     *  @CheckResult(suggest="#redirectErrorStream(boolean)")
-     *  public boolean redirectErrorStream() { ... }
-     * 
- */ - String suggest() default ""; -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ColorInt.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ColorInt.java deleted file mode 100644 index 34b78f4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ColorInt.java +++ /dev/null @@ -1,40 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated element represents a packed color - * int, {@code AARRGGBB}. If applied to an int array, every element - * in the array represents a color integer. - *

- * Example: - *

{@code
- *  public abstract void setTextColor(@ColorInt int color);
- * }
- */ -@Retention(CLASS) -@Target({PARAMETER,METHOD,LOCAL_VARIABLE,FIELD}) -public @interface ColorInt { -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ColorRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ColorRes.java deleted file mode 100644 index da8079f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/ColorRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a color resource reference (e.g. {@link android.R.color#black}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface ColorRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/DimenRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/DimenRes.java deleted file mode 100644 index ed6b2de..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/DimenRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a dimension resource reference (e.g. {@link android.R.dimen#app_icon_size}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface DimenRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/DrawableRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/DrawableRes.java deleted file mode 100644 index a0d41be..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/DrawableRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a drawable resource reference (e.g. {@link android.R.attr#alertDialogIcon}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface DrawableRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/FloatRange.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/FloatRange.java deleted file mode 100644 index 233719e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/FloatRange.java +++ /dev/null @@ -1,54 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated element should be a float or double in the given range - *

- * Example: - *

{@code
- *  @FloatRange(from=0.0,to=1.0)
- *  public float getAlpha() {
- *      ...
- *  }
- * }
- */ -@Retention(CLASS) -@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE}) -public @interface FloatRange { - /** Smallest value. Whether it is inclusive or not is determined - * by {@link #fromInclusive} */ - double from() default Double.NEGATIVE_INFINITY; - /** Largest value. Whether it is inclusive or not is determined - * by {@link #toInclusive} */ - double to() default Double.POSITIVE_INFINITY; - - /** Whether the from value is included in the range */ - boolean fromInclusive() default true; - - /** Whether the to value is included in the range */ - boolean toInclusive() default true; -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/FractionRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/FractionRes.java deleted file mode 100644 index c559a8e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/FractionRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a fraction resource reference. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface FractionRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IdRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IdRes.java deleted file mode 100644 index b63ea5f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IdRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an id resource reference (e.g. {@link android.R.id#copy}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface IdRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntDef.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntDef.java deleted file mode 100644 index 3774890..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntDef.java +++ /dev/null @@ -1,58 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated element of integer type, represents - * a logical type and that its value should be one of the explicitly - * named constants. If the IntDef#flag() attribute is set to true, - * multiple constants can be combined. - *

- * Example: - *

{@code
- *  @Retention(SOURCE)
- *  @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
- *  public @interface NavigationMode {}
- *  public static final int NAVIGATION_MODE_STANDARD = 0;
- *  public static final int NAVIGATION_MODE_LIST = 1;
- *  public static final int NAVIGATION_MODE_TABS = 2;
- *  ...
- *  public abstract void setNavigationMode(@NavigationMode int mode);
- *  @NavigationMode
- *  public abstract int getNavigationMode();
- * }
- * For a flag, set the flag attribute: - *
{@code
- *  @IntDef(
- *      flag = true
- *      value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
- * }
- */ -@Retention(SOURCE) -@Target({ANNOTATION_TYPE}) -public @interface IntDef { - /** Defines the allowed constants for this element */ - long[] value() default {}; - - /** Defines whether the constants can be used as a flag, or just as an enum (the default) */ - boolean flag() default false; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntRange.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntRange.java deleted file mode 100644 index 321c3a7..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntRange.java +++ /dev/null @@ -1,45 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated element should be an int or long in the given range - *

- * Example: - *

{@code
- *  @IntRange(from=0,to=255)
- *  public int getAlpha() {
- *      ...
- *  }
- * }
- */ -@Retention(CLASS) -@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE}) -public @interface IntRange { - /** Smallest value, inclusive */ - long from() default Long.MIN_VALUE; - /** Largest value, inclusive */ - long to() default Long.MAX_VALUE; -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntegerRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntegerRes.java deleted file mode 100644 index e114ed3..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/IntegerRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an integer resource reference (e.g. {@link android.R.integer#config_shortAnimTime}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface IntegerRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/InterpolatorRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/InterpolatorRes.java deleted file mode 100644 index 27e24ec..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/InterpolatorRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an interpolator resource reference (e.g. {@link android.R.interpolator#cycle}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface InterpolatorRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Keep.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Keep.java deleted file mode 100644 index aa11890..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Keep.java +++ /dev/null @@ -1,46 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated element should not be removed when - * the code is minified at build time. This is typically used - * on methods and classes that are accessed only via reflection - * so a compiler may think that the code is unused. - *

- * Example: - *

{@code
- *  @Keep
- *  public void foo() {
- *      ...
- *  }
- * }
- */ -@Retention(CLASS) -@Target({PACKAGE,TYPE,ANNOTATION_TYPE,CONSTRUCTOR,METHOD,FIELD}) -public @interface Keep { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/LayoutRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/LayoutRes.java deleted file mode 100644 index f56ceeb..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/LayoutRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a layout resource reference (e.g. {@link android.R.layout#list_content}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface LayoutRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/MainThread.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/MainThread.java deleted file mode 100644 index 2b31fad..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/MainThread.java +++ /dev/null @@ -1,42 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated method should only be called on the main thread. - * If the annotated element is a class, then all methods in the class should be called - * on the main thread. - *

- * Example: - *

{@code
- *  @MainThread
- *  public void deliverResult(D data) { ... }
- * }
- */ -@Documented -@Retention(CLASS) -@Target({METHOD,CONSTRUCTOR,TYPE}) -public @interface MainThread { -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/MenuRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/MenuRes.java deleted file mode 100644 index acb7415..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/MenuRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a menu resource reference. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface MenuRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/NonNull.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/NonNull.java deleted file mode 100644 index 25455f7..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/NonNull.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that a parameter, field or method return value can never be null. - *

- * This is a marker annotation and it has no specific attributes. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD}) -public @interface NonNull { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Nullable.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Nullable.java deleted file mode 100644 index 63a91e4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Nullable.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that a parameter, field or method return value can be null. - *

- * When decorating a method call parameter, this denotes that the parameter can - * legitimately be null and the method will gracefully deal with it. Typically - * used on optional parameters. - *

- * When decorating a method, this denotes the method might legitimately return - * null. - *

- * This is a marker annotation and it has no specific attributes. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD}) -public @interface Nullable { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/PluralsRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/PluralsRes.java deleted file mode 100644 index acf4bd1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/PluralsRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a plurals resource reference. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface PluralsRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/RawRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/RawRes.java deleted file mode 100644 index c397586..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/RawRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a raw resource reference. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface RawRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/RequiresPermission.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/RequiresPermission.java deleted file mode 100644 index 4eb9c5a..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/RequiresPermission.java +++ /dev/null @@ -1,104 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated element requires (or may require) one or more permissions. - *

- * Example of requiring a single permission: - *

{@code
- *   @RequiresPermission(Manifest.permission.SET_WALLPAPER)
- *   public abstract void setWallpaper(Bitmap bitmap) throws IOException;
- *
- *   @RequiresPermission(ACCESS_COARSE_LOCATION)
- *   public abstract Location getLastKnownLocation(String provider);
- * }
- * Example of requiring at least one permission from a set: - *
{@code
- *   @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
- *   public abstract Location getLastKnownLocation(String provider);
- * }
- * Example of requiring multiple permissions: - *
{@code
- *   @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
- *   public abstract Location getLastKnownLocation(String provider);
- * }
- * Example of requiring separate read and write permissions for a content provider: - *
{@code
- *   @RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
- *   @RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
- *   public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
- * }
- * - * @hide - */ -@Retention(CLASS) -@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD}) -public @interface RequiresPermission { - /** - * The name of the permission that is required, if precisely one permission - * is required. If more than one permission is required, specify either - * {@link #allOf()} or {@link #anyOf()} instead. - *

- * If specified, {@link #anyOf()} and {@link #allOf()} must both be null. - */ - String value() default ""; - - /** - * Specifies a list of permission names that are all required. - *

- * If specified, {@link #anyOf()} and {@link #value()} must both be null. - */ - String[] allOf() default {}; - - /** - * Specifies a list of permission names where at least one is required - *

- * If specified, {@link #allOf()} and {@link #value()} must both be null. - */ - String[] anyOf() default {}; - - /** - * If true, the permission may not be required in all cases (e.g. it may only be - * enforced on certain platforms, or for certain call parameters, etc. - */ - boolean conditional() default false; - - /** - * Specifies that the given permission is required for read operations - */ - @Target(FIELD) - @interface Read { - RequiresPermission value(); - } - - /** - * Specifies that the given permission is required for write operations - */ - @Target(FIELD) - @interface Write { - RequiresPermission value(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Size.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Size.java deleted file mode 100644 index e83e2cc..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/Size.java +++ /dev/null @@ -1,51 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated element should have a given size or length. - * Note that "-1" means "unset". Typically used with a parameter or - * return value of type array or collection. - *

- * Example: - *

{@code
- *  public void getLocationInWindow(@Size(2) int[] location) {
- *      ...
- *  }
- * }
- */ -@Retention(CLASS) -@Target({PARAMETER,LOCAL_VARIABLE,METHOD,FIELD,ANNOTATION_TYPE}) -public @interface Size { - /** An exact size (or -1 if not specified) */ - long value() default -1; - /** A minimum size, inclusive */ - long min() default Long.MIN_VALUE; - /** A maximum size, inclusive */ - long max() default Long.MAX_VALUE; - /** The size must be a multiple of this factor */ - long multiple() default 1; -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StringDef.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StringDef.java deleted file mode 100644 index 1358d98..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StringDef.java +++ /dev/null @@ -1,49 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that the annotated String element, represents a logical - * type and that its value should be one of the explicitly named constants. - *

- * Example: - *

{@code
- *  @Retention(SOURCE)
- *  @StringDef({
- *     POWER_SERVICE,
- *     WINDOW_SERVICE,
- *     LAYOUT_INFLATER_SERVICE
- *  })
- *  public @interface ServiceName {}
- *  public static final String POWER_SERVICE = "power";
- *  public static final String WINDOW_SERVICE = "window";
- *  public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
- *  ...
- *  public abstract Object getSystemService(@ServiceName String name);
- * }
- */ -@Retention(SOURCE) -@Target({ANNOTATION_TYPE}) -public @interface StringDef { - /** Defines the allowed constants for this element */ - String[] value() default {}; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StringRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StringRes.java deleted file mode 100644 index 7a9795e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StringRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a String resource reference (e.g. {@link android.R.string#ok}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface StringRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StyleRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StyleRes.java deleted file mode 100644 index 118c960..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StyleRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a style resource reference (e.g. {@link android.R.style#TextAppearance}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface StyleRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StyleableRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StyleableRes.java deleted file mode 100644 index c2f2ea4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/StyleableRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a styleable resource reference (e.g. {@link android.R.styleable#TextView_text}). - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface StyleableRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/TransitionRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/TransitionRes.java deleted file mode 100644 index 1ea9411..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/TransitionRes.java +++ /dev/null @@ -1,35 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be a transition resource reference. - */ -@Documented -@Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) -public @interface TransitionRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/UiThread.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/UiThread.java deleted file mode 100644 index ca46884..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/UiThread.java +++ /dev/null @@ -1,43 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated method or constructor should only be called on the UI thread. - * If the annotated element is a class, then all methods in the class should be called - * on the UI thread. - *

- * Example: - *

{@code
- *  @UiThread
- *
- *  public abstract void setText(@NonNull String text) { ... }
- * }
- */ -@Documented -@Retention(CLASS) -@Target({METHOD,CONSTRUCTOR,TYPE}) -public @interface UiThread { -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/VisibleForTesting.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/VisibleForTesting.java deleted file mode 100644 index 5a1f941..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/VisibleForTesting.java +++ /dev/null @@ -1,28 +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 p.android.support.annotation; - -import java.lang.annotation.Retention; - -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the class, method or field has its visibility relaxed, so that it is more widely - * visible than otherwise necessary to make code testable. - */ -@Retention(CLASS) -public @interface VisibleForTesting { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/WorkerThread.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/WorkerThread.java deleted file mode 100644 index 57c69ac..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/WorkerThread.java +++ /dev/null @@ -1,42 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that the annotated method should only be called on a worker thread. - * If the annotated element is a class, then all methods in the class should be called - * on a worker thread. - *

- * Example: - *

{@code
- *  (@WorkerThread
- *  protected abstract FilterResults performFiltering(CharSequence constraint);
- * }
- */ -@Documented -@Retention(CLASS) -@Target({METHOD,CONSTRUCTOR,TYPE}) -public @interface WorkerThread { -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/XmlRes.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/XmlRes.java deleted file mode 100644 index c4b021d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/annotation/XmlRes.java +++ /dev/null @@ -1,36 +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 p.android.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.CLASS; - -/** - * Denotes that an integer parameter, field or method return value is expected - * to be an XML resource reference. - */ -@Documented -@Retention(CLASS) -@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) -public @interface XmlRes { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/BaseFragmentActivityEclair.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/BaseFragmentActivityEclair.java deleted file mode 100644 index 95a7889..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/BaseFragmentActivityEclair.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4; - -import p.android.support.v4.app.BaseFragmentActivityDonut; - -/** - * Base class for {@code FragmentActivity} to be able to use v5 APIs. - */ -public abstract class BaseFragmentActivityEclair extends BaseFragmentActivityDonut { - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java deleted file mode 100644 index 57b35f1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.accessibilityservice; - -import android.accessibilityservice.AccessibilityService; -import android.accessibilityservice.AccessibilityServiceInfo; -import android.content.pm.ResolveInfo; -import android.os.Build; -import android.view.View; - -/** - * Helper for accessing features in {@link AccessibilityService} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class AccessibilityServiceInfoCompat { - - static interface AccessibilityServiceInfoVersionImpl { - public String getId(AccessibilityServiceInfo info); - public ResolveInfo getResolveInfo(AccessibilityServiceInfo info); - public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info); - public String getDescription(AccessibilityServiceInfo info); - public String getSettingsActivityName(AccessibilityServiceInfo info); - public int getCapabilities(AccessibilityServiceInfo info); - } - - static class AccessibilityServiceInfoStubImpl implements AccessibilityServiceInfoVersionImpl { - - public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { - return false; - } - - public String getDescription(AccessibilityServiceInfo info) { - return null; - } - - public String getId(AccessibilityServiceInfo info) { - return null; - } - - public ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { - return null; - } - - public String getSettingsActivityName(AccessibilityServiceInfo info) { - return null; - } - - public int getCapabilities(AccessibilityServiceInfo info) { - return 0; - } - } - - static class AccessibilityServiceInfoIcsImpl extends AccessibilityServiceInfoStubImpl { - - @Override - public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { - return AccessibilityServiceInfoCompatIcs.getCanRetrieveWindowContent(info); - } - - @Override - public String getDescription(AccessibilityServiceInfo info) { - return AccessibilityServiceInfoCompatIcs.getDescription(info); - } - - @Override - public String getId(AccessibilityServiceInfo info) { - return AccessibilityServiceInfoCompatIcs.getId(info); - } - - @Override - public ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { - return AccessibilityServiceInfoCompatIcs.getResolveInfo(info); - } - - @Override - public String getSettingsActivityName(AccessibilityServiceInfo info) { - return AccessibilityServiceInfoCompatIcs.getSettingsActivityName(info); - } - - @Override - public int getCapabilities(AccessibilityServiceInfo info) { - if (getCanRetrieveWindowContent(info)) { - return CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT; - } - return 0; - } - } - - static class AccessibilityServiceInfoJellyBeanMr2 extends AccessibilityServiceInfoIcsImpl { - @Override - public int getCapabilities(AccessibilityServiceInfo info) { - return AccessibilityServiceInfoCompatJellyBeanMr2.getCapabilities(info); - } - } - - static { - if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2 - IMPL = new AccessibilityServiceInfoJellyBeanMr2(); - } else if (Build.VERSION.SDK_INT >= 14) { // ICS - IMPL = new AccessibilityServiceInfoIcsImpl(); - } else { - IMPL = new AccessibilityServiceInfoStubImpl(); - } - } - - // Capabilities - - private static final AccessibilityServiceInfoVersionImpl IMPL; - - /** - * Capability: This accessibility service can retrieve the active window content. - */ - public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001; - - /** - * Capability: This accessibility service can request touch exploration mode in which - * touched items are spoken aloud and the UI can be explored via gestures. - */ - public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002; - - /** - * Capability: This accessibility service can request enhanced web accessibility - * enhancements. For example, installing scripts to make app content more accessible. - */ - public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004; - - /** - * Capability: This accessibility service can filter the key event stream. - */ - public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 0x00000008; - - // Feedback types - - /** - * Denotes braille feedback. - */ - public static final int FEEDBACK_BRAILLE = 0x0000020; - - /** - * Mask for all feedback types. - * - * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN - * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC - * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE - * @see AccessibilityServiceInfo#FEEDBACK_VISUAL - * @see AccessibilityServiceInfo#FEEDBACK_GENERIC - * @see FEEDBACK_BRAILLE - */ - public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF; - - // Flags - - /** - * If an {@link AccessibilityService} is the default for a given type. - * Default service is invoked only if no package specific one exists. In case of - * more than one package specific service only the earlier registered is notified. - */ - public static final int DEFAULT = 0x0000001; - - /** - * If this flag is set the system will regard views that are not important - * for accessibility in addition to the ones that are important for accessibility. - * That is, views that are marked as not important for accessibility via - * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or - * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are - * marked as potentially important for accessibility via - * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined - * that are not important for accessibility, are both reported while querying the - * window content and also the accessibility service will receive accessibility events - * from them. - *

- * Note: For accessibility services targeting API version - * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly - * set for the system to regard views that are not important for accessibility. For - * accessibility services targeting API version lower than - * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are - * regarded for accessibility purposes. - *

- *

- * Usually views not important for accessibility are layout managers that do not - * react to user actions, do not draw any content, and do not have any special - * semantics in the context of the screen content. For example, a three by three - * grid can be implemented as three horizontal linear layouts and one vertical, - * or three vertical linear layouts and one horizontal, or one grid layout, etc. - * In this context the actual layout mangers used to achieve the grid configuration - * are not important, rather it is important that there are nine evenly distributed - * elements. - *

- */ - public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002; - - /** - * This flag requests that the system gets into touch exploration mode. - * In this mode a single finger moving on the screen behaves as a mouse - * pointer hovering over the user interface. The system will also detect - * certain gestures performed on the touch screen and notify this service. - * The system will enable touch exploration mode if there is at least one - * accessibility service that has this flag set. Hence, clearing this - * flag does not guarantee that the device will not be in touch exploration - * mode since there may be another enabled service that requested it. - *

- * For accessibility services targeting API version higher than - * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set - * this flag have to declare this capability in their meta-data by setting - * the attribute canRequestTouchExplorationMode to true, otherwise this flag - * will be ignored. For how to declare the meta-data of a service refer to - * {@value AccessibilityService#SERVICE_META_DATA}. - *

- *

- * Services targeting API version equal to or lower than - * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e. - * the first time they are run, if this flag is specified, a dialog is - * shown to the user to confirm enabling explore by touch. - *

- */ - public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004; - - /** - * This flag requests from the system to enable web accessibility enhancing - * extensions. Such extensions aim to provide improved accessibility support - * for content presented in a {@link android.webkit.WebView}. An example of such - * an extension is injecting JavaScript from a secure source. The system will enable - * enhanced web accessibility if there is at least one accessibility service - * that has this flag set. Hence, clearing this flag does not guarantee that the - * device will not have enhanced web accessibility enabled since there may be - * another enabled service that requested it. - *

- * Services that want to set this flag have to declare this capability - * in their meta-data by setting the attribute canRequestEnhancedWebAccessibility - * to true, otherwise this flag will be ignored. For how to declare the meta-data - * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. - *

- */ - public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008; - - /** - * This flag requests that the AccessibilityNodeInfos obtained - * by an {@link AccessibilityService} contain the id of the source view. - * The source view id will be a fully qualified resource name of the - * form "package:id/name", for example "foo.bar:id/my_list", and it is - * useful for UI test automation. This flag is not set by default. - */ - public static final int FLAG_REPORT_VIEW_IDS = 0x00000010; - - /** - * This flag requests from the system to filter key events. If this flag - * is set the accessibility service will receive the key events before - * applications allowing it implement global shortcuts. Setting this flag - * does not guarantee that this service will filter key events since only - * one service can do so at any given time. This avoids user confusion due - * to behavior change in case different key filtering services are enabled. - * If there is already another key filtering service enabled, this one will - * not receive key events. - *

- * Services that want to set this flag have to declare this capability - * in their meta-data by setting the attribute canRequestFilterKeyEvents - * to true, otherwise this flag will be ignored. For how to declare the meta - * -data of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. - *

- */ - public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020; - - /* - * Hide constructor - */ - private AccessibilityServiceInfoCompat() {} - - /** - * The accessibility service id. - *

- * Generated by the system. - *

- * - * @return The id. - */ - public static String getId(AccessibilityServiceInfo info) { - return IMPL.getId(info); - } - - /** - * The service {@link ResolveInfo}. - *

- * Generated by the system. - *

- * - * @return The info. - */ - public static ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { - return IMPL.getResolveInfo(info); - } - - /** - * The settings activity name. - *

- * Statically set from {@link AccessibilityService#SERVICE_META_DATA - * meta-data}. - *

- * - * @return The settings activity name. - */ - public static String getSettingsActivityName(AccessibilityServiceInfo info) { - return IMPL.getSettingsActivityName(info); - } - - /** - * Whether this service can retrieve the current window's content. - *

- * Statically set from {@link AccessibilityService#SERVICE_META_DATA - * meta-data}. - *

- * - * @return True window content can be retrieved. - */ - public static boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { - return IMPL.getCanRetrieveWindowContent(info); - } - - /** - * Description of the accessibility service. - *

- * Statically set from {@link AccessibilityService#SERVICE_META_DATA - * meta-data}. - *

- * - * @return The description. - */ - public static String getDescription(AccessibilityServiceInfo info) { - return IMPL.getDescription(info); - } - - /** - * Returns the string representation of a feedback type. For example, - * {@link AccessibilityServiceInfo#FEEDBACK_SPOKEN} is represented by the - * string FEEDBACK_SPOKEN. - * - * @param feedbackType The feedback type. - * @return The string representation. - */ - public static String feedbackTypeToString(int feedbackType) { - StringBuilder builder = new StringBuilder(); - builder.append("["); - while (feedbackType > 0) { - final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType); - feedbackType &= ~feedbackTypeFlag; - if (builder.length() > 1) { - builder.append(", "); - } - switch (feedbackTypeFlag) { - case AccessibilityServiceInfo.FEEDBACK_AUDIBLE: - builder.append("FEEDBACK_AUDIBLE"); - break; - case AccessibilityServiceInfo.FEEDBACK_HAPTIC: - builder.append("FEEDBACK_HAPTIC"); - break; - case AccessibilityServiceInfo.FEEDBACK_GENERIC: - builder.append("FEEDBACK_GENERIC"); - break; - case AccessibilityServiceInfo.FEEDBACK_SPOKEN: - builder.append("FEEDBACK_SPOKEN"); - break; - case AccessibilityServiceInfo.FEEDBACK_VISUAL: - builder.append("FEEDBACK_VISUAL"); - break; - } - } - builder.append("]"); - return builder.toString(); - } - - /** - * Returns the string representation of a flag. For example, - * {@link AccessibilityServiceInfo#DEFAULT} is represented by the - * string DEFAULT. - * - * @param flag The flag. - * @return The string representation. - */ - public static String flagToString(int flag) { - switch (flag) { - case DEFAULT: - return "DEFAULT"; - case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS: - return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS"; - case FLAG_REQUEST_TOUCH_EXPLORATION_MODE: - return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE"; - case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY: - return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; - case FLAG_REPORT_VIEW_IDS: - return "FLAG_REPORT_VIEW_IDS"; - case FLAG_REQUEST_FILTER_KEY_EVENTS: - return "FLAG_REQUEST_FILTER_KEY_EVENTS"; - default: - return null; - } - } - - /** - * Returns the bit mask of capabilities this accessibility service has such as - * being able to retrieve the active window content, etc. - * - * @param info The service info whose capabilities to get. - * @return The capability bit mask. - * - * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT - * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION - * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY - * @see #CAPABILITY_CAN_FILTER_KEY_EVENTS - */ - public static int getCapabilities(AccessibilityServiceInfo info) { - return IMPL.getCapabilities(info); - } - - /** - * Returns the string representation of a capability. For example, - * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented - * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT. - * - * @param capability The capability. - * @return The string representation. - */ - public static String capabilityToString(int capability) { - switch (capability) { - case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT: - return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT"; - case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION: - return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION"; - case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY: - return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; - case CAPABILITY_CAN_FILTER_KEY_EVENTS: - return "CAPABILITY_CAN_FILTER_KEY_EVENTS"; - default: - return "UNKNOWN"; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatIcs.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatIcs.java deleted file mode 100644 index 048ef42..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatIcs.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package p.android.support.v4.accessibilityservice; - -import android.accessibilityservice.AccessibilityServiceInfo; -import android.content.pm.ResolveInfo; - -/** - * ICS implementation of the new APIs in AccessibilityServiceInfo. - */ -class AccessibilityServiceInfoCompatIcs { - - public static boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) { - return info.getCanRetrieveWindowContent(); - } - - public static String getDescription(AccessibilityServiceInfo info) { - return info.getDescription(); - } - - public static String getId(AccessibilityServiceInfo info) { - return info.getId(); - } - - public static ResolveInfo getResolveInfo(AccessibilityServiceInfo info) { - return info.getResolveInfo(); - } - - public static String getSettingsActivityName(AccessibilityServiceInfo info) { - return info.getSettingsActivityName(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatJellyBeanMr2.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatJellyBeanMr2.java deleted file mode 100644 index 5505308..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatJellyBeanMr2.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.accessibilityservice; - -import android.accessibilityservice.AccessibilityServiceInfo; - -/** - * ICS implementation of the new APIs in AccessibilityServiceInfo. - */ -class AccessibilityServiceInfoCompatJellyBeanMr2 { - - public static int getCapabilities(AccessibilityServiceInfo info) { - return info.getCapabilities(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/package.html b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/package.html deleted file mode 100755 index 3d017b0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/accessibilityservice/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - -Support android.accessibilityservice classes to assist with development of applications for -android API level 4 or later. - - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorCompatHelper.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorCompatHelper.java deleted file mode 100644 index 3df98dd..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorCompatHelper.java +++ /dev/null @@ -1,46 +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 p.android.support.v4.animation; - -import android.os.Build; -import android.view.View; - -/** - * @hide - */ -public final class AnimatorCompatHelper { - - private final static AnimatorProvider IMPL; - - static { - if (Build.VERSION.SDK_INT >= 12) { - IMPL = new HoneycombMr1AnimatorCompatProvider(); - } else { - IMPL = new DonutAnimatorCompatProvider(); - } - } - - public static ValueAnimatorCompat emptyValueAnimator() { - return IMPL.emptyValueAnimator(); - } - - private AnimatorCompatHelper() {} - - public static void clearInterpolator(View view) { - IMPL.clearInterpolator(view); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorListenerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorListenerCompat.java deleted file mode 100644 index 016bb17..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorListenerCompat.java +++ /dev/null @@ -1,57 +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 p.android.support.v4.animation; - -/** - *

An animation listener that receives notifications from an animation. - * Notifications indicate animation related events, such as the end or the - * repetition of the animation.

- * - * @hide - */ -public interface AnimatorListenerCompat { - - /** - *

Notifies the start of the animation.

- * - * @param animation The started animation. - */ - void onAnimationStart(ValueAnimatorCompat animation); - - /** - *

Notifies the end of the animation. This callback is not invoked - * for animations with repeat count set to INFINITE.

- * - * @param animation The animation which reached its end. - */ - void onAnimationEnd(ValueAnimatorCompat animation); - - /** - *

Notifies the cancellation of the animation. This callback is not invoked - * for animations with repeat count set to INFINITE.

- * - * @param animation The animation which was canceled. - */ - void onAnimationCancel(ValueAnimatorCompat animation); - - /** - *

Notifies the repetition of the animation.

- * - * @param animation The animation which was repeated. - */ - void onAnimationRepeat(ValueAnimatorCompat animation); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorProvider.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorProvider.java deleted file mode 100644 index 74e747b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorProvider.java +++ /dev/null @@ -1,39 +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 p.android.support.v4.animation; - -import android.view.View; - -/** - * A simple interface to do things in animation pulse. - *

- * Before Honeycomb, it uses a simple Handler to mimic animation callback. - *

- * This is only a minimal implementation which is why this class is hidden. - * - * @hide - */ -interface AnimatorProvider { - - /** - * Provides a simple ValueAnimator w/o any start or end values. It provides the same - * Animator callback interface. - */ - ValueAnimatorCompat emptyValueAnimator(); - - void clearInterpolator(View view); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorUpdateListenerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorUpdateListenerCompat.java deleted file mode 100644 index 1654d54..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/AnimatorUpdateListenerCompat.java +++ /dev/null @@ -1,36 +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 p.android.support.v4.animation; - -/** - * Implementors of this interface can add themselves as update listeners - * to a ValueAnimator instance to receive callbacks on every animation - * frame, after the current frame's values have been calculated for that - * ValueAnimator. - * - * @hide - */ -public interface AnimatorUpdateListenerCompat { - - /** - *

Notifies the occurrence of another frame of the animation.

- * - * @param animation The animation which was repeated. - */ - void onAnimationUpdate(ValueAnimatorCompat animation); - -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/DonutAnimatorCompatProvider.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/DonutAnimatorCompatProvider.java deleted file mode 100644 index ba92645..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/DonutAnimatorCompatProvider.java +++ /dev/null @@ -1,155 +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 p.android.support.v4.animation; - -import android.view.View; - -import java.util.ArrayList; -import java.util.List; - -/** - * Provides similar functionality to Animators on platforms prior to Honeycomb. - *

- * This is not a fully implemented API which is why it is not public. - * - * @hide - */ -class DonutAnimatorCompatProvider implements AnimatorProvider { - - @Override - public ValueAnimatorCompat emptyValueAnimator() { - return new DonutFloatValueAnimator(); - } - - private static class DonutFloatValueAnimator implements ValueAnimatorCompat { - - List mListeners = new ArrayList(); - List mUpdateListeners - = new ArrayList(); - View mTarget; - private long mStartTime; - private long mDuration = 200; - private float mFraction = 0f; - - private boolean mStarted = false; - private boolean mEnded = false; - - public DonutFloatValueAnimator() { - } - - private Runnable mLoopRunnable = new Runnable() { - @Override - public void run() { - long dt = getTime() - mStartTime; - float fraction = dt * 1f / mDuration; - if (fraction > 1f || mTarget.getParent() == null) { - fraction = 1f; - } - mFraction = fraction; - notifyUpdateListeners(); - if (mFraction >= 1f) { - dispatchEnd(); - } else { - mTarget.postDelayed(mLoopRunnable, 16); - } - } - }; - - private void notifyUpdateListeners() { - for (int i = mUpdateListeners.size() - 1; i >= 0; i--) { - mUpdateListeners.get(i).onAnimationUpdate(this); - } - } - - @Override - public void setTarget(View view) { - mTarget = view; - } - - @Override - public void addListener(AnimatorListenerCompat listener) { - mListeners.add(listener); - } - - @Override - public void setDuration(long duration) { - if (!mStarted) { - mDuration = duration; - } - } - - @Override - public void start() { - if (mStarted) { - return; - } - mStarted = true; - dispatchStart(); - mFraction = 0f; - mStartTime = getTime(); - mTarget.postDelayed(mLoopRunnable, 16); - } - - private long getTime() { - return mTarget.getDrawingTime(); - } - - private void dispatchStart() { - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).onAnimationStart(this); - } - } - - private void dispatchEnd() { - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).onAnimationEnd(this); - } - } - - private void dispatchCancel() { - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).onAnimationCancel(this); - } - } - - @Override - public void cancel() { - if (mEnded) { - return; - } - mEnded = true; - if (mStarted) { - dispatchCancel(); - } - dispatchEnd(); - } - - @Override - public void addUpdateListener(AnimatorUpdateListenerCompat animatorUpdateListener) { - mUpdateListeners.add(animatorUpdateListener); - } - - @Override - public float getAnimatedFraction() { - return mFraction; - } - } - - @Override - public void clearInterpolator(View view) { - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/HoneycombMr1AnimatorCompatProvider.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/HoneycombMr1AnimatorCompatProvider.java deleted file mode 100644 index c974ad0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/HoneycombMr1AnimatorCompatProvider.java +++ /dev/null @@ -1,133 +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 p.android.support.v4.animation; - -import android.animation.Animator; -import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; -import android.view.View; - -/** - * Uses framework Animators to provide ValueAnimatorCompat interface. - *

- * This is not a fully implemented API which is why it is not public. - * - * @hide - */ -class HoneycombMr1AnimatorCompatProvider implements AnimatorProvider { - - private TimeInterpolator mDefaultInterpolator; - - @Override - public ValueAnimatorCompat emptyValueAnimator() { - return new HoneycombValueAnimatorCompat(ValueAnimator.ofFloat(0f, 1f)); - } - - static class HoneycombValueAnimatorCompat implements ValueAnimatorCompat { - - final Animator mWrapped; - - public HoneycombValueAnimatorCompat(Animator wrapped) { - mWrapped = wrapped; - } - - @Override - public void setTarget(View view) { - mWrapped.setTarget(view); - } - - @Override - public void addListener(AnimatorListenerCompat listener) { - mWrapped.addListener(new AnimatorListenerCompatWrapper(listener, this)); - } - - @Override - public void setDuration(long duration) { - mWrapped.setDuration(duration); - } - - @Override - public void start() { - mWrapped.start(); - } - - @Override - public void cancel() { - mWrapped.cancel(); - } - - @Override - public void addUpdateListener(final AnimatorUpdateListenerCompat animatorUpdateListener) { - if (mWrapped instanceof ValueAnimator) { - ((ValueAnimator) mWrapped).addUpdateListener( - new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - animatorUpdateListener - .onAnimationUpdate(HoneycombValueAnimatorCompat.this); - } - }); - } - } - - @Override - public float getAnimatedFraction() { - return ((ValueAnimator) mWrapped).getAnimatedFraction(); - } - } - - static class AnimatorListenerCompatWrapper implements Animator.AnimatorListener { - - final AnimatorListenerCompat mWrapped; - - final ValueAnimatorCompat mValueAnimatorCompat; - - public AnimatorListenerCompatWrapper( - AnimatorListenerCompat wrapped, ValueAnimatorCompat valueAnimatorCompat) { - mWrapped = wrapped; - mValueAnimatorCompat = valueAnimatorCompat; - } - - @Override - public void onAnimationStart(Animator animation) { - mWrapped.onAnimationStart(mValueAnimatorCompat); - } - - @Override - public void onAnimationEnd(Animator animation) { - mWrapped.onAnimationEnd(mValueAnimatorCompat); - } - - @Override - public void onAnimationCancel(Animator animation) { - mWrapped.onAnimationCancel(mValueAnimatorCompat); - } - - @Override - public void onAnimationRepeat(Animator animation) { - mWrapped.onAnimationRepeat(mValueAnimatorCompat); - } - } - - @Override - public void clearInterpolator(View view) { - if (mDefaultInterpolator == null) { - mDefaultInterpolator = new ValueAnimator().getInterpolator(); - } - view.animate().setInterpolator(mDefaultInterpolator); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/ValueAnimatorCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/ValueAnimatorCompat.java deleted file mode 100644 index 4a2f71e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/animation/ValueAnimatorCompat.java +++ /dev/null @@ -1,41 +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 p.android.support.v4.animation; - -import android.view.View; - -/** - * Compatibility implementation for {@code android.animation.ValueAnimator}. - * - * @hide - */ -public interface ValueAnimatorCompat { - - public void setTarget(View view); - - public void addListener(AnimatorListenerCompat listener); - - public void setDuration(long duration); - - public void start(); - - public void cancel(); - - void addUpdateListener(AnimatorUpdateListenerCompat animatorUpdateListener); - - public float getAnimatedFraction(); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggle.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggle.java deleted file mode 100644 index efb17ad..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggle.java +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.InsetDrawable; -import android.os.Build; -import p.android.support.v4.content.ContextCompat; -import p.android.support.annotation.DrawableRes; -import p.android.support.annotation.Nullable; -import p.android.support.annotation.StringRes; -import p.android.support.v4.view.GravityCompat; -import p.android.support.v4.view.ViewCompat; -import p.android.support.v4.widget.DrawerLayout; -import android.view.MenuItem; -import android.view.View; - -/** - * @deprecated Please use ActionBarDrawerToggle in support-v7-appcompat. - * - *

- * This class provides a handy way to tie together the functionality of - * {@link DrawerLayout} and the framework ActionBar to implement the recommended - * design for navigation drawers. - * - *

To use ActionBarDrawerToggle, create one in your Activity and call through - * to the following methods corresponding to your Activity callbacks:

- * - *
    - *
  • {@link Activity#onConfigurationChanged(Configuration) onConfigurationChanged}
  • - *
  • {@link Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected}
  • - *
- * - *

Call {@link #syncState()} from your Activity's - * {@link Activity#onPostCreate(android.os.Bundle) onPostCreate} to synchronize the indicator - * with the state of the linked DrawerLayout after onRestoreInstanceState - * has occurred.

- * - *

ActionBarDrawerToggle can be used directly as a - * {@link DrawerLayout.DrawerListener}, or if you are already providing your own listener, - * call through to each of the listener methods from your own.

- * - */ -@Deprecated -public class ActionBarDrawerToggle implements DrawerLayout.DrawerListener { - - /** - * Allows an implementing Activity to return an {@link Delegate} to use - * with ActionBarDrawerToggle. - */ - public interface DelegateProvider { - - /** - * @return Delegate to use for ActionBarDrawableToggles, or null if the Activity - * does not wish to override the default behavior. - */ - @Nullable - Delegate getDrawerToggleDelegate(); - } - - public interface Delegate { - /** - * @return Up indicator drawable as defined in the Activity's theme, or null if one is not - * defined. - */ - @Nullable - Drawable getThemeUpIndicator(); - - /** - * Set the Action Bar's up indicator drawable and content description. - * - * @param upDrawable - Drawable to set as up indicator - * @param contentDescRes - Content description to set - */ - void setActionBarUpIndicator(Drawable upDrawable, @StringRes int contentDescRes); - - /** - * Set the Action Bar's up indicator content description. - * - * @param contentDescRes - Content description to set - */ - void setActionBarDescription(@StringRes int contentDescRes); - } - - private interface ActionBarDrawerToggleImpl { - Drawable getThemeUpIndicator(Activity activity); - Object setActionBarUpIndicator(Object info, Activity activity, - Drawable themeImage, int contentDescRes); - Object setActionBarDescription(Object info, Activity activity, int contentDescRes); - } - - private static class ActionBarDrawerToggleImplBase implements ActionBarDrawerToggleImpl { - @Override - public Drawable getThemeUpIndicator(Activity activity) { - return null; - } - - @Override - public Object setActionBarUpIndicator(Object info, Activity activity, - Drawable themeImage, int contentDescRes) { - // No action bar to set. - return info; - } - - @Override - public Object setActionBarDescription(Object info, Activity activity, int contentDescRes) { - // No action bar to set - return info; - } - } - - private static class ActionBarDrawerToggleImplHC implements ActionBarDrawerToggleImpl { - @Override - public Drawable getThemeUpIndicator(Activity activity) { - return ActionBarDrawerToggleHoneycomb.getThemeUpIndicator(activity); - } - - @Override - public Object setActionBarUpIndicator(Object info, Activity activity, - Drawable themeImage, int contentDescRes) { - return ActionBarDrawerToggleHoneycomb.setActionBarUpIndicator(info, activity, - themeImage, contentDescRes); - } - - @Override - public Object setActionBarDescription(Object info, Activity activity, int contentDescRes) { - return ActionBarDrawerToggleHoneycomb.setActionBarDescription(info, activity, - contentDescRes); - } - } - - private static class ActionBarDrawerToggleImplJellybeanMR2 - implements ActionBarDrawerToggleImpl { - @Override - public Drawable getThemeUpIndicator(Activity activity) { - return ActionBarDrawerToggleJellybeanMR2.getThemeUpIndicator(activity); - } - - @Override - public Object setActionBarUpIndicator(Object info, Activity activity, - Drawable themeImage, int contentDescRes) { - return ActionBarDrawerToggleJellybeanMR2.setActionBarUpIndicator(info, activity, - themeImage, contentDescRes); - } - - @Override - public Object setActionBarDescription(Object info, Activity activity, int contentDescRes) { - return ActionBarDrawerToggleJellybeanMR2.setActionBarDescription(info, activity, - contentDescRes); - } - } - - private static final ActionBarDrawerToggleImpl IMPL; - - static { - final int version = Build.VERSION.SDK_INT; - if (version >= 18) { - IMPL = new ActionBarDrawerToggleImplJellybeanMR2(); - } else if (version >= 11) { - IMPL = new ActionBarDrawerToggleImplHC(); - } else { - IMPL = new ActionBarDrawerToggleImplBase(); - } - } - - /** Fraction of its total width by which to offset the toggle drawable. */ - private static final float TOGGLE_DRAWABLE_OFFSET = 1 / 3f; - - // android.R.id.home as defined by public API in v11 - private static final int ID_HOME = 0x0102002c; - - private final Activity mActivity; - private final Delegate mActivityImpl; - private final DrawerLayout mDrawerLayout; - private boolean mDrawerIndicatorEnabled = true; - private boolean mHasCustomUpIndicator; - - private Drawable mHomeAsUpIndicator; - private Drawable mDrawerImage; - private SlideDrawable mSlider; - private final int mDrawerImageResource; - private final int mOpenDrawerContentDescRes; - private final int mCloseDrawerContentDescRes; - - private Object mSetIndicatorInfo; - - /** - * Construct a new ActionBarDrawerToggle. - * - *

The given {@link Activity} will be linked to the specified {@link DrawerLayout}. - * The provided drawer indicator drawable will animate slightly off-screen as the drawer - * is opened, indicating that in the open state the drawer will move off-screen when pressed - * and in the closed state the drawer will move on-screen when pressed.

- * - *

String resources must be provided to describe the open/close drawer actions for - * accessibility services.

- * - * @param activity The Activity hosting the drawer - * @param drawerLayout The DrawerLayout to link to the given Activity's ActionBar - * @param drawerImageRes A Drawable resource to use as the drawer indicator - * @param openDrawerContentDescRes A String resource to describe the "open drawer" action - * for accessibility - * @param closeDrawerContentDescRes A String resource to describe the "close drawer" action - * for accessibility - */ - public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, - @DrawableRes int drawerImageRes, @StringRes int openDrawerContentDescRes, - @StringRes int closeDrawerContentDescRes) { - this(activity, drawerLayout, !assumeMaterial(activity), drawerImageRes, - openDrawerContentDescRes, closeDrawerContentDescRes); - } - - private static boolean assumeMaterial(Context context) { - return context.getApplicationInfo().targetSdkVersion >= 21 && - (Build.VERSION.SDK_INT >= 21); - } - - /** - * Construct a new ActionBarDrawerToggle. - * - *

The given {@link Activity} will be linked to the specified {@link DrawerLayout}. - * The provided drawer indicator drawable will animate slightly off-screen as the drawer - * is opened, indicating that in the open state the drawer will move off-screen when pressed - * and in the closed state the drawer will move on-screen when pressed.

- * - *

String resources must be provided to describe the open/close drawer actions for - * accessibility services.

- * - * @param activity The Activity hosting the drawer - * @param drawerLayout The DrawerLayout to link to the given Activity's ActionBar - * @param animate True to animate the drawer indicator along with the drawer's position. - * Material apps should set this to false. - * @param drawerImageRes A Drawable resource to use as the drawer indicator - * @param openDrawerContentDescRes A String resource to describe the "open drawer" action - * for accessibility - * @param closeDrawerContentDescRes A String resource to describe the "close drawer" action - * for accessibility - */ - public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, boolean animate, - @DrawableRes int drawerImageRes, @StringRes int openDrawerContentDescRes, - @StringRes int closeDrawerContentDescRes) { - mActivity = activity; - - // Allow the Activity to provide an impl - if (activity instanceof DelegateProvider) { - mActivityImpl = ((DelegateProvider) activity).getDrawerToggleDelegate(); - } else { - mActivityImpl = null; - } - - mDrawerLayout = drawerLayout; - mDrawerImageResource = drawerImageRes; - mOpenDrawerContentDescRes = openDrawerContentDescRes; - mCloseDrawerContentDescRes = closeDrawerContentDescRes; - - mHomeAsUpIndicator = getThemeUpIndicator(); - mDrawerImage = ContextCompat.getDrawable(activity, drawerImageRes); - mSlider = new SlideDrawable(mDrawerImage); - mSlider.setOffset(animate ? TOGGLE_DRAWABLE_OFFSET : 0); - } - - /** - * Synchronize the state of the drawer indicator/affordance with the linked DrawerLayout. - * - *

This should be called from your Activity's - * {@link Activity#onPostCreate(android.os.Bundle) onPostCreate} method to synchronize after - * the DrawerLayout's instance state has been restored, and any other time when the state - * may have diverged in such a way that the ActionBarDrawerToggle was not notified. - * (For example, if you stop forwarding appropriate drawer events for a period of time.)

- */ - public void syncState() { - if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) { - mSlider.setPosition(1); - } else { - mSlider.setPosition(0); - } - - if (mDrawerIndicatorEnabled) { - setActionBarUpIndicator(mSlider, mDrawerLayout.isDrawerOpen(GravityCompat.START) ? - mCloseDrawerContentDescRes : mOpenDrawerContentDescRes); - } - } - - /** - * Set the up indicator to display when the drawer indicator is not - * enabled. - *

- * If you pass null to this method, the default drawable from - * the theme will be used. - * - * @param indicator A drawable to use for the up indicator, or null to use - * the theme's default - * @see #setDrawerIndicatorEnabled(boolean) - */ - public void setHomeAsUpIndicator(Drawable indicator) { - if (indicator == null) { - mHomeAsUpIndicator = getThemeUpIndicator(); - mHasCustomUpIndicator = false; - } else { - mHomeAsUpIndicator = indicator; - mHasCustomUpIndicator = true; - } - - if (!mDrawerIndicatorEnabled) { - setActionBarUpIndicator(mHomeAsUpIndicator, 0); - } - } - - /** - * Set the up indicator to display when the drawer indicator is not - * enabled. - *

- * If you pass 0 to this method, the default drawable from the theme will - * be used. - * - * @param resId Resource ID of a drawable to use for the up indicator, or 0 - * to use the theme's default - * @see #setDrawerIndicatorEnabled(boolean) - */ - public void setHomeAsUpIndicator(int resId) { - Drawable indicator = null; - if (resId != 0) { - indicator = ContextCompat.getDrawable(mActivity, resId); - } - - setHomeAsUpIndicator(indicator); - } - - /** - * Enable or disable the drawer indicator. The indicator defaults to enabled. - * - *

When the indicator is disabled, the ActionBar will revert to displaying - * the home-as-up indicator provided by the Activity's theme in the - * android.R.attr.homeAsUpIndicator attribute instead of the animated - * drawer glyph.

- * - * @param enable true to enable, false to disable - */ - public void setDrawerIndicatorEnabled(boolean enable) { - if (enable != mDrawerIndicatorEnabled) { - if (enable) { - setActionBarUpIndicator(mSlider, mDrawerLayout.isDrawerOpen(GravityCompat.START) ? - mCloseDrawerContentDescRes : mOpenDrawerContentDescRes); - } else { - setActionBarUpIndicator(mHomeAsUpIndicator, 0); - } - mDrawerIndicatorEnabled = enable; - } - } - - /** - * @return true if the enhanced drawer indicator is enabled, false otherwise - * @see #setDrawerIndicatorEnabled(boolean) - */ - public boolean isDrawerIndicatorEnabled() { - return mDrawerIndicatorEnabled; - } - - /** - * This method should always be called by your Activity's - * {@link Activity#onConfigurationChanged(Configuration) onConfigurationChanged} - * method. - * - * @param newConfig The new configuration - */ - public void onConfigurationChanged(Configuration newConfig) { - // Reload drawables that can change with configuration - if (!mHasCustomUpIndicator) { - mHomeAsUpIndicator = getThemeUpIndicator(); - } - mDrawerImage = ContextCompat.getDrawable(mActivity, mDrawerImageResource); - syncState(); - } - - /** - * This method should be called by your Activity's - * {@link Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected} method. - * If it returns true, your onOptionsItemSelected method should return true and - * skip further processing. - * - * @param item the MenuItem instance representing the selected menu item - * @return true if the event was handled and further processing should not occur - */ - public boolean onOptionsItemSelected(MenuItem item) { - if (item != null && item.getItemId() == ID_HOME && mDrawerIndicatorEnabled) { - if (mDrawerLayout.isDrawerVisible(GravityCompat.START)) { - mDrawerLayout.closeDrawer(GravityCompat.START); - } else { - mDrawerLayout.openDrawer(GravityCompat.START); - } - return true; - } - return false; - } - - /** - * {@link DrawerLayout.DrawerListener} callback method. If you do not use your - * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call - * through to this method from your own listener object. - * - * @param drawerView The child view that was moved - * @param slideOffset The new offset of this drawer within its range, from 0-1 - */ - @Override - public void onDrawerSlide(View drawerView, float slideOffset) { - float glyphOffset = mSlider.getPosition(); - if (slideOffset > 0.5f) { - glyphOffset = Math.max(glyphOffset, Math.max(0.f, slideOffset - 0.5f) * 2); - } else { - glyphOffset = Math.min(glyphOffset, slideOffset * 2); - } - mSlider.setPosition(glyphOffset); - } - - /** - * {@link DrawerLayout.DrawerListener} callback method. If you do not use your - * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call - * through to this method from your own listener object. - * - * @param drawerView Drawer view that is now open - */ - @Override - public void onDrawerOpened(View drawerView) { - mSlider.setPosition(1); - if (mDrawerIndicatorEnabled) { - setActionBarDescription(mCloseDrawerContentDescRes); - } - } - - /** - * {@link DrawerLayout.DrawerListener} callback method. If you do not use your - * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call - * through to this method from your own listener object. - * - * @param drawerView Drawer view that is now closed - */ - @Override - public void onDrawerClosed(View drawerView) { - mSlider.setPosition(0); - if (mDrawerIndicatorEnabled) { - setActionBarDescription(mOpenDrawerContentDescRes); - } - } - - /** - * {@link DrawerLayout.DrawerListener} callback method. If you do not use your - * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call - * through to this method from your own listener object. - * - * @param newState The new drawer motion state - */ - @Override - public void onDrawerStateChanged(int newState) { - } - - Drawable getThemeUpIndicator() { - if (mActivityImpl != null) { - return mActivityImpl.getThemeUpIndicator(); - } - return IMPL.getThemeUpIndicator(mActivity); - } - - void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) { - if (mActivityImpl != null) { - mActivityImpl.setActionBarUpIndicator(upDrawable, contentDescRes); - return; - } - mSetIndicatorInfo = IMPL - .setActionBarUpIndicator(mSetIndicatorInfo, mActivity, upDrawable, contentDescRes); - } - - void setActionBarDescription(int contentDescRes) { - if (mActivityImpl != null) { - mActivityImpl.setActionBarDescription(contentDescRes); - return; - } - mSetIndicatorInfo = IMPL - .setActionBarDescription(mSetIndicatorInfo, mActivity, contentDescRes); - } - - private class SlideDrawable extends InsetDrawable implements Drawable.Callback { - private final boolean mHasMirroring = Build.VERSION.SDK_INT > 18; - private final Rect mTmpRect = new Rect(); - - private float mPosition; - private float mOffset; - - private SlideDrawable(Drawable wrapped) { - super(wrapped, 0); - } - - /** - * Sets the current position along the offset. - * - * @param position a value between 0 and 1 - */ - public void setPosition(float position) { - mPosition = position; - invalidateSelf(); - } - - public float getPosition() { - return mPosition; - } - - /** - * Specifies the maximum offset when the position is at 1. - * - * @param offset maximum offset as a fraction of the drawable width, - * positive to shift left or negative to shift right. - * @see #setPosition(float) - */ - public void setOffset(float offset) { - mOffset = offset; - invalidateSelf(); - } - - @Override - public void draw(Canvas canvas) { - copyBounds(mTmpRect); - canvas.save(); - - // Layout direction must be obtained from the activity. - final boolean isLayoutRTL = ViewCompat.getLayoutDirection( - mActivity.getWindow().getDecorView()) == ViewCompat.LAYOUT_DIRECTION_RTL; - final int flipRtl = isLayoutRTL ? -1 : 1; - final int width = mTmpRect.width(); - canvas.translate(-mOffset * width * mPosition * flipRtl, 0); - - // Force auto-mirroring if it's not supported by the platform. - if (isLayoutRTL && !mHasMirroring) { - canvas.translate(width, 0); - canvas.scale(-1, 1); - } - - super.draw(canvas); - canvas.restore(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggleHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggleHoneycomb.java deleted file mode 100644 index ca574ae..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggleHoneycomb.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package p.android.support.v4.app; - -import android.R; -import android.app.ActionBar; -import android.app.Activity; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import java.lang.reflect.Method; - -/** - * This class encapsulates some awful hacks. - * - * Before JB-MR2 (API 18) it was not possible to change the home-as-up indicator glyph - * in an action bar without some really gross hacks. Since the MR2 SDK is not published as of - * this writing, the new API is accessed via reflection here if available. - */ -class ActionBarDrawerToggleHoneycomb { - private static final String TAG = "ActionBarDrawerToggleHoneycomb"; - - private static final int[] THEME_ATTRS = new int[] { - R.attr.homeAsUpIndicator - }; - - public static Object setActionBarUpIndicator(Object info, Activity activity, - Drawable drawable, int contentDescRes) { - if (info == null) { - info = new SetIndicatorInfo(activity); - } - final SetIndicatorInfo sii = (SetIndicatorInfo) info; - if (sii.setHomeAsUpIndicator != null) { - try { - final ActionBar actionBar = activity.getActionBar(); - sii.setHomeAsUpIndicator.invoke(actionBar, drawable); - sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); - } catch (Exception e) { - Log.w(TAG, "Couldn't set home-as-up indicator via JB-MR2 API", e); - } - } else if (sii.upIndicatorView != null) { - sii.upIndicatorView.setImageDrawable(drawable); - } else { - Log.w(TAG, "Couldn't set home-as-up indicator"); - } - return info; - } - - public static Object setActionBarDescription(Object info, Activity activity, - int contentDescRes) { - if (info == null) { - info = new SetIndicatorInfo(activity); - } - final SetIndicatorInfo sii = (SetIndicatorInfo) info; - if (sii.setHomeAsUpIndicator != null) { - try { - final ActionBar actionBar = activity.getActionBar(); - sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); - if (Build.VERSION.SDK_INT <= 19) { - // For API 19 and earlier, we need to manually force the - // action bar to generate a new content description. - actionBar.setSubtitle(actionBar.getSubtitle()); - } - } catch (Exception e) { - Log.w(TAG, "Couldn't set content description via JB-MR2 API", e); - } - } - return info; - } - - public static Drawable getThemeUpIndicator(Activity activity) { - final TypedArray a = activity.obtainStyledAttributes(THEME_ATTRS); - final Drawable result = a.getDrawable(0); - a.recycle(); - return result; - } - - private static class SetIndicatorInfo { - public Method setHomeAsUpIndicator; - public Method setHomeActionContentDescription; - public ImageView upIndicatorView; - - SetIndicatorInfo(Activity activity) { - try { - setHomeAsUpIndicator = ActionBar.class.getDeclaredMethod("setHomeAsUpIndicator", - Drawable.class); - setHomeActionContentDescription = ActionBar.class.getDeclaredMethod( - "setHomeActionContentDescription", Integer.TYPE); - - // If we got the method we won't need the stuff below. - return; - } catch (NoSuchMethodException e) { - // Oh well. We'll use the other mechanism below instead. - } - - final View home = activity.findViewById(R.id.home); - if (home == null) { - // Action bar doesn't have a known configuration, an OEM messed with things. - return; - } - - final ViewGroup parent = (ViewGroup) home.getParent(); - final int childCount = parent.getChildCount(); - if (childCount != 2) { - // No idea which one will be the right one, an OEM messed with things. - return; - } - - final View first = parent.getChildAt(0); - final View second = parent.getChildAt(1); - final View up = first.getId() == R.id.home ? second : first; - - if (up instanceof ImageView) { - // Jackpot! (Probably...) - upIndicatorView = (ImageView) up; - } - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggleJellybeanMR2.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggleJellybeanMR2.java deleted file mode 100644 index 07d5f7f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActionBarDrawerToggleJellybeanMR2.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package p.android.support.v4.app; - -import android.R; -import android.app.ActionBar; -import android.app.Activity; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; - -class ActionBarDrawerToggleJellybeanMR2 { - private static final String TAG = "ActionBarDrawerToggleImplJellybeanMR2"; - - private static final int[] THEME_ATTRS = new int[] { - R.attr.homeAsUpIndicator - }; - - public static Object setActionBarUpIndicator(Object info, Activity activity, - Drawable drawable, int contentDescRes) { - final ActionBar actionBar = activity.getActionBar(); - if (actionBar != null) { - actionBar.setHomeAsUpIndicator(drawable); - actionBar.setHomeActionContentDescription(contentDescRes); - } - return info; - } - - public static Object setActionBarDescription(Object info, Activity activity, - int contentDescRes) { - final ActionBar actionBar = activity.getActionBar(); - if (actionBar != null) { - actionBar.setHomeActionContentDescription(contentDescRes); - } - return info; - } - - public static Drawable getThemeUpIndicator(Activity activity) { - final ActionBar actionBar = activity.getActionBar(); - final Context context; - if (actionBar != null) { - context = actionBar.getThemedContext(); - } else { - context = activity; - } - - final TypedArray a = context.obtainStyledAttributes(null, THEME_ATTRS, - R.attr.actionBarStyle, 0); - final Drawable result = a.getDrawable(0); - a.recycle(); - return result; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat.java deleted file mode 100644 index 87921db..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.graphics.Matrix; -import android.graphics.RectF; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Parcelable; -import p.android.support.v4.content.ContextCompat; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import android.view.View; - -import java.util.List; -import java.util.Map; - -/** - * Helper for accessing features in {@link Activity} - * introduced after API level 4 in a backwards compatible fashion. - */ -public class ActivityCompat extends ContextCompat { - - /** - * This interface is the contract for receiving the results for permission requests. - */ - public interface OnRequestPermissionsResultCallback { - - /** - * Callback for the result from requesting permissions. This method - * is invoked for every call on {@link #requestPermissions(Activity, - * String[], int)}. - *

- * Note: It is possible that the permissions request interaction - * with the user is interrupted. In this case you will receive empty permissions - * and results arrays which should be treated as a cancellation. - *

- * - * @param requestCode The request code passed in {@link #requestPermissions( - * Activity, String[], int)} - * @param permissions The requested permissions. Never null. - * @param grantResults The grant results for the corresponding permissions - * which is either {@link PackageManager#PERMISSION_GRANTED} - * or {@link PackageManager#PERMISSION_DENIED}. Never null. - * - * @see #requestPermissions(Activity, String[], int) - */ - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults); - } - - /** - * Invalidate the activity's options menu, if able. - * - *

Before API level 11 (Android 3.0/Honeycomb) the lifecycle of the - * options menu was controlled primarily by the user's operation of - * the hardware menu key. When the user presses down on the menu key - * for the first time the menu was created and prepared by calls - * to {@link Activity#onCreateOptionsMenu(android.view.Menu)} and - * {@link Activity#onPrepareOptionsMenu(android.view.Menu)} respectively. - * Subsequent presses of the menu key kept the existing instance of the - * Menu itself and called {@link Activity#onPrepareOptionsMenu(android.view.Menu)} - * to give the activity an opportunity to contextually alter the menu - * before the menu panel was shown.

- * - *

In Android 3.0+ the Action Bar forces the options menu to be built early - * so that items chosen to show as actions may be displayed when the activity - * first becomes visible. The Activity method invalidateOptionsMenu forces - * the entire menu to be destroyed and recreated from - * {@link Activity#onCreateOptionsMenu(android.view.Menu)}, offering a similar - * though heavier-weight opportunity to change the menu's contents. Normally - * this functionality is used to support a changing configuration of Fragments.

- * - *

Applications may use this support helper to signal a significant change in - * activity state that should cause the options menu to be rebuilt. If the app - * is running on an older platform version that does not support menu invalidation - * the app will still receive {@link Activity#onPrepareOptionsMenu(android.view.Menu)} - * the next time the user presses the menu key and this method will return false. - * If this method returns true the options menu was successfully invalidated.

- * - * @param activity Invalidate the options menu of this activity - * @return true if this operation was supported and it completed; false if it was not available. - */ - public static boolean invalidateOptionsMenu(Activity activity) { - if (Build.VERSION.SDK_INT >= 11) { - ActivityCompatHoneycomb.invalidateOptionsMenu(activity); - return true; - } - return false; - } - - /** - * Start an activity with additional launch information, if able. - * - *

In Android 4.1+ additional options were introduced to allow for more - * control on activity launch animations. Applications can use this method - * along with {@link ActivityOptionsCompat} to use these animations when - * available. When run on versions of the platform where this feature does - * not exist the activity will be launched normally.

- * - * @param activity Context to launch activity from. - * @param intent The description of the activity to start. - * @param options Additional options for how the Activity should be started. - * May be null if there are no options. See - * {@link ActivityOptionsCompat} for how to build the Bundle - * supplied here; there are no supported definitions for - * building it manually. - */ - public static void startActivity(Activity activity, Intent intent, @Nullable Bundle options) { - if (Build.VERSION.SDK_INT >= 16) { - ActivityCompatJB.startActivity(activity, intent, options); - } else { - activity.startActivity(intent); - } - } - - /** - * Start new activity with options, if able, for which you would like a - * result when it finished. - * - *

In Android 4.1+ additional options were introduced to allow for more - * control on activity launch animations. Applications can use this method - * along with {@link ActivityOptionsCompat} to use these animations when - * available. When run on versions of the platform where this feature does - * not exist the activity will be launched normally.

- * - * @param activity Origin activity to launch from. - * @param intent The description of the activity to start. - * @param requestCode If >= 0, this code will be returned in - * onActivityResult() when the activity exits. - * @param options Additional options for how the Activity should be started. - * May be null if there are no options. See - * {@link ActivityOptionsCompat} for how to build the Bundle - * supplied here; there are no supported definitions for - * building it manually. - */ - public static void startActivityForResult(Activity activity, Intent intent, int requestCode, - @Nullable Bundle options) { - if (Build.VERSION.SDK_INT >= 16) { - ActivityCompatJB.startActivityForResult(activity, intent, requestCode, options); - } else { - activity.startActivityForResult(intent, requestCode); - } - } - - /** - * Finish this activity, and tries to finish all activities immediately below it - * in the current task that have the same affinity. - * - *

On Android 4.1+ calling this method will call through to the native version of this - * method. For other platforms {@link Activity#finish()} will be called instead.

- */ - public static void finishAffinity(Activity activity) { - if (Build.VERSION.SDK_INT >= 16) { - ActivityCompatJB.finishAffinity(activity); - } else { - activity.finish(); - } - } - - /** - * Reverses the Activity Scene entry Transition and triggers the calling Activity - * to reverse its exit Transition. When the exit Transition completes, - * {@link Activity#finish()} is called. If no entry Transition was used, finish() is called - * immediately and the Activity exit Transition is run. - * - *

On Android 4.4 or lower, this method only finishes the Activity with no - * special exit transition.

- */ - public static void finishAfterTransition(Activity activity) { - if (Build.VERSION.SDK_INT >= 21) { - ActivityCompat21.finishAfterTransition(activity); - } else { - activity.finish(); - } - } - - /** - * Backwards compatible implementation of {@link Activity#getReferrer() - * Activity.getReferrer}. Uses the platform's implementation if available, otherwise - * only falls back to digging any explicitly specified referrer from the activity's intent. - */ - public Uri getReferrer(Activity activity) { - if (Build.VERSION.SDK_INT >= 22) { - return ActivityCompat22.getReferrer(activity); - } - Intent intent = activity.getIntent(); - Uri referrer = intent.getParcelableExtra("android.intent.extra.REFERRER"); - if (referrer != null) { - return referrer; - } - String referrerName = intent.getStringExtra("android.intent.extra.REFERRER_NAME"); - if (referrerName != null) { - return Uri.parse(referrerName); - } - return null; - } - - /** - * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, - * View, String)} was used to start an Activity, callback - * will be called to handle shared elements on the launched Activity. This requires - * {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS}. - * - * @param callback Used to manipulate shared element transitions on the launched Activity. - */ - public static void setEnterSharedElementCallback(Activity activity, - SharedElementCallback callback) { - if (Build.VERSION.SDK_INT >= 21) { - ActivityCompat21.setEnterSharedElementCallback(activity, createCallback(callback)); - } - } - - /** - * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, - * View, String)} was used to start an Activity, callback - * will be called to handle shared elements on the launching Activity. Most - * calls will only come when returning from the started Activity. - * This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS}. - * - * @param callback Used to manipulate shared element transitions on the launching Activity. - */ - public static void setExitSharedElementCallback(Activity activity, - SharedElementCallback callback) { - if (Build.VERSION.SDK_INT >= 21) { - ActivityCompat21.setExitSharedElementCallback(activity, createCallback(callback)); - } - } - - public static void postponeEnterTransition(Activity activity) { - if (Build.VERSION.SDK_INT >= 21) { - ActivityCompat21.postponeEnterTransition(activity); - } - } - - public static void startPostponedEnterTransition(Activity activity) { - if (Build.VERSION.SDK_INT >= 21) { - ActivityCompat21.startPostponedEnterTransition(activity); - } - } - - /** - * Requests permissions to be granted to this application. These permissions - * must be requested in your manifest, they should not be granted to your app, - * and they should have protection level {@link android.content.pm.PermissionInfo - * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by - * the platform or a third-party app. - *

- * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL} - * are granted at install time if requested in the manifest. Signature permissions - * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at - * install time if requested in the manifest and the signature of your app matches - * the signature of the app declaring the permissions. - *

- *

- * If your app does not have the requested permissions the user will be presented - * with UI for accepting them. After the user has accepted or rejected the - * requested permissions you will receive a callback reporting whether the - * permissions were granted or not. Your activity has to implement {@link - * OnRequestPermissionsResultCallback} - * and the results of permission requests will be delivered to its {@link - * OnRequestPermissionsResultCallback#onRequestPermissionsResult( - * int, String[], int[])} method. - *

- *

- * Note that requesting a permission does not guarantee it will be granted and - * your app should be able to run without having this permission. - *

- *

- * This method may start an activity allowing the user to choose which permissions - * to grant and which to reject. Hence, you should be prepared that your activity - * may be paused and resumed. Further, granting some permissions may require - * a restart of you application. In such a case, the system will recreate the - * activity stack before delivering the result to your onRequestPermissionsResult( - * int, String[], int[]). - *

- *

- * When checking whether you have a permission you should use {@link - * #checkSelfPermission(Context, String)}. - *

- * - * @param activity The target activity. - * @param permissions The requested permissions. - * @param requestCode Application specific request code to match with a result - * reported to {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult( - * int, String[], int[])}. - * - * @see #checkSelfPermission(Context, String) - * @see #shouldShowRequestPermissionRationale(Activity, String) - */ - public static void requestPermissions(final @NonNull Activity activity, - final @NonNull String[] permissions, final int requestCode) { - if (Build.VERSION.SDK_INT >= 23) { - ActivityCompatApi23.requestPermissions(activity, permissions, requestCode); - } else if (activity instanceof OnRequestPermissionsResultCallback) { - Handler handler = new Handler(Looper.getMainLooper()); - handler.post(new Runnable() { - @Override - public void run() { - final int[] grantResults = new int[permissions.length]; - - PackageManager packageManager = activity.getPackageManager(); - String packageName = activity.getPackageName(); - - final int permissionCount = permissions.length; - for (int i = 0; i < permissionCount; i++) { - grantResults[i] = packageManager.checkPermission( - permissions[i], packageName); - } - - ((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult( - requestCode, permissions, grantResults); - } - }); - } - } - - /** - * Gets whether you should show UI with rationale for requesting a permission. - * You should do this only if you do not have the permission and the context in - * which the permission is requested does not clearly communicate to the user - * what would be the benefit from granting this permission. - *

- * For example, if you write a camera app, requesting the camera permission - * would be expected by the user and no rationale for why it is requested is - * needed. If however, the app needs location for tagging photos then a non-tech - * savvy user may wonder how location is related to taking photos. In this case - * you may choose to show UI with rationale of requesting this permission. - *

- * - * @param activity The target activity. - * @param permission A permission your app wants to request. - * @return Whether you can show permission rationale UI. - * - * @see #checkSelfPermission(Context, String) - * @see #requestPermissions(Activity, String[], int) - */ - public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity, - @NonNull String permission) { - if (Build.VERSION.SDK_INT >= 23) { - return ActivityCompatApi23.shouldShowRequestPermissionRationale(activity, permission); - } - return false; - } - - private static ActivityCompat21.SharedElementCallback21 createCallback( - SharedElementCallback callback) { - ActivityCompat21.SharedElementCallback21 newCallback = null; - if (callback != null) { - newCallback = new SharedElementCallback21Impl(callback); - } - return newCallback; - } - - private static class SharedElementCallback21Impl - extends ActivityCompat21.SharedElementCallback21 { - - private SharedElementCallback mCallback; - - public SharedElementCallback21Impl(SharedElementCallback callback) { - mCallback = callback; - } - - @Override - public void onSharedElementStart(List sharedElementNames, - List sharedElements, List sharedElementSnapshots) { - mCallback.onSharedElementStart(sharedElementNames, sharedElements, - sharedElementSnapshots); - } - - @Override - public void onSharedElementEnd(List sharedElementNames, List sharedElements, - List sharedElementSnapshots) { - mCallback.onSharedElementEnd(sharedElementNames, sharedElements, - sharedElementSnapshots); - } - - @Override - public void onRejectSharedElements(List rejectedSharedElements) { - mCallback.onRejectSharedElements(rejectedSharedElements); - } - - @Override - public void onMapSharedElements(List names, Map sharedElements) { - mCallback.onMapSharedElements(names, sharedElements); - } - - @Override - public Parcelable onCaptureSharedElementSnapshot(View sharedElement, - Matrix viewToGlobalMatrix, RectF screenBounds) { - return mCallback.onCaptureSharedElementSnapshot(sharedElement, viewToGlobalMatrix, - screenBounds); - } - - @Override - public View onCreateSnapshotView(Context context, Parcelable snapshot) { - return mCallback.onCreateSnapshotView(context, snapshot); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat21.java deleted file mode 100644 index 19c0a70..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat21.java +++ /dev/null @@ -1,129 +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 p.android.support.v4.app; - -import android.app.Activity; -import android.app.SharedElementCallback; -import android.content.Context; -import android.graphics.Matrix; -import android.graphics.RectF; -import android.media.session.MediaController; -import android.os.Parcelable; -import android.view.View; - -import java.lang.Override; -import java.lang.String; -import java.util.List; -import java.util.Map; - -class ActivityCompat21 { - - public static void setMediaController(Activity activity, Object mediaControllerObj) { - activity.setMediaController((MediaController) mediaControllerObj); - } - - public static void finishAfterTransition(Activity activity) { - activity.finishAfterTransition(); - } - - public static void setEnterSharedElementCallback(Activity activity, - SharedElementCallback21 callback) { - activity.setEnterSharedElementCallback(createCallback(callback)); - } - - public static void setExitSharedElementCallback(Activity activity, - SharedElementCallback21 callback) { - activity.setExitSharedElementCallback(createCallback(callback)); - } - - public static void postponeEnterTransition(Activity activity) { - activity.postponeEnterTransition(); - } - - public static void startPostponedEnterTransition(Activity activity) { - activity.startPostponedEnterTransition(); - } - - public abstract static class SharedElementCallback21 { - public abstract void onSharedElementStart(List sharedElementNames, - List sharedElements, List sharedElementSnapshots); - - public abstract void onSharedElementEnd(List sharedElementNames, - List sharedElements, List sharedElementSnapshots); - - public abstract void onRejectSharedElements(List rejectedSharedElements); - - public abstract void onMapSharedElements(List names, - Map sharedElements); - public abstract Parcelable onCaptureSharedElementSnapshot(View sharedElement, - Matrix viewToGlobalMatrix, RectF screenBounds); - public abstract View onCreateSnapshotView(Context context, Parcelable snapshot); - } - - private static SharedElementCallback createCallback(SharedElementCallback21 callback) { - SharedElementCallback newListener = null; - if (callback != null) { - newListener = new SharedElementCallbackImpl(callback); - } - return newListener; - } - - private static class SharedElementCallbackImpl extends SharedElementCallback { - private SharedElementCallback21 mCallback; - - public SharedElementCallbackImpl(SharedElementCallback21 callback) { - mCallback = callback; - } - - @Override - public void onSharedElementStart(List sharedElementNames, - List sharedElements, List sharedElementSnapshots) { - mCallback.onSharedElementStart(sharedElementNames, sharedElements, - sharedElementSnapshots); - } - - @Override - public void onSharedElementEnd(List sharedElementNames, List sharedElements, - List sharedElementSnapshots) { - mCallback.onSharedElementEnd(sharedElementNames, sharedElements, - sharedElementSnapshots); - } - - @Override - public void onRejectSharedElements(List rejectedSharedElements) { - mCallback.onRejectSharedElements(rejectedSharedElements); - } - - @Override - public void onMapSharedElements(List names, Map sharedElements) { - mCallback.onMapSharedElements(names, sharedElements); - } - - @Override - public Parcelable onCaptureSharedElementSnapshot(View sharedElement, - Matrix viewToGlobalMatrix, - RectF screenBounds) { - return mCallback.onCaptureSharedElementSnapshot(sharedElement, viewToGlobalMatrix, - screenBounds); - } - - @Override - public View onCreateSnapshotView(Context context, Parcelable snapshot) { - return mCallback.onCreateSnapshotView(context, snapshot); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat22.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat22.java deleted file mode 100644 index 4d71cdd..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat22.java +++ /dev/null @@ -1,26 +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 p.android.support.v4.app; - -import android.app.Activity; -import android.net.Uri; - -class ActivityCompat22 { - public static Uri getReferrer(Activity activity) { - return activity.getReferrer(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat23.java deleted file mode 100644 index e9b9c0d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompat23.java +++ /dev/null @@ -1,39 +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 p.android.support.v4.app; - -import android.app.Activity; - -class ActivityCompatApi23 { - public interface RequestPermissionsRequestCodeValidator { - public void validateRequestPermissionsRequestCode(int requestCode); - } - - public static void requestPermissions(Activity activity, String[] permissions, - int requestCode) { - if (activity instanceof RequestPermissionsRequestCodeValidator) { - ((RequestPermissionsRequestCodeValidator) activity) - .validateRequestPermissionsRequestCode(requestCode); - } - activity.requestPermissions(permissions, requestCode); - } - - public static boolean shouldShowRequestPermissionRationale(Activity activity, - String permission) { - return activity.shouldShowRequestPermissionRationale(permission); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompatHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompatHoneycomb.java deleted file mode 100644 index 617b673..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompatHoneycomb.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Implementation of activity compatibility that can call Honeycomb APIs. - */ -class ActivityCompatHoneycomb { - static void invalidateOptionsMenu(Activity activity) { - activity.invalidateOptionsMenu(); - } - - static void dump(Activity activity, String prefix, FileDescriptor fd, - PrintWriter writer, String[] args) { - activity.dump(prefix, fd, writer, args); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompatJB.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompatJB.java deleted file mode 100644 index 0ecc1b2..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityCompatJB.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; - -class ActivityCompatJB { - public static void startActivity(Context context, Intent intent, Bundle options) { - context.startActivity(intent, options); - } - - public static void startActivityForResult(Activity activity, Intent intent, int requestCode, Bundle options) { - activity.startActivityForResult(intent, requestCode, options); - } - - public static void finishAffinity(Activity activity) { - activity.finishAffinity(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityManagerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityManagerCompat.java deleted file mode 100644 index 50faa64..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityManagerCompat.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 p.android.support.v4.app; - -import android.app.ActivityManager; -import android.os.Build; -import p.android.support.annotation.NonNull; - -/** - * Helper for accessing features in {@link ActivityManager} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class ActivityManagerCompat { - - private ActivityManagerCompat() {} - - /** - * Returns true if this is a low-RAM device. Exactly whether a device is low-RAM - * is ultimately up to the device configuration, but currently it generally means - * something in the class of a 512MB device with about a 800x480 or less screen. - * This is mostly intended to be used by apps to determine whether they should turn - * off certain features that require more RAM. - */ - public static boolean isLowRamDevice(@NonNull ActivityManager am) { - if (Build.VERSION.SDK_INT >= 19) { - return ActivityManagerCompatKitKat.isLowRamDevice(am); - } - return false; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityManagerCompatKitKat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityManagerCompatKitKat.java deleted file mode 100644 index f42553e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityManagerCompatKitKat.java +++ /dev/null @@ -1,25 +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 p.android.support.v4.app; - -import android.app.ActivityManager; - -class ActivityManagerCompatKitKat { - public static boolean isLowRamDevice(ActivityManager am) { - return am.isLowRamDevice(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompat.java deleted file mode 100644 index cbc41bb..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompat.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Context; -import android.graphics.Bitmap; -import android.os.Build; -import android.os.Bundle; -import p.android.support.v4.util.Pair; -import android.view.View; - -/** - * Helper for accessing features in {@link android.app.ActivityOptions} - * introduced in API level 16 in a backwards compatible fashion. - */ -public class ActivityOptionsCompat { - /** - * Create an ActivityOptions specifying a custom animation to run when the - * activity is displayed. - * - * @param context Who is defining this. This is the application that the - * animation resources will be loaded from. - * @param enterResId A resource ID of the animation resource to use for the - * incoming activity. Use 0 for no animation. - * @param exitResId A resource ID of the animation resource to use for the - * outgoing activity. Use 0 for no animation. - * @return Returns a new ActivityOptions object that you can use to supply - * these options as the options Bundle when starting an activity. - */ - public static ActivityOptionsCompat makeCustomAnimation(Context context, - int enterResId, int exitResId) { - if (Build.VERSION.SDK_INT >= 16) { - return new ActivityOptionsImplJB( - ActivityOptionsCompatJB.makeCustomAnimation(context, enterResId, exitResId)); - } - return new ActivityOptionsCompat(); - } - - /** - * Create an ActivityOptions specifying an animation where the new activity is - * scaled from a small originating area of the screen to its final full - * representation. - *

- * If the Intent this is being used with has not set its - * {@link android.content.Intent#setSourceBounds(android.graphics.Rect)}, - * those bounds will be filled in for you based on the initial bounds passed - * in here. - * - * @param source The View that the new activity is animating from. This - * defines the coordinate space for startX and startY. - * @param startX The x starting location of the new activity, relative to - * source. - * @param startY The y starting location of the activity, relative to source. - * @param startWidth The initial width of the new activity. - * @param startHeight The initial height of the new activity. - * @return Returns a new ActivityOptions object that you can use to supply - * these options as the options Bundle when starting an activity. - */ - public static ActivityOptionsCompat makeScaleUpAnimation(View source, - int startX, int startY, int startWidth, int startHeight) { - if (Build.VERSION.SDK_INT >= 16) { - return new ActivityOptionsImplJB( - ActivityOptionsCompatJB.makeScaleUpAnimation(source, startX, startY, - startWidth, startHeight)); - } - return new ActivityOptionsCompat(); - } - - /** - * Create an ActivityOptions specifying an animation where a thumbnail is - * scaled from a given position to the new activity window that is being - * started. - *

- * If the Intent this is being used with has not set its - * {@link android.content.Intent#setSourceBounds(android.graphics.Rect)}, - * those bounds will be filled in for you based on the initial thumbnail - * location and size provided here. - * - * @param source The View that this thumbnail is animating from. This - * defines the coordinate space for startX and startY. - * @param thumbnail The bitmap that will be shown as the initial thumbnail - * of the animation. - * @param startX The x starting location of the bitmap, relative to source. - * @param startY The y starting location of the bitmap, relative to source. - * @return Returns a new ActivityOptions object that you can use to supply - * these options as the options Bundle when starting an activity. - */ - public static ActivityOptionsCompat makeThumbnailScaleUpAnimation(View source, - Bitmap thumbnail, int startX, int startY) { - if (Build.VERSION.SDK_INT >= 16) { - return new ActivityOptionsImplJB( - ActivityOptionsCompatJB.makeThumbnailScaleUpAnimation(source, thumbnail, - startX, startY)); - } - return new ActivityOptionsCompat(); - } - - /** - * Create an ActivityOptions to transition between Activities using cross-Activity scene - * animations. This method carries the position of one shared element to the started Activity. - * The position of sharedElement will be used as the epicenter for the - * exit Transition. The position of the shared element in the launched Activity will be the - * epicenter of its entering Transition. - * - *

This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be - * enabled on the calling Activity to cause an exit transition. The same must be in - * the called Activity to get an entering transition.

- * @param activity The Activity whose window contains the shared elements. - * @param sharedElement The View to transition to the started Activity. sharedElement must - * have a non-null sharedElementName. - * @param sharedElementName The shared element name as used in the target Activity. This may - * be null if it has the same name as sharedElement. - * @return Returns a new ActivityOptions object that you can use to - * supply these options as the options Bundle when starting an activity. - */ - public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity, - View sharedElement, String sharedElementName) { - if (Build.VERSION.SDK_INT >= 21) { - return new ActivityOptionsImpl21( - ActivityOptionsCompat21.makeSceneTransitionAnimation(activity, - sharedElement, sharedElementName)); - } - return new ActivityOptionsCompat(); - } - - /** - * Create an ActivityOptions to transition between Activities using cross-Activity scene - * animations. This method carries the position of multiple shared elements to the started - * Activity. The position of the first element in sharedElements - * will be used as the epicenter for the exit Transition. The position of the associated - * shared element in the launched Activity will be the epicenter of its entering Transition. - * - *

This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be - * enabled on the calling Activity to cause an exit transition. The same must be in - * the called Activity to get an entering transition.

- * @param activity The Activity whose window contains the shared elements. - * @param sharedElements The names of the shared elements to transfer to the called - * Activity and their associated Views. The Views must each have - * a unique shared element name. - * @return Returns a new ActivityOptions object that you can use to - * supply these options as the options Bundle when starting an activity. - */ - public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity, - Pair... sharedElements) { - if (Build.VERSION.SDK_INT >= 21) { - View[] views = null; - String[] names = null; - if (sharedElements != null) { - views = new View[sharedElements.length]; - names = new String[sharedElements.length]; - for (int i = 0; i < sharedElements.length; i++) { - views[i] = sharedElements[i].first; - names[i] = sharedElements[i].second; - } - } - return new ActivityOptionsImpl21( - ActivityOptionsCompat21.makeSceneTransitionAnimation(activity, views, names)); - } - return new ActivityOptionsCompat(); - } - - private static class ActivityOptionsImplJB extends ActivityOptionsCompat { - private final ActivityOptionsCompatJB mImpl; - - ActivityOptionsImplJB(ActivityOptionsCompatJB impl) { - mImpl = impl; - } - - @Override - public Bundle toBundle() { - return mImpl.toBundle(); - } - - @Override - public void update(ActivityOptionsCompat otherOptions) { - if (otherOptions instanceof ActivityOptionsImplJB) { - ActivityOptionsImplJB otherImpl = (ActivityOptionsImplJB)otherOptions; - mImpl.update(otherImpl.mImpl); - } - } - } - - private static class ActivityOptionsImpl21 extends ActivityOptionsCompat { - private final ActivityOptionsCompat21 mImpl; - - ActivityOptionsImpl21(ActivityOptionsCompat21 impl) { - mImpl = impl; - } - - @Override - public Bundle toBundle() { - return mImpl.toBundle(); - } - - @Override - public void update(ActivityOptionsCompat otherOptions) { - if (otherOptions instanceof ActivityOptionsImpl21) { - ActivityOptionsImpl21 - otherImpl = (ActivityOptionsImpl21)otherOptions; - mImpl.update(otherImpl.mImpl); - } - } - } - - protected ActivityOptionsCompat() { - } - - /** - * Returns the created options as a Bundle, which can be passed to - * {@link ActivityCompat#startActivity(Activity, android.content.Intent, Bundle)}. - * Note that the returned Bundle is still owned by the ActivityOptions - * object; you must not modify it, but can supply it to the startActivity - * methods that take an options Bundle. - */ - public Bundle toBundle() { - return null; - } - - /** - * Update the current values in this ActivityOptions from those supplied in - * otherOptions. Any values defined in otherOptions replace those in the - * base options. - */ - public void update(ActivityOptionsCompat otherOptions) { - // Do nothing. - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompat21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompat21.java deleted file mode 100644 index d71b49b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompat21.java +++ /dev/null @@ -1,60 +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 p.android.support.v4.app; - -import android.app.ActivityOptions; -import android.app.Activity; -import android.os.Bundle; -import android.util.Pair; -import android.view.View; - -class ActivityOptionsCompat21 { - - private final ActivityOptions mActivityOptions; - - public static ActivityOptionsCompat21 makeSceneTransitionAnimation(Activity activity, - View sharedElement, String sharedElementName) { - return new ActivityOptionsCompat21( - ActivityOptions.makeSceneTransitionAnimation(activity, sharedElement, - sharedElementName)); - } - - public static ActivityOptionsCompat21 makeSceneTransitionAnimation(Activity activity, - View[] sharedElements, String[] sharedElementNames) { - Pair[] pairs = null; - if (sharedElements != null) { - pairs = new Pair[sharedElements.length]; - for (int i = 0; i < pairs.length; i++) { - pairs[i] = Pair.create(sharedElements[i], sharedElementNames[i]); - } - } - return new ActivityOptionsCompat21( - ActivityOptions.makeSceneTransitionAnimation(activity, pairs)); - } - - private ActivityOptionsCompat21(ActivityOptions activityOptions) { - mActivityOptions = activityOptions; - } - - public Bundle toBundle() { - return mActivityOptions.toBundle(); - } - - public void update(ActivityOptionsCompat21 otherOptions) { - mActivityOptions.update(otherOptions.mActivityOptions); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompatJB.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompatJB.java deleted file mode 100644 index f32c60b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ActivityOptionsCompatJB.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.ActivityOptions; -import android.content.Context; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.view.View; - -class ActivityOptionsCompatJB { - - public static ActivityOptionsCompatJB makeCustomAnimation(Context context, - int enterResId, int exitResId) { - return new ActivityOptionsCompatJB( - ActivityOptions.makeCustomAnimation(context, enterResId, exitResId)); - } - - public static ActivityOptionsCompatJB makeScaleUpAnimation(View source, - int startX, int startY, int startWidth, int startHeight) { - return new ActivityOptionsCompatJB( - ActivityOptions.makeScaleUpAnimation(source, startX, startY, startWidth, startHeight)); - } - - public static ActivityOptionsCompatJB makeThumbnailScaleUpAnimation(View source, - Bitmap thumbnail, int startX, int startY) { - return new ActivityOptionsCompatJB( - ActivityOptions.makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY)); - } - - private final ActivityOptions mActivityOptions; - - private ActivityOptionsCompatJB(ActivityOptions activityOptions) { - mActivityOptions = activityOptions; - } - - public Bundle toBundle() { - return mActivityOptions.toBundle(); - } - - public void update(ActivityOptionsCompatJB otherOptions) { - mActivityOptions.update(otherOptions.mActivityOptions); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppLaunchChecker.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppLaunchChecker.java deleted file mode 100644 index e396360..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppLaunchChecker.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import p.android.support.v4.content.IntentCompat; -import p.android.support.v4.content.SharedPreferencesCompat; - -/** - * This class provides APIs for determining how an app has been launched. - * This can be useful if you want to confirm that a user has launched your - * app through its front door activity from their launcher/home screen, rather - * than just if the app has been opened in the past in order to view a link, - * open a document or perform some other service for other apps on the device. - */ -public class AppLaunchChecker { - private static final String SHARED_PREFS_NAME = "android.support.AppLaunchChecker"; - private static final String KEY_STARTED_FROM_LAUNCHER = "startedFromLauncher"; - - /** - * Checks if this app has been launched by the user from their launcher or home screen - * since it was installed. - * - *

To track this state properly you must call {@link #onActivityCreate(Activity)} - * in your launcher activity's {@link Activity#onCreate(Bundle)} method.

- * - * @param context Context to check - * @return true if this app has been started by the user from the launcher at least once - */ - public static boolean hasStartedFromLauncher(Context context) { - return context.getSharedPreferences(SHARED_PREFS_NAME, 0) - .getBoolean(KEY_STARTED_FROM_LAUNCHER, false); - } - - /** - * Records the parameters of an activity's launch for later use by the other - * methods available on this class. - * - *

Your app should call this method in your launcher activity's - * {@link Activity#onCreate(Bundle)} method to track launch state. - * If the app targets API 23 (Android 6.0 Marshmallow) or later, this state will be - * eligible for full data backup and may be restored to the user's device automatically.

* - * - * @param activity the Activity currently running onCreate - */ - public static void onActivityCreate(Activity activity) { - final SharedPreferences sp = activity.getSharedPreferences(SHARED_PREFS_NAME, 0); - if (sp.getBoolean(KEY_STARTED_FROM_LAUNCHER, false)) { - return; - } - - final Intent launchIntent = activity.getIntent(); - if (launchIntent == null) { - return; - } - - if (Intent.ACTION_MAIN.equals(launchIntent.getAction()) - && (launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER) - || launchIntent.hasCategory(IntentCompat.CATEGORY_LEANBACK_LAUNCHER))) { - SharedPreferencesCompat.EditorCompat.getInstance().apply( - sp.edit().putBoolean(KEY_STARTED_FROM_LAUNCHER, true)); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppOpsManagerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppOpsManagerCompat.java deleted file mode 100644 index a275080..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppOpsManagerCompat.java +++ /dev/null @@ -1,142 +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 p.android.support.v4.app; - -import android.content.Context; -import android.os.Build; -import p.android.support.annotation.NonNull; - -/** - * Helper for accessing features in android.app.AppOpsManager - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class AppOpsManagerCompat { - - /** - * Result from {@link #noteOp}: the given caller is allowed to - * perform the given operation. - */ - public static final int MODE_ALLOWED = 0; - - /** - * Result from {@link #noteOp}: the given caller is not allowed to perform - * the given operation, and this attempt should silently fail (it - * should not cause the app to crash). - */ - public static final int MODE_IGNORED = 1; - - /** - * Result from {@link #noteOp}: the given caller should use its default - * security check. This mode is not normally used; it should only be used - * with appop permissions, and callers must explicitly check for it and - * deal with it. - */ - public static final int MODE_DEFAULT = 3; - - private static class AppOpsManagerImpl { - public String permissionToOp(String permission) { - return null; - } - - public int noteOp(Context context, String op, int uid, String packageName) { - return MODE_IGNORED; - } - - public int noteProxyOp(Context context, String op, String proxiedPackageName) { - return MODE_IGNORED; - } - } - - private static class AppOpsManager23 extends AppOpsManagerImpl { - @Override - public String permissionToOp(String permission) { - return AppOpsManagerCompat23.permissionToOp(permission); - } - - @Override - public int noteOp(Context context, String op, int uid, String packageName) { - return AppOpsManagerCompat23.noteOp(context, op, uid, packageName); - } - - @Override - public int noteProxyOp(Context context, String op, String proxiedPackageName) { - return AppOpsManagerCompat23.noteProxyOp(context, op, proxiedPackageName); - } - } - - private static final AppOpsManagerImpl IMPL; - static { - if (Build.VERSION.SDK_INT >= 23) { - IMPL = new AppOpsManager23(); - } else { - IMPL = new AppOpsManagerImpl(); - } - } - - private AppOpsManagerCompat() {} - - /** - * Gets the app op name associated with a given permission. - * - * @param permission The permission. - * @return The app op associated with the permission or null. - */ - public static String permissionToOp(@NonNull String permission) { - return IMPL.permissionToOp(permission); - } - - /** - * Make note of an application performing an operation. Note that you must pass - * in both the uid and name of the application to be checked; this function will verify - * that these two match, and if not, return {@link #MODE_IGNORED}. If this call - * succeeds, the last execution time of the operation for this app will be updated to - * the current time. - * @param context Your context. - * @param op The operation to note. One of the OPSTR_* constants. - * @param uid The user id of the application attempting to perform the operation. - * @param packageName The name of the application attempting to perform the operation. - * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or - * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without - * causing the app to crash). - * @throws SecurityException If the app has been configured to crash on this op. - */ - public static int noteOp(@NonNull Context context, @NonNull String op, int uid, - @NonNull String packageName) { - return IMPL.noteOp(context, op, uid, packageName); - } - - /** - * Make note of an application performing an operation on behalf of another - * application when handling an IPC. Note that you must pass the package name - * of the application that is being proxied while its UID will be inferred from - * the IPC state; this function will verify that the calling uid and proxied - * package name match, and if not, return {@link #MODE_IGNORED}. If this call - * succeeds, the last execution time of the operation for the proxied app and - * your app will be updated to the current time. - * @param context Your context. - * @param op The operation to note. One of the OPSTR_* constants. - * @param proxiedPackageName The name of the application calling into the proxy application. - * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or - * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without - * causing the app to crash). - * @throws SecurityException If the app has been configured to crash on this op. - */ - public static int noteProxyOp(@NonNull Context context, @NonNull String op, - @NonNull String proxiedPackageName) { - return IMPL.noteProxyOp(context, op, proxiedPackageName); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppOpsManagerCompat23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppOpsManagerCompat23.java deleted file mode 100644 index c690b44..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/AppOpsManagerCompat23.java +++ /dev/null @@ -1,39 +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 p.android.support.v4.app; - -import android.app.AppOpsManager; -import android.content.Context; - -/** - * AppOpsManager implementations for API 23. - */ -class AppOpsManagerCompat23 { - public static String permissionToOp(String permission) { - return AppOpsManager.permissionToOp(permission); - } - - public static int noteOp(Context context, String op, int uid, String packageName) { - AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); - return appOpsManager.noteOp(op, uid, packageName); - } - - public static int noteProxyOp(Context context, String op, String proxiedPackageName) { - AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); - return appOpsManager.noteProxyOp(op, proxiedPackageName); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BackStackRecord.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BackStackRecord.java deleted file mode 100644 index 3a762ae..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BackStackRecord.java +++ /dev/null @@ -1,1476 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import p.android.support.v4.util.ArrayMap; -import p.android.support.v4.util.LogWriter; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseArray; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; - -final class BackStackState implements Parcelable { - final int[] mOps; - final int mTransition; - final int mTransitionStyle; - final String mName; - final int mIndex; - final int mBreadCrumbTitleRes; - final CharSequence mBreadCrumbTitleText; - final int mBreadCrumbShortTitleRes; - final CharSequence mBreadCrumbShortTitleText; - final ArrayList mSharedElementSourceNames; - final ArrayList mSharedElementTargetNames; - - public BackStackState(BackStackRecord bse) { - int numRemoved = 0; - BackStackRecord.Op op = bse.mHead; - while (op != null) { - if (op.removed != null) numRemoved += op.removed.size(); - op = op.next; - } - mOps = new int[bse.mNumOp*7 + numRemoved]; - - if (!bse.mAddToBackStack) { - throw new IllegalStateException("Not on back stack"); - } - - op = bse.mHead; - int pos = 0; - while (op != null) { - mOps[pos++] = op.cmd; - mOps[pos++] = op.fragment != null ? op.fragment.mIndex : -1; - mOps[pos++] = op.enterAnim; - mOps[pos++] = op.exitAnim; - mOps[pos++] = op.popEnterAnim; - mOps[pos++] = op.popExitAnim; - if (op.removed != null) { - final int N = op.removed.size(); - mOps[pos++] = N; - for (int i=0; i= 0) { - Fragment f = fm.mActive.get(findex); - op.fragment = f; - } else { - op.fragment = null; - } - op.enterAnim = mOps[pos++]; - op.exitAnim = mOps[pos++]; - op.popEnterAnim = mOps[pos++]; - op.popExitAnim = mOps[pos++]; - final int N = mOps[pos++]; - if (N > 0) { - op.removed = new ArrayList(N); - for (int i=0; i CREATOR - = new Creator() { - public BackStackState createFromParcel(Parcel in) { - return new BackStackState(in); - } - - public BackStackState[] newArray(int size) { - return new BackStackState[size]; - } - }; -} - -/** - * @hide Entry of an operation on the fragment back stack. - */ -final class BackStackRecord extends FragmentTransaction implements - FragmentManager.BackStackEntry, Runnable { - static final String TAG = FragmentManagerImpl.TAG; - static final boolean SUPPORTS_TRANSITIONS = Build.VERSION.SDK_INT >= 21; - - final FragmentManagerImpl mManager; - - static final int OP_NULL = 0; - static final int OP_ADD = 1; - static final int OP_REPLACE = 2; - static final int OP_REMOVE = 3; - static final int OP_HIDE = 4; - static final int OP_SHOW = 5; - static final int OP_DETACH = 6; - static final int OP_ATTACH = 7; - - static final class Op { - Op next; - Op prev; - int cmd; - Fragment fragment; - int enterAnim; - int exitAnim; - int popEnterAnim; - int popExitAnim; - ArrayList removed; - } - - Op mHead; - Op mTail; - int mNumOp; - int mEnterAnim; - int mExitAnim; - int mPopEnterAnim; - int mPopExitAnim; - int mTransition; - int mTransitionStyle; - boolean mAddToBackStack; - boolean mAllowAddToBackStack = true; - String mName; - boolean mCommitted; - int mIndex = -1; - - int mBreadCrumbTitleRes; - CharSequence mBreadCrumbTitleText; - int mBreadCrumbShortTitleRes; - CharSequence mBreadCrumbShortTitleText; - - ArrayList mSharedElementSourceNames; - ArrayList mSharedElementTargetNames; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(128); - sb.append("BackStackEntry{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - if (mIndex >= 0) { - sb.append(" #"); - sb.append(mIndex); - } - if (mName != null) { - sb.append(" "); - sb.append(mName); - } - sb.append("}"); - return sb.toString(); - } - - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - dump(prefix, writer, true); - } - - public void dump(String prefix, PrintWriter writer, boolean full) { - if (full) { - writer.print(prefix); writer.print("mName="); writer.print(mName); - writer.print(" mIndex="); writer.print(mIndex); - writer.print(" mCommitted="); writer.println(mCommitted); - if (mTransition != FragmentTransaction.TRANSIT_NONE) { - writer.print(prefix); writer.print("mTransition=#"); - writer.print(Integer.toHexString(mTransition)); - writer.print(" mTransitionStyle=#"); - writer.println(Integer.toHexString(mTransitionStyle)); - } - if (mEnterAnim != 0 || mExitAnim !=0) { - writer.print(prefix); writer.print("mEnterAnim=#"); - writer.print(Integer.toHexString(mEnterAnim)); - writer.print(" mExitAnim=#"); - writer.println(Integer.toHexString(mExitAnim)); - } - if (mPopEnterAnim != 0 || mPopExitAnim !=0) { - writer.print(prefix); writer.print("mPopEnterAnim=#"); - writer.print(Integer.toHexString(mPopEnterAnim)); - writer.print(" mPopExitAnim=#"); - writer.println(Integer.toHexString(mPopExitAnim)); - } - if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) { - writer.print(prefix); writer.print("mBreadCrumbTitleRes=#"); - writer.print(Integer.toHexString(mBreadCrumbTitleRes)); - writer.print(" mBreadCrumbTitleText="); - writer.println(mBreadCrumbTitleText); - } - if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) { - writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#"); - writer.print(Integer.toHexString(mBreadCrumbShortTitleRes)); - writer.print(" mBreadCrumbShortTitleText="); - writer.println(mBreadCrumbShortTitleText); - } - } - - if (mHead != null) { - writer.print(prefix); writer.println("Operations:"); - String innerPrefix = prefix + " "; - Op op = mHead; - int num = 0; - while (op != null) { - String cmdStr; - switch (op.cmd) { - case OP_NULL: cmdStr="NULL"; break; - case OP_ADD: cmdStr="ADD"; break; - case OP_REPLACE: cmdStr="REPLACE"; break; - case OP_REMOVE: cmdStr="REMOVE"; break; - case OP_HIDE: cmdStr="HIDE"; break; - case OP_SHOW: cmdStr="SHOW"; break; - case OP_DETACH: cmdStr="DETACH"; break; - case OP_ATTACH: cmdStr="ATTACH"; break; - default: cmdStr="cmd=" + op.cmd; break; - } - writer.print(prefix); writer.print(" Op #"); writer.print(num); - writer.print(": "); writer.print(cmdStr); - writer.print(" "); writer.println(op.fragment); - if (full) { - if (op.enterAnim != 0 || op.exitAnim != 0) { - writer.print(prefix); writer.print("enterAnim=#"); - writer.print(Integer.toHexString(op.enterAnim)); - writer.print(" exitAnim=#"); - writer.println(Integer.toHexString(op.exitAnim)); - } - if (op.popEnterAnim != 0 || op.popExitAnim != 0) { - writer.print(prefix); writer.print("popEnterAnim=#"); - writer.print(Integer.toHexString(op.popEnterAnim)); - writer.print(" popExitAnim=#"); - writer.println(Integer.toHexString(op.popExitAnim)); - } - } - if (op.removed != null && op.removed.size() > 0) { - for (int i=0; i(); - mSharedElementTargetNames = new ArrayList(); - } - - mSharedElementSourceNames.add(transitionName); - mSharedElementTargetNames.add(name); - } - return this; - } - - public FragmentTransaction setTransitionStyle(int styleRes) { - mTransitionStyle = styleRes; - return this; - } - - public FragmentTransaction addToBackStack(String name) { - if (!mAllowAddToBackStack) { - throw new IllegalStateException( - "This FragmentTransaction is not allowed to be added to the back stack."); - } - mAddToBackStack = true; - mName = name; - return this; - } - - public boolean isAddToBackStackAllowed() { - return mAllowAddToBackStack; - } - - public FragmentTransaction disallowAddToBackStack() { - if (mAddToBackStack) { - throw new IllegalStateException( - "This transaction is already being added to the back stack"); - } - mAllowAddToBackStack = false; - return this; - } - - public FragmentTransaction setBreadCrumbTitle(int res) { - mBreadCrumbTitleRes = res; - mBreadCrumbTitleText = null; - return this; - } - - public FragmentTransaction setBreadCrumbTitle(CharSequence text) { - mBreadCrumbTitleRes = 0; - mBreadCrumbTitleText = text; - return this; - } - - public FragmentTransaction setBreadCrumbShortTitle(int res) { - mBreadCrumbShortTitleRes = res; - mBreadCrumbShortTitleText = null; - return this; - } - - public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) { - mBreadCrumbShortTitleRes = 0; - mBreadCrumbShortTitleText = text; - return this; - } - - void bumpBackStackNesting(int amt) { - if (!mAddToBackStack) { - return; - } - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting in " + this - + " by " + amt); - Op op = mHead; - while (op != null) { - if (op.fragment != null) { - op.fragment.mBackStackNesting += amt; - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " - + op.fragment + " to " + op.fragment.mBackStackNesting); - } - if (op.removed != null) { - for (int i=op.removed.size()-1; i>=0; i--) { - Fragment r = op.removed.get(i); - r.mBackStackNesting += amt; - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " - + r + " to " + r.mBackStackNesting); - } - } - op = op.next; - } - } - - public int commit() { - return commitInternal(false); - } - - public int commitAllowingStateLoss() { - return commitInternal(true); - } - - int commitInternal(boolean allowStateLoss) { - if (mCommitted) throw new IllegalStateException("commit already called"); - if (FragmentManagerImpl.DEBUG) { - Log.v(TAG, "Commit: " + this); - LogWriter logw = new LogWriter(TAG); - PrintWriter pw = new PrintWriter(logw); - dump(" ", null, pw, null); - } - mCommitted = true; - if (mAddToBackStack) { - mIndex = mManager.allocBackStackIndex(this); - } else { - mIndex = -1; - } - mManager.enqueueAction(this, allowStateLoss); - return mIndex; - } - - public void run() { - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this); - - if (mAddToBackStack) { - if (mIndex < 0) { - throw new IllegalStateException("addToBackStack() called after commit()"); - } - } - - bumpBackStackNesting(1); - - TransitionState state = null; - SparseArray firstOutFragments = null; - SparseArray lastInFragments = null; - if (SUPPORTS_TRANSITIONS && mManager.mCurState >= Fragment.CREATED) { - firstOutFragments = new SparseArray(); - lastInFragments = new SparseArray(); - - calculateFragments(firstOutFragments, lastInFragments); - - state = beginTransition(firstOutFragments, lastInFragments, false); - } - - int transitionStyle = state != null ? 0 : mTransitionStyle; - int transition = state != null ? 0 : mTransition; - Op op = mHead; - while (op != null) { - int enterAnim = state != null ? 0 : op.enterAnim; - int exitAnim = state != null ? 0 : op.exitAnim; - switch (op.cmd) { - case OP_ADD: { - Fragment f = op.fragment; - f.mNextAnim = enterAnim; - mManager.addFragment(f, false); - } break; - case OP_REPLACE: { - Fragment f = op.fragment; - int containerId = f.mContainerId; - if (mManager.mAdded != null) { - for (int i = mManager.mAdded.size() - 1; i >= 0; i--) { - Fragment old = mManager.mAdded.get(i); - if (FragmentManagerImpl.DEBUG) Log.v(TAG, - "OP_REPLACE: adding=" + f + " old=" + old); - if (old.mContainerId == containerId) { - if (old == f) { - op.fragment = f = null; - } else { - if (op.removed == null) { - op.removed = new ArrayList(); - } - op.removed.add(old); - old.mNextAnim = exitAnim; - if (mAddToBackStack) { - old.mBackStackNesting += 1; - if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " - + old + " to " + old.mBackStackNesting); - } - mManager.removeFragment(old, transition, transitionStyle); - } - } - } - } - if (f != null) { - f.mNextAnim = enterAnim; - mManager.addFragment(f, false); - } - } break; - case OP_REMOVE: { - Fragment f = op.fragment; - f.mNextAnim = exitAnim; - mManager.removeFragment(f, transition, transitionStyle); - } break; - case OP_HIDE: { - Fragment f = op.fragment; - f.mNextAnim = exitAnim; - mManager.hideFragment(f, transition, transitionStyle); - } break; - case OP_SHOW: { - Fragment f = op.fragment; - f.mNextAnim = enterAnim; - mManager.showFragment(f, transition, transitionStyle); - } break; - case OP_DETACH: { - Fragment f = op.fragment; - f.mNextAnim = exitAnim; - mManager.detachFragment(f, transition, transitionStyle); - } break; - case OP_ATTACH: { - Fragment f = op.fragment; - f.mNextAnim = enterAnim; - mManager.attachFragment(f, transition, transitionStyle); - } break; - default: { - throw new IllegalArgumentException("Unknown cmd: " + op.cmd); - } - } - - op = op.next; - } - - mManager.moveToState(mManager.mCurState, transition, transitionStyle, true); - - if (mAddToBackStack) { - mManager.addBackStackState(this); - } - } - - private static void setFirstOut(SparseArray firstOutFragments, - SparseArray lastInFragments, Fragment fragment) { - if (fragment != null) { - int containerId = fragment.mContainerId; - if (containerId != 0 && !fragment.isHidden()) { - if (fragment.isAdded() && fragment.getView() != null - && firstOutFragments.get(containerId) == null) { - firstOutFragments.put(containerId, fragment); - } - if (lastInFragments.get(containerId) == fragment) { - lastInFragments.remove(containerId); - } - } - } - } - - private void setLastIn(SparseArray firstOutFragments, - SparseArray lastInFragments, Fragment fragment) { - if (fragment != null) { - int containerId = fragment.mContainerId; - if (containerId != 0) { - if (!fragment.isAdded()) { - lastInFragments.put(containerId, fragment); - } - if (firstOutFragments.get(containerId) == fragment) { - firstOutFragments.remove(containerId); - } - } - if (fragment.mState < Fragment.CREATED && mManager.mCurState >= Fragment.CREATED) { - mManager.makeActive(fragment); - mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false); - } - } - } - - /** - * Finds the first removed fragment and last added fragments when going forward. - * If none of the fragments have transitions, then both lists will be empty. - * - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. This list will be modified by the method. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. This list will be modified by the method. - */ - private void calculateFragments(SparseArray firstOutFragments, - SparseArray lastInFragments) { - if (!mManager.mContainer.onHasView()) { - return; // nothing to see, so no transitions - } - Op op = mHead; - while (op != null) { - switch (op.cmd) { - case OP_ADD: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_REPLACE: { - Fragment f = op.fragment; - if (mManager.mAdded != null) { - for (int i = 0; i < mManager.mAdded.size(); i++) { - Fragment old = mManager.mAdded.get(i); - if (f == null || old.mContainerId == f.mContainerId) { - if (old == f) { - f = null; - lastInFragments.remove(old.mContainerId); - } else { - setFirstOut(firstOutFragments, lastInFragments, old); - } - } - } - } - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - } - case OP_REMOVE: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_HIDE: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_SHOW: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_DETACH: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_ATTACH: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - } - - op = op.next; - } - } - - /** - * Finds the first removed fragment and last added fragments when popping the back stack. - * If none of the fragments have transitions, then both lists will be empty. - * - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. This list will be modified by the method. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. This list will be modified by the method. - */ - public void calculateBackFragments(SparseArray firstOutFragments, - SparseArray lastInFragments) { - if (!mManager.mContainer.onHasView()) { - return; // nothing to see, so no transitions - } - Op op = mTail; - while (op != null) { - switch (op.cmd) { - case OP_ADD: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_REPLACE: - if (op.removed != null) { - for (int i = op.removed.size() - 1; i >= 0; i--) { - setLastIn(firstOutFragments, lastInFragments, op.removed.get(i)); - } - } - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_REMOVE: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_HIDE: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_SHOW: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_DETACH: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_ATTACH: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - } - - op = op.prev; - } - } - - public TransitionState popFromBackStack(boolean doStateMove, TransitionState state, - SparseArray firstOutFragments, SparseArray lastInFragments) { - if (FragmentManagerImpl.DEBUG) { - Log.v(TAG, "popFromBackStack: " + this); - LogWriter logw = new LogWriter(TAG); - PrintWriter pw = new PrintWriter(logw); - dump(" ", null, pw, null); - } - - if (SUPPORTS_TRANSITIONS && mManager.mCurState >= Fragment.CREATED) { - if (state == null) { - if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) { - state = beginTransition(firstOutFragments, lastInFragments, true); - } - } else if (!doStateMove) { - setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames); - } - } - - bumpBackStackNesting(-1); - - int transitionStyle = state != null ? 0 : mTransitionStyle; - int transition = state != null ? 0 : mTransition; - Op op = mTail; - while (op != null) { - int popEnterAnim = state != null ? 0 : op.popEnterAnim; - int popExitAnim= state != null ? 0 : op.popExitAnim; - switch (op.cmd) { - case OP_ADD: { - Fragment f = op.fragment; - f.mNextAnim = popExitAnim; - mManager.removeFragment(f, - FragmentManagerImpl.reverseTransit(transition), transitionStyle); - } break; - case OP_REPLACE: { - Fragment f = op.fragment; - if (f != null) { - f.mNextAnim = popExitAnim; - mManager.removeFragment(f, - FragmentManagerImpl.reverseTransit(transition), transitionStyle); - } - if (op.removed != null) { - for (int i=0; i= 0) { - mManager.freeBackStackIndex(mIndex); - mIndex = -1; - } - return state; - } - - public String getName() { - return mName; - } - - public int getTransition() { - return mTransition; - } - - public int getTransitionStyle() { - return mTransitionStyle; - } - - public boolean isEmpty() { - return mNumOp == 0; - } - - /** - * When custom fragment transitions are used, this sets up the state for each transition - * and begins the transition. A different transition is started for each fragment container - * and consists of up to 3 different transitions: the exit transition, a shared element - * transition and an enter transition. - * - *

The exit transition operates against the leaf nodes of the first fragment - * with a view that was removed. If no such fragment was removed, then no exit - * transition is executed. The exit transition comes from the outgoing fragment.

- * - *

The enter transition operates against the last fragment that was added. If - * that fragment does not have a view or no fragment was added, then no enter - * transition is executed. The enter transition comes from the incoming fragment.

- * - *

The shared element transition operates against all views and comes either - * from the outgoing fragment or the incoming fragment, depending on whether this - * is going forward or popping the back stack. When going forward, the incoming - * fragment's enter shared element transition is used, but when going back, the - * outgoing fragment's return shared element transition is used. Shared element - * transitions only operate if there is both an incoming and outgoing fragment.

- * - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. - * @param isBack true if this is popping the back stack or false if this is a - * forward operation. - * @return The TransitionState used to complete the operation of the transition - * in {@link #setNameOverrides(TransitionState, ArrayList, - * ArrayList)}. - */ - private TransitionState beginTransition(SparseArray firstOutFragments, - SparseArray lastInFragments, boolean isBack) { - TransitionState state = new TransitionState(); - - // Adding a non-existent target view makes sure that the transitions don't target - // any views by default. They'll only target the views we tell add. If we don't - // add any, then no views will be targeted. - state.nonExistentView = new View(mManager.mHost.getContext()); - - boolean anyTransitionStarted = false; - // Go over all leaving fragments. - for (int i = 0; i < firstOutFragments.size(); i++) { - int containerId = firstOutFragments.keyAt(i); - if (configureTransitions(containerId, state, isBack, firstOutFragments, - lastInFragments)) { - anyTransitionStarted = true; - } - } - - // Now go over all entering fragments that didn't have a leaving fragment. - for (int i = 0; i < lastInFragments.size(); i++) { - int containerId = lastInFragments.keyAt(i); - if (firstOutFragments.get(containerId) == null && - configureTransitions(containerId, state, isBack, firstOutFragments, - lastInFragments)) { - anyTransitionStarted = true; - } - } - - if (!anyTransitionStarted) { - state = null; - } - - return state; - } - - private static Object getEnterTransition(Fragment inFragment, boolean isBack) { - if (inFragment == null) { - return null; - } - return FragmentTransitionCompat21.cloneTransition(isBack ? - inFragment.getReenterTransition() : inFragment.getEnterTransition()); - } - - private static Object getExitTransition(Fragment outFragment, boolean isBack) { - if (outFragment == null) { - return null; - } - return FragmentTransitionCompat21.cloneTransition(isBack ? - outFragment.getReturnTransition() : outFragment.getExitTransition()); - } - - private static Object getSharedElementTransition(Fragment inFragment, Fragment outFragment, - boolean isBack) { - if (inFragment == null || outFragment == null) { - return null; - } - return FragmentTransitionCompat21.wrapSharedElementTransition(isBack ? - outFragment.getSharedElementReturnTransition() : - inFragment.getSharedElementEnterTransition()); - } - - private static Object captureExitingViews(Object exitTransition, Fragment outFragment, - ArrayList exitingViews, ArrayMap namedViews, View nonExistentView) { - if (exitTransition != null) { - exitTransition = FragmentTransitionCompat21.captureExitingViews(exitTransition, - outFragment.getView(), exitingViews, namedViews, nonExistentView); - } - return exitTransition; - } - - private ArrayMap remapSharedElements(TransitionState state, Fragment outFragment, - boolean isBack) { - ArrayMap namedViews = new ArrayMap(); - if (mSharedElementSourceNames != null) { - FragmentTransitionCompat21.findNamedViews(namedViews, outFragment.getView()); - if (isBack) { - namedViews.retainAll(mSharedElementTargetNames); - } else { - namedViews = remapNames(mSharedElementSourceNames, mSharedElementTargetNames, - namedViews); - } - } - - if (isBack) { - if (outFragment.mEnterTransitionCallback != null) { - outFragment.mEnterTransitionCallback.onMapSharedElements( - mSharedElementTargetNames, namedViews); - } - setBackNameOverrides(state, namedViews, false); - } else { - if (outFragment.mExitTransitionCallback != null) { - outFragment.mExitTransitionCallback.onMapSharedElements( - mSharedElementTargetNames, namedViews); - } - setNameOverrides(state, namedViews, false); - } - - return namedViews; - } - - /** - * Configures custom transitions for a specific fragment container. - * - * @param containerId The container ID of the fragments to configure the transition for. - * @param state The Transition State keeping track of the executing transitions. - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. - * @param isBack true if this is popping the back stack or false if this is a - * forward operation. - */ - private boolean configureTransitions(int containerId, TransitionState state, boolean isBack, - SparseArray firstOutFragments, SparseArray lastInFragments) { - ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.onFindViewById(containerId); - if (sceneRoot == null) { - return false; - } - final Fragment inFragment = lastInFragments.get(containerId); - Fragment outFragment = firstOutFragments.get(containerId); - - Object enterTransition = getEnterTransition(inFragment, isBack); - Object sharedElementTransition = getSharedElementTransition(inFragment, outFragment, - isBack); - Object exitTransition = getExitTransition(outFragment, isBack); - ArrayMap namedViews = null; - ArrayList sharedElementTargets = new ArrayList(); - if (sharedElementTransition != null) { - namedViews = remapSharedElements(state, outFragment, isBack); - if (namedViews.isEmpty()) { - sharedElementTransition = null; - namedViews = null; - } else { - // Notify the start of the transition. - SharedElementCallback callback = isBack ? - outFragment.mEnterTransitionCallback : - inFragment.mEnterTransitionCallback; - if (callback != null) { - ArrayList names = new ArrayList(namedViews.keySet()); - ArrayList views = new ArrayList(namedViews.values()); - callback.onSharedElementStart(names, views, null); - } - prepareSharedElementTransition(state, sceneRoot, sharedElementTransition, - inFragment, outFragment, isBack, sharedElementTargets); - } - } - if (enterTransition == null && sharedElementTransition == null && - exitTransition == null) { - return false; // no transitions! - } - - ArrayList exitingViews = new ArrayList(); - exitTransition = captureExitingViews(exitTransition, outFragment, exitingViews, - namedViews, state.nonExistentView); - - // Set the epicenter of the exit transition - if (mSharedElementTargetNames != null && namedViews != null) { - View epicenterView = namedViews.get(mSharedElementTargetNames.get(0)); - if (epicenterView != null) { - if (exitTransition != null) { - FragmentTransitionCompat21.setEpicenter(exitTransition, epicenterView); - } - if (sharedElementTransition != null) { - FragmentTransitionCompat21.setEpicenter(sharedElementTransition, - epicenterView); - } - } - } - - FragmentTransitionCompat21.ViewRetriever viewRetriever = - new FragmentTransitionCompat21.ViewRetriever() { - @Override - public View getView() { - return inFragment.getView(); - } - }; - - ArrayList enteringViews = new ArrayList(); - ArrayMap renamedViews = new ArrayMap(); - - boolean allowOverlap = true; - if (inFragment != null) { - allowOverlap = isBack ? inFragment.getAllowReturnTransitionOverlap() : - inFragment.getAllowEnterTransitionOverlap(); - } - Object transition = FragmentTransitionCompat21.mergeTransitions(enterTransition, - exitTransition, sharedElementTransition, allowOverlap); - - if (transition != null) { - FragmentTransitionCompat21.addTransitionTargets(enterTransition, - sharedElementTransition, sceneRoot, viewRetriever, state.nonExistentView, - state.enteringEpicenterView, state.nameOverrides, enteringViews, - namedViews, renamedViews, sharedElementTargets); - excludeHiddenFragmentsAfterEnter(sceneRoot, state, containerId, transition); - - // We want to exclude hidden views later, so we need a non-null list in the - // transition now. - FragmentTransitionCompat21.excludeTarget(transition, state.nonExistentView, true); - // Now exclude all currently hidden fragments. - excludeHiddenFragments(state, containerId, transition); - - FragmentTransitionCompat21.beginDelayedTransition(sceneRoot, transition); - - FragmentTransitionCompat21.cleanupTransitions(sceneRoot, state.nonExistentView, - enterTransition, enteringViews, exitTransition, exitingViews, - sharedElementTransition, sharedElementTargets, - transition, state.hiddenFragmentViews, renamedViews); - } - return transition != null; - } - - private void prepareSharedElementTransition(final TransitionState state, final View sceneRoot, - final Object sharedElementTransition, final Fragment inFragment, - final Fragment outFragment, final boolean isBack, - final ArrayList sharedElementTargets) { - sceneRoot.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this); - - if (sharedElementTransition != null) { - FragmentTransitionCompat21.removeTargets(sharedElementTransition, - sharedElementTargets); - sharedElementTargets.clear(); - - ArrayMap namedViews = mapSharedElementsIn( - state, isBack, inFragment); - FragmentTransitionCompat21.setSharedElementTargets(sharedElementTransition, - state.nonExistentView, namedViews, sharedElementTargets); - - setEpicenterIn(namedViews, state); - - callSharedElementEnd(state, inFragment, outFragment, isBack, - namedViews); - } - - return true; - } - }); - } - - private void callSharedElementEnd(TransitionState state, Fragment inFragment, - Fragment outFragment, boolean isBack, ArrayMap namedViews) { - SharedElementCallback sharedElementCallback = isBack ? - outFragment.mEnterTransitionCallback : - inFragment.mEnterTransitionCallback; - if (sharedElementCallback != null) { - ArrayList names = new ArrayList(namedViews.keySet()); - ArrayList views = new ArrayList(namedViews.values()); - sharedElementCallback.onSharedElementEnd(names, views, null); - } - } - - private void setEpicenterIn(ArrayMap namedViews, TransitionState state) { - if (mSharedElementTargetNames != null && !namedViews.isEmpty()) { - // now we know the epicenter of the entering transition. - View epicenter = namedViews - .get(mSharedElementTargetNames.get(0)); - if (epicenter != null) { - state.enteringEpicenterView.epicenter = epicenter; - } - } - } - - private ArrayMap mapSharedElementsIn(TransitionState state, - boolean isBack, Fragment inFragment) { - // Now map the shared elements in the incoming fragment - ArrayMap namedViews = mapEnteringSharedElements(state, inFragment, isBack); - - // remap shared elements and set the name mapping used - // in the shared element transition. - if (isBack) { - if (inFragment.mExitTransitionCallback != null) { - inFragment.mExitTransitionCallback.onMapSharedElements( - mSharedElementTargetNames, namedViews); - } - setBackNameOverrides(state, namedViews, true); - } else { - if (inFragment.mEnterTransitionCallback != null) { - inFragment.mEnterTransitionCallback.onMapSharedElements( - mSharedElementTargetNames, namedViews); - } - setNameOverrides(state, namedViews, true); - } - return namedViews; - } - - /** - * Remaps a name-to-View map, substituting different names for keys. - * - * @param inMap A list of keys found in the map, in the order in toGoInMap - * @param toGoInMap A list of keys to use for the new map, in the order of inMap - * @param namedViews The current mapping - * @return A copy of namedViews with the keys coming from toGoInMap. - */ - private static ArrayMap remapNames(ArrayList inMap, - ArrayList toGoInMap, ArrayMap namedViews) { - if (namedViews.isEmpty()) { - return namedViews; - } - ArrayMap remappedViews = new ArrayMap(); - int numKeys = inMap.size(); - for (int i = 0; i < numKeys; i++) { - View view = namedViews.get(inMap.get(i)); - if (view != null) { - remappedViews.put(toGoInMap.get(i), view); - } - } - return remappedViews; - } - - /** - * Maps shared elements to views in the entering fragment. - * - * @param state The transition State as returned from {@link #beginTransition( - * SparseArray, SparseArray, boolean)}. - * @param inFragment The last fragment to be added. - * @param isBack true if this is popping the back stack or false if this is a - * forward operation. - */ - private ArrayMap mapEnteringSharedElements(TransitionState state, - Fragment inFragment, boolean isBack) { - ArrayMap namedViews = new ArrayMap(); - View root = inFragment.getView(); - if (root != null) { - if (mSharedElementSourceNames != null) { - FragmentTransitionCompat21.findNamedViews(namedViews, root); - if (isBack) { - namedViews = remapNames(mSharedElementSourceNames, - mSharedElementTargetNames, namedViews); - } else { - namedViews.retainAll(mSharedElementTargetNames); - } - } - } - return namedViews; - } - - private void excludeHiddenFragmentsAfterEnter(final View sceneRoot, final TransitionState state, - final int containerId, final Object transition) { - sceneRoot.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - public boolean onPreDraw() { - sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this); - excludeHiddenFragments(state, containerId, transition); - return true; - } - }); - } - - private void excludeHiddenFragments(TransitionState state, int containerId, Object transition) { - if (mManager.mAdded != null) { - for (int i = 0; i < mManager.mAdded.size(); i++) { - Fragment fragment = mManager.mAdded.get(i); - if (fragment.mView != null && fragment.mContainer != null && - fragment.mContainerId == containerId) { - if (fragment.mHidden) { - if (!state.hiddenFragmentViews.contains(fragment.mView)) { - FragmentTransitionCompat21.excludeTarget(transition, fragment.mView, - true); - state.hiddenFragmentViews.add(fragment.mView); - } - } else { - FragmentTransitionCompat21.excludeTarget(transition, fragment.mView, - false); - state.hiddenFragmentViews.remove(fragment.mView); - } - } - } - } - } - - private static void setNameOverride(ArrayMap overrides, - String source, String target) { - if (source != null && target != null) { - for (int index = 0; index < overrides.size(); index++) { - if (source.equals(overrides.valueAt(index))) { - overrides.setValueAt(index, target); - return; - } - } - overrides.put(source, target); - } - } - - private static void setNameOverrides(TransitionState state, ArrayList sourceNames, - ArrayList targetNames) { - if (sourceNames != null) { - for (int i = 0; i < sourceNames.size(); i++) { - String source = sourceNames.get(i); - String target = targetNames.get(i); - setNameOverride(state.nameOverrides, source, target); - } - } - } - - private void setBackNameOverrides(TransitionState state, ArrayMap namedViews, - boolean isEnd) { - int count = mSharedElementTargetNames == null ? 0 : mSharedElementTargetNames.size(); - for (int i = 0; i < count; i++) { - String source = mSharedElementSourceNames.get(i); - String originalTarget = mSharedElementTargetNames.get(i); - View view = namedViews.get(originalTarget); - if (view != null) { - String target = FragmentTransitionCompat21.getTransitionName(view); - if (isEnd) { - setNameOverride(state.nameOverrides, source, target); - } else { - setNameOverride(state.nameOverrides, target, source); - } - } - } - } - - private void setNameOverrides(TransitionState state, ArrayMap namedViews, - boolean isEnd) { - int count = namedViews.size(); - for (int i = 0; i < count; i++) { - String source = namedViews.keyAt(i); - String target = FragmentTransitionCompat21.getTransitionName(namedViews.valueAt(i)); - if (isEnd) { - setNameOverride(state.nameOverrides, source, target); - } else { - setNameOverride(state.nameOverrides, target, source); - } - } - } - - public class TransitionState { - public ArrayMap nameOverrides = new ArrayMap(); - public ArrayList hiddenFragmentViews = new ArrayList(); - - public FragmentTransitionCompat21.EpicenterView enteringEpicenterView = - new FragmentTransitionCompat21.EpicenterView(); - public View nonExistentView; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BaseFragmentActivityDonut.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BaseFragmentActivityDonut.java deleted file mode 100644 index ba09ab8..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BaseFragmentActivityDonut.java +++ /dev/null @@ -1,47 +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 p.android.support.v4.app; - -import android.app.Activity; -import android.os.Build; -import android.os.Bundle; - -/** - * Base class for {@code FragmentActivity} to be able to use Donut APIs. - */ -public abstract class BaseFragmentActivityDonut extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - if (Build.VERSION.SDK_INT < 11 && getLayoutInflater().getFactory() == null) { - // On pre-HC devices we need to manually install ourselves as a Factory. - // On HC and above, we are automatically installed as a private factory - getLayoutInflater().setFactory(this); - } - - super.onCreate(savedInstanceState); - } - - /** - * Called when the back button has been pressed.and not handled by the support fragment manager. - */ - void onBackPressedNotHandled() { - // on v4, just call finish manually - finish(); - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BaseFragmentActivityHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BaseFragmentActivityHoneycomb.java deleted file mode 100644 index 21ba673..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BaseFragmentActivityHoneycomb.java +++ /dev/null @@ -1,27 +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 p.android.support.v4.app; - -import p.android.support.v4.BaseFragmentActivityEclair; - -/** - * Base class for {@code FragmentActivity} to be able to use v11 APIs. - */ -abstract class BaseFragmentActivityHoneycomb extends BaseFragmentActivityEclair { - - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompat.java deleted file mode 100644 index 14d2b36..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompat.java +++ /dev/null @@ -1,60 +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 p.android.support.v4.app; - -import android.os.Build; -import android.os.Bundle; -import android.os.IBinder; - -/** - * Helper for accessing features in {@link Bundle} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class BundleCompat { - - private BundleCompat() {} - - /** - * A convenience method to handle getting an {@link IBinder} inside a {@link Bundle} for all - * Android versions. - * @param bundle The bundle to get the {@link IBinder}. - * @param key The key to use while getting the {@link IBinder}. - * @return The {@link IBinder} that was obtained. - */ - public static IBinder getBinder(Bundle bundle, String key) { - if (Build.VERSION.SDK_INT >= 18) { - return BundleCompatJellybeanMR2.getBinder(bundle, key); - } else { - return BundleCompatDonut.getBinder(bundle, key); - } - } - - /** - * A convenience method to handle putting an {@link IBinder} inside a {@link Bundle} for all - * Android versions. - * @param bundle The bundle to insert the {@link IBinder}. - * @param key The key to use while putting the {@link IBinder}. - * @param binder The {@link IBinder} to put. - */ - public static void putBinder(Bundle bundle, String key, IBinder binder) { - if (Build.VERSION.SDK_INT >= 18) { - BundleCompatJellybeanMR2.putBinder(bundle, key, binder); - } else { - BundleCompatDonut.putBinder(bundle, key, binder); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompatDonut.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompatDonut.java deleted file mode 100644 index 8749df4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompatDonut.java +++ /dev/null @@ -1,83 +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 p.android.support.v4.app; - -import android.os.Bundle; -import android.os.IBinder; -import android.util.Log; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * @hide - */ -class BundleCompatDonut { - private static final String TAG = "BundleCompatDonut"; - - private static Method sGetIBinderMethod; - private static boolean sGetIBinderMethodFetched; - - private static Method sPutIBinderMethod; - private static boolean sPutIBinderMethodFetched; - - public static IBinder getBinder(Bundle bundle, String key) { - if (!sGetIBinderMethodFetched) { - try { - sGetIBinderMethod = Bundle.class.getMethod("getIBinder", String.class); - sGetIBinderMethod.setAccessible(true); - } catch (NoSuchMethodException e) { - Log.i(TAG, "Failed to retrieve getIBinder method", e); - } - sGetIBinderMethodFetched = true; - } - - if (sGetIBinderMethod != null) { - try { - return (IBinder) sGetIBinderMethod.invoke(bundle, key); - } catch (InvocationTargetException | IllegalAccessException - | IllegalArgumentException e) { - Log.i(TAG, "Failed to invoke getIBinder via reflection", e); - sGetIBinderMethod = null; - } - } - return null; - } - - public static void putBinder(Bundle bundle, String key, IBinder binder) { - if (!sPutIBinderMethodFetched) { - try { - sPutIBinderMethod = - Bundle.class.getMethod("putIBinder", String.class, IBinder.class); - sPutIBinderMethod.setAccessible(true); - } catch (NoSuchMethodException e) { - Log.i(TAG, "Failed to retrieve putIBinder method", e); - } - sPutIBinderMethodFetched = true; - } - - if (sPutIBinderMethod != null) { - try { - sPutIBinderMethod.invoke(bundle, key, binder); - } catch (InvocationTargetException | IllegalAccessException - | IllegalArgumentException e) { - Log.i(TAG, "Failed to invoke putIBinder via reflection", e); - sPutIBinderMethod = null; - } - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompatJellybeanMR2.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompatJellybeanMR2.java deleted file mode 100644 index 72be270..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleCompatJellybeanMR2.java +++ /dev/null @@ -1,33 +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 p.android.support.v4.app; - -import android.os.Bundle; -import android.os.IBinder; - -/** - * @hide - */ -class BundleCompatJellybeanMR2 { - public static IBinder getBinder(Bundle bundle, String key) { - return bundle.getBinder(key); - } - - public static void putBinder(Bundle bundle, String key, IBinder binder) { - bundle.putBinder(key, binder); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleUtil.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleUtil.java deleted file mode 100644 index 8609143..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/BundleUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package p.android.support.v4.app; - -import android.os.Bundle; -import android.os.Parcelable; - -import java.util.Arrays; - -/** - * @hide - */ -class BundleUtil { - /** - * Get an array of Bundle objects from a parcelable array field in a bundle. - * Update the bundle to have a typed array so fetches in the future don't need - * to do an array copy. - */ - public static Bundle[] getBundleArrayFromBundle(Bundle bundle, String key) { - Parcelable[] array = bundle.getParcelableArray(key); - if (array instanceof Bundle[] || array == null) { - return (Bundle[]) array; - } - Bundle[] typedArray = Arrays.copyOf(array, array.length, - Bundle[].class); - bundle.putParcelableArray(key, typedArray); - return typedArray; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/DialogFragment.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/DialogFragment.java deleted file mode 100644 index 8c28546..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/DialogFragment.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.os.Bundle; -import p.android.support.annotation.IntDef; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.annotation.StyleRes; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Static library support version of the framework's {@link android.app.DialogFragment}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework SDK - * documentation for a class overview. - */ -public class DialogFragment extends Fragment - implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { - - /** @hide */ - @IntDef({STYLE_NORMAL, STYLE_NO_TITLE, STYLE_NO_FRAME, STYLE_NO_INPUT}) - @Retention(RetentionPolicy.SOURCE) - private @interface DialogStyle {} - - /** - * Style for {@link #setStyle(int, int)}: a basic, - * normal dialog. - */ - public static final int STYLE_NORMAL = 0; - - /** - * Style for {@link #setStyle(int, int)}: don't include - * a title area. - */ - public static final int STYLE_NO_TITLE = 1; - - /** - * Style for {@link #setStyle(int, int)}: don't draw - * any frame at all; the view hierarchy returned by {@link #onCreateView} - * is entirely responsible for drawing the dialog. - */ - public static final int STYLE_NO_FRAME = 2; - - /** - * Style for {@link #setStyle(int, int)}: like - * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog. - * The user can not touch it, and its window will not receive input focus. - */ - public static final int STYLE_NO_INPUT = 3; - - private static final String SAVED_DIALOG_STATE_TAG = "android:savedDialogState"; - private static final String SAVED_STYLE = "android:style"; - private static final String SAVED_THEME = "android:theme"; - private static final String SAVED_CANCELABLE = "android:cancelable"; - private static final String SAVED_SHOWS_DIALOG = "android:showsDialog"; - private static final String SAVED_BACK_STACK_ID = "android:backStackId"; - - int mStyle = STYLE_NORMAL; - int mTheme = 0; - boolean mCancelable = true; - boolean mShowsDialog = true; - int mBackStackId = -1; - - Dialog mDialog; - boolean mViewDestroyed; - boolean mDismissed; - boolean mShownByMe; - - public DialogFragment() { - } - - /** - * Call to customize the basic appearance and behavior of the - * fragment's dialog. This can be used for some common dialog behaviors, - * taking care of selecting flags, theme, and other options for you. The - * same effect can be achieve by manually setting Dialog and Window - * attributes yourself. Calling this after the fragment's Dialog is - * created will have no effect. - * - * @param style Selects a standard style: may be {@link #STYLE_NORMAL}, - * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or - * {@link #STYLE_NO_INPUT}. - * @param theme Optional custom theme. If 0, an appropriate theme (based - * on the style) will be selected for you. - */ - public void setStyle(@DialogStyle int style, @StyleRes int theme) { - mStyle = style; - if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { - mTheme = android.R.style.Theme_Panel; - } - if (theme != 0) { - mTheme = theme; - } - } - - /** - * Display the dialog, adding the fragment to the given FragmentManager. This - * is a convenience for explicitly creating a transaction, adding the - * fragment to it with the given tag, and committing it. This does - * not add the transaction to the back stack. When the fragment - * is dismissed, a new transaction will be executed to remove it from - * the activity. - * @param manager The FragmentManager this fragment will be added to. - * @param tag The tag for this fragment, as per - * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. - */ - public void show(FragmentManager manager, String tag) { - mDismissed = false; - mShownByMe = true; - FragmentTransaction ft = manager.beginTransaction(); - ft.add(this, tag); - ft.commit(); - } - - /** - * Display the dialog, adding the fragment using an existing transaction - * and then committing the transaction. - * @param transaction An existing transaction in which to add the fragment. - * @param tag The tag for this fragment, as per - * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. - * @return Returns the identifier of the committed transaction, as per - * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. - */ - public int show(FragmentTransaction transaction, String tag) { - mDismissed = false; - mShownByMe = true; - transaction.add(this, tag); - mViewDestroyed = false; - mBackStackId = transaction.commit(); - return mBackStackId; - } - - /** - * Dismiss the fragment and its dialog. If the fragment was added to the - * back stack, all back stack state up to and including this entry will - * be popped. Otherwise, a new transaction will be committed to remove - * the fragment. - */ - public void dismiss() { - dismissInternal(false); - } - - /** - * Version of {@link #dismiss()} that uses - * {@link FragmentTransaction#commitAllowingStateLoss() - * FragmentTransaction.commitAllowingStateLoss()}. See linked - * documentation for further details. - */ - public void dismissAllowingStateLoss() { - dismissInternal(true); - } - - void dismissInternal(boolean allowStateLoss) { - if (mDismissed) { - return; - } - mDismissed = true; - mShownByMe = false; - if (mDialog != null) { - mDialog.dismiss(); - mDialog = null; - } - mViewDestroyed = true; - if (mBackStackId >= 0) { - getFragmentManager().popBackStack(mBackStackId, - FragmentManager.POP_BACK_STACK_INCLUSIVE); - mBackStackId = -1; - } else { - FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.remove(this); - if (allowStateLoss) { - ft.commitAllowingStateLoss(); - } else { - ft.commit(); - } - } - } - - public Dialog getDialog() { - return mDialog; - } - - @StyleRes - public int getTheme() { - return mTheme; - } - - /** - * Control whether the shown Dialog is cancelable. Use this instead of - * directly calling {@link Dialog#setCancelable(boolean) - * Dialog.setCancelable(boolean)}, because DialogFragment needs to change - * its behavior based on this. - * - * @param cancelable If true, the dialog is cancelable. The default - * is true. - */ - public void setCancelable(boolean cancelable) { - mCancelable = cancelable; - if (mDialog != null) mDialog.setCancelable(cancelable); - } - - /** - * Return the current value of {@link #setCancelable(boolean)}. - */ - public boolean isCancelable() { - return mCancelable; - } - - /** - * Controls whether this fragment should be shown in a dialog. If not - * set, no Dialog will be created in {@link #onActivityCreated(Bundle)}, - * and the fragment's view hierarchy will thus not be added to it. This - * allows you to instead use it as a normal fragment (embedded inside of - * its activity). - * - *

This is normally set for you based on whether the fragment is - * associated with a container view ID passed to - * {@link FragmentTransaction#add(int, Fragment) FragmentTransaction.add(int, Fragment)}. - * If the fragment was added with a container, setShowsDialog will be - * initialized to false; otherwise, it will be true. - * - * @param showsDialog If true, the fragment will be displayed in a Dialog. - * If false, no Dialog will be created and the fragment's view hierarchly - * left undisturbed. - */ - public void setShowsDialog(boolean showsDialog) { - mShowsDialog = showsDialog; - } - - /** - * Return the current value of {@link #setShowsDialog(boolean)}. - */ - public boolean getShowsDialog() { - return mShowsDialog; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - if (!mShownByMe) { - // If not explicitly shown through our API, take this as an - // indication that the dialog is no longer dismissed. - mDismissed = false; - } - } - - @Override - public void onDetach() { - super.onDetach(); - if (!mShownByMe && !mDismissed) { - // The fragment was not shown by a direct call here, it is not - // dismissed, and now it is being detached... well, okay, thou - // art now dismissed. Have fun. - mDismissed = true; - } - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mShowsDialog = mContainerId == 0; - - if (savedInstanceState != null) { - mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL); - mTheme = savedInstanceState.getInt(SAVED_THEME, 0); - mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true); - mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog); - mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1); - } - - } - - /** @hide */ - @Override - public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { - if (!mShowsDialog) { - return super.getLayoutInflater(savedInstanceState); - } - - mDialog = onCreateDialog(savedInstanceState); - - if (mDialog != null) { - setupDialog(mDialog, mStyle); - - return (LayoutInflater) mDialog.getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - } - return (LayoutInflater) mHost.getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - } - - /** @hide */ - public void setupDialog(Dialog dialog, int style) { - switch (style) { - case STYLE_NO_INPUT: - dialog.getWindow().addFlags( - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - // fall through... - case STYLE_NO_FRAME: - case STYLE_NO_TITLE: - dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); - } - } - - /** - * Override to build your own custom Dialog container. This is typically - * used to show an AlertDialog instead of a generic Dialog; when doing so, - * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} does not need - * to be implemented since the AlertDialog takes care of its own content. - * - *

This method will be called after {@link #onCreate(Bundle)} and - * before {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. The - * default implementation simply instantiates and returns a {@link Dialog} - * class. - * - *

Note: DialogFragment own the {@link Dialog#setOnCancelListener - * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener - * Dialog.setOnDismissListener} callbacks. You must not set them yourself. - * To find out about these events, override {@link #onCancel(DialogInterface)} - * and {@link #onDismiss(DialogInterface)}.

- * - * @param savedInstanceState The last saved instance state of the Fragment, - * or null if this is a freshly created Fragment. - * - * @return Return a new Dialog instance to be displayed by the Fragment. - */ - @NonNull - public Dialog onCreateDialog(Bundle savedInstanceState) { - return new Dialog(getActivity(), getTheme()); - } - - public void onCancel(DialogInterface dialog) { - } - - public void onDismiss(DialogInterface dialog) { - if (!mViewDestroyed) { - // Note: we need to use allowStateLoss, because the dialog - // dispatches this asynchronously so we can receive the call - // after the activity is paused. Worst case, when the user comes - // back to the activity they see the dialog again. - dismissInternal(true); - } - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - if (!mShowsDialog) { - return; - } - - View view = getView(); - if (view != null) { - if (view.getParent() != null) { - throw new IllegalStateException("DialogFragment can not be attached to a container view"); - } - mDialog.setContentView(view); - } - mDialog.setOwnerActivity(getActivity()); - mDialog.setCancelable(mCancelable); - mDialog.setOnCancelListener(this); - mDialog.setOnDismissListener(this); - if (savedInstanceState != null) { - Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG); - if (dialogState != null) { - mDialog.onRestoreInstanceState(dialogState); - } - } - } - - @Override - public void onStart() { - super.onStart(); - if (mDialog != null) { - mViewDestroyed = false; - mDialog.show(); - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - if (mDialog != null) { - Bundle dialogState = mDialog.onSaveInstanceState(); - if (dialogState != null) { - outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState); - } - } - if (mStyle != STYLE_NORMAL) { - outState.putInt(SAVED_STYLE, mStyle); - } - if (mTheme != 0) { - outState.putInt(SAVED_THEME, mTheme); - } - if (!mCancelable) { - outState.putBoolean(SAVED_CANCELABLE, mCancelable); - } - if (!mShowsDialog) { - outState.putBoolean(SAVED_SHOWS_DIALOG, mShowsDialog); - } - if (mBackStackId != -1) { - outState.putInt(SAVED_BACK_STACK_ID, mBackStackId); - } - } - - @Override - public void onStop() { - super.onStop(); - if (mDialog != null) { - mDialog.hide(); - } - } - - /** - * Remove dialog. - */ - @Override - public void onDestroyView() { - super.onDestroyView(); - if (mDialog != null) { - // Set removed here because this dismissal is just to hide - // the dialog -- we don't want this to cause the fragment to - // actually be removed. - mViewDestroyed = true; - mDialog.dismiss(); - mDialog = null; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/Fragment.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/Fragment.java deleted file mode 100644 index 5e2a33e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/Fragment.java +++ /dev/null @@ -1,2208 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.ComponentCallbacks; -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.annotation.StringRes; -import p.android.support.v4.util.SimpleArrayMap; -import p.android.support.v4.util.DebugUtils; -import p.android.support.v4.view.LayoutInflaterCompat; -import android.util.AttributeSet; -import android.util.Log; -import android.util.SparseArray; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.View.OnCreateContextMenuListener; -import android.view.animation.Animation; -import android.widget.AdapterView; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -final class FragmentState implements Parcelable { - final String mClassName; - final int mIndex; - final boolean mFromLayout; - final int mFragmentId; - final int mContainerId; - final String mTag; - final boolean mRetainInstance; - final boolean mDetached; - final Bundle mArguments; - - Bundle mSavedFragmentState; - - Fragment mInstance; - - public FragmentState(Fragment frag) { - mClassName = frag.getClass().getName(); - mIndex = frag.mIndex; - mFromLayout = frag.mFromLayout; - mFragmentId = frag.mFragmentId; - mContainerId = frag.mContainerId; - mTag = frag.mTag; - mRetainInstance = frag.mRetainInstance; - mDetached = frag.mDetached; - mArguments = frag.mArguments; - } - - public FragmentState(Parcel in) { - mClassName = in.readString(); - mIndex = in.readInt(); - mFromLayout = in.readInt() != 0; - mFragmentId = in.readInt(); - mContainerId = in.readInt(); - mTag = in.readString(); - mRetainInstance = in.readInt() != 0; - mDetached = in.readInt() != 0; - mArguments = in.readBundle(); - mSavedFragmentState = in.readBundle(); - } - - public Fragment instantiate(FragmentHostCallback host, Fragment parent) { - if (mInstance != null) { - return mInstance; - } - - final Context context = host.getContext(); - if (mArguments != null) { - mArguments.setClassLoader(context.getClassLoader()); - } - - mInstance = Fragment.instantiate(context, mClassName, mArguments); - - if (mSavedFragmentState != null) { - mSavedFragmentState.setClassLoader(context.getClassLoader()); - mInstance.mSavedFragmentState = mSavedFragmentState; - } - mInstance.setIndex(mIndex, parent); - mInstance.mFromLayout = mFromLayout; - mInstance.mRestored = true; - mInstance.mFragmentId = mFragmentId; - mInstance.mContainerId = mContainerId; - mInstance.mTag = mTag; - mInstance.mRetainInstance = mRetainInstance; - mInstance.mDetached = mDetached; - mInstance.mFragmentManager = host.mFragmentManager; - - if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, - "Instantiated fragment " + mInstance); - - return mInstance; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mClassName); - dest.writeInt(mIndex); - dest.writeInt(mFromLayout ? 1 : 0); - dest.writeInt(mFragmentId); - dest.writeInt(mContainerId); - dest.writeString(mTag); - dest.writeInt(mRetainInstance ? 1 : 0); - dest.writeInt(mDetached ? 1 : 0); - dest.writeBundle(mArguments); - dest.writeBundle(mSavedFragmentState); - } - - public static final Creator CREATOR - = new Creator() { - public FragmentState createFromParcel(Parcel in) { - return new FragmentState(in); - } - - public FragmentState[] newArray(int size) { - return new FragmentState[size]; - } - }; -} - -/** - * Static library support version of the framework's {@link android.app.Fragment}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework {@link android.app.Fragment} - * documentation for a class overview. - * - *

The main differences when using this support version instead of the framework version are: - *

    - *
  • Your activity must extend {@link FragmentActivity} - *
  • You must call {@link FragmentActivity#getSupportFragmentManager} to get the - * {@link FragmentManager} - *
- * - */ -public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener { - private static final SimpleArrayMap> sClassMap = - new SimpleArrayMap>(); - - static final Object USE_DEFAULT_TRANSITION = new Object(); - - static final int INITIALIZING = 0; // Not yet created. - static final int CREATED = 1; // Created. - static final int ACTIVITY_CREATED = 2; // The activity has finished its creation. - static final int STOPPED = 3; // Fully created, not started. - static final int STARTED = 4; // Created and started, not resumed. - static final int RESUMED = 5; // Created started and resumed. - - int mState = INITIALIZING; - - // Non-null if the fragment's view hierarchy is currently animating away, - // meaning we need to wait a bit on completely destroying it. This is the - // view that is animating. - View mAnimatingAway; - - // If mAnimatingAway != null, this is the state we should move to once the - // animation is done. - int mStateAfterAnimating; - - // When instantiated from saved state, this is the saved state. - Bundle mSavedFragmentState; - SparseArray mSavedViewState; - - // Index into active fragment array. - int mIndex = -1; - - // Internal unique name for this fragment; - String mWho; - - // Construction arguments; - Bundle mArguments; - - // Target fragment. - Fragment mTarget; - - // For use when retaining a fragment: this is the index of the last mTarget. - int mTargetIndex = -1; - - // Target request code. - int mTargetRequestCode; - - // True if the fragment is in the list of added fragments. - boolean mAdded; - - // If set this fragment is being removed from its activity. - boolean mRemoving; - - // Set to true if this fragment was instantiated from a layout file. - boolean mFromLayout; - - // Set to true when the view has actually been inflated in its layout. - boolean mInLayout; - - // True if this fragment has been restored from previously saved state. - boolean mRestored; - - // Number of active back stack entries this fragment is in. - int mBackStackNesting; - - // The fragment manager we are associated with. Set as soon as the - // fragment is used in a transaction; cleared after it has been removed - // from all transactions. - FragmentManagerImpl mFragmentManager; - - // Host this fragment is attached to. - FragmentHostCallback mHost; - - // Private fragment manager for child fragments inside of this one. - FragmentManagerImpl mChildFragmentManager; - - // If this Fragment is contained in another Fragment, this is that container. - Fragment mParentFragment; - - // The optional identifier for this fragment -- either the container ID if it - // was dynamically added to the view hierarchy, or the ID supplied in - // layout. - int mFragmentId; - - // When a fragment is being dynamically added to the view hierarchy, this - // is the identifier of the parent container it is being added to. - int mContainerId; - - // The optional named tag for this fragment -- usually used to find - // fragments that are not part of the layout. - String mTag; - - // Set to true when the app has requested that this fragment be hidden - // from the user. - boolean mHidden; - - // Set to true when the app has requested that this fragment be deactivated. - boolean mDetached; - - // If set this fragment would like its instance retained across - // configuration changes. - boolean mRetainInstance; - - // If set this fragment is being retained across the current config change. - boolean mRetaining; - - // If set this fragment has menu items to contribute. - boolean mHasMenu; - - // Set to true to allow the fragment's menu to be shown. - boolean mMenuVisible = true; - - // Used to verify that subclasses call through to super class. - boolean mCalled; - - // If app has requested a specific animation, this is the one to use. - int mNextAnim; - - // The parent container of the fragment after dynamically added to UI. - ViewGroup mContainer; - - // The View generated for this fragment. - View mView; - - // The real inner view that will save/restore state. - View mInnerView; - - // Whether this fragment should defer starting until after other fragments - // have been started and their loaders are finished. - boolean mDeferStart; - - // Hint provided by the app that this fragment is currently visible to the user. - boolean mUserVisibleHint = true; - - LoaderManagerImpl mLoaderManager; - boolean mLoadersStarted; - boolean mCheckedForLoaderManager; - - Object mEnterTransition = null; - Object mReturnTransition = USE_DEFAULT_TRANSITION; - Object mExitTransition = null; - Object mReenterTransition = USE_DEFAULT_TRANSITION; - Object mSharedElementEnterTransition = null; - Object mSharedElementReturnTransition = USE_DEFAULT_TRANSITION; - Boolean mAllowReturnTransitionOverlap; - Boolean mAllowEnterTransitionOverlap; - - SharedElementCallback mEnterTransitionCallback = null; - SharedElementCallback mExitTransitionCallback = null; - - /** - * State information that has been retrieved from a fragment instance - * through {@link FragmentManager#saveFragmentInstanceState(Fragment) - * FragmentManager.saveFragmentInstanceState}. - */ - public static class SavedState implements Parcelable { - final Bundle mState; - - SavedState(Bundle state) { - mState = state; - } - - SavedState(Parcel in, ClassLoader loader) { - mState = in.readBundle(); - if (loader != null && mState != null) { - mState.setClassLoader(loader); - } - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeBundle(mState); - } - - public static final Creator CREATOR - = new Creator() { - @Override - public SavedState createFromParcel(Parcel in) { - return new SavedState(in, null); - } - - @Override - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - /** - * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when - * there is an instantiation failure. - */ - static public class InstantiationException extends RuntimeException { - public InstantiationException(String msg, Exception cause) { - super(msg, cause); - } - } - - /** - * Default constructor. Every fragment must have an - * empty constructor, so it can be instantiated when restoring its - * activity's state. It is strongly recommended that subclasses do not - * have other constructors with parameters, since these constructors - * will not be called when the fragment is re-instantiated; instead, - * arguments can be supplied by the caller with {@link #setArguments} - * and later retrieved by the Fragment with {@link #getArguments}. - * - *

Applications should generally not implement a constructor. The - * first place application code an run where the fragment is ready to - * be used is in {@link #onAttach(Activity)}, the point where the fragment - * is actually associated with its activity. Some applications may also - * want to implement {@link #onInflate} to retrieve attributes from a - * layout resource, though should take care here because this happens for - * the fragment is attached to its activity. - */ - public Fragment() { - } - - /** - * Like {@link #instantiate(Context, String, Bundle)} but with a null - * argument Bundle. - */ - public static Fragment instantiate(Context context, String fname) { - return instantiate(context, fname, null); - } - - /** - * Create a new instance of a Fragment with the given class name. This is - * the same as calling its empty constructor. - * - * @param context The calling context being used to instantiate the fragment. - * This is currently just used to get its ClassLoader. - * @param fname The class name of the fragment to instantiate. - * @param args Bundle of arguments to supply to the fragment, which it - * can retrieve with {@link #getArguments()}. May be null. - * @return Returns a new fragment instance. - * @throws InstantiationException If there is a failure in instantiating - * the given fragment class. This is a runtime exception; it is not - * normally expected to happen. - */ - public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) { - try { - Class clazz = sClassMap.get(fname); - if (clazz == null) { - // Class not found in the cache, see if it's real, and try to add it - clazz = context.getClassLoader().loadClass(fname); - sClassMap.put(fname, clazz); - } - Fragment f = (Fragment)clazz.newInstance(); - if (args != null) { - args.setClassLoader(f.getClass().getClassLoader()); - f.mArguments = args; - } - return f; - } catch (ClassNotFoundException e) { - throw new InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (java.lang.InstantiationException e) { - throw new InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (IllegalAccessException e) { - throw new InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } - } - - /** - * Determine if the given fragment name is a support library fragment class. - * - * @param context Context used to determine the correct ClassLoader to use - * @param fname Class name of the fragment to test - * @return true if fname is Fragment - * or a subclass, false otherwise. - */ - static boolean isSupportFragmentClass(Context context, String fname) { - try { - Class clazz = sClassMap.get(fname); - if (clazz == null) { - // Class not found in the cache, see if it's real, and try to add it - clazz = context.getClassLoader().loadClass(fname); - sClassMap.put(fname, clazz); - } - return Fragment.class.isAssignableFrom(clazz); - } catch (ClassNotFoundException e) { - return false; - } - } - - final void restoreViewState(Bundle savedInstanceState) { - if (mSavedViewState != null) { - mInnerView.restoreHierarchyState(mSavedViewState); - mSavedViewState = null; - } - mCalled = false; - onViewStateRestored(savedInstanceState); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onViewStateRestored()"); - } - } - - final void setIndex(int index, Fragment parent) { - mIndex = index; - if (parent != null) { - mWho = parent.mWho + ":" + mIndex; - } else { - mWho = "android:fragment:" + mIndex; - } - } - - final boolean isInBackStack() { - return mBackStackNesting > 0; - } - - /** - * Subclasses can not override equals(). - */ - @Override final public boolean equals(Object o) { - return super.equals(o); - } - - /** - * Subclasses can not override hashCode(). - */ - @Override final public int hashCode() { - return super.hashCode(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(128); - DebugUtils.buildShortClassTag(this, sb); - if (mIndex >= 0) { - sb.append(" #"); - sb.append(mIndex); - } - if (mFragmentId != 0) { - sb.append(" id=0x"); - sb.append(Integer.toHexString(mFragmentId)); - } - if (mTag != null) { - sb.append(" "); - sb.append(mTag); - } - sb.append('}'); - return sb.toString(); - } - - /** - * Return the identifier this fragment is known by. This is either - * the android:id value supplied in a layout or the container view ID - * supplied when adding the fragment. - */ - final public int getId() { - return mFragmentId; - } - - /** - * Get the tag name of the fragment, if specified. - */ - final public String getTag() { - return mTag; - } - - /** - * Supply the construction arguments for this fragment. This can only - * be called before the fragment has been attached to its activity; that - * is, you should call it immediately after constructing the fragment. The - * arguments supplied here will be retained across fragment destroy and - * creation. - */ - public void setArguments(Bundle args) { - if (mIndex >= 0) { - throw new IllegalStateException("Fragment already active"); - } - mArguments = args; - } - - /** - * Return the arguments supplied when the fragment was instantiated, - * if any. - */ - final public Bundle getArguments() { - return mArguments; - } - - /** - * Set the initial saved state that this Fragment should restore itself - * from when first being constructed, as returned by - * {@link FragmentManager#saveFragmentInstanceState(Fragment) - * FragmentManager.saveFragmentInstanceState}. - * - * @param state The state the fragment should be restored from. - */ - public void setInitialSavedState(SavedState state) { - if (mIndex >= 0) { - throw new IllegalStateException("Fragment already active"); - } - mSavedFragmentState = state != null && state.mState != null - ? state.mState : null; - } - - /** - * Optional target for this fragment. This may be used, for example, - * if this fragment is being started by another, and when done wants to - * give a result back to the first. The target set here is retained - * across instances via {@link FragmentManager#putFragment - * FragmentManager.putFragment()}. - * - * @param fragment The fragment that is the target of this one. - * @param requestCode Optional request code, for convenience if you - * are going to call back with {@link #onActivityResult(int, int, Intent)}. - */ - public void setTargetFragment(Fragment fragment, int requestCode) { - mTarget = fragment; - mTargetRequestCode = requestCode; - } - - /** - * Return the target fragment set by {@link #setTargetFragment}. - */ - final public Fragment getTargetFragment() { - return mTarget; - } - - /** - * Return the target request code set by {@link #setTargetFragment}. - */ - final public int getTargetRequestCode() { - return mTargetRequestCode; - } - - /** - * Return the {@link Context} this fragment is currently associated with. - */ - public Context getContext() { - return mHost == null ? null : mHost.getContext(); - } - - /** - * Return the {@link FragmentActivity} this fragment is currently associated with. - * May return {@code null} if the fragment is associated with a {@link Context} - * instead. - */ - final public FragmentActivity getActivity() { - return mHost == null ? null : (FragmentActivity) mHost.getActivity(); - } - - /** - * Return the host object of this fragment. May return {@code null} if the fragment - * isn't currently being hosted. - */ - final public Object getHost() { - return mHost == null ? null : mHost.onGetHost(); - } - - /** - * Return getActivity().getResources(). - */ - final public Resources getResources() { - if (mHost == null) { - throw new IllegalStateException("Fragment " + this + " not attached to Activity"); - } - return mHost.getContext().getResources(); - } - - /** - * Return a localized, styled CharSequence from the application's package's - * default string table. - * - * @param resId Resource id for the CharSequence text - */ - public final CharSequence getText(@StringRes int resId) { - return getResources().getText(resId); - } - - /** - * Return a localized string from the application's package's - * default string table. - * - * @param resId Resource id for the string - */ - public final String getString(@StringRes int resId) { - return getResources().getString(resId); - } - - /** - * Return a localized formatted string from the application's package's - * default string table, substituting the format arguments as defined in - * {@link java.util.Formatter} and {@link String#format}. - * - * @param resId Resource id for the format string - * @param formatArgs The format arguments that will be used for substitution. - */ - - public final String getString(@StringRes int resId, Object... formatArgs) { - return getResources().getString(resId, formatArgs); - } - - /** - * Return the FragmentManager for interacting with fragments associated - * with this fragment's activity. Note that this will be non-null slightly - * before {@link #getActivity()}, during the time from when the fragment is - * placed in a {@link FragmentTransaction} until it is committed and - * attached to its activity. - * - *

If this Fragment is a child of another Fragment, the FragmentManager - * returned here will be the parent's {@link #getChildFragmentManager()}. - */ - final public FragmentManager getFragmentManager() { - return mFragmentManager; - } - - /** - * Return a private FragmentManager for placing and managing Fragments - * inside of this Fragment. - */ - final public FragmentManager getChildFragmentManager() { - if (mChildFragmentManager == null) { - instantiateChildFragmentManager(); - if (mState >= RESUMED) { - mChildFragmentManager.dispatchResume(); - } else if (mState >= STARTED) { - mChildFragmentManager.dispatchStart(); - } else if (mState >= ACTIVITY_CREATED) { - mChildFragmentManager.dispatchActivityCreated(); - } else if (mState >= CREATED) { - mChildFragmentManager.dispatchCreate(); - } - } - return mChildFragmentManager; - } - - /** - * Returns the parent Fragment containing this Fragment. If this Fragment - * is attached directly to an Activity, returns null. - */ - final public Fragment getParentFragment() { - return mParentFragment; - } - - /** - * Return true if the fragment is currently added to its activity. - */ - final public boolean isAdded() { - return mHost != null && mAdded; - } - - /** - * Return true if the fragment has been explicitly detached from the UI. - * That is, {@link FragmentTransaction#detach(Fragment) - * FragmentTransaction.detach(Fragment)} has been used on it. - */ - final public boolean isDetached() { - return mDetached; - } - - /** - * Return true if this fragment is currently being removed from its - * activity. This is not whether its activity is finishing, but - * rather whether it is in the process of being removed from its activity. - */ - final public boolean isRemoving() { - return mRemoving; - } - - /** - * Return true if the layout is included as part of an activity view - * hierarchy via the <fragment> tag. This will always be true when - * fragments are created through the <fragment> tag, except - * in the case where an old fragment is restored from a previous state and - * it does not appear in the layout of the current state. - */ - final public boolean isInLayout() { - return mInLayout; - } - - /** - * Return true if the fragment is in the resumed state. This is true - * for the duration of {@link #onResume()} and {@link #onPause()} as well. - */ - final public boolean isResumed() { - return mState >= RESUMED; - } - - /** - * Return true if the fragment is currently visible to the user. This means - * it: (1) has been added, (2) has its view attached to the window, and - * (3) is not hidden. - */ - final public boolean isVisible() { - return isAdded() && !isHidden() && mView != null - && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; - } - - /** - * Return true if the fragment has been hidden. By default fragments - * are shown. You can find out about changes to this state with - * {@link #onHiddenChanged}. Note that the hidden state is orthogonal - * to other states -- that is, to be visible to the user, a fragment - * must be both started and not hidden. - */ - final public boolean isHidden() { - return mHidden; - } - - /** @hide */ - final public boolean hasOptionsMenu() { - return mHasMenu; - } - - /** @hide */ - final public boolean isMenuVisible() { - return mMenuVisible; - } - - /** - * Called when the hidden state (as returned by {@link #isHidden()} of - * the fragment has changed. Fragments start out not hidden; this will - * be called whenever the fragment changes state from that. - * @param hidden True if the fragment is now hidden, false if it is not - * visible. - */ - public void onHiddenChanged(boolean hidden) { - } - - /** - * Control whether a fragment instance is retained across Activity - * re-creation (such as from a configuration change). This can only - * be used with fragments not in the back stack. If set, the fragment - * lifecycle will be slightly different when an activity is recreated: - *

    - *
  • {@link #onDestroy()} will not be called (but {@link #onDetach()} still - * will be, because the fragment is being detached from its current activity). - *
  • {@link #onCreate(Bundle)} will not be called since the fragment - * is not being re-created. - *
  • {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} will - * still be called. - *
- */ - public void setRetainInstance(boolean retain) { - if (retain && mParentFragment != null) { - throw new IllegalStateException( - "Can't retain fragements that are nested in other fragments"); - } - mRetainInstance = retain; - } - - final public boolean getRetainInstance() { - return mRetainInstance; - } - - /** - * Report that this fragment would like to participate in populating - * the options menu by receiving a call to {@link #onCreateOptionsMenu} - * and related methods. - * - * @param hasMenu If true, the fragment has menu items to contribute. - */ - public void setHasOptionsMenu(boolean hasMenu) { - if (mHasMenu != hasMenu) { - mHasMenu = hasMenu; - if (isAdded() && !isHidden()) { - mHost.onSupportInvalidateOptionsMenu(); - } - } - } - - /** - * Set a hint for whether this fragment's menu should be visible. This - * is useful if you know that a fragment has been placed in your view - * hierarchy so that the user can not currently seen it, so any menu items - * it has should also not be shown. - * - * @param menuVisible The default is true, meaning the fragment's menu will - * be shown as usual. If false, the user will not see the menu. - */ - public void setMenuVisibility(boolean menuVisible) { - if (mMenuVisible != menuVisible) { - mMenuVisible = menuVisible; - if (mHasMenu && isAdded() && !isHidden()) { - mHost.onSupportInvalidateOptionsMenu(); - } - } - } - - /** - * Set a hint to the system about whether this fragment's UI is currently visible - * to the user. This hint defaults to true and is persistent across fragment instance - * state save and restore. - * - *

An app may set this to false to indicate that the fragment's UI is - * scrolled out of visibility or is otherwise not directly visible to the user. - * This may be used by the system to prioritize operations such as fragment lifecycle updates - * or loader ordering behavior.

- * - * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), - * false if it is not. - */ - public void setUserVisibleHint(boolean isVisibleToUser) { - if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) { - mFragmentManager.performPendingDeferredStart(this); - } - mUserVisibleHint = isVisibleToUser; - mDeferStart = !isVisibleToUser; - } - - /** - * @return The current value of the user-visible hint on this fragment. - * @see #setUserVisibleHint(boolean) - */ - public boolean getUserVisibleHint() { - return mUserVisibleHint; - } - - /** - * Return the LoaderManager for this fragment, creating it if needed. - */ - public LoaderManager getLoaderManager() { - if (mLoaderManager != null) { - return mLoaderManager; - } - if (mHost == null) { - throw new IllegalStateException("Fragment " + this + " not attached to Activity"); - } - mCheckedForLoaderManager = true; - mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, true); - return mLoaderManager; - } - - /** - * Call {@link Activity#startActivity(Intent)} from the fragment's - * containing Activity. - */ - public void startActivity(Intent intent) { - startActivity(intent, null); - } - - /** - * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's - * containing Activity. - */ - public void startActivity(Intent intent, @Nullable Bundle options) { - if (mHost == null) { - throw new IllegalStateException("Fragment " + this + " not attached to Activity"); - } - mHost.onStartActivityFromFragment(this /*fragment*/, intent, -1, options); - } - - /** - * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment's - * containing Activity. - */ - public void startActivityForResult(Intent intent, int requestCode) { - startActivityForResult(intent, requestCode, null); - } - - /** - * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's - * containing Activity. - */ - public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { - if (mHost == null) { - throw new IllegalStateException("Fragment " + this + " not attached to Activity"); - } - mHost.onStartActivityFromFragment(this /*fragment*/, intent, requestCode, options); - } - - /** - * Receive the result from a previous call to - * {@link #startActivityForResult(Intent, int)}. This follows the - * related Activity API as described there in - * {@link Activity#onActivityResult(int, int, Intent)}. - * - * @param requestCode The integer request code originally supplied to - * startActivityForResult(), allowing you to identify who this - * result came from. - * @param resultCode The integer result code returned by the child activity - * through its setResult(). - * @param data An Intent, which can return result data to the caller - * (various data can be attached to Intent "extras"). - */ - public void onActivityResult(int requestCode, int resultCode, Intent data) { - } - - /** - * Requests permissions to be granted to this application. These permissions - * must be requested in your manifest, they should not be granted to your app, - * and they should have protection level {@link android.content.pm.PermissionInfo - * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by - * the platform or a third-party app. - *

- * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL} - * are granted at install time if requested in the manifest. Signature permissions - * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at - * install time if requested in the manifest and the signature of your app matches - * the signature of the app declaring the permissions. - *

- *

- * If your app does not have the requested permissions the user will be presented - * with UI for accepting them. After the user has accepted or rejected the - * requested permissions you will receive a callback on {@link - * #onRequestPermissionsResult(int, String[], int[])} reporting whether the - * permissions were granted or not. - *

- *

- * Note that requesting a permission does not guarantee it will be granted and - * your app should be able to run without having this permission. - *

- *

- * This method may start an activity allowing the user to choose which permissions - * to grant and which to reject. Hence, you should be prepared that your activity - * may be paused and resumed. Further, granting some permissions may require - * a restart of you application. In such a case, the system will recreate the - * activity stack before delivering the result to {@link - * #onRequestPermissionsResult(int, String[], int[])}. - *

- *

- * When checking whether you have a permission you should use {@link - * Context#checkSelfPermission(String)}. - *

- *

- * A sample permissions request looks like this: - *

- *

- * private void showContacts() { - * if (getActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) - * != PackageManager.PERMISSION_GRANTED) { - * requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, - * PERMISSIONS_REQUEST_READ_CONTACTS); - * } else { - * doShowContacts(); - * } - * } - * - * {@literal @}Override - * public void onRequestPermissionsResult(int requestCode, String[] permissions, - * int[] grantResults) { - * if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS - * && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - * doShowContacts(); - * } - * } - *

- * - * @param permissions The requested permissions. - * @param requestCode Application specific request code to match with a result - * reported to {@link #onRequestPermissionsResult(int, String[], int[])}. - * - * @see #onRequestPermissionsResult(int, String[], int[]) - * @see Context#checkSelfPermission(String) - */ - public final void requestPermissions(@NonNull String[] permissions, int requestCode) { - if (mHost == null) { - throw new IllegalStateException("Fragment " + this + " not attached to Activity"); - } - mHost.onRequestPermissionsFromFragment(this, permissions,requestCode); - } - - /** - * Callback for the result from requesting permissions. This method - * is invoked for every call on {@link #requestPermissions(String[], int)}. - *

- * Note: It is possible that the permissions request interaction - * with the user is interrupted. In this case you will receive empty permissions - * and results arrays which should be treated as a cancellation. - *

- * - * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}. - * @param permissions The requested permissions. Never null. - * @param grantResults The grant results for the corresponding permissions - * which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED} - * or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null. - * - * @see #requestPermissions(String[], int) - */ - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - /* callback - do nothing */ - } - - /** - * Gets whether you should show UI with rationale for requesting a permission. - * You should do this only if you do not have the permission and the context in - * which the permission is requested does not clearly communicate to the user - * what would be the benefit from granting this permission. - *

- * For example, if you write a camera app, requesting the camera permission - * would be expected by the user and no rationale for why it is requested is - * needed. If however, the app needs location for tagging photos then a non-tech - * savvy user may wonder how location is related to taking photos. In this case - * you may choose to show UI with rationale of requesting this permission. - *

- * - * @param permission A permission your app wants to request. - * @return Whether you can show permission rationale UI. - * - * @see Context#checkSelfPermission(String) - * @see #requestPermissions(String[], int) - * @see #onRequestPermissionsResult(int, String[], int[]) - */ - public boolean shouldShowRequestPermissionRationale(@NonNull String permission) { - if (mHost != null) { - return mHost.onShouldShowRequestPermissionRationale(permission); - } - return false; - } - - /** - * @hide Hack so that DialogFragment can make its Dialog before creating - * its views, and the view construction can use the dialog's context for - * inflation. Maybe this should become a public API. Note sure. - */ - public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { - LayoutInflater result = mHost.onGetLayoutInflater(); - getChildFragmentManager(); // Init if needed; use raw implementation below. - LayoutInflaterCompat.setFactory(result, mChildFragmentManager.getLayoutInflaterFactory()); - return result; - } - - /** - * Called when a fragment is being created as part of a view layout - * inflation, typically from setting the content view of an activity. This - * may be called immediately after the fragment is created from a - * tag in a layout file. Note this is before the fragment's - * {@link #onAttach(Activity)} has been called; all you should do here is - * parse the attributes and save them away. - * - *

This is called every time the fragment is inflated, even if it is - * being inflated into a new instance with saved state. It typically makes - * sense to re-parse the parameters each time, to allow them to change with - * different configurations.

- * - *

Here is a typical implementation of a fragment that can take parameters - * both through attributes supplied here as well from {@link #getArguments()}:

- * - * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java - * fragment} - * - *

Note that parsing the XML attributes uses a "styleable" resource. The - * declaration for the styleable used here is:

- * - * {@sample development/samples/ApiDemos/res/values/attrs.xml fragment_arguments} - * - *

The fragment can then be declared within its activity's content layout - * through a tag like this:

- * - * {@sample development/samples/ApiDemos/res/layout/fragment_arguments.xml from_attributes} - * - *

This fragment can also be created dynamically from arguments given - * at runtime in the arguments Bundle; here is an example of doing so at - * creation of the containing activity:

- * - * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java - * create} - * - * @param context The Activity that is inflating this fragment. - * @param attrs The attributes at the tag where the fragment is - * being created. - * @param savedInstanceState If the fragment is being re-created from - * a previous saved state, this is the state. - */ - public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) { - mCalled = true; - final Activity hostActivity = mHost == null ? null : mHost.getActivity(); - if (hostActivity != null) { - mCalled = false; - onInflate(hostActivity, attrs, savedInstanceState); - } - } - - /** - * Called when a fragment is being created as part of a view layout - * inflation, typically from setting the content view of an activity. - *

Deprecated. See {@link #onInflate(Context, AttributeSet, Bundle)}. - */ - @Deprecated - public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { - mCalled = true; - } - - /** - * Called when a fragment is first attached to its context. - * {@link #onCreate(Bundle)} will be called after this. - */ - public void onAttach(Context context) { - mCalled = true; - final Activity hostActivity = mHost == null ? null : mHost.getActivity(); - if (hostActivity != null) { - mCalled = false; - onAttach(hostActivity); - } - } - - /** - * Called when a fragment is first attached to its activity. - * {@link #onCreate(Bundle)} will be called after this. - *

Deprecated. See {@link #onAttach(Context)}. - */ - @Deprecated - public void onAttach(Activity activity) { - mCalled = true; - } - - /** - * Called when a fragment loads an animation. - */ - public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { - return null; - } - - /** - * Called to do initial creation of a fragment. This is called after - * {@link #onAttach(Activity)} and before - * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. - * - *

Note that this can be called while the fragment's activity is - * still in the process of being created. As such, you can not rely - * on things like the activity's content view hierarchy being initialized - * at this point. If you want to do work once the activity itself is - * created, see {@link #onActivityCreated(Bundle)}. - * - * @param savedInstanceState If the fragment is being re-created from - * a previous saved state, this is the state. - */ - public void onCreate(@Nullable Bundle savedInstanceState) { - mCalled = true; - } - - /** - * Called to have the fragment instantiate its user interface view. - * This is optional, and non-graphical fragments can return null (which - * is the default implementation). This will be called between - * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}. - * - *

If you return a View from here, you will later be called in - * {@link #onDestroyView} when the view is being released. - * - * @param inflater The LayoutInflater object that can be used to inflate - * any views in the fragment, - * @param container If non-null, this is the parent view that the fragment's - * UI should be attached to. The fragment should not add the view itself, - * but this can be used to generate the LayoutParams of the view. - * @param savedInstanceState If non-null, this fragment is being re-constructed - * from a previous saved state as given here. - * - * @return Return the View for the fragment's UI, or null. - */ - @Nullable - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - return null; - } - - /** - * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} - * has returned, but before any saved state has been restored in to the view. - * This gives subclasses a chance to initialize themselves once - * they know their view hierarchy has been completely created. The fragment's - * view hierarchy is not however attached to its parent at this point. - * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. - * @param savedInstanceState If non-null, this fragment is being re-constructed - * from a previous saved state as given here. - */ - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - } - - /** - * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}), - * if provided. - * - * @return The fragment's root view, or null if it has no layout. - */ - @Nullable - public View getView() { - return mView; - } - - /** - * Called when the fragment's activity has been created and this - * fragment's view hierarchy instantiated. It can be used to do final - * initialization once these pieces are in place, such as retrieving - * views or restoring state. It is also useful for fragments that use - * {@link #setRetainInstance(boolean)} to retain their instance, - * as this callback tells the fragment when it is fully associated with - * the new activity instance. This is called after {@link #onCreateView} - * and before {@link #onViewStateRestored(Bundle)}. - * - * @param savedInstanceState If the fragment is being re-created from - * a previous saved state, this is the state. - */ - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - mCalled = true; - } - - /** - * Called when all saved state has been restored into the view hierarchy - * of the fragment. This can be used to do initialization based on saved - * state that you are letting the view hierarchy track itself, such as - * whether check box widgets are currently checked. This is called - * after {@link #onActivityCreated(Bundle)} and before - * {@link #onStart()}. - * - * @param savedInstanceState If the fragment is being re-created from - * a previous saved state, this is the state. - */ - public void onViewStateRestored(@Nullable Bundle savedInstanceState) { - mCalled = true; - } - - /** - * Called when the Fragment is visible to the user. This is generally - * tied to {@link Activity#onStart() Activity.onStart} of the containing - * Activity's lifecycle. - */ - public void onStart() { - mCalled = true; - - if (!mLoadersStarted) { - mLoadersStarted = true; - if (!mCheckedForLoaderManager) { - mCheckedForLoaderManager = true; - mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); - } - if (mLoaderManager != null) { - mLoaderManager.doStart(); - } - } - } - - /** - * Called when the fragment is visible to the user and actively running. - * This is generally - * tied to {@link Activity#onResume() Activity.onResume} of the containing - * Activity's lifecycle. - */ - public void onResume() { - mCalled = true; - } - - /** - * Called to ask the fragment to save its current dynamic state, so it - * can later be reconstructed in a new instance of its process is - * restarted. If a new instance of the fragment later needs to be - * created, the data you place in the Bundle here will be available - * in the Bundle given to {@link #onCreate(Bundle)}, - * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and - * {@link #onActivityCreated(Bundle)}. - * - *

This corresponds to {@link Activity#onSaveInstanceState(Bundle) - * Activity.onSaveInstanceState(Bundle)} and most of the discussion there - * applies here as well. Note however: this method may be called - * at any time before {@link #onDestroy()}. There are many situations - * where a fragment may be mostly torn down (such as when placed on the - * back stack with no UI showing), but its state will not be saved until - * its owning activity actually needs to save its state. - * - * @param outState Bundle in which to place your saved state. - */ - public void onSaveInstanceState(Bundle outState) { - } - - public void onConfigurationChanged(Configuration newConfig) { - mCalled = true; - } - - /** - * Called when the Fragment is no longer resumed. This is generally - * tied to {@link Activity#onPause() Activity.onPause} of the containing - * Activity's lifecycle. - */ - public void onPause() { - mCalled = true; - } - - /** - * Called when the Fragment is no longer started. This is generally - * tied to {@link Activity#onStop() Activity.onStop} of the containing - * Activity's lifecycle. - */ - public void onStop() { - mCalled = true; - } - - public void onLowMemory() { - mCalled = true; - } - - /** - * Called when the view previously created by {@link #onCreateView} has - * been detached from the fragment. The next time the fragment needs - * to be displayed, a new view will be created. This is called - * after {@link #onStop()} and before {@link #onDestroy()}. It is called - * regardless of whether {@link #onCreateView} returned a - * non-null view. Internally it is called after the view's state has - * been saved but before it has been removed from its parent. - */ - public void onDestroyView() { - mCalled = true; - } - - /** - * Called when the fragment is no longer in use. This is called - * after {@link #onStop()} and before {@link #onDetach()}. - */ - public void onDestroy() { - mCalled = true; - //Log.v("foo", "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager - // + " mLoaderManager=" + mLoaderManager); - if (!mCheckedForLoaderManager) { - mCheckedForLoaderManager = true; - mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); - } - if (mLoaderManager != null) { - mLoaderManager.doDestroy(); - } - } - - /** - * Called by the fragment manager once this fragment has been removed, - * so that we don't have any left-over state if the application decides - * to re-use the instance. This only clears state that the framework - * internally manages, not things the application sets. - */ - void initState() { - mIndex = -1; - mWho = null; - mAdded = false; - mRemoving = false; - mFromLayout = false; - mInLayout = false; - mRestored = false; - mBackStackNesting = 0; - mFragmentManager = null; - mChildFragmentManager = null; - mHost = null; - mFragmentId = 0; - mContainerId = 0; - mTag = null; - mHidden = false; - mDetached = false; - mRetaining = false; - mLoaderManager = null; - mLoadersStarted = false; - mCheckedForLoaderManager = false; - } - - /** - * Called when the fragment is no longer attached to its activity. This - * is called after {@link #onDestroy()}. - */ - public void onDetach() { - mCalled = true; - } - - /** - * Initialize the contents of the Activity's standard options menu. You - * should place your menu items in to menu. For this method - * to be called, you must have first called {@link #setHasOptionsMenu}. See - * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu} - * for more information. - * - * @param menu The options menu in which you place your items. - * - * @see #setHasOptionsMenu - * @see #onPrepareOptionsMenu - * @see #onOptionsItemSelected - */ - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - } - - /** - * Prepare the Screen's standard options menu to be displayed. This is - * called right before the menu is shown, every time it is shown. You can - * use this method to efficiently enable/disable items or otherwise - * dynamically modify the contents. See - * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu} - * for more information. - * - * @param menu The options menu as last shown or first initialized by - * onCreateOptionsMenu(). - * - * @see #setHasOptionsMenu - * @see #onCreateOptionsMenu - */ - public void onPrepareOptionsMenu(Menu menu) { - } - - /** - * Called when this fragment's option menu items are no longer being - * included in the overall options menu. Receiving this call means that - * the menu needed to be rebuilt, but this fragment's items were not - * included in the newly built menu (its {@link #onCreateOptionsMenu(Menu, MenuInflater)} - * was not called). - */ - public void onDestroyOptionsMenu() { - } - - /** - * This hook is called whenever an item in your options menu is selected. - * The default implementation simply returns false to have the normal - * processing happen (calling the item's Runnable or sending a message to - * its Handler as appropriate). You can use this method for any items - * for which you would like to do processing without those other - * facilities. - * - *

Derived classes should call through to the base class for it to - * perform the default menu handling. - * - * @param item The menu item that was selected. - * - * @return boolean Return false to allow normal menu processing to - * proceed, true to consume it here. - * - * @see #onCreateOptionsMenu - */ - public boolean onOptionsItemSelected(MenuItem item) { - return false; - } - - /** - * This hook is called whenever the options menu is being closed (either by the user canceling - * the menu with the back/menu button, or when an item is selected). - * - * @param menu The options menu as last shown or first initialized by - * onCreateOptionsMenu(). - */ - public void onOptionsMenuClosed(Menu menu) { - } - - /** - * Called when a context menu for the {@code view} is about to be shown. - * Unlike {@link #onCreateOptionsMenu}, this will be called every - * time the context menu is about to be shown and should be populated for - * the view (or item inside the view for {@link AdapterView} subclasses, - * this can be found in the {@code menuInfo})). - *

- * Use {@link #onContextItemSelected(MenuItem)} to know when an - * item has been selected. - *

- * The default implementation calls up to - * {@link Activity#onCreateContextMenu Activity.onCreateContextMenu}, though - * you can not call this implementation if you don't want that behavior. - *

- * It is not safe to hold onto the context menu after this method returns. - * {@inheritDoc} - */ - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - getActivity().onCreateContextMenu(menu, v, menuInfo); - } - - /** - * Registers a context menu to be shown for the given view (multiple views - * can show the context menu). This method will set the - * {@link OnCreateContextMenuListener} on the view to this fragment, so - * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be - * called when it is time to show the context menu. - * - * @see #unregisterForContextMenu(View) - * @param view The view that should show a context menu. - */ - public void registerForContextMenu(View view) { - view.setOnCreateContextMenuListener(this); - } - - /** - * Prevents a context menu to be shown for the given view. This method will - * remove the {@link OnCreateContextMenuListener} on the view. - * - * @see #registerForContextMenu(View) - * @param view The view that should stop showing a context menu. - */ - public void unregisterForContextMenu(View view) { - view.setOnCreateContextMenuListener(null); - } - - /** - * This hook is called whenever an item in a context menu is selected. The - * default implementation simply returns false to have the normal processing - * happen (calling the item's Runnable or sending a message to its Handler - * as appropriate). You can use this method for any items for which you - * would like to do processing without those other facilities. - *

- * Use {@link MenuItem#getMenuInfo()} to get extra information set by the - * View that added this menu item. - *

- * Derived classes should call through to the base class for it to perform - * the default menu handling. - * - * @param item The context menu item that was selected. - * @return boolean Return false to allow normal context menu processing to - * proceed, true to consume it here. - */ - public boolean onContextItemSelected(MenuItem item) { - return false; - } - - /** - * When custom transitions are used with Fragments, the enter transition callback - * is called when this Fragment is attached or detached when not popping the back stack. - * - * @param callback Used to manipulate the shared element transitions on this Fragment - * when added not as a pop from the back stack. - */ - public void setEnterSharedElementCallback(SharedElementCallback callback) { - mEnterTransitionCallback = callback; - } - - /** - * When custom transitions are used with Fragments, the exit transition callback - * is called when this Fragment is attached or detached when popping the back stack. - * - * @param callback Used to manipulate the shared element transitions on this Fragment - * when added as a pop from the back stack. - */ - public void setExitSharedElementCallback(SharedElementCallback callback) { - mExitTransitionCallback = callback; - } - - /** - * Sets the Transition that will be used to move Views into the initial scene. The entering - * Views will be those that are regular Views or ViewGroups that have - * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend - * {@link android.transition.Visibility} as entering is governed by changing visibility from - * {@link View#INVISIBLE} to {@link View#VISIBLE}. If transition is null, - * entering Views will remain unaffected. - * - * @param transition The Transition to use to move Views into the initial Scene. - */ - public void setEnterTransition(Object transition) { - mEnterTransition = transition; - } - - /** - * Returns the Transition that will be used to move Views into the initial scene. The entering - * Views will be those that are regular Views or ViewGroups that have - * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend - * {@link android.transition.Visibility} as entering is governed by changing visibility from - * {@link View#INVISIBLE} to {@link View#VISIBLE}. - * - * @return the Transition to use to move Views into the initial Scene. - */ - public Object getEnterTransition() { - return mEnterTransition; - } - - /** - * Sets the Transition that will be used to move Views out of the scene when the Fragment is - * preparing to be removed, hidden, or detached because of popping the back stack. The exiting - * Views will be those that are regular Views or ViewGroups that have - * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend - * {@link android.transition.Visibility} as entering is governed by changing visibility from - * {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, - * entering Views will remain unaffected. If nothing is set, the default will be to - * use the same value as set in {@link #setEnterTransition(Object)}. - * - * @param transition The Transition to use to move Views out of the Scene when the Fragment - * is preparing to close. transition must be an - * android.transition.Transition. - */ - public void setReturnTransition(Object transition) { - mReturnTransition = transition; - } - - /** - * Returns the Transition that will be used to move Views out of the scene when the Fragment is - * preparing to be removed, hidden, or detached because of popping the back stack. The exiting - * Views will be those that are regular Views or ViewGroups that have - * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend - * {@link android.transition.Visibility} as entering is governed by changing visibility from - * {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, - * entering Views will remain unaffected. - * - * @return the Transition to use to move Views out of the Scene when the Fragment - * is preparing to close. - */ - public Object getReturnTransition() { - return mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition() - : mReturnTransition; - } - - /** - * Sets the Transition that will be used to move Views out of the scene when the - * fragment is removed, hidden, or detached when not popping the back stack. - * The exiting Views will be those that are regular Views or ViewGroups that - * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend - * {@link android.transition.Visibility} as exiting is governed by changing visibility - * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will - * remain unaffected. - * - * @param transition The Transition to use to move Views out of the Scene when the Fragment - * is being closed not due to popping the back stack. transition - * must be an android.transition.Transition. - */ - public void setExitTransition(Object transition) { - mExitTransition = transition; - } - - /** - * Returns the Transition that will be used to move Views out of the scene when the - * fragment is removed, hidden, or detached when not popping the back stack. - * The exiting Views will be those that are regular Views or ViewGroups that - * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend - * {@link android.transition.Visibility} as exiting is governed by changing visibility - * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will - * remain unaffected. - * - * @return the Transition to use to move Views out of the Scene when the Fragment - * is being closed not due to popping the back stack. - */ - public Object getExitTransition() { - return mExitTransition; - } - - /** - * Sets the Transition that will be used to move Views in to the scene when returning due - * to popping a back stack. The entering Views will be those that are regular Views - * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions - * will extend {@link android.transition.Visibility} as exiting is governed by changing - * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, - * the views will remain unaffected. If nothing is set, the default will be to use the same - * transition as {@link #setExitTransition(Object)}. - * - * @param transition The Transition to use to move Views into the scene when reentering from a - * previously-started Activity. transition - * must be an android.transition.Transition. - */ - public void setReenterTransition(Object transition) { - mReenterTransition = transition; - } - - /** - * Returns the Transition that will be used to move Views in to the scene when returning due - * to popping a back stack. The entering Views will be those that are regular Views - * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions - * will extend {@link android.transition.Visibility} as exiting is governed by changing - * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, - * the views will remain unaffected. If nothing is set, the default will be to use the same - * transition as {@link #setExitTransition(Object)}. - * - * @return the Transition to use to move Views into the scene when reentering from a - * previously-started Activity. - */ - public Object getReenterTransition() { - return mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition() - : mReenterTransition; - } - - /** - * Sets the Transition that will be used for shared elements transferred into the content - * Scene. Typical Transitions will affect size and location, such as - * {@link android.transition.ChangeBounds}. A null - * value will cause transferred shared elements to blink to the final position. - * - * @param transition The Transition to use for shared elements transferred into the content - * Scene. transition must be an android.transition.Transition. - */ - public void setSharedElementEnterTransition(Object transition) { - mSharedElementEnterTransition = transition; - } - - /** - * Returns the Transition that will be used for shared elements transferred into the content - * Scene. Typical Transitions will affect size and location, such as - * {@link android.transition.ChangeBounds}. A null - * value will cause transferred shared elements to blink to the final position. - * - * @return The Transition to use for shared elements transferred into the content - * Scene. - */ - public Object getSharedElementEnterTransition() { - return mSharedElementEnterTransition; - } - - /** - * Sets the Transition that will be used for shared elements transferred back during a - * pop of the back stack. This Transition acts in the leaving Fragment. - * Typical Transitions will affect size and location, such as - * {@link android.transition.ChangeBounds}. A null - * value will cause transferred shared elements to blink to the final position. - * If no value is set, the default will be to use the same value as - * {@link #setSharedElementEnterTransition(Object)}. - * - * @param transition The Transition to use for shared elements transferred out of the content - * Scene. transition must be an android.transition.Transition. - */ - public void setSharedElementReturnTransition(Object transition) { - mSharedElementReturnTransition = transition; - } - - /** - * Return the Transition that will be used for shared elements transferred back during a - * pop of the back stack. This Transition acts in the leaving Fragment. - * Typical Transitions will affect size and location, such as - * {@link android.transition.ChangeBounds}. A null - * value will cause transferred shared elements to blink to the final position. - * If no value is set, the default will be to use the same value as - * {@link #setSharedElementEnterTransition(Object)}. - * - * @return The Transition to use for shared elements transferred out of the content - * Scene. - */ - public Object getSharedElementReturnTransition() { - return mSharedElementReturnTransition == USE_DEFAULT_TRANSITION ? - getSharedElementEnterTransition() : mSharedElementReturnTransition; - } - - /** - * Sets whether the the exit transition and enter transition overlap or not. - * When true, the enter transition will start as soon as possible. When false, the - * enter transition will wait until the exit transition completes before starting. - * - * @param allow true to start the enter transition when possible or false to - * wait until the exiting transition completes. - */ - public void setAllowEnterTransitionOverlap(boolean allow) { - mAllowEnterTransitionOverlap = allow; - } - - /** - * Returns whether the the exit transition and enter transition overlap or not. - * When true, the enter transition will start as soon as possible. When false, the - * enter transition will wait until the exit transition completes before starting. - * - * @return true when the enter transition should start as soon as possible or false to - * when it should wait until the exiting transition completes. - */ - public boolean getAllowEnterTransitionOverlap() { - return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap; - } - - /** - * Sets whether the the return transition and reenter transition overlap or not. - * When true, the reenter transition will start as soon as possible. When false, the - * reenter transition will wait until the return transition completes before starting. - * - * @param allow true to start the reenter transition when possible or false to wait until the - * return transition completes. - */ - public void setAllowReturnTransitionOverlap(boolean allow) { - mAllowReturnTransitionOverlap = allow; - } - - /** - * Returns whether the the return transition and reenter transition overlap or not. - * When true, the reenter transition will start as soon as possible. When false, the - * reenter transition will wait until the return transition completes before starting. - * - * @return true to start the reenter transition when possible or false to wait until the - * return transition completes. - */ - public boolean getAllowReturnTransitionOverlap() { - return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap; - } - - /** - * Print the Fragments's state into the given stream. - * - * @param prefix Text to print at the front of each line. - * @param fd The raw file descriptor that the dump is being sent to. - * @param writer The PrintWriter to which you should dump your state. This will be - * closed for you after you return. - * @param args additional arguments to the dump request. - */ - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - writer.print(prefix); writer.print("mFragmentId=#"); - writer.print(Integer.toHexString(mFragmentId)); - writer.print(" mContainerId=#"); - writer.print(Integer.toHexString(mContainerId)); - writer.print(" mTag="); writer.println(mTag); - writer.print(prefix); writer.print("mState="); writer.print(mState); - writer.print(" mIndex="); writer.print(mIndex); - writer.print(" mWho="); writer.print(mWho); - writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); - writer.print(prefix); writer.print("mAdded="); writer.print(mAdded); - writer.print(" mRemoving="); writer.print(mRemoving); - writer.print(" mFromLayout="); writer.print(mFromLayout); - writer.print(" mInLayout="); writer.println(mInLayout); - writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); - writer.print(" mDetached="); writer.print(mDetached); - writer.print(" mMenuVisible="); writer.print(mMenuVisible); - writer.print(" mHasMenu="); writer.println(mHasMenu); - writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance); - writer.print(" mRetaining="); writer.print(mRetaining); - writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint); - if (mFragmentManager != null) { - writer.print(prefix); writer.print("mFragmentManager="); - writer.println(mFragmentManager); - } - if (mHost != null) { - writer.print(prefix); writer.print("mHost="); - writer.println(mHost); - } - if (mParentFragment != null) { - writer.print(prefix); writer.print("mParentFragment="); - writer.println(mParentFragment); - } - if (mArguments != null) { - writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); - } - if (mSavedFragmentState != null) { - writer.print(prefix); writer.print("mSavedFragmentState="); - writer.println(mSavedFragmentState); - } - if (mSavedViewState != null) { - writer.print(prefix); writer.print("mSavedViewState="); - writer.println(mSavedViewState); - } - if (mTarget != null) { - writer.print(prefix); writer.print("mTarget="); writer.print(mTarget); - writer.print(" mTargetRequestCode="); - writer.println(mTargetRequestCode); - } - if (mNextAnim != 0) { - writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim); - } - if (mContainer != null) { - writer.print(prefix); writer.print("mContainer="); writer.println(mContainer); - } - if (mView != null) { - writer.print(prefix); writer.print("mView="); writer.println(mView); - } - if (mInnerView != null) { - writer.print(prefix); writer.print("mInnerView="); writer.println(mView); - } - if (mAnimatingAway != null) { - writer.print(prefix); writer.print("mAnimatingAway="); writer.println(mAnimatingAway); - writer.print(prefix); writer.print("mStateAfterAnimating="); - writer.println(mStateAfterAnimating); - } - if (mLoaderManager != null) { - writer.print(prefix); writer.println("Loader Manager:"); - mLoaderManager.dump(prefix + " ", fd, writer, args); - } - if (mChildFragmentManager != null) { - writer.print(prefix); writer.println("Child " + mChildFragmentManager + ":"); - mChildFragmentManager.dump(prefix + " ", fd, writer, args); - } - } - - Fragment findFragmentByWho(String who) { - if (who.equals(mWho)) { - return this; - } - if (mChildFragmentManager != null) { - return mChildFragmentManager.findFragmentByWho(who); - } - return null; - } - - void instantiateChildFragmentManager() { - mChildFragmentManager = new FragmentManagerImpl(); - mChildFragmentManager.attachController(mHost, new FragmentContainer() { - @Override - @Nullable - public View onFindViewById(int id) { - if (mView == null) { - throw new IllegalStateException("Fragment does not have a view"); - } - return mView.findViewById(id); - } - - @Override - public boolean onHasView() { - return (mView != null); - } - }, this); - } - - void performCreate(Bundle savedInstanceState) { - if (mChildFragmentManager != null) { - mChildFragmentManager.noteStateNotSaved(); - } - mState = CREATED; - mCalled = false; - onCreate(savedInstanceState); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onCreate()"); - } - if (savedInstanceState != null) { - Parcelable p = savedInstanceState.getParcelable( - FragmentActivity.FRAGMENTS_TAG); - if (p != null) { - if (mChildFragmentManager == null) { - instantiateChildFragmentManager(); - } - mChildFragmentManager.restoreAllState(p, null); - mChildFragmentManager.dispatchCreate(); - } - } - } - - View performCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - if (mChildFragmentManager != null) { - mChildFragmentManager.noteStateNotSaved(); - } - return onCreateView(inflater, container, savedInstanceState); - } - - void performActivityCreated(Bundle savedInstanceState) { - if (mChildFragmentManager != null) { - mChildFragmentManager.noteStateNotSaved(); - } - mState = ACTIVITY_CREATED; - mCalled = false; - onActivityCreated(savedInstanceState); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onActivityCreated()"); - } - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchActivityCreated(); - } - } - - void performStart() { - if (mChildFragmentManager != null) { - mChildFragmentManager.noteStateNotSaved(); - mChildFragmentManager.execPendingActions(); - } - mState = STARTED; - mCalled = false; - onStart(); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onStart()"); - } - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchStart(); - } - if (mLoaderManager != null) { - mLoaderManager.doReportStart(); - } - } - - void performResume() { - if (mChildFragmentManager != null) { - mChildFragmentManager.noteStateNotSaved(); - mChildFragmentManager.execPendingActions(); - } - mState = RESUMED; - mCalled = false; - onResume(); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onResume()"); - } - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchResume(); - mChildFragmentManager.execPendingActions(); - } - } - - void performConfigurationChanged(Configuration newConfig) { - onConfigurationChanged(newConfig); - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchConfigurationChanged(newConfig); - } - } - - void performLowMemory() { - onLowMemory(); - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchLowMemory(); - } - } - - /* - void performTrimMemory(int level) { - onTrimMemory(level); - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchTrimMemory(level); - } - } - */ - - boolean performCreateOptionsMenu(Menu menu, MenuInflater inflater) { - boolean show = false; - if (!mHidden) { - if (mHasMenu && mMenuVisible) { - show = true; - onCreateOptionsMenu(menu, inflater); - } - if (mChildFragmentManager != null) { - show |= mChildFragmentManager.dispatchCreateOptionsMenu(menu, inflater); - } - } - return show; - } - - boolean performPrepareOptionsMenu(Menu menu) { - boolean show = false; - if (!mHidden) { - if (mHasMenu && mMenuVisible) { - show = true; - onPrepareOptionsMenu(menu); - } - if (mChildFragmentManager != null) { - show |= mChildFragmentManager.dispatchPrepareOptionsMenu(menu); - } - } - return show; - } - - boolean performOptionsItemSelected(MenuItem item) { - if (!mHidden) { - if (mHasMenu && mMenuVisible) { - if (onOptionsItemSelected(item)) { - return true; - } - } - if (mChildFragmentManager != null) { - if (mChildFragmentManager.dispatchOptionsItemSelected(item)) { - return true; - } - } - } - return false; - } - - boolean performContextItemSelected(MenuItem item) { - if (!mHidden) { - if (onContextItemSelected(item)) { - return true; - } - if (mChildFragmentManager != null) { - if (mChildFragmentManager.dispatchContextItemSelected(item)) { - return true; - } - } - } - return false; - } - - void performOptionsMenuClosed(Menu menu) { - if (!mHidden) { - if (mHasMenu && mMenuVisible) { - onOptionsMenuClosed(menu); - } - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchOptionsMenuClosed(menu); - } - } - } - - void performSaveInstanceState(Bundle outState) { - onSaveInstanceState(outState); - if (mChildFragmentManager != null) { - Parcelable p = mChildFragmentManager.saveAllState(); - if (p != null) { - outState.putParcelable(FragmentActivity.FRAGMENTS_TAG, p); - } - } - } - - void performPause() { - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchPause(); - } - mState = STARTED; - mCalled = false; - onPause(); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onPause()"); - } - } - - void performStop() { - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchStop(); - } - mState = STOPPED; - mCalled = false; - onStop(); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onStop()"); - } - } - - void performReallyStop() { - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchReallyStop(); - } - mState = ACTIVITY_CREATED; - if (mLoadersStarted) { - mLoadersStarted = false; - if (!mCheckedForLoaderManager) { - mCheckedForLoaderManager = true; - mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); - } - if (mLoaderManager != null) { - if (mHost.getRetainLoaders()) { - mLoaderManager.doRetain(); - } else { - mLoaderManager.doStop(); - } - } - } - } - - void performDestroyView() { - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchDestroyView(); - } - mState = CREATED; - mCalled = false; - onDestroyView(); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onDestroyView()"); - } - if (mLoaderManager != null) { - mLoaderManager.doReportNextStart(); - } - } - - void performDestroy() { - if (mChildFragmentManager != null) { - mChildFragmentManager.dispatchDestroy(); - } - mState = INITIALIZING; - mCalled = false; - onDestroy(); - if (!mCalled) { - throw new SuperNotCalledException("Fragment " + this - + " did not call through to super.onDestroy()"); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentActivity.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentActivity.java deleted file mode 100644 index fd05c6c..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentActivity.java +++ /dev/null @@ -1,1039 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Parcelable; -import p.android.support.v4.content.Loader; -import p.android.support.v4.media.session.MediaControllerCompat; -import p.android.support.v4.media.session.MediaSessionCompat; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.v4.util.SimpleArrayMap; -import p.android.support.v4.util.SparseArrayCompat; -import android.util.Log; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; - -/** - * Base class for activities that want to use the support-based - * {@link Fragment} and - * {@link Loader} APIs. - * - *

When using this class as opposed to new platform's built-in fragment - * and loader support, you must use the {@link #getSupportFragmentManager()} - * and {@link #getSupportLoaderManager()} methods respectively to access - * those features. - * - *

Note: If you want to implement an activity that includes - * an action bar, you should instead use - * the {@link android.support.v7.app.ActionBarActivity} class, which is a subclass of this one, - * so allows you to use {@link Fragment} APIs on API level 7 and higher.

- * - *

Known limitations:

- *
    - *
  • When using the <fragment> tag, this implementation can not - * use the parent view's ID as the new fragment's ID. You must explicitly - * specify an ID (or tag) in the <fragment>.

    - *
  • Prior to Honeycomb (3.0), an activity's state was saved before pausing. - * Fragments are a significant amount of new state, and dynamic enough that one - * often wants them to change between pausing and stopping. These classes - * throw an exception if you try to change the fragment state after it has been - * saved, to avoid accidental loss of UI state. However this is too restrictive - * prior to Honeycomb, where the state is saved before pausing. To address this, - * when running on platforms prior to Honeycomb an exception will not be thrown - * if you change fragments between the state save and the activity being stopped. - * This means that in some cases if the activity is restored from its last saved - * state, this may be a snapshot slightly before what the user last saw.

    - *
- */ -public class FragmentActivity extends BaseFragmentActivityHoneycomb implements - ActivityCompat.OnRequestPermissionsResultCallback, - ActivityCompatApi23.RequestPermissionsRequestCodeValidator { - private static final String TAG = "FragmentActivity"; - - static final String FRAGMENTS_TAG = "android:support:fragments"; - static final String NEXT_CANDIDATE_REQUEST_INDEX_TAG = "android:support:next_request_index"; - static final String ALLOCATED_REQUEST_INDICIES_TAG = "android:support:request_indicies"; - static final String REQUEST_FRAGMENT_WHO_TAG = "android:support:request_fragment_who"; - static final int MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS = 0xffff - 1; - - // This is the SDK API version of Honeycomb (3.0). - private static final int HONEYCOMB = 11; - - static final int MSG_REALLY_STOPPED = 1; - static final int MSG_RESUME_PENDING = 2; - - final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_REALLY_STOPPED: - if (mStopped) { - doReallyStop(false); - } - break; - case MSG_RESUME_PENDING: - onResumeFragments(); - mFragments.execPendingActions(); - break; - default: - super.handleMessage(msg); - } - } - - }; - final FragmentController mFragments = FragmentController.createController(new HostCallbacks()); - - boolean mCreated; - boolean mResumed; - boolean mStopped; - boolean mReallyStopped; - boolean mRetaining; - - boolean mOptionsMenuInvalidated; - boolean mRequestedPermissionsFromFragment; - - // A hint for the next candidate request index. Request indicies are ints between 0 and 2^16-1 - // which are encoded into the upper 16 bits of the requestCode for - // Fragment.startActivityForResult(...) calls. This allows us to dispatch onActivityResult(...) - // to the appropriate Fragment. Request indicies are allocated by allocateRequestIndex(...). - int mNextCandidateRequestIndex; - // We need to keep track of whether startActivityForResult originated from a Fragment, so we - // can conditionally check whether the requestCode collides with our reserved ID space for the - // request index (see above). Unfortunately we can't just call - // super.startActivityForResult(...) to bypass the check when the call didn't come from a - // fragment, since we need to use the ActivityCompat version for backward compatibility. - boolean mStartedActivityFromFragment; - // A map from request index to Fragment "who" (i.e. a Fragment's unique identifier). Used to - // keep track of the originating Fragment for Fragment.startActivityForResult(...) calls, so we - // can dispatch the onActivityResult(...) to the appropriate Fragment. Will only contain entries - // for startActivityForResult calls where a result has not yet been delivered. - SparseArrayCompat mPendingFragmentActivityResults; - - static final class NonConfigurationInstances { - Object custom; - List fragments; - SimpleArrayMap loaders; - } - - MediaControllerCompat mMediaController; - - // ------------------------------------------------------------------------ - // HOOKS INTO ACTIVITY - // ------------------------------------------------------------------------ - - /** - * Dispatch incoming result to the correct fragment. - */ - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - mFragments.noteStateNotSaved(); - int requestIndex = requestCode>>16; - if (requestIndex != 0) { - requestIndex--; - - String who = mPendingFragmentActivityResults.get(requestIndex); - mPendingFragmentActivityResults.remove(requestIndex); - if (who == null) { - Log.w(TAG, "Activity result delivered for unknown Fragment."); - return; - } - Fragment targetFragment = mFragments.findFragmentByWho(who); - if (targetFragment == null) { - Log.w(TAG, "Activity result no fragment exists for who: " + who); - } else { - targetFragment.onActivityResult(requestCode&0xffff, resultCode, data); - } - return; - } - - super.onActivityResult(requestCode, resultCode, data); - } - - - - /** - * Sets a {@link MediaControllerCompat} for later retrieval via - * {@link #getSupportMediaController()}. - * - *

On API 21 and later, this controller will be tied to the window of the activity and - * media key and volume events which are received while the Activity is in the foreground - * will be forwarded to the controller and used to invoke transport controls or adjust the - * volume. Prior to API 21, the global handling of media key and volume events through an - * active {@link MediaSessionCompat} and media button receiver - * will still be respected.

- * - * @param mediaController The controller for the session which should receive - * media keys and volume changes on API 21 and later. - * @see #setMediaController(android.media.session.MediaController) - */ - final public void setSupportMediaController(MediaControllerCompat mediaController) { - mMediaController = mediaController; - if (android.os.Build.VERSION.SDK_INT >= 21) { - ActivityCompat21.setMediaController(this, mediaController.getMediaController()); - } - } - - /** - * Retrieves the current {@link MediaControllerCompat} for sending media key and volume events. - * - * @return The controller which should receive events. - * @see #setSupportMediaController(android.support.v4.media.session.MediaController) - * @see #getMediaController() - */ - final public MediaControllerCompat getSupportMediaController() { - return mMediaController; - } - - /** - * Reverses the Activity Scene entry Transition and triggers the calling Activity - * to reverse its exit Transition. When the exit Transition completes, - * {@link #finish()} is called. If no entry Transition was used, finish() is called - * immediately and the Activity exit Transition is run. - * - *

On Android 4.4 or lower, this method only finishes the Activity with no - * special exit transition.

- */ - public void supportFinishAfterTransition() { - ActivityCompat.finishAfterTransition(this); - } - - /** - * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, - * View, String)} was used to start an Activity, callback - * will be called to handle shared elements on the launched Activity. This requires - * {@link Window#FEATURE_CONTENT_TRANSITIONS}. - * - * @param callback Used to manipulate shared element transitions on the launched Activity. - */ - public void setEnterSharedElementCallback(SharedElementCallback callback) { - ActivityCompat.setEnterSharedElementCallback(this, callback); - } - - /** - * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, - * View, String)} was used to start an Activity, listener - * will be called to handle shared elements on the launching Activity. Most - * calls will only come when returning from the started Activity. - * This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}. - * - * @param listener Used to manipulate shared element transitions on the launching Activity. - */ - public void setExitSharedElementCallback(SharedElementCallback listener) { - ActivityCompat.setExitSharedElementCallback(this, listener); - } - - /** - * Support library version of {@link Activity#postponeEnterTransition()} that works - * only on API 21 and later. - */ - public void supportPostponeEnterTransition() { - ActivityCompat.postponeEnterTransition(this); - } - - /** - * Support library version of {@link Activity#startPostponedEnterTransition()} - * that only works with API 21 and later. - */ - public void supportStartPostponedEnterTransition() { - ActivityCompat.startPostponedEnterTransition(this); - } - - /** - * Dispatch configuration change to all fragments. - */ - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mFragments.dispatchConfigurationChanged(newConfig); - } - - /** - * Perform initialization of all fragments and loaders. - */ - @SuppressWarnings("deprecation") - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - mFragments.attachHost(null /*parent*/); - - super.onCreate(savedInstanceState); - - NonConfigurationInstances nc = - (NonConfigurationInstances) getLastNonConfigurationInstance(); - if (nc != null) { - mFragments.restoreLoaderNonConfig(nc.loaders); - } - if (savedInstanceState != null) { - Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); - mFragments.restoreAllState(p, nc != null ? nc.fragments : null); - - // Check if there are any pending onActivityResult calls to descendent Fragments. - if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) { - mNextCandidateRequestIndex = - savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG); - int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG); - String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG); - if (requestCodes == null || fragmentWhos == null || - requestCodes.length != fragmentWhos.length) { - Log.w(TAG, "Invalid requestCode mapping in savedInstanceState."); - } else { - mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length); - for (int i = 0; i < requestCodes.length; i++) { - mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]); - } - } - } - } - - if (mPendingFragmentActivityResults == null) { - mPendingFragmentActivityResults = new SparseArrayCompat<>(); - mNextCandidateRequestIndex = 0; - } - - mFragments.dispatchCreate(); - } - - /** - * Dispatch to Fragment.onCreateOptionsMenu(). - */ - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - boolean show = super.onCreatePanelMenu(featureId, menu); - show |= mFragments.dispatchCreateOptionsMenu(menu, getMenuInflater()); - if (android.os.Build.VERSION.SDK_INT >= HONEYCOMB) { - return show; - } - // Prior to Honeycomb, the framework can't invalidate the options - // menu, so we must always say we have one in case the app later - // invalidates it and needs to have it shown. - return true; - } - return super.onCreatePanelMenu(featureId, menu); - } - - /** - * Destroy all fragments and loaders. - */ - @Override - protected void onDestroy() { - super.onDestroy(); - - doReallyStop(false); - - mFragments.dispatchDestroy(); - mFragments.doLoaderDestroy(); - } - - /** - * Take care of calling onBackPressed() for pre-Eclair platforms. - */ - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (android.os.Build.VERSION.SDK_INT < 5 /* ECLAIR */ - && keyCode == KeyEvent.KEYCODE_BACK - && event.getRepeatCount() == 0) { - // Take care of calling this method on earlier versions of - // the platform where it doesn't exist. - onBackPressed(); - return true; - } - - return super.onKeyDown(keyCode, event); - } - - /** - * Dispatch onLowMemory() to all fragments. - */ - @Override - public void onLowMemory() { - super.onLowMemory(); - mFragments.dispatchLowMemory(); - } - - /** - * Dispatch context and options menu to fragments. - */ - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (super.onMenuItemSelected(featureId, item)) { - return true; - } - - switch (featureId) { - case Window.FEATURE_OPTIONS_PANEL: - return mFragments.dispatchOptionsItemSelected(item); - - case Window.FEATURE_CONTEXT_MENU: - return mFragments.dispatchContextItemSelected(item); - - default: - return false; - } - } - - /** - * Call onOptionsMenuClosed() on fragments. - */ - @Override - public void onPanelClosed(int featureId, Menu menu) { - switch (featureId) { - case Window.FEATURE_OPTIONS_PANEL: - mFragments.dispatchOptionsMenuClosed(menu); - break; - } - super.onPanelClosed(featureId, menu); - } - - /** - * Dispatch onPause() to fragments. - */ - @Override - protected void onPause() { - super.onPause(); - mResumed = false; - if (mHandler.hasMessages(MSG_RESUME_PENDING)) { - mHandler.removeMessages(MSG_RESUME_PENDING); - onResumeFragments(); - } - mFragments.dispatchPause(); - } - - /** - * Handle onNewIntent() to inform the fragment manager that the - * state is not saved. If you are handling new intents and may be - * making changes to the fragment state, you want to be sure to call - * through to the super-class here first. Otherwise, if your state - * is saved but the activity is not stopped, you could get an - * onNewIntent() call which happens before onResume() and trying to - * perform fragment operations at that point will throw IllegalStateException - * because the fragment manager thinks the state is still saved. - */ - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - mFragments.noteStateNotSaved(); - } - - /** - * Hook in to note that fragment state is no longer saved. - */ - public void onStateNotSaved() { - mFragments.noteStateNotSaved(); - } - - /** - * Dispatch onResume() to fragments. Note that for better inter-operation - * with older versions of the platform, at the point of this call the - * fragments attached to the activity are not resumed. This means - * that in some cases the previous state may still be saved, not allowing - * fragment transactions that modify the state. To correctly interact - * with fragments in their proper state, you should instead override - * {@link #onResumeFragments()}. - */ - @Override - protected void onResume() { - super.onResume(); - mHandler.sendEmptyMessage(MSG_RESUME_PENDING); - mResumed = true; - mFragments.execPendingActions(); - } - - /** - * Dispatch onResume() to fragments. - */ - @Override - protected void onPostResume() { - super.onPostResume(); - mHandler.removeMessages(MSG_RESUME_PENDING); - onResumeFragments(); - mFragments.execPendingActions(); - } - - /** - * This is the fragment-orientated version of {@link #onResume()} that you - * can override to perform operations in the Activity at the same point - * where its fragments are resumed. Be sure to always call through to - * the super-class. - */ - protected void onResumeFragments() { - mFragments.dispatchResume(); - } - - /** - * Dispatch onPrepareOptionsMenu() to fragments. - */ - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) { - if (mOptionsMenuInvalidated) { - mOptionsMenuInvalidated = false; - menu.clear(); - onCreatePanelMenu(featureId, menu); - } - boolean goforit = onPrepareOptionsPanel(view, menu); - goforit |= mFragments.dispatchPrepareOptionsMenu(menu); - return goforit; - } - return super.onPreparePanel(featureId, view, menu); - } - - /** - * @hide - */ - protected boolean onPrepareOptionsPanel(View view, Menu menu) { - return super.onPreparePanel(Window.FEATURE_OPTIONS_PANEL, view, menu); - } - - /** - * Retain all appropriate fragment and loader state. You can NOT - * override this yourself! Use {@link #onRetainCustomNonConfigurationInstance()} - * if you want to retain your own state. - */ - @Override - public final Object onRetainNonConfigurationInstance() { - if (mStopped) { - doReallyStop(true); - } - - Object custom = onRetainCustomNonConfigurationInstance(); - - List fragments = mFragments.retainNonConfig(); - SimpleArrayMap loaders = mFragments.retainLoaderNonConfig(); - - if (fragments == null && loaders == null && custom == null) { - return null; - } - - NonConfigurationInstances nci = new NonConfigurationInstances(); - nci.custom = custom; - nci.fragments = fragments; - nci.loaders = loaders; - return nci; - } - - /** - * Save all appropriate fragment state. - */ - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - Parcelable p = mFragments.saveAllState(); - if (p != null) { - outState.putParcelable(FRAGMENTS_TAG, p); - } - if (mPendingFragmentActivityResults.size() > 0) { - outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG, mNextCandidateRequestIndex); - - int[] requestCodes = new int[mPendingFragmentActivityResults.size()]; - String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()]; - for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) { - requestCodes[i] = mPendingFragmentActivityResults.keyAt(i); - fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i); - } - outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes); - outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos); - } - } - - /** - * Dispatch onStart() to all fragments. Ensure any created loaders are - * now started. - */ - @Override - protected void onStart() { - super.onStart(); - - mStopped = false; - mReallyStopped = false; - mHandler.removeMessages(MSG_REALLY_STOPPED); - - if (!mCreated) { - mCreated = true; - mFragments.dispatchActivityCreated(); - } - - mFragments.noteStateNotSaved(); - mFragments.execPendingActions(); - - mFragments.doLoaderStart(); - - // NOTE: HC onStart goes here. - - mFragments.dispatchStart(); - mFragments.reportLoaderStart(); - } - - /** - * Dispatch onStop() to all fragments. Ensure all loaders are stopped. - */ - @Override - protected void onStop() { - super.onStop(); - - mStopped = true; - mHandler.sendEmptyMessage(MSG_REALLY_STOPPED); - - mFragments.dispatchStop(); - } - - // ------------------------------------------------------------------------ - // NEW METHODS - // ------------------------------------------------------------------------ - - /** - * Use this instead of {@link #onRetainNonConfigurationInstance()}. - * Retrieve later with {@link #getLastCustomNonConfigurationInstance()}. - */ - public Object onRetainCustomNonConfigurationInstance() { - return null; - } - - /** - * Return the value previously returned from - * {@link #onRetainCustomNonConfigurationInstance()}. - */ - @SuppressWarnings("deprecation") - public Object getLastCustomNonConfigurationInstance() { - NonConfigurationInstances nc = (NonConfigurationInstances) - getLastNonConfigurationInstance(); - return nc != null ? nc.custom : null; - } - - /** - * Support library version of {@link Activity#invalidateOptionsMenu}. - * - *

Invalidate the activity's options menu. This will cause relevant presentations - * of the menu to fully update via calls to onCreateOptionsMenu and - * onPrepareOptionsMenu the next time the menu is requested. - */ - public void supportInvalidateOptionsMenu() { - if (android.os.Build.VERSION.SDK_INT >= HONEYCOMB) { - // If we are running on HC or greater, we can use the framework - // API to invalidate the options menu. - ActivityCompatHoneycomb.invalidateOptionsMenu(this); - return; - } - - // Whoops, older platform... we'll use a hack, to manually rebuild - // the options menu the next time it is prepared. - mOptionsMenuInvalidated = true; - } - - /** - * Print the Activity's state into the given stream. This gets invoked if - * you run "adb shell dumpsys activity ". - * - * @param prefix Desired prefix to prepend at each line of output. - * @param fd The raw file descriptor that the dump is being sent to. - * @param writer The PrintWriter to which you should dump your state. This will be - * closed for you after you return. - * @param args additional arguments to the dump request. - */ - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - if (android.os.Build.VERSION.SDK_INT >= HONEYCOMB) { - // XXX This can only work if we can call the super-class impl. :/ - //ActivityCompatHoneycomb.dump(this, prefix, fd, writer, args); - } - writer.print(prefix); writer.print("Local FragmentActivity "); - writer.print(Integer.toHexString(System.identityHashCode(this))); - writer.println(" State:"); - String innerPrefix = prefix + " "; - writer.print(innerPrefix); writer.print("mCreated="); - writer.print(mCreated); writer.print("mResumed="); - writer.print(mResumed); writer.print(" mStopped="); - writer.print(mStopped); writer.print(" mReallyStopped="); - writer.println(mReallyStopped); - mFragments.dumpLoaders(innerPrefix, fd, writer, args); - mFragments.getSupportFragmentManager().dump(prefix, fd, writer, args); - writer.print(prefix); writer.println("View Hierarchy:"); - dumpViewHierarchy(prefix + " ", writer, getWindow().getDecorView()); - } - - private static String viewToString(View view) { - StringBuilder out = new StringBuilder(128); - out.append(view.getClass().getName()); - out.append('{'); - out.append(Integer.toHexString(System.identityHashCode(view))); - out.append(' '); - switch (view.getVisibility()) { - case View.VISIBLE: out.append('V'); break; - case View.INVISIBLE: out.append('I'); break; - case View.GONE: out.append('G'); break; - default: out.append('.'); break; - } - out.append(view.isFocusable() ? 'F' : '.'); - out.append(view.isEnabled() ? 'E' : '.'); - out.append(view.willNotDraw() ? '.' : 'D'); - out.append(view.isHorizontalScrollBarEnabled()? 'H' : '.'); - out.append(view.isVerticalScrollBarEnabled() ? 'V' : '.'); - out.append(view.isClickable() ? 'C' : '.'); - out.append(view.isLongClickable() ? 'L' : '.'); - out.append(' '); - out.append(view.isFocused() ? 'F' : '.'); - out.append(view.isSelected() ? 'S' : '.'); - out.append(view.isPressed() ? 'P' : '.'); - out.append(' '); - out.append(view.getLeft()); - out.append(','); - out.append(view.getTop()); - out.append('-'); - out.append(view.getRight()); - out.append(','); - out.append(view.getBottom()); - final int id = view.getId(); - if (id != View.NO_ID) { - out.append(" #"); - out.append(Integer.toHexString(id)); - final Resources r = view.getResources(); - if (id != 0 && r != null) { - try { - String pkgname; - switch (id&0xff000000) { - case 0x7f000000: - pkgname="app"; - break; - case 0x01000000: - pkgname="android"; - break; - default: - pkgname = r.getResourcePackageName(id); - break; - } - String typename = r.getResourceTypeName(id); - String entryname = r.getResourceEntryName(id); - out.append(" "); - out.append(pkgname); - out.append(":"); - out.append(typename); - out.append("/"); - out.append(entryname); - } catch (Resources.NotFoundException e) { - } - } - } - out.append("}"); - return out.toString(); - } - - private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) { - writer.print(prefix); - if (view == null) { - writer.println("null"); - return; - } - writer.println(viewToString(view)); - if (!(view instanceof ViewGroup)) { - return; - } - ViewGroup grp = (ViewGroup)view; - final int N = grp.getChildCount(); - if (N <= 0) { - return; - } - prefix = prefix + " "; - for (int i=0; i - * Note: It is possible that the permissions request interaction - * with the user is interrupted. In this case you will receive empty permissions - * and results arrays which should be treated as a cancellation. - *

- * - * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}. - * @param permissions The requested permissions. Never null. - * @param grantResults The grant results for the corresponding permissions - * which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED} - * or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null. - * - * @see #requestPermissions(String[], int) - */ - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { - int index = (requestCode>>16)&0xffff; - if (index != 0) { - index--; - - String who = mPendingFragmentActivityResults.get(index); - mPendingFragmentActivityResults.remove(index); - if (who == null) { - Log.w(TAG, "Activity result delivered for unknown Fragment."); - return; - } - Fragment frag = mFragments.findFragmentByWho(who); - if (frag == null) { - Log.w(TAG, "Activity result no fragment exists for who: " + who); - } else { - frag.onRequestPermissionsResult(requestCode&0xffff, permissions, grantResults); - } - } - } - - /** - * Called by Fragment.startActivityForResult() to implement its behavior. - */ - public void startActivityFromFragment(Fragment fragment, Intent intent, - int requestCode) { - startActivityFromFragment(fragment, intent, requestCode, null); - } - - /** - * Called by Fragment.startActivityForResult() to implement its behavior. - */ - public void startActivityFromFragment(Fragment fragment, Intent intent, - int requestCode, @Nullable Bundle options) { - mStartedActivityFromFragment = true; - try { - if (requestCode == -1) { - ActivityCompat.startActivityForResult(this, intent, -1, options); - return; - } - if ((requestCode&0xffff0000) != 0) { - throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); - } - int requestIndex = allocateRequestIndex(fragment); - ActivityCompat.startActivityForResult( - this, intent, ((requestIndex+1)<<16) + (requestCode&0xffff), options); - } finally { - mStartedActivityFromFragment = false; - } - } - - // Allocates the next available startActivityForResult request index. - private int allocateRequestIndex(Fragment fragment) { - // Sanity check that we havn't exhaused the request index space. - if (mPendingFragmentActivityResults.size() >= MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS) { - throw new IllegalStateException("Too many pending Fragment activity results."); - } - - // Find an unallocated request index in the mPendingFragmentActivityResults map. - while (mPendingFragmentActivityResults.indexOfKey(mNextCandidateRequestIndex) >= 0) { - mNextCandidateRequestIndex = - (mNextCandidateRequestIndex + 1) % MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS; - } - - int requestIndex = mNextCandidateRequestIndex; - mPendingFragmentActivityResults.put(requestIndex, fragment.mWho); - mNextCandidateRequestIndex = - (mNextCandidateRequestIndex + 1) % MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS; - - return requestIndex; - } - - /** - * Called by Fragment.requestPermissions() to implement its behavior. - */ - private void requestPermissionsFromFragment(Fragment fragment, String[] permissions, - int requestCode) { - if (requestCode == -1) { - ActivityCompat.requestPermissions(this, permissions, requestCode); - return; - } - if ((requestCode&0xffff0000) != 0) { - throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); - } - try { - mRequestedPermissionsFromFragment = true; - int requestIndex = allocateRequestIndex(fragment); - ActivityCompat.requestPermissions(this, permissions, - ((requestIndex + 1) << 16) + (requestCode & 0xffff)); - } finally { - mRequestedPermissionsFromFragment = false; - } - } - - class HostCallbacks extends FragmentHostCallback { - public HostCallbacks() { - super(FragmentActivity.this /*fragmentActivity*/); - } - - @Override - public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - FragmentActivity.this.dump(prefix, fd, writer, args); - } - - @Override - public boolean onShouldSaveFragmentState(Fragment fragment) { - return !isFinishing(); - } - - @Override - public LayoutInflater onGetLayoutInflater() { - return FragmentActivity.this.getLayoutInflater().cloneInContext(FragmentActivity.this); - } - - @Override - public FragmentActivity onGetHost() { - return FragmentActivity.this; - } - - @Override - public void onSupportInvalidateOptionsMenu() { - FragmentActivity.this.supportInvalidateOptionsMenu(); - } - - @Override - public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { - FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode); - } - - @Override - public void onStartActivityFromFragment( - Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options) { - FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode, options); - } - - @Override - public void onRequestPermissionsFromFragment(@NonNull Fragment fragment, - @NonNull String[] permissions, int requestCode) { - FragmentActivity.this.requestPermissionsFromFragment(fragment, permissions, - requestCode); - } - - @Override - public boolean onShouldShowRequestPermissionRationale(@NonNull String permission) { - return ActivityCompat.shouldShowRequestPermissionRationale( - FragmentActivity.this, permission); - } - - @Override - public boolean onHasWindowAnimations() { - return getWindow() != null; - } - - @Override - public int onGetWindowAnimations() { - final Window w = getWindow(); - return (w == null) ? 0 : w.getAttributes().windowAnimations; - } - - @Override - public void onAttachFragment(Fragment fragment) { - FragmentActivity.this.onAttachFragment(fragment); - } - - @Nullable - @Override - public View onFindViewById(int id) { - return FragmentActivity.this.findViewById(id); - } - - @Override - public boolean onHasView() { - final Window w = getWindow(); - return (w != null && w.peekDecorView() != null); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentContainer.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentContainer.java deleted file mode 100644 index 75ac83b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentContainer.java +++ /dev/null @@ -1,23 +0,0 @@ -package p.android.support.v4.app; - -import p.android.support.annotation.IdRes; -import p.android.support.annotation.Nullable; -import android.view.View; - - -/** - * Callbacks to a {@link Fragment}'s container. - */ -public abstract class FragmentContainer { - /** - * Return the view with the given resource ID. May return {@code null} if the - * view is not a child of this container. - */ - @Nullable - public abstract View onFindViewById(@IdRes int id); - - /** - * Return {@code true} if the container holds any view. - */ - public abstract boolean onHasView(); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentController.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentController.java deleted file mode 100644 index 843300f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentController.java +++ /dev/null @@ -1,405 +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 p.android.support.v4.app; - -import android.content.Context; -import android.content.res.Configuration; -import android.os.Parcelable; -import p.android.support.annotation.Nullable; -import p.android.support.v4.util.SimpleArrayMap; -import android.util.AttributeSet; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * Provides integration points with a {@link FragmentManager} for a fragment host. - *

- * It is the responsibility of the host to take care of the Fragment's lifecycle. - * The methods provided by {@link FragmentController} are for that purpose. - */ -public class FragmentController { - private final FragmentHostCallback mHost; - - /** - * Returns a {@link FragmentController}. - */ - public static final FragmentController createController(FragmentHostCallback callbacks) { - return new FragmentController(callbacks); - } - - private FragmentController(FragmentHostCallback callbacks) { - mHost = callbacks; - } - - /** - * Returns a {@link FragmentManager} for this controller. - */ - public FragmentManager getSupportFragmentManager() { - return mHost.getFragmentManagerImpl(); - } - - /** - * Returns a {@link LoaderManager}. - */ - public LoaderManager getSupportLoaderManager() { - return mHost.getLoaderManagerImpl(); - } - - /** - * Returns a fragment with the given identifier. - */ - @Nullable - Fragment findFragmentByWho(String who) { - return mHost.mFragmentManager.findFragmentByWho(who); - } - - /** - * Returns the number of active fragments. - */ - public int getActiveFragmentsCount() { - final List actives = mHost.mFragmentManager.mActive; - return actives == null ? 0 : actives.size(); - } - - /** - * Returns the list of active fragments. - */ - public List getActiveFragments(List actives) { - if (mHost.mFragmentManager.mActive == null) { - return null; - } - if (actives == null) { - actives = new ArrayList(getActiveFragmentsCount()); - } - actives.addAll(mHost.mFragmentManager.mActive); - return actives; - } - - /** - * Attaches the host to the FragmentManager for this controller. The host must be - * attached before the FragmentManager can be used to manage Fragments. - */ - public void attachHost(Fragment parent) { - mHost.mFragmentManager.attachController( - mHost, mHost /*container*/, parent); - } - - /** - * Instantiates a Fragment's view. - * - * @param parent The parent that the created view will be placed - * in; note that this may be null. - * @param name Tag name to be inflated. - * @param context The context the view is being created in. - * @param attrs Inflation attributes as specified in XML file. - * - * @return view the newly created view - */ - public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { - return mHost.mFragmentManager.onCreateView(parent, name, context, attrs); - } - - /** - * Marks the fragment state as unsaved. This allows for "state loss" detection. - */ - public void noteStateNotSaved() { - mHost.mFragmentManager.noteStateNotSaved(); - } - - /** - * Saves the state for all Fragments. - */ - public Parcelable saveAllState() { - return mHost.mFragmentManager.saveAllState(); - } - - /** - * Restores the saved state for all Fragments. The given Fragment list are Fragment - * instances retained across configuration changes. - * - * @see #retainNonConfig() - */ - public void restoreAllState(Parcelable state, List nonConfigList) { - mHost.mFragmentManager.restoreAllState(state, nonConfigList); - } - - /** - * Returns a list of Fragments that have opted to retain their instance across - * configuration changes. - */ - public List retainNonConfig() { - return mHost.mFragmentManager.retainNonConfig(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the create state. - *

Call when Fragments should be created. - * - * @see Fragment#onCreate(Bundle) - */ - public void dispatchCreate() { - mHost.mFragmentManager.dispatchCreate(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the activity created state. - *

Call when Fragments should be informed their host has been created. - * - * @see Fragment#onActivityCreated(Bundle) - */ - public void dispatchActivityCreated() { - mHost.mFragmentManager.dispatchActivityCreated(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the start state. - *

Call when Fragments should be started. - * - * @see Fragment#onStart() - */ - public void dispatchStart() { - mHost.mFragmentManager.dispatchStart(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the resume state. - *

Call when Fragments should be resumed. - * - * @see Fragment#onResume() - */ - public void dispatchResume() { - mHost.mFragmentManager.dispatchResume(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the pause state. - *

Call when Fragments should be paused. - * - * @see Fragment#onPause() - */ - public void dispatchPause() { - mHost.mFragmentManager.dispatchPause(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the stop state. - *

Call when Fragments should be stopped. - * - * @see Fragment#onStop() - */ - public void dispatchStop() { - mHost.mFragmentManager.dispatchStop(); - } - - public void dispatchReallyStop() { - mHost.mFragmentManager.dispatchReallyStop(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the destroy view state. - *

Call when the Fragment's views should be destroyed. - * - * @see Fragment#onDestroyView() - */ - public void dispatchDestroyView() { - mHost.mFragmentManager.dispatchDestroyView(); - } - - /** - * Moves all Fragments managed by the controller's FragmentManager - * into the destroy state. - *

Call when Fragments should be destroyed. - * - * @see Fragment#onDestroy() - */ - public void dispatchDestroy() { - mHost.mFragmentManager.dispatchDestroy(); - } - - /** - * Lets all Fragments managed by the controller's FragmentManager - * know a configuration change occurred. - *

Call when there is a configuration change. - * - * @see Fragment#onConfigurationChanged(Configuration) - */ - public void dispatchConfigurationChanged(Configuration newConfig) { - mHost.mFragmentManager.dispatchConfigurationChanged(newConfig); - } - - /** - * Lets all Fragments managed by the controller's FragmentManager - * know the device is in a low memory condition. - *

Call when the device is low on memory and Fragment's should trim - * their memory usage. - * - * @see Fragment#onLowMemory() - */ - public void dispatchLowMemory() { - mHost.mFragmentManager.dispatchLowMemory(); - } - - /** - * Lets all Fragments managed by the controller's FragmentManager - * know they should create an options menu. - *

Call when the Fragment should create an options menu. - * - * @return {@code true} if the options menu contains items to display - * @see Fragment#onCreateOptionsMenu(Menu, MenuInflater) - */ - public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) { - return mHost.mFragmentManager.dispatchCreateOptionsMenu(menu, inflater); - } - - /** - * Lets all Fragments managed by the controller's FragmentManager - * know they should prepare their options menu for display. - *

Call immediately before displaying the Fragment's options menu. - * - * @return {@code true} if the options menu contains items to display - * @see Fragment#onPrepareOptionsMenu(Menu) - */ - public boolean dispatchPrepareOptionsMenu(Menu menu) { - return mHost.mFragmentManager.dispatchPrepareOptionsMenu(menu); - } - - /** - * Sends an option item selection event to the Fragments managed by the - * controller's FragmentManager. Once the event has been consumed, - * no additional handling will be performed. - *

Call immediately after an options menu item has been selected - * - * @return {@code true} if the options menu selection event was consumed - * @see Fragment#onOptionsItemSelected(MenuItem) - */ - public boolean dispatchOptionsItemSelected(MenuItem item) { - return mHost.mFragmentManager.dispatchOptionsItemSelected(item); - } - - /** - * Sends a context item selection event to the Fragments managed by the - * controller's FragmentManager. Once the event has been consumed, - * no additional handling will be performed. - *

Call immediately after an options menu item has been selected - * - * @return {@code true} if the context menu selection event was consumed - * @see Fragment#onContextItemSelected(MenuItem) - */ - public boolean dispatchContextItemSelected(MenuItem item) { - return mHost.mFragmentManager.dispatchContextItemSelected(item); - } - - /** - * Lets all Fragments managed by the controller's FragmentManager - * know their options menu has closed. - *

Call immediately after closing the Fragment's options menu. - * - * @see Fragment#onOptionsMenuClosed(Menu) - */ - public void dispatchOptionsMenuClosed(Menu menu) { - mHost.mFragmentManager.dispatchOptionsMenuClosed(menu); - } - - /** - * Execute any pending actions for the Fragments managed by the - * controller's FragmentManager. - *

Call when queued actions can be performed [eg when the - * Fragment moves into a start or resume state]. - * @return {@code true} if queued actions were performed - */ - public boolean execPendingActions() { - return mHost.mFragmentManager.execPendingActions(); - } - - /** - * Starts the loaders. - */ - public void doLoaderStart() { - mHost.doLoaderStart(); - } - - /** - * Stops the loaders, optionally retaining their state. This is useful for keeping the - * loader state across configuration changes. - * - * @param retain When {@code true}, the loaders aren't stopped, but, their instances - * are retained in a started state - */ - public void doLoaderStop(boolean retain) { - mHost.doLoaderStop(retain); - } - - /** - * Retains the state of each of the loaders. - */ - public void doLoaderRetain() { - mHost.doLoaderRetain(); - } - - /** - * Destroys the loaders and, if their state is not being retained, removes them. - */ - public void doLoaderDestroy() { - mHost.doLoaderDestroy(); - } - - /** - * Lets the loaders know the host is ready to receive notifications. - */ - public void reportLoaderStart() { - mHost.reportLoaderStart(); - } - - /** - * Returns a list of LoaderManagers that have opted to retain their instance across - * configuration changes. - */ - public SimpleArrayMap retainLoaderNonConfig() { - return mHost.retainLoaderNonConfig(); - } - - /** - * Restores the saved state for all LoaderManagers. The given LoaderManager list are - * LoaderManager instances retained across configuration changes. - * - * @see #retainLoaderNonConfig() - */ - public void restoreLoaderNonConfig(SimpleArrayMap loaderManagers) { - mHost.restoreLoaderNonConfig(loaderManagers); - } - - /** - * Dumps the current state of the loaders. - */ - public void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - mHost.dumpLoaders(prefix, fd, writer, args); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentHostCallback.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentHostCallback.java deleted file mode 100644 index f17dfac..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentHostCallback.java +++ /dev/null @@ -1,343 +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 p.android.support.v4.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.v4.util.SimpleArrayMap; -import android.view.LayoutInflater; -import android.view.View; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Integration points with the Fragment host. - *

- * Fragments may be hosted by any object; such as an {@link Activity}. In order to - * host fragments, implement {@link FragmentHostCallback}, overriding the methods - * applicable to the host. - */ -public abstract class FragmentHostCallback extends FragmentContainer { - private final Activity mActivity; - final Context mContext; - private final Handler mHandler; - final int mWindowAnimations; - final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl(); - /** The loader managers for individual fragments [i.e. Fragment#getLoaderManager()] */ - private SimpleArrayMap mAllLoaderManagers; - /** Whether or not fragment loaders should retain their state */ - private boolean mRetainLoaders; - /** The loader manger for the fragment host [i.e. Activity#getLoaderManager()] */ - private LoaderManagerImpl mLoaderManager; - private boolean mCheckedForLoaderManager; - /** Whether or not the fragment host loader manager was started */ - private boolean mLoadersStarted; - - public FragmentHostCallback(Context context, Handler handler, int windowAnimations) { - this(null /*activity*/, context, handler, windowAnimations); - } - - FragmentHostCallback(FragmentActivity activity) { - this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/); - } - - FragmentHostCallback(Activity activity, Context context, Handler handler, - int windowAnimations) { - mActivity = activity; - mContext = context; - mHandler = handler; - mWindowAnimations = windowAnimations; - } - - /** - * Print internal state into the given stream. - * - * @param prefix Desired prefix to prepend at each line of output. - * @param fd The raw file descriptor that the dump is being sent to. - * @param writer The PrintWriter to which you should dump your state. This will be closed - * for you after you return. - * @param args additional arguments to the dump request. - */ - public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - } - - /** - * Return {@code true} if the fragment's state needs to be saved. - */ - public boolean onShouldSaveFragmentState(Fragment fragment) { - return true; - } - - /** - * Return a {@link LayoutInflater}. - * See {@link Activity#getLayoutInflater()}. - */ - public LayoutInflater onGetLayoutInflater() { - return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - /** - * Return the object that's currently hosting the fragment. If a {@link Fragment} - * is hosted by a {@link FragmentActivity}, the object returned here should be - * the same object returned from {@link Fragment#getActivity()}. - */ - @Nullable - public abstract E onGetHost(); - - /** - * Invalidates the activity's options menu. - * See {@link FragmentActivity#supportInvalidateOptionsMenu()} - */ - public void onSupportInvalidateOptionsMenu() { - } - - /** - * Starts a new {@link Activity} from the given fragment. - * See {@link FragmentActivity#startActivityForResult(Intent, int)}. - */ - public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { - onStartActivityFromFragment(fragment, intent, requestCode, null); - } - - /** - * Starts a new {@link Activity} from the given fragment. - * See {@link FragmentActivity#startActivityForResult(Intent, int, Bundle)}. - */ - public void onStartActivityFromFragment( - Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options) { - if (requestCode != -1) { - throw new IllegalStateException( - "Starting activity with a requestCode requires a FragmentActivity host"); - } - mContext.startActivity(intent); - } - - /** - * Requests permissions from the given fragment. - * See {@link FragmentActivity#requestPermissions(String[], int)} - */ - public void onRequestPermissionsFromFragment(@NonNull Fragment fragment, - @NonNull String[] permissions, int requestCode) { - } - - /** - * Checks wehter to show permission rationale UI from a fragment. - * See {@link FragmentActivity#shouldShowRequestPermissionRationale(String)} - */ - public boolean onShouldShowRequestPermissionRationale(@NonNull String permission) { - return false; - } - - /** - * Return {@code true} if there are window animations. - */ - public boolean onHasWindowAnimations() { - return true; - } - - /** - * Return the window animations. - */ - public int onGetWindowAnimations() { - return mWindowAnimations; - } - - @Nullable - @Override - public View onFindViewById(int id) { - return null; - } - - @Override - public boolean onHasView() { - return true; - } - - Activity getActivity() { - return mActivity; - } - - Context getContext() { - return mContext; - } - - Handler getHandler() { - return mHandler; - } - - FragmentManagerImpl getFragmentManagerImpl() { - return mFragmentManager; - } - - LoaderManagerImpl getLoaderManagerImpl() { - if (mLoaderManager != null) { - return mLoaderManager; - } - mCheckedForLoaderManager = true; - mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true /*create*/); - return mLoaderManager; - } - - void inactivateFragment(String who) { - //Log.v(TAG, "invalidateSupportFragment: who=" + who); - if (mAllLoaderManagers != null) { - LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who); - if (lm != null && !lm.mRetaining) { - lm.doDestroy(); - mAllLoaderManagers.remove(who); - } - } - } - - void onAttachFragment(Fragment fragment) { - } - - boolean getRetainLoaders() { - return mRetainLoaders; - } - - void doLoaderStart() { - if (mLoadersStarted) { - return; - } - mLoadersStarted = true; - - if (mLoaderManager != null) { - mLoaderManager.doStart(); - } else if (!mCheckedForLoaderManager) { - mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false); - // the returned loader manager may be a new one, so we have to start it - if ((mLoaderManager != null) && (!mLoaderManager.mStarted)) { - mLoaderManager.doStart(); - } - } - mCheckedForLoaderManager = true; - } - - // retain -- whether to stop the loader or retain it - void doLoaderStop(boolean retain) { - mRetainLoaders = retain; - - if (mLoaderManager == null) { - return; - } - - if (!mLoadersStarted) { - return; - } - mLoadersStarted = false; - - if (retain) { - mLoaderManager.doRetain(); - } else { - mLoaderManager.doStop(); - } - } - - void doLoaderRetain() { - if (mLoaderManager == null) { - return; - } - mLoaderManager.doRetain(); - } - - void doLoaderDestroy() { - if (mLoaderManager == null) { - return; - } - mLoaderManager.doDestroy(); - } - - void reportLoaderStart() { - if (mAllLoaderManagers != null) { - final int N = mAllLoaderManagers.size(); - LoaderManagerImpl loaders[] = new LoaderManagerImpl[N]; - for (int i=N-1; i>=0; i--) { - loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i); - } - for (int i=0; i(); - } - LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who); - if (lm == null) { - if (create) { - lm = new LoaderManagerImpl(who, this, started); - mAllLoaderManagers.put(who, lm); - } - } else { - lm.updateHostController(this); - } - return lm; - } - - SimpleArrayMap retainLoaderNonConfig() { - boolean retainLoaders = false; - if (mAllLoaderManagers != null) { - // prune out any loader managers that were already stopped and so - // have nothing useful to retain. - final int N = mAllLoaderManagers.size(); - LoaderManagerImpl loaders[] = new LoaderManagerImpl[N]; - for (int i=N-1; i>=0; i--) { - loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i); - } - for (int i=0; i loaderManagers) { - mAllLoaderManagers = loaderManagers; - } - - void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - writer.print(prefix); writer.print("mLoadersStarted="); - writer.println(mLoadersStarted); - if (mLoaderManager != null) { - writer.print(prefix); writer.print("Loader Manager "); - writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager))); - writer.println(":"); - mLoaderManager.dump(prefix + " ", fd, writer, args); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentManager.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentManager.java deleted file mode 100644 index 0a89abe..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentManager.java +++ /dev/null @@ -1,2343 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Parcel; -import android.os.Parcelable; -import p.android.support.annotation.CallSuper; -import p.android.support.annotation.IdRes; -import p.android.support.annotation.StringRes; -import p.android.support.v4.util.DebugUtils; -import p.android.support.v4.util.LogWriter; -import p.android.support.v4.view.LayoutInflaterFactory; -import p.android.support.v4.view.ViewCompat; -import android.util.AttributeSet; -import android.util.Log; -import android.util.SparseArray; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.view.animation.AnimationSet; -import android.view.animation.AnimationUtils; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.view.animation.ScaleAnimation; -import android.view.animation.Animation.AnimationListener; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Static library support version of the framework's {@link android.app.FragmentManager}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework {@link FragmentManager} - * documentation for a class overview. - * - *

Your activity must derive from {@link FragmentActivity} to use this. From such an activity, - * you can acquire the {@link FragmentManager} by calling - * {@link FragmentActivity#getSupportFragmentManager}. - */ -public abstract class FragmentManager { - /** - * Representation of an entry on the fragment back stack, as created - * with {@link FragmentTransaction#addToBackStack(String) - * FragmentTransaction.addToBackStack()}. Entries can later be - * retrieved with {@link FragmentManager#getBackStackEntryAt(int) - * FragmentManager.getBackStackEntry()}. - * - *

Note that you should never hold on to a BackStackEntry object; - * the identifier as returned by {@link #getId} is the only thing that - * will be persisted across activity instances. - */ - public interface BackStackEntry { - /** - * Return the unique identifier for the entry. This is the only - * representation of the entry that will persist across activity - * instances. - */ - public int getId(); - - /** - * Get the name that was supplied to - * {@link FragmentTransaction#addToBackStack(String) - * FragmentTransaction.addToBackStack(String)} when creating this entry. - */ - public String getName(); - - /** - * Return the full bread crumb title resource identifier for the entry, - * or 0 if it does not have one. - */ - @StringRes - public int getBreadCrumbTitleRes(); - - /** - * Return the short bread crumb title resource identifier for the entry, - * or 0 if it does not have one. - */ - @StringRes - public int getBreadCrumbShortTitleRes(); - - /** - * Return the full bread crumb title for the entry, or null if it - * does not have one. - */ - public CharSequence getBreadCrumbTitle(); - - /** - * Return the short bread crumb title for the entry, or null if it - * does not have one. - */ - public CharSequence getBreadCrumbShortTitle(); - } - - /** - * Interface to watch for changes to the back stack. - */ - public interface OnBackStackChangedListener { - /** - * Called whenever the contents of the back stack change. - */ - public void onBackStackChanged(); - } - - /** - * Start a series of edit operations on the Fragments associated with - * this FragmentManager. - * - *

Note: A fragment transaction can only be created/committed prior - * to an activity saving its state. If you try to commit a transaction - * after {@link FragmentActivity#onSaveInstanceState FragmentActivity.onSaveInstanceState()} - * (and prior to a following {@link FragmentActivity#onStart FragmentActivity.onStart} - * or {@link FragmentActivity#onResume FragmentActivity.onResume()}, you will get an error. - * This is because the framework takes care of saving your current fragments - * in the state, and if changes are made after the state is saved then they - * will be lost.

- */ - public abstract FragmentTransaction beginTransaction(); - - /** @hide -- remove once prebuilts are in. */ - @Deprecated - public FragmentTransaction openTransaction() { - return beginTransaction(); - } - - /** - * After a {@link FragmentTransaction} is committed with - * {@link FragmentTransaction#commit FragmentTransaction.commit()}, it - * is scheduled to be executed asynchronously on the process's main thread. - * If you want to immediately executing any such pending operations, you - * can call this function (only from the main thread) to do so. Note that - * all callbacks and other related behavior will be done from within this - * call, so be careful about where this is called from. - * - * @return Returns true if there were any pending transactions to be - * executed. - */ - public abstract boolean executePendingTransactions(); - - /** - * Finds a fragment that was identified by the given id either when inflated - * from XML or as the container ID when added in a transaction. This first - * searches through fragments that are currently added to the manager's - * activity; if no such fragment is found, then all fragments currently - * on the back stack associated with this ID are searched. - * @return The fragment if found or null otherwise. - */ - public abstract Fragment findFragmentById(@IdRes int id); - - /** - * Finds a fragment that was identified by the given tag either when inflated - * from XML or as supplied when added in a transaction. This first - * searches through fragments that are currently added to the manager's - * activity; if no such fragment is found, then all fragments currently - * on the back stack are searched. - * @return The fragment if found or null otherwise. - */ - public abstract Fragment findFragmentByTag(String tag); - - /** - * Flag for {@link #popBackStack(String, int)} - * and {@link #popBackStack(int, int)}: If set, and the name or ID of - * a back stack entry has been supplied, then all matching entries will - * be consumed until one that doesn't match is found or the bottom of - * the stack is reached. Otherwise, all entries up to but not including that entry - * will be removed. - */ - public static final int POP_BACK_STACK_INCLUSIVE = 1<<0; - - /** - * Pop the top state off the back stack. Returns true if there was one - * to pop, else false. This function is asynchronous -- it enqueues the - * request to pop, but the action will not be performed until the application - * returns to its event loop. - */ - public abstract void popBackStack(); - - /** - * Like {@link #popBackStack()}, but performs the operation immediately - * inside of the call. This is like calling {@link #executePendingTransactions()} - * afterwards. - * @return Returns true if there was something popped, else false. - */ - public abstract boolean popBackStackImmediate(); - - /** - * Pop the last fragment transition from the manager's fragment - * back stack. If there is nothing to pop, false is returned. - * This function is asynchronous -- it enqueues the - * request to pop, but the action will not be performed until the application - * returns to its event loop. - * - * @param name If non-null, this is the name of a previous back state - * to look for; if found, all states up to that state will be popped. The - * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether - * 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); - - /** - * Like {@link #popBackStack(String, int)}, but performs the operation immediately - * inside of the call. This is like calling {@link #executePendingTransactions()} - * afterwards. - * @return Returns true if there was something popped, else false. - */ - public abstract boolean popBackStackImmediate(String name, int flags); - - /** - * Pop all back stack states up to the one with the given identifier. - * This function is asynchronous -- it enqueues the - * request to pop, but the action will not be performed until the application - * returns to its event loop. - * - * @param id Identifier of the stated to be popped. If no identifier exists, - * false is returned. - * The identifier is the number returned by - * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. The - * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether - * the named state itself is popped. - * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. - */ - public abstract void popBackStack(int id, int flags); - - /** - * Like {@link #popBackStack(int, int)}, but performs the operation immediately - * inside of the call. This is like calling {@link #executePendingTransactions()} - * afterwards. - * @return Returns true if there was something popped, else false. - */ - public abstract boolean popBackStackImmediate(int id, int flags); - - /** - * Return the number of entries currently in the back stack. - */ - public abstract int getBackStackEntryCount(); - - /** - * Return the BackStackEntry at index index in the back stack; - * entries start index 0 being the bottom of the stack. - */ - public abstract BackStackEntry getBackStackEntryAt(int index); - - /** - * Add a new listener for changes to the fragment back stack. - */ - public abstract void addOnBackStackChangedListener(OnBackStackChangedListener listener); - - /** - * Remove a listener that was previously added with - * {@link #addOnBackStackChangedListener(OnBackStackChangedListener)}. - */ - public abstract void removeOnBackStackChangedListener(OnBackStackChangedListener listener); - - /** - * Put a reference to a fragment in a Bundle. This Bundle can be - * persisted as saved state, and when later restoring - * {@link #getFragment(Bundle, String)} will return the current - * instance of the same fragment. - * - * @param bundle The bundle in which to put the fragment reference. - * @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); - - /** - * Retrieve the current Fragment instance for a reference previously - * placed with {@link #putFragment(Bundle, String, Fragment)}. - * - * @param bundle The bundle from which to retrieve the fragment reference. - * @param key The name of the entry in the bundle. - * @return Returns the current Fragment instance that is associated with - * the given reference. - */ - public abstract Fragment getFragment(Bundle bundle, String key); - - /** - * Get a list of all fragments that have been added to the fragment manager. - * - * @return The list of all fragments or null if none. - * @hide - */ - public abstract List getFragments(); - - /** - * Save the current instance state of the given Fragment. This can be - * used later when creating a new instance of the Fragment and adding - * it to the fragment manager, to have it create itself to match the - * current state returned here. Note that there are limits on how - * this can be used: - * - *
    - *
  • The Fragment must currently be attached to the FragmentManager. - *
  • A new Fragment created using this saved state must be the same class - * type as the Fragment it was created from. - *
  • The saved state can not contain dependencies on other fragments -- - * that is it can't use {@link #putFragment(Bundle, String, Fragment)} to - * store a fragment reference because that reference may not be valid when - * this saved state is later used. Likewise the Fragment's target and - * result code are not included in this state. - *
- * - * @param f The Fragment whose state is to be saved. - * @return The generated state. This will be null if there was no - * interesting state created by the fragment. - */ - public abstract Fragment.SavedState saveFragmentInstanceState(Fragment f); - - /** - * Returns true if the final {@link android.app.Activity#onDestroy() Activity.onDestroy()} - * call has been made on the FragmentManager's Activity, so this instance is now dead. - */ - public abstract boolean isDestroyed(); - - /** - * Print the FragmentManager's state into the given stream. - * - * @param prefix Text to print at the front of each line. - * @param fd The raw file descriptor that the dump is being sent to. - * @param writer A PrintWriter to which the dump is to be set. - * @param args Additional arguments to the dump request. - */ - public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args); - - /** - * Control whether the framework's internal fragment manager debugging - * logs are turned on. If enabled, you will see output in logcat as - * the framework performs fragment operations. - */ - public static void enableDebugLogging(boolean enabled) { - FragmentManagerImpl.DEBUG = enabled; - } -} - -final class FragmentManagerState implements Parcelable { - FragmentState[] mActive; - int[] mAdded; - BackStackState[] mBackStack; - - public FragmentManagerState() { - } - - public FragmentManagerState(Parcel in) { - mActive = in.createTypedArray(FragmentState.CREATOR); - mAdded = in.createIntArray(); - mBackStack = in.createTypedArray(BackStackState.CREATOR); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeTypedArray(mActive, flags); - dest.writeIntArray(mAdded); - dest.writeTypedArray(mBackStack, flags); - } - - public static final Creator CREATOR - = new Creator() { - public FragmentManagerState createFromParcel(Parcel in) { - return new FragmentManagerState(in); - } - - public FragmentManagerState[] newArray(int size) { - return new FragmentManagerState[size]; - } - }; -} - -/** - * Container for fragments associated with an activity. - */ -final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory { - static boolean DEBUG = false; - static final String TAG = "FragmentManager"; - - static final boolean HONEYCOMB = Build.VERSION.SDK_INT >= 11; - - static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state"; - static final String TARGET_STATE_TAG = "android:target_state"; - static final String VIEW_STATE_TAG = "android:view_state"; - static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint"; - - - static class AnimateOnHWLayerIfNeededListener implements AnimationListener { - private AnimationListener mOrignalListener = null; - private boolean mShouldRunOnHWLayer = false; - private View mView = null; - public AnimateOnHWLayerIfNeededListener(final View v, Animation anim) { - if (v == null || anim == null) { - return; - } - mView = v; - } - - public AnimateOnHWLayerIfNeededListener(final View v, Animation anim, - AnimationListener listener) { - if (v == null || anim == null) { - return; - } - mOrignalListener = listener; - mView = v; - } - - @Override - @CallSuper - public void onAnimationStart(Animation animation) { - if (mView != null) { - mShouldRunOnHWLayer = shouldRunOnHWLayer(mView, animation); - if (mShouldRunOnHWLayer) { - mView.post(new Runnable() { - @Override - public void run() { - ViewCompat.setLayerType(mView, ViewCompat.LAYER_TYPE_HARDWARE, null); - } - }); - } - } - if (mOrignalListener != null) { - mOrignalListener.onAnimationStart(animation); - } - } - - @Override - @CallSuper - public void onAnimationEnd(Animation animation) { - if (mView != null && mShouldRunOnHWLayer) { - mView.post(new Runnable() { - @Override - public void run() { - ViewCompat.setLayerType(mView, ViewCompat.LAYER_TYPE_NONE, null); - } - }); - } - if (mOrignalListener != null) { - mOrignalListener.onAnimationEnd(animation); - } - } - - @Override - public void onAnimationRepeat(Animation animation) { - if (mOrignalListener != null) { - mOrignalListener.onAnimationRepeat(animation); - } - } - } - - ArrayList mPendingActions; - Runnable[] mTmpActions; - boolean mExecutingActions; - - ArrayList mActive; - ArrayList mAdded; - ArrayList mAvailIndices; - ArrayList mBackStack; - ArrayList mCreatedMenus; - - // Must be accessed while locked. - ArrayList mBackStackIndices; - ArrayList mAvailBackStackIndices; - - ArrayList mBackStackChangeListeners; - - int mCurState = Fragment.INITIALIZING; - FragmentHostCallback mHost; - FragmentController mController; - FragmentContainer mContainer; - Fragment mParent; - - static Field sAnimationListenerField = null; - - boolean mNeedMenuInvalidate; - boolean mStateSaved; - boolean mDestroyed; - String mNoTransactionsBecause; - boolean mHavePendingDeferredStart; - - // Temporary vars for state save and restore. - Bundle mStateBundle = null; - SparseArray mStateArray = null; - - Runnable mExecCommit = new Runnable() { - @Override - public void run() { - execPendingActions(); - } - }; - - static boolean modifiesAlpha(Animation anim) { - if (anim instanceof AlphaAnimation) { - return true; - } else if (anim instanceof AnimationSet) { - List anims = ((AnimationSet) anim).getAnimations(); - for (int i = 0; i < anims.size(); i++) { - if (anims.get(i) instanceof AlphaAnimation) { - return true; - } - } - } - return false; - } - - static boolean shouldRunOnHWLayer(View v, Animation anim) { - return Build.VERSION.SDK_INT >= 19 - && ViewCompat.getLayerType(v) == ViewCompat.LAYER_TYPE_NONE - && ViewCompat.hasOverlappingRendering(v) - && modifiesAlpha(anim); - } - - private void throwException(RuntimeException ex) { - Log.e(TAG, ex.getMessage()); - Log.e(TAG, "Activity state:"); - LogWriter logw = new LogWriter(TAG); - PrintWriter pw = new PrintWriter(logw); - if (mHost != null) { - try { - mHost.onDump(" ", null, pw, new String[] { }); - } catch (Exception e) { - Log.e(TAG, "Failed dumping state", e); - } - } else { - try { - dump(" ", null, pw, new String[] { }); - } catch (Exception e) { - Log.e(TAG, "Failed dumping state", e); - } - } - throw ex; - } - - @Override - public FragmentTransaction beginTransaction() { - return new BackStackRecord(this); - } - - @Override - public boolean executePendingTransactions() { - return execPendingActions(); - } - - @Override - public void popBackStack() { - enqueueAction(new Runnable() { - @Override public void run() { - popBackStackState(mHost.getHandler(), null, -1, 0); - } - }, false); - } - - @Override - public boolean popBackStackImmediate() { - checkStateLoss(); - executePendingTransactions(); - return popBackStackState(mHost.getHandler(), null, -1, 0); - } - - @Override - public void popBackStack(final String name, final int flags) { - enqueueAction(new Runnable() { - @Override public void run() { - popBackStackState(mHost.getHandler(), name, -1, flags); - } - }, false); - } - - @Override - public boolean popBackStackImmediate(String name, int flags) { - checkStateLoss(); - executePendingTransactions(); - return popBackStackState(mHost.getHandler(), name, -1, flags); - } - - @Override - public void popBackStack(final int id, final int flags) { - if (id < 0) { - throw new IllegalArgumentException("Bad id: " + id); - } - enqueueAction(new Runnable() { - @Override public void run() { - popBackStackState(mHost.getHandler(), null, id, flags); - } - }, false); - } - - @Override - public boolean popBackStackImmediate(int id, int flags) { - checkStateLoss(); - executePendingTransactions(); - if (id < 0) { - throw new IllegalArgumentException("Bad id: " + id); - } - return popBackStackState(mHost.getHandler(), null, id, flags); - } - - @Override - public int getBackStackEntryCount() { - return mBackStack != null ? mBackStack.size() : 0; - } - - @Override - public BackStackEntry getBackStackEntryAt(int index) { - return mBackStack.get(index); - } - - @Override - public void addOnBackStackChangedListener(OnBackStackChangedListener listener) { - if (mBackStackChangeListeners == null) { - mBackStackChangeListeners = new ArrayList(); - } - mBackStackChangeListeners.add(listener); - } - - @Override - public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) { - if (mBackStackChangeListeners != null) { - mBackStackChangeListeners.remove(listener); - } - } - - @Override - public void putFragment(Bundle bundle, String key, Fragment fragment) { - if (fragment.mIndex < 0) { - throwException(new IllegalStateException("Fragment " + fragment - + " is not currently in the FragmentManager")); - } - bundle.putInt(key, fragment.mIndex); - } - - @Override - public Fragment getFragment(Bundle bundle, String key) { - int index = bundle.getInt(key, -1); - if (index == -1) { - return null; - } - if (index >= mActive.size()) { - throwException(new IllegalStateException("Fragment no longer exists for key " - + key + ": index " + index)); - } - Fragment f = mActive.get(index); - if (f == null) { - throwException(new IllegalStateException("Fragment no longer exists for key " - + key + ": index " + index)); - } - return f; - } - - @Override - public List getFragments() { - return mActive; - } - - @Override - public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) { - if (fragment.mIndex < 0) { - throwException( new IllegalStateException("Fragment " + fragment - + " is not currently in the FragmentManager")); - } - if (fragment.mState > Fragment.INITIALIZING) { - Bundle result = saveFragmentBasicState(fragment); - return result != null ? new Fragment.SavedState(result) : null; - } - return null; - } - - @Override - public boolean isDestroyed() { - return mDestroyed; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(128); - sb.append("FragmentManager{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" in "); - if (mParent != null) { - DebugUtils.buildShortClassTag(mParent, sb); - } else { - DebugUtils.buildShortClassTag(mHost, sb); - } - sb.append("}}"); - return sb.toString(); - } - - @Override - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - String innerPrefix = prefix + " "; - - int N; - if (mActive != null) { - N = mActive.size(); - if (N > 0) { - writer.print(prefix); writer.print("Active Fragments in "); - writer.print(Integer.toHexString(System.identityHashCode(this))); - writer.println(":"); - for (int i=0; i 0) { - writer.print(prefix); writer.println("Added Fragments:"); - for (int i=0; i 0) { - writer.print(prefix); writer.println("Fragments Created Menus:"); - for (int i=0; i 0) { - writer.print(prefix); writer.println("Back Stack:"); - for (int i=0; i 0) { - writer.print(prefix); writer.println("Back Stack Indices:"); - for (int i=0; i 0) { - writer.print(prefix); writer.print("mAvailBackStackIndices: "); - writer.println(Arrays.toString(mAvailBackStackIndices.toArray())); - } - } - - if (mPendingActions != null) { - N = mPendingActions.size(); - if (N > 0) { - writer.print(prefix); writer.println("Pending Actions:"); - for (int i=0; i Fragment.CREATED) { - newState = Fragment.CREATED; - } - if (f.mRemoving && newState > f.mState) { - // While removing a fragment, we can't change it to a higher state. - newState = f.mState; - } - // Defer start if requested; don't allow it to move to STARTED or higher - // if it's not already started. - if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) { - newState = Fragment.STOPPED; - } - if (f.mState < newState) { - // For fragments that are created from a layout, when restoring from - // state we don't want to allow them to be created until they are - // being reloaded from the layout. - if (f.mFromLayout && !f.mInLayout) { - return; - } - if (f.mAnimatingAway != null) { - // The fragment is currently being animated... but! Now we - // want to move our state back up. Give up on waiting for the - // animation, move to whatever the final state should be once - // the animation is done, and then we can proceed from there. - f.mAnimatingAway = null; - moveToState(f, f.mStateAfterAnimating, 0, 0, true); - } - switch (f.mState) { - case Fragment.INITIALIZING: - if (DEBUG) Log.v(TAG, "moveto CREATED: " + f); - if (f.mSavedFragmentState != null) { - f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader()); - f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray( - FragmentManagerImpl.VIEW_STATE_TAG); - f.mTarget = getFragment(f.mSavedFragmentState, - FragmentManagerImpl.TARGET_STATE_TAG); - if (f.mTarget != null) { - 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.mUserVisibleHint) { - f.mDeferStart = true; - if (newState > Fragment.STOPPED) { - newState = Fragment.STOPPED; - } - } - } - f.mHost = mHost; - f.mParentFragment = mParent; - f.mFragmentManager = mParent != null - ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl(); - f.mCalled = false; - f.onAttach(mHost.getContext()); - if (!f.mCalled) { - throw new SuperNotCalledException("Fragment " + f - + " did not call through to super.onAttach()"); - } - if (f.mParentFragment == null) { - mHost.onAttachFragment(f); - } - - if (!f.mRetaining) { - f.performCreate(f.mSavedFragmentState); - } - f.mRetaining = false; - if (f.mFromLayout) { - // For fragments that are part of the content view - // layout, we need to instantiate the view immediately - // and the inflater will take care of adding it. - f.mView = f.performCreateView(f.getLayoutInflater( - f.mSavedFragmentState), null, f.mSavedFragmentState); - if (f.mView != null) { - f.mInnerView = f.mView; - if (Build.VERSION.SDK_INT >= 11) { - ViewCompat.setSaveFromParentEnabled(f.mView, false); - } else { - f.mView = NoSaveStateFrameLayout.wrap(f.mView); - } - if (f.mHidden) f.mView.setVisibility(View.GONE); - f.onViewCreated(f.mView, f.mSavedFragmentState); - } else { - f.mInnerView = null; - } - } - case Fragment.CREATED: - if (newState > Fragment.CREATED) { - if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f); - if (!f.mFromLayout) { - ViewGroup container = null; - if (f.mContainerId != 0) { - container = (ViewGroup)mContainer.onFindViewById(f.mContainerId); - if (container == null && !f.mRestored) { - throwException(new IllegalArgumentException( - "No view found for id 0x" - + Integer.toHexString(f.mContainerId) + " (" - + f.getResources().getResourceName(f.mContainerId) - + ") for fragment " + f)); - } - } - f.mContainer = container; - f.mView = f.performCreateView(f.getLayoutInflater( - f.mSavedFragmentState), container, f.mSavedFragmentState); - if (f.mView != null) { - f.mInnerView = f.mView; - if (Build.VERSION.SDK_INT >= 11) { - ViewCompat.setSaveFromParentEnabled(f.mView, false); - } else { - f.mView = NoSaveStateFrameLayout.wrap(f.mView); - } - if (container != null) { - Animation anim = loadAnimation(f, transit, true, - transitionStyle); - if (anim != null) { - setHWLayerAnimListenerIfAlpha(f.mView, anim); - f.mView.startAnimation(anim); - } - container.addView(f.mView); - } - if (f.mHidden) f.mView.setVisibility(View.GONE); - f.onViewCreated(f.mView, f.mSavedFragmentState); - } else { - f.mInnerView = null; - } - } - - f.performActivityCreated(f.mSavedFragmentState); - if (f.mView != null) { - f.restoreViewState(f.mSavedFragmentState); - } - f.mSavedFragmentState = null; - } - case Fragment.ACTIVITY_CREATED: - case Fragment.STOPPED: - if (newState > Fragment.STOPPED) { - if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); - f.performStart(); - } - case Fragment.STARTED: - if (newState > Fragment.STARTED) { - if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f); - f.performResume(); - f.mSavedFragmentState = null; - f.mSavedViewState = null; - } - } - } else if (f.mState > newState) { - switch (f.mState) { - case Fragment.RESUMED: - if (newState < Fragment.RESUMED) { - if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f); - f.performPause(); - } - case Fragment.STARTED: - if (newState < Fragment.STARTED) { - if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f); - f.performStop(); - } - case Fragment.STOPPED: - if (newState < Fragment.STOPPED) { - if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f); - f.performReallyStop(); - } - case Fragment.ACTIVITY_CREATED: - if (newState < Fragment.ACTIVITY_CREATED) { - if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f); - if (f.mView != null) { - // Need to save the current view state if not - // done already. - if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) { - saveFragmentViewState(f); - } - } - f.performDestroyView(); - if (f.mView != null && f.mContainer != null) { - Animation anim = null; - if (mCurState > Fragment.INITIALIZING && !mDestroyed) { - anim = loadAnimation(f, transit, false, - transitionStyle); - } - if (anim != null) { - final Fragment fragment = f; - f.mAnimatingAway = f.mView; - f.mStateAfterAnimating = newState; - final View viewToAnimate = f.mView; - anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener( - viewToAnimate, anim) { - @Override - public void onAnimationEnd(Animation animation) { - super.onAnimationEnd(animation); - if (fragment.mAnimatingAway != null) { - fragment.mAnimatingAway = null; - moveToState(fragment, fragment.mStateAfterAnimating, - 0, 0, false); - } - } - }); - f.mView.startAnimation(anim); - } - f.mContainer.removeView(f.mView); - } - f.mContainer = null; - f.mView = null; - f.mInnerView = null; - } - case Fragment.CREATED: - if (newState < Fragment.CREATED) { - if (mDestroyed) { - if (f.mAnimatingAway != null) { - // The fragment's containing activity is - // being destroyed, but this fragment is - // currently animating away. Stop the - // animation right now -- it is not needed, - // and we can't wait any more on destroying - // the fragment. - View v = f.mAnimatingAway; - f.mAnimatingAway = null; - v.clearAnimation(); - } - } - if (f.mAnimatingAway != null) { - // We are waiting for the fragment's view to finish - // animating away. Just make a note of the state - // the fragment now should move to once the animation - // is done. - f.mStateAfterAnimating = newState; - newState = Fragment.CREATED; - } else { - if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f); - if (!f.mRetaining) { - f.performDestroy(); - } else { - f.mState = Fragment.INITIALIZING; - } - - f.mCalled = false; - f.onDetach(); - if (!f.mCalled) { - throw new SuperNotCalledException("Fragment " + f - + " did not call through to super.onDetach()"); - } - if (!keepActive) { - if (!f.mRetaining) { - makeInactive(f); - } else { - f.mHost = null; - f.mParentFragment = null; - f.mFragmentManager = null; - f.mChildFragmentManager = null; - } - } - } - } - } - } - - if (f.mState != newState) { - Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; " - + "expected state " + newState + " found " + f.mState); - f.mState = newState; - } - } - - void moveToState(Fragment f) { - moveToState(f, mCurState, 0, 0, false); - } - - void moveToState(int newState, boolean always) { - moveToState(newState, 0, 0, always); - } - - void moveToState(int newState, int transit, int transitStyle, boolean always) { - if (mHost == null && newState != Fragment.INITIALIZING) { - throw new IllegalStateException("No host"); - } - - if (!always && mCurState == newState) { - return; - } - - mCurState = newState; - if (mActive != null) { - boolean loadersRunning = false; - for (int i=0; i= 0) { - return; - } - - if (mAvailIndices == null || mAvailIndices.size() <= 0) { - if (mActive == null) { - mActive = new ArrayList(); - } - f.setIndex(mActive.size(), mParent); - mActive.add(f); - - } else { - f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent); - mActive.set(f.mIndex, f); - } - if (DEBUG) Log.v(TAG, "Allocated fragment index " + f); - } - - void makeInactive(Fragment f) { - if (f.mIndex < 0) { - return; - } - - if (DEBUG) Log.v(TAG, "Freeing fragment index " + f); - mActive.set(f.mIndex, null); - if (mAvailIndices == null) { - mAvailIndices = new ArrayList(); - } - mAvailIndices.add(f.mIndex); - mHost.inactivateFragment(f.mWho); - f.initState(); - } - - public void addFragment(Fragment fragment, boolean moveToStateNow) { - if (mAdded == null) { - mAdded = new ArrayList(); - } - if (DEBUG) Log.v(TAG, "add: " + fragment); - makeActive(fragment); - if (!fragment.mDetached) { - if (mAdded.contains(fragment)) { - throw new IllegalStateException("Fragment already added: " + fragment); - } - mAdded.add(fragment); - fragment.mAdded = true; - fragment.mRemoving = false; - if (fragment.mHasMenu && fragment.mMenuVisible) { - mNeedMenuInvalidate = true; - } - if (moveToStateNow) { - moveToState(fragment); - } - } - } - - public void removeFragment(Fragment fragment, int transition, int transitionStyle) { - if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting); - final boolean inactive = !fragment.isInBackStack(); - if (!fragment.mDetached || inactive) { - if (mAdded != null) { - mAdded.remove(fragment); - } - if (fragment.mHasMenu && fragment.mMenuVisible) { - mNeedMenuInvalidate = true; - } - fragment.mAdded = false; - fragment.mRemoving = true; - moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, - transition, transitionStyle, false); - } - } - - public void hideFragment(Fragment fragment, int transition, int transitionStyle) { - if (DEBUG) Log.v(TAG, "hide: " + fragment); - if (!fragment.mHidden) { - fragment.mHidden = true; - if (fragment.mView != null) { - Animation anim = loadAnimation(fragment, transition, false, - transitionStyle); - if (anim != null) { - setHWLayerAnimListenerIfAlpha(fragment.mView, anim); - fragment.mView.startAnimation(anim); - } - fragment.mView.setVisibility(View.GONE); - } - if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) { - mNeedMenuInvalidate = true; - } - fragment.onHiddenChanged(true); - } - } - - public void showFragment(Fragment fragment, int transition, int transitionStyle) { - if (DEBUG) Log.v(TAG, "show: " + fragment); - if (fragment.mHidden) { - fragment.mHidden = false; - if (fragment.mView != null) { - Animation anim = loadAnimation(fragment, transition, true, - transitionStyle); - if (anim != null) { - setHWLayerAnimListenerIfAlpha(fragment.mView, anim); - fragment.mView.startAnimation(anim); - } - fragment.mView.setVisibility(View.VISIBLE); - } - if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) { - mNeedMenuInvalidate = true; - } - fragment.onHiddenChanged(false); - } - } - - public void detachFragment(Fragment fragment, int transition, int transitionStyle) { - if (DEBUG) Log.v(TAG, "detach: " + fragment); - if (!fragment.mDetached) { - fragment.mDetached = true; - if (fragment.mAdded) { - // We are not already in back stack, so need to remove the fragment. - if (mAdded != null) { - if (DEBUG) Log.v(TAG, "remove from detach: " + fragment); - mAdded.remove(fragment); - } - if (fragment.mHasMenu && fragment.mMenuVisible) { - mNeedMenuInvalidate = true; - } - fragment.mAdded = false; - moveToState(fragment, Fragment.CREATED, transition, transitionStyle, false); - } - } - } - - public void attachFragment(Fragment fragment, int transition, int transitionStyle) { - if (DEBUG) Log.v(TAG, "attach: " + fragment); - if (fragment.mDetached) { - fragment.mDetached = false; - if (!fragment.mAdded) { - if (mAdded == null) { - mAdded = new ArrayList(); - } - if (mAdded.contains(fragment)) { - throw new IllegalStateException("Fragment already added: " + fragment); - } - if (DEBUG) Log.v(TAG, "add from attach: " + fragment); - mAdded.add(fragment); - fragment.mAdded = true; - if (fragment.mHasMenu && fragment.mMenuVisible) { - mNeedMenuInvalidate = true; - } - moveToState(fragment, mCurState, transition, transitionStyle, false); - } - } - } - - public Fragment findFragmentById(int id) { - if (mAdded != null) { - // First look through added fragments. - for (int i=mAdded.size()-1; i>=0; i--) { - Fragment f = mAdded.get(i); - if (f != null && f.mFragmentId == id) { - return f; - } - } - } - if (mActive != null) { - // Now for any known fragment. - for (int i=mActive.size()-1; i>=0; i--) { - Fragment f = mActive.get(i); - if (f != null && f.mFragmentId == id) { - return f; - } - } - } - return null; - } - - public Fragment findFragmentByTag(String tag) { - if (mAdded != null && tag != null) { - // First look through added fragments. - for (int i=mAdded.size()-1; i>=0; i--) { - Fragment f = mAdded.get(i); - if (f != null && tag.equals(f.mTag)) { - return f; - } - } - } - if (mActive != null && tag != null) { - // Now for any known fragment. - for (int i=mActive.size()-1; i>=0; i--) { - Fragment f = mActive.get(i); - if (f != null && tag.equals(f.mTag)) { - return f; - } - } - } - return null; - } - - public Fragment findFragmentByWho(String who) { - if (mActive != null && who != null) { - for (int i=mActive.size()-1; i>=0; i--) { - Fragment f = mActive.get(i); - if (f != null && (f=f.findFragmentByWho(who)) != null) { - return f; - } - } - } - return null; - } - - private void checkStateLoss() { - if (mStateSaved) { - throw new IllegalStateException( - "Can not perform this action after onSaveInstanceState"); - } - if (mNoTransactionsBecause != null) { - throw new IllegalStateException( - "Can not perform this action inside of " + mNoTransactionsBecause); - } - } - - /** - * Adds an action to the queue of pending actions. - * - * @param action the action to add - * @param allowStateLoss whether to allow loss of state information - * @throws IllegalStateException if the activity has been destroyed - */ - public void enqueueAction(Runnable action, boolean allowStateLoss) { - if (!allowStateLoss) { - checkStateLoss(); - } - synchronized (this) { - if (mDestroyed || mHost == null) { - throw new IllegalStateException("Activity has been destroyed"); - } - if (mPendingActions == null) { - mPendingActions = new ArrayList(); - } - mPendingActions.add(action); - if (mPendingActions.size() == 1) { - mHost.getHandler().removeCallbacks(mExecCommit); - mHost.getHandler().post(mExecCommit); - } - } - } - - public int allocBackStackIndex(BackStackRecord bse) { - synchronized (this) { - if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) { - if (mBackStackIndices == null) { - mBackStackIndices = new ArrayList(); - } - int index = mBackStackIndices.size(); - if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse); - mBackStackIndices.add(bse); - return index; - - } else { - int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1); - if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse); - mBackStackIndices.set(index, bse); - return index; - } - } - } - - public void setBackStackIndex(int index, BackStackRecord bse) { - synchronized (this) { - if (mBackStackIndices == null) { - mBackStackIndices = new ArrayList(); - } - int N = mBackStackIndices.size(); - if (index < N) { - if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse); - mBackStackIndices.set(index, bse); - } else { - while (N < index) { - mBackStackIndices.add(null); - if (mAvailBackStackIndices == null) { - mAvailBackStackIndices = new ArrayList(); - } - if (DEBUG) Log.v(TAG, "Adding available back stack index " + N); - mAvailBackStackIndices.add(N); - N++; - } - if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse); - mBackStackIndices.add(bse); - } - } - } - - public void freeBackStackIndex(int index) { - synchronized (this) { - mBackStackIndices.set(index, null); - if (mAvailBackStackIndices == null) { - mAvailBackStackIndices = new ArrayList(); - } - if (DEBUG) Log.v(TAG, "Freeing back stack index " + index); - mAvailBackStackIndices.add(index); - } - } - - /** - * Only call from main thread! - */ - public boolean execPendingActions() { - if (mExecutingActions) { - throw new IllegalStateException("Recursive entry to executePendingTransactions"); - } - - if (Looper.myLooper() != mHost.getHandler().getLooper()) { - throw new IllegalStateException("Must be called from main thread of process"); - } - - boolean didSomething = false; - - while (true) { - int numActions; - - synchronized (this) { - if (mPendingActions == null || mPendingActions.size() == 0) { - break; - } - - numActions = mPendingActions.size(); - if (mTmpActions == null || mTmpActions.length < numActions) { - mTmpActions = new Runnable[numActions]; - } - mPendingActions.toArray(mTmpActions); - mPendingActions.clear(); - mHost.getHandler().removeCallbacks(mExecCommit); - } - - mExecutingActions = true; - for (int i=0; i(); - } - mBackStack.add(state); - reportBackStackChanged(); - } - - @SuppressWarnings("unused") - boolean popBackStackState(Handler handler, String name, int id, int flags) { - if (mBackStack == null) { - return false; - } - if (name == null && id < 0 && (flags&POP_BACK_STACK_INCLUSIVE) == 0) { - int last = mBackStack.size()-1; - if (last < 0) { - return false; - } - final BackStackRecord bss = mBackStack.remove(last); - SparseArray firstOutFragments = new SparseArray(); - SparseArray lastInFragments = new SparseArray(); - bss.calculateBackFragments(firstOutFragments, lastInFragments); - bss.popFromBackStack(true, null, firstOutFragments, lastInFragments); - reportBackStackChanged(); - } else { - int index = -1; - if (name != null || id >= 0) { - // If a name or ID is specified, look for that place in - // the stack. - index = mBackStack.size()-1; - while (index >= 0) { - BackStackRecord bss = mBackStack.get(index); - if (name != null && name.equals(bss.getName())) { - break; - } - if (id >= 0 && id == bss.mIndex) { - break; - } - index--; - } - if (index < 0) { - return false; - } - if ((flags&POP_BACK_STACK_INCLUSIVE) != 0) { - index--; - // Consume all following entries that match. - while (index >= 0) { - BackStackRecord bss = mBackStack.get(index); - if ((name != null && name.equals(bss.getName())) - || (id >= 0 && id == bss.mIndex)) { - index--; - continue; - } - break; - } - } - } - if (index == mBackStack.size()-1) { - return false; - } - final ArrayList states - = new ArrayList(); - for (int i=mBackStack.size()-1; i>index; i--) { - states.add(mBackStack.remove(i)); - } - final int LAST = states.size()-1; - SparseArray firstOutFragments = new SparseArray(); - SparseArray lastInFragments = new SparseArray(); - for (int i=0; i<=LAST; i++) { - states.get(i).calculateBackFragments(firstOutFragments, lastInFragments); - } - BackStackRecord.TransitionState state = null; - for (int i=0; i<=LAST; i++) { - if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i)); - state = states.get(i).popFromBackStack(i == LAST, state, - firstOutFragments, lastInFragments); - } - reportBackStackChanged(); - } - return true; - } - - ArrayList retainNonConfig() { - ArrayList fragments = null; - if (mActive != null) { - for (int i=0; i(); - } - fragments.add(f); - f.mRetaining = true; - f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1; - if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f); - } - } - } - return fragments; - } - - void saveFragmentViewState(Fragment f) { - if (f.mInnerView == null) { - return; - } - if (mStateArray == null) { - mStateArray = new SparseArray(); - } else { - mStateArray.clear(); - } - f.mInnerView.saveHierarchyState(mStateArray); - if (mStateArray.size() > 0) { - f.mSavedViewState = mStateArray; - mStateArray = null; - } - } - - Bundle saveFragmentBasicState(Fragment f) { - Bundle result = null; - - if (mStateBundle == null) { - mStateBundle = new Bundle(); - } - f.performSaveInstanceState(mStateBundle); - if (!mStateBundle.isEmpty()) { - result = mStateBundle; - mStateBundle = null; - } - - if (f.mView != null) { - saveFragmentViewState(f); - } - if (f.mSavedViewState != null) { - if (result == null) { - result = new Bundle(); - } - result.putSparseParcelableArray( - FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState); - } - if (!f.mUserVisibleHint) { - if (result == null) { - result = new Bundle(); - } - // Only add this if it's not the default value - result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint); - } - - return result; - } - - Parcelable saveAllState() { - // Make sure all pending operations have now been executed to get - // our state update-to-date. - execPendingActions(); - - if (HONEYCOMB) { - // As of Honeycomb, we save state after pausing. Prior to that - // it is before pausing. With fragments this is an issue, since - // there are many things you may do after pausing but before - // stopping that change the fragment state. For those older - // devices, we will not at this point say that we have saved - // the state, so we will allow them to continue doing fragment - // transactions. This retains the same semantics as Honeycomb, - // though you do have the risk of losing the very most recent state - // if the process is killed... we'll live with that. - mStateSaved = true; - } - - if (mActive == null || mActive.size() <= 0) { - return null; - } - - // First collect all active fragments. - int N = mActive.size(); - FragmentState[] active = new FragmentState[N]; - boolean haveFragments = false; - for (int i=0; i Fragment.INITIALIZING && fs.mSavedFragmentState == null) { - fs.mSavedFragmentState = saveFragmentBasicState(f); - - if (f.mTarget != null) { - if (f.mTarget.mIndex < 0) { - throwException(new IllegalStateException( - "Failure saving state: " + f - + " has target not in fragment manager: " + f.mTarget)); - } - if (fs.mSavedFragmentState == null) { - fs.mSavedFragmentState = new Bundle(); - } - putFragment(fs.mSavedFragmentState, - FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget); - if (f.mTargetRequestCode != 0) { - fs.mSavedFragmentState.putInt( - FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, - f.mTargetRequestCode); - } - } - - } else { - fs.mSavedFragmentState = f.mSavedFragmentState; - } - - if (DEBUG) Log.v(TAG, "Saved state of " + f + ": " - + fs.mSavedFragmentState); - } - } - - if (!haveFragments) { - if (DEBUG) Log.v(TAG, "saveAllState: no fragments!"); - return null; - } - - int[] added = null; - BackStackState[] backStack = null; - - // Build list of currently added fragments. - if (mAdded != null) { - N = mAdded.size(); - if (N > 0) { - added = new int[N]; - for (int i=0; i 0) { - backStack = new BackStackState[N]; - for (int i=0; i nonConfig) { - // If there is no saved state at all, then there can not be - // any nonConfig fragments either, so that is that. - if (state == null) return; - FragmentManagerState fms = (FragmentManagerState)state; - if (fms.mActive == null) return; - - // First re-attach any non-config instances we are retaining back - // to their saved state, so we don't try to instantiate them again. - if (nonConfig != null) { - for (int i=0; i(fms.mActive.length); - if (mAvailIndices != null) { - mAvailIndices.clear(); - } - for (int i=0; i(); - } - if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i); - mAvailIndices.add(i); - } - } - - // Update the target of all retained fragments. - if (nonConfig != null) { - for (int i=0; i= 0) { - if (f.mTargetIndex < mActive.size()) { - f.mTarget = mActive.get(f.mTargetIndex); - } else { - Log.w(TAG, "Re-attaching retained fragment " + f - + " target no longer exists: " + f.mTargetIndex); - f.mTarget = null; - } - } - } - } - - // Build the list of currently added fragments. - if (fms.mAdded != null) { - mAdded = new ArrayList(fms.mAdded.length); - for (int i=0; i(fms.mBackStack.length); - for (int i=0; i= 0) { - setBackStackIndex(bse.mIndex, bse); - } - } - } else { - mBackStack = null; - } - } - - public void attachController(FragmentHostCallback host, - FragmentContainer container, Fragment parent) { - if (mHost != null) throw new IllegalStateException("Already attached"); - mHost = host; - mContainer = container; - mParent = parent; - } - - public void noteStateNotSaved() { - mStateSaved = false; - } - - public void dispatchCreate() { - mStateSaved = false; - moveToState(Fragment.CREATED, false); - } - - public void dispatchActivityCreated() { - mStateSaved = false; - moveToState(Fragment.ACTIVITY_CREATED, false); - } - - public void dispatchStart() { - mStateSaved = false; - moveToState(Fragment.STARTED, false); - } - - public void dispatchResume() { - mStateSaved = false; - moveToState(Fragment.RESUMED, false); - } - - public void dispatchPause() { - moveToState(Fragment.STARTED, false); - } - - public void dispatchStop() { - // See saveAllState() for the explanation of this. We do this for - // all platform versions, to keep our behavior more consistent between - // them. - mStateSaved = true; - - moveToState(Fragment.STOPPED, false); - } - - public void dispatchReallyStop() { - moveToState(Fragment.ACTIVITY_CREATED, false); - } - - public void dispatchDestroyView() { - moveToState(Fragment.CREATED, false); - } - - public void dispatchDestroy() { - mDestroyed = true; - execPendingActions(); - moveToState(Fragment.INITIALIZING, false); - mHost = null; - mContainer = null; - mParent = null; - } - - public void dispatchConfigurationChanged(Configuration newConfig) { - if (mAdded != null) { - for (int i=0; i newMenus = null; - if (mAdded != null) { - for (int i=0; i(); - } - newMenus.add(f); - } - } - } - } - - if (mCreatedMenus != null) { - for (int i=0; iThis version of the pager is best for use when there are a handful of - * typically more static fragments to be paged through, such as a set of tabs. - * The fragment of each page the user visits will be kept in memory, though its - * view hierarchy may be destroyed when not visible. This can result in using - * a significant amount of memory since fragment instances can hold on to an - * arbitrary amount of state. For larger sets of pages, consider - * {@link FragmentStatePagerAdapter}. - * - *

When using FragmentPagerAdapter the host ViewPager must have a - * valid ID set.

- * - *

Subclasses only need to implement {@link #getItem(int)} - * and {@link #getCount()} to have a working adapter. - * - *

Here is an example implementation of a pager containing fragments of - * lists: - * - * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentPagerSupport.java - * complete} - * - *

The R.layout.fragment_pager resource of the top-level fragment is: - * - * {@sample development/samples/Support4Demos/res/layout/fragment_pager.xml - * complete} - * - *

The R.layout.fragment_pager_list resource containing each - * individual fragment's layout is: - * - * {@sample development/samples/Support4Demos/res/layout/fragment_pager_list.xml - * complete} - */ -public abstract class FragmentPagerAdapter extends PagerAdapter { - private static final String TAG = "FragmentPagerAdapter"; - private static final boolean DEBUG = false; - - private final FragmentManager mFragmentManager; - private FragmentTransaction mCurTransaction = null; - private Fragment mCurrentPrimaryItem = null; - - public FragmentPagerAdapter(FragmentManager fm) { - mFragmentManager = fm; - } - - /** - * Return the Fragment associated with a specified position. - */ - public abstract Fragment getItem(int position); - - @Override - public void startUpdate(ViewGroup container) { - } - - @Override - public Object instantiateItem(ViewGroup container, int position) { - if (mCurTransaction == null) { - mCurTransaction = mFragmentManager.beginTransaction(); - } - - final long itemId = getItemId(position); - - // Do we already have this fragment? - String name = makeFragmentName(container.getId(), itemId); - Fragment fragment = mFragmentManager.findFragmentByTag(name); - if (fragment != null) { - if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); - mCurTransaction.attach(fragment); - } else { - fragment = getItem(position); - if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment); - mCurTransaction.add(container.getId(), fragment, - makeFragmentName(container.getId(), itemId)); - } - if (fragment != mCurrentPrimaryItem) { - fragment.setMenuVisibility(false); - fragment.setUserVisibleHint(false); - } - - return fragment; - } - - @Override - public void destroyItem(ViewGroup container, int position, Object object) { - if (mCurTransaction == null) { - mCurTransaction = mFragmentManager.beginTransaction(); - } - if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object - + " v=" + ((Fragment)object).getView()); - mCurTransaction.detach((Fragment)object); - } - - @Override - public void setPrimaryItem(ViewGroup container, int position, Object object) { - Fragment fragment = (Fragment)object; - if (fragment != mCurrentPrimaryItem) { - if (mCurrentPrimaryItem != null) { - mCurrentPrimaryItem.setMenuVisibility(false); - mCurrentPrimaryItem.setUserVisibleHint(false); - } - if (fragment != null) { - fragment.setMenuVisibility(true); - fragment.setUserVisibleHint(true); - } - mCurrentPrimaryItem = fragment; - } - } - - @Override - public void finishUpdate(ViewGroup container) { - if (mCurTransaction != null) { - mCurTransaction.commitAllowingStateLoss(); - mCurTransaction = null; - mFragmentManager.executePendingTransactions(); - } - } - - @Override - public boolean isViewFromObject(View view, Object object) { - return ((Fragment)object).getView() == view; - } - - @Override - public Parcelable saveState() { - return null; - } - - @Override - public void restoreState(Parcelable state, ClassLoader loader) { - } - - /** - * Return a unique identifier for the item at the given position. - * - *

The default implementation returns the given position. - * Subclasses should override this method if the positions of items can change.

- * - * @param position Position within this adapter - * @return Unique identifier for the item at position - */ - public long getItemId(int position) { - return position; - } - - private static String makeFragmentName(int viewId, long id) { - return "android:switcher:" + viewId + ":" + id; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentStatePagerAdapter.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentStatePagerAdapter.java deleted file mode 100644 index 8d4c217..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentStatePagerAdapter.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.os.Bundle; -import android.os.Parcelable; -import p.android.support.v4.view.PagerAdapter; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; - -import java.util.ArrayList; - -/** - * Implementation of {@link PagerAdapter} that - * uses a {@link Fragment} to manage each page. This class also handles - * saving and restoring of fragment's state. - * - *

This version of the pager is more useful when there are a large number - * of pages, working more like a list view. When pages are not visible to - * the user, their entire fragment may be destroyed, only keeping the saved - * state of that fragment. This allows the pager to hold on to much less - * memory associated with each visited page as compared to - * {@link FragmentPagerAdapter} at the cost of potentially more overhead when - * switching between pages. - * - *

When using FragmentPagerAdapter the host ViewPager must have a - * valid ID set.

- * - *

Subclasses only need to implement {@link #getItem(int)} - * and {@link #getCount()} to have a working adapter. - * - *

Here is an example implementation of a pager containing fragments of - * lists: - * - * {@sample development/samples/Support13Demos/src/com/example/android/supportv13/app/FragmentStatePagerSupport.java - * complete} - * - *

The R.layout.fragment_pager resource of the top-level fragment is: - * - * {@sample development/samples/Support13Demos/res/layout/fragment_pager.xml - * complete} - * - *

The R.layout.fragment_pager_list resource containing each - * individual fragment's layout is: - * - * {@sample development/samples/Support13Demos/res/layout/fragment_pager_list.xml - * complete} - */ -public abstract class FragmentStatePagerAdapter extends PagerAdapter { - private static final String TAG = "FragmentStatePagerAdapter"; - private static final boolean DEBUG = false; - - private final FragmentManager mFragmentManager; - private FragmentTransaction mCurTransaction = null; - - private ArrayList mSavedState = new ArrayList(); - private ArrayList mFragments = new ArrayList(); - private Fragment mCurrentPrimaryItem = null; - - public FragmentStatePagerAdapter(FragmentManager fm) { - mFragmentManager = fm; - } - - /** - * Return the Fragment associated with a specified position. - */ - public abstract Fragment getItem(int position); - - @Override - public void startUpdate(ViewGroup container) { - } - - @Override - public Object instantiateItem(ViewGroup container, int position) { - // If we already have this item instantiated, there is nothing - // to do. This can happen when we are restoring the entire pager - // from its saved state, where the fragment manager has already - // taken care of restoring the fragments we previously had instantiated. - if (mFragments.size() > position) { - Fragment f = mFragments.get(position); - if (f != null) { - return f; - } - } - - if (mCurTransaction == null) { - mCurTransaction = mFragmentManager.beginTransaction(); - } - - Fragment fragment = getItem(position); - if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment); - if (mSavedState.size() > position) { - Fragment.SavedState fss = mSavedState.get(position); - if (fss != null) { - fragment.setInitialSavedState(fss); - } - } - while (mFragments.size() <= position) { - mFragments.add(null); - } - fragment.setMenuVisibility(false); - fragment.setUserVisibleHint(false); - mFragments.set(position, fragment); - mCurTransaction.add(container.getId(), fragment); - - return fragment; - } - - @Override - public void destroyItem(ViewGroup container, int position, Object object) { - Fragment fragment = (Fragment) object; - - if (mCurTransaction == null) { - mCurTransaction = mFragmentManager.beginTransaction(); - } - if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object - + " v=" + ((Fragment)object).getView()); - while (mSavedState.size() <= position) { - mSavedState.add(null); - } - mSavedState.set(position, fragment.isAdded() - ? mFragmentManager.saveFragmentInstanceState(fragment) : null); - mFragments.set(position, null); - - mCurTransaction.remove(fragment); - } - - @Override - public void setPrimaryItem(ViewGroup container, int position, Object object) { - Fragment fragment = (Fragment)object; - if (fragment != mCurrentPrimaryItem) { - if (mCurrentPrimaryItem != null) { - mCurrentPrimaryItem.setMenuVisibility(false); - mCurrentPrimaryItem.setUserVisibleHint(false); - } - if (fragment != null) { - fragment.setMenuVisibility(true); - fragment.setUserVisibleHint(true); - } - mCurrentPrimaryItem = fragment; - } - } - - @Override - public void finishUpdate(ViewGroup container) { - if (mCurTransaction != null) { - mCurTransaction.commitAllowingStateLoss(); - mCurTransaction = null; - mFragmentManager.executePendingTransactions(); - } - } - - @Override - public boolean isViewFromObject(View view, Object object) { - return ((Fragment)object).getView() == view; - } - - @Override - public Parcelable saveState() { - Bundle state = null; - if (mSavedState.size() > 0) { - state = new Bundle(); - Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()]; - mSavedState.toArray(fss); - state.putParcelableArray("states", fss); - } - for (int i=0; i keys = bundle.keySet(); - for (String key: keys) { - if (key.startsWith("f")) { - int index = Integer.parseInt(key.substring(1)); - Fragment f = mFragmentManager.getFragment(bundle, key); - if (f != null) { - while (mFragments.size() <= index) { - mFragments.add(null); - } - f.setMenuVisibility(false); - mFragments.set(index, f); - } else { - Log.w(TAG, "Bad fragment at key " + key); - } - } - } - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentTabHost.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentTabHost.java deleted file mode 100644 index e946885..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentTabHost.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import java.util.ArrayList; - -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.TabHost; -import android.widget.TabWidget; - -/** - * Special TabHost that allows the use of {@link Fragment} objects for - * its tab content. When placing this in a view hierarchy, after inflating - * the hierarchy you must call {@link #setup(Context, FragmentManager, int)} - * to complete the initialization of the tab host. - * - *

Here is a simple example of using a FragmentTabHost in an Activity: - * - * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentTabs.java - * complete} - * - *

This can also be used inside of a fragment through fragment nesting: - * - * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentTabsFragmentSupport.java - * complete} - */ -public class FragmentTabHost extends TabHost - implements TabHost.OnTabChangeListener { - private final ArrayList mTabs = new ArrayList(); - private FrameLayout mRealTabContent; - private Context mContext; - private FragmentManager mFragmentManager; - private int mContainerId; - private OnTabChangeListener mOnTabChangeListener; - private TabInfo mLastTab; - private boolean mAttached; - - static final class TabInfo { - private final String tag; - private final Class clss; - private final Bundle args; - private Fragment fragment; - - TabInfo(String _tag, Class _class, Bundle _args) { - tag = _tag; - clss = _class; - args = _args; - } - } - - static class DummyTabFactory implements TabContentFactory { - private final Context mContext; - - public DummyTabFactory(Context context) { - mContext = context; - } - - @Override - public View createTabContent(String tag) { - View v = new View(mContext); - v.setMinimumWidth(0); - v.setMinimumHeight(0); - return v; - } - } - - static class SavedState extends BaseSavedState { - String curTab; - - SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - curTab = in.readString(); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeString(curTab); - } - - @Override - public String toString() { - return "FragmentTabHost.SavedState{" - + Integer.toHexString(System.identityHashCode(this)) - + " curTab=" + curTab + "}"; - } - - public static final Creator CREATOR - = new Creator() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - public FragmentTabHost(Context context) { - // Note that we call through to the version that takes an AttributeSet, - // because the simple Context construct can result in a broken object! - super(context, null); - initFragmentTabHost(context, null); - } - - public FragmentTabHost(Context context, AttributeSet attrs) { - super(context, attrs); - initFragmentTabHost(context, attrs); - } - - private void initFragmentTabHost(Context context, AttributeSet attrs) { - TypedArray a = context.obtainStyledAttributes(attrs, - new int[] { android.R.attr.inflatedId }, 0, 0); - mContainerId = a.getResourceId(0, 0); - a.recycle(); - - super.setOnTabChangedListener(this); - } - - private void ensureHierarchy(Context context) { - // If owner hasn't made its own view hierarchy, then as a convenience - // we will construct a standard one here. - if (findViewById(android.R.id.tabs) == null) { - LinearLayout ll = new LinearLayout(context); - ll.setOrientation(LinearLayout.VERTICAL); - addView(ll, new LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT)); - - TabWidget tw = new TabWidget(context); - tw.setId(android.R.id.tabs); - tw.setOrientation(TabWidget.HORIZONTAL); - ll.addView(tw, new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT, 0)); - - FrameLayout fl = new FrameLayout(context); - fl.setId(android.R.id.tabcontent); - ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0)); - - mRealTabContent = fl = new FrameLayout(context); - mRealTabContent.setId(mContainerId); - ll.addView(fl, new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.FILL_PARENT, 0, 1)); - } - } - - /** - * @deprecated Don't call the original TabHost setup, you must instead - * call {@link #setup(Context, FragmentManager)} or - * {@link #setup(Context, FragmentManager, int)}. - */ - @Override @Deprecated - public void setup() { - throw new IllegalStateException( - "Must call setup() that takes a Context and FragmentManager"); - } - - public void setup(Context context, FragmentManager manager) { - ensureHierarchy(context); // Ensure views required by super.setup() - super.setup(); - mContext = context; - mFragmentManager = manager; - ensureContent(); - } - - public void setup(Context context, FragmentManager manager, int containerId) { - ensureHierarchy(context); // Ensure views required by super.setup() - super.setup(); - mContext = context; - mFragmentManager = manager; - mContainerId = containerId; - ensureContent(); - mRealTabContent.setId(containerId); - - // We must have an ID to be able to save/restore our state. If - // the owner hasn't set one at this point, we will set it ourself. - if (getId() == View.NO_ID) { - setId(android.R.id.tabhost); - } - } - - private void ensureContent() { - if (mRealTabContent == null) { - mRealTabContent = (FrameLayout)findViewById(mContainerId); - if (mRealTabContent == null) { - throw new IllegalStateException( - "No tab content FrameLayout found for id " + mContainerId); - } - } - } - - @Override - public void setOnTabChangedListener(OnTabChangeListener l) { - mOnTabChangeListener = l; - } - - public void addTab(TabSpec tabSpec, Class clss, Bundle args) { - tabSpec.setContent(new DummyTabFactory(mContext)); - String tag = tabSpec.getTag(); - - TabInfo info = new TabInfo(tag, clss, args); - - if (mAttached) { - // If we are already attached to the window, then check to make - // sure this tab's fragment is inactive if it exists. This shouldn't - // normally happen. - info.fragment = mFragmentManager.findFragmentByTag(tag); - if (info.fragment != null && !info.fragment.isDetached()) { - FragmentTransaction ft = mFragmentManager.beginTransaction(); - ft.detach(info.fragment); - ft.commit(); - } - } - - mTabs.add(info); - addTab(tabSpec); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - String currentTab = getCurrentTabTag(); - - // Go through all tabs and make sure their fragments match - // the correct state. - FragmentTransaction ft = null; - for (int i=0; i

A transaction can only be committed with this method - * prior to its containing activity saving its state. If the commit is - * attempted after that point, an exception will be thrown. This is - * because the state after the commit can be lost if the activity needs to - * be restored from its state. See {@link #commitAllowingStateLoss()} for - * situations where it may be okay to lose the commit.

- * - * @return Returns the identifier of this transaction's back stack entry, - * if {@link #addToBackStack(String)} had been called. Otherwise, returns - * a negative number. - */ - public abstract int commit(); - - /** - * Like {@link #commit} but allows the commit to be executed after an - * activity's state is saved. This is dangerous because the commit can - * be lost if the activity needs to later be restored from its state, so - * this should only be used for cases where it is okay for the UI state - * to change unexpectedly on the user. - */ - public abstract int commitAllowingStateLoss(); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentTransitionCompat21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentTransitionCompat21.java deleted file mode 100644 index dd7c739..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/FragmentTransitionCompat21.java +++ /dev/null @@ -1,453 +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 p.android.support.v4.app; - -import android.graphics.Rect; -import android.transition.Transition; -import android.transition.TransitionManager; -import android.transition.TransitionSet; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -class FragmentTransitionCompat21 { - public static String getTransitionName(View view) { - return view.getTransitionName(); - } - - public static Object cloneTransition(Object transition) { - if (transition != null) { - transition = ((Transition)transition).clone(); - } - return transition; - } - - public static Object captureExitingViews(Object exitTransition, View root, - ArrayList viewList, Map namedViews, View nonExistentView) { - if (exitTransition != null) { - captureTransitioningViews(viewList, root); - if (namedViews != null) { - viewList.removeAll(namedViews.values()); - } - if (viewList.isEmpty()) { - exitTransition = null; - } else { - viewList.add(nonExistentView); - addTargets((Transition) exitTransition, viewList); - } - } - return exitTransition; - } - - public static void excludeTarget(Object transitionObject, View view, boolean exclude) { - Transition transition = (Transition) transitionObject; - transition.excludeTarget(view, exclude); - } - - public static void beginDelayedTransition(ViewGroup sceneRoot, Object transitionObject) { - Transition transition = (Transition) transitionObject; - TransitionManager.beginDelayedTransition(sceneRoot, transition); - } - - public static void setEpicenter(Object transitionObject, View view) { - Transition transition = (Transition) transitionObject; - final Rect epicenter = getBoundsOnScreen(view); - - transition.setEpicenterCallback(new Transition.EpicenterCallback() { - @Override - public Rect onGetEpicenter(Transition transition) { - return epicenter; - } - }); - } - - public static Object wrapSharedElementTransition(Object transitionObj) { - if (transitionObj == null) { - return null; - } - Transition transition = (Transition) transitionObj; - if (transition == null) { - return null; - } - TransitionSet transitionSet = new TransitionSet(); - transitionSet.addTransition(transition); - return transitionSet; - } - - /** - * Prepares the enter transition by adding a non-existent view to the transition's target list - * and setting it epicenter callback. By adding a non-existent view to the target list, - * we can prevent any view from being targeted at the beginning of the transition. - * We will add to the views before the end state of the transition is captured so that the - * views will appear. At the start of the transition, we clear the list of targets so that - * we can restore the state of the transition and use it again. - * - *

The shared element transition maps its shared elements immediately prior to - * capturing the final state of the Transition.

- */ - public static void addTransitionTargets(Object enterTransitionObject, - Object sharedElementTransitionObject, final View container, - final ViewRetriever inFragment, final View nonExistentView, - EpicenterView epicenterView, final Map nameOverrides, - final ArrayList enteringViews, final Map namedViews, - final Map renamedViews, final ArrayList sharedElementTargets) { - if (enterTransitionObject != null || sharedElementTransitionObject != null) { - final Transition enterTransition = (Transition) enterTransitionObject; - if (enterTransition != null) { - enterTransition.addTarget(nonExistentView); - } - if (sharedElementTransitionObject != null) { - setSharedElementTargets(sharedElementTransitionObject, nonExistentView, - namedViews, sharedElementTargets); - } - - if (inFragment != null) { - container.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - public boolean onPreDraw() { - container.getViewTreeObserver().removeOnPreDrawListener(this); - if (enterTransition != null) { - enterTransition.removeTarget(nonExistentView); - } - View fragmentView = inFragment.getView(); - if (fragmentView != null) { - if (!nameOverrides.isEmpty()) { - findNamedViews(renamedViews, fragmentView); - renamedViews.keySet().retainAll(nameOverrides.values()); - for (Map.Entry entry : nameOverrides.entrySet()) { - String to = entry.getValue(); - View view = renamedViews.get(to); - if (view != null) { - String from = entry.getKey(); - view.setTransitionName(from); - } - } - } - if (enterTransition != null) { - captureTransitioningViews(enteringViews, fragmentView); - enteringViews.removeAll(renamedViews.values()); - enteringViews.add(nonExistentView); - addTargets(enterTransition, enteringViews); - } - } - return true; - } - }); - } - setSharedElementEpicenter(enterTransition, epicenterView); - } - } - - public static Object mergeTransitions(Object enterTransitionObject, - Object exitTransitionObject, Object sharedElementTransitionObject, - boolean allowOverlap) { - boolean overlap = true; - Transition enterTransition = (Transition) enterTransitionObject; - Transition exitTransition = (Transition) exitTransitionObject; - Transition sharedElementTransition = (Transition) sharedElementTransitionObject; - - if (enterTransition != null && exitTransition != null) { - overlap = allowOverlap; - } - - // Wrap the transitions. Explicit targets like in enter and exit will cause the - // views to be targeted regardless of excluded views. If that happens, then the - // excluded fragments views (hidden fragments) will still be in the transition. - - Transition transition; - if (overlap) { - // Regular transition -- do it all together - TransitionSet transitionSet = new TransitionSet(); - if (enterTransition != null) { - transitionSet.addTransition(enterTransition); - } - if (exitTransition != null) { - transitionSet.addTransition(exitTransition); - } - if (sharedElementTransition != null) { - transitionSet.addTransition(sharedElementTransition); - } - transition = transitionSet; - } else { - // First do exit, then enter, but allow shared element transition to happen - // during both. - Transition staggered = null; - if (exitTransition != null && enterTransition != null) { - staggered = new TransitionSet() - .addTransition(exitTransition) - .addTransition(enterTransition) - .setOrdering(TransitionSet.ORDERING_SEQUENTIAL); - } else if (exitTransition != null) { - staggered = exitTransition; - } else if (enterTransition != null) { - staggered = enterTransition; - } - if (sharedElementTransition != null) { - TransitionSet together = new TransitionSet(); - if (staggered != null) { - together.addTransition(staggered); - } - together.addTransition(sharedElementTransition); - transition = together; - } else { - transition = staggered; - } - } - return transition; - } - - /** - * Finds all children of the shared elements and sets the wrapping TransitionSet - * targets to point to those. It also limits transitions that have no targets to the - * specific shared elements. This allows developers to target child views of the - * shared elements specifically, but this doesn't happen by default. - */ - public static void setSharedElementTargets(Object transitionObj, - View nonExistentView, Map namedViews, - ArrayList sharedElementTargets) { - TransitionSet transition = (TransitionSet) transitionObj; - sharedElementTargets.clear(); - sharedElementTargets.addAll(namedViews.values()); - - final List views = transition.getTargets(); - views.clear(); - final int count = sharedElementTargets.size(); - for (int i = 0; i < count; i++) { - final View view = sharedElementTargets.get(i); - bfsAddViewChildren(views, view); - } - sharedElementTargets.add(nonExistentView); - addTargets(transition, sharedElementTargets); - } - - /** - * Uses a breadth-first scheme to add startView and all of its children to views. - * It won't add a child if it is already in views. - */ - private static void bfsAddViewChildren(final List views, final View startView) { - final int startIndex = views.size(); - if (containedBeforeIndex(views, startView, startIndex)) { - return; // This child is already in the list, so all its children are also. - } - views.add(startView); - for (int index = startIndex; index < views.size(); index++) { - final View view = views.get(index); - if (view instanceof ViewGroup) { - ViewGroup viewGroup = (ViewGroup) view; - final int childCount = viewGroup.getChildCount(); - for (int childIndex = 0; childIndex < childCount; childIndex++) { - final View child = viewGroup.getChildAt(childIndex); - if (!containedBeforeIndex(views, child, startIndex)) { - views.add(child); - } - } - } - } - } - - /** - * Does a linear search through views for view, limited to maxIndex. - */ - private static boolean containedBeforeIndex(final List views, final View view, - final int maxIndex) { - for (int i = 0; i < maxIndex; i++) { - if (views.get(i) == view) { - return true; - } - } - return false; - } - - private static void setSharedElementEpicenter(Transition transition, - final EpicenterView epicenterView) { - if (transition != null) { - transition.setEpicenterCallback(new Transition.EpicenterCallback() { - private Rect mEpicenter; - - @Override - public Rect onGetEpicenter(Transition transition) { - if (mEpicenter == null && epicenterView.epicenter != null) { - mEpicenter = getBoundsOnScreen(epicenterView.epicenter); - } - return mEpicenter; - } - }); - } - } - - private static Rect getBoundsOnScreen(View view) { - Rect epicenter = new Rect(); - int[] loc = new int[2]; - view.getLocationOnScreen(loc); - // not as good as View.getBoundsOnScreen, but that's not public - epicenter.set(loc[0], loc[1], loc[0] + view.getWidth(), loc[1] + view.getHeight()); - return epicenter; - } - - private static void captureTransitioningViews(ArrayList transitioningViews, View view) { - if (view.getVisibility() == View.VISIBLE) { - if (view instanceof ViewGroup) { - ViewGroup viewGroup = (ViewGroup) view; - if (viewGroup.isTransitionGroup()) { - transitioningViews.add(viewGroup); - } else { - int count = viewGroup.getChildCount(); - for (int i = 0; i < count; i++) { - View child = viewGroup.getChildAt(i); - captureTransitioningViews(transitioningViews, child); - } - } - } else { - transitioningViews.add(view); - } - } - } - - public static void findNamedViews(Map namedViews, View view) { - if (view.getVisibility() == View.VISIBLE) { - String transitionName = view.getTransitionName(); - if (transitionName != null) { - namedViews.put(transitionName, view); - } - if (view instanceof ViewGroup) { - ViewGroup viewGroup = (ViewGroup) view; - int count = viewGroup.getChildCount(); - for (int i = 0; i < count; i++) { - View child = viewGroup.getChildAt(i); - findNamedViews(namedViews, child); - } - } - } - } - - public static void cleanupTransitions(final View sceneRoot, final View nonExistentView, - Object enterTransitionObject, final ArrayList enteringViews, - Object exitTransitionObject, final ArrayList exitingViews, - Object sharedElementTransitionObject, final ArrayList sharedElementTargets, - Object overallTransitionObject, final ArrayList hiddenViews, - final Map renamedViews) { - final Transition enterTransition = (Transition) enterTransitionObject; - final Transition exitTransition = (Transition) exitTransitionObject; - final Transition sharedElementTransition = (Transition) sharedElementTransitionObject; - final Transition overallTransition = (Transition) overallTransitionObject; - if (overallTransition != null) { - sceneRoot.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - public boolean onPreDraw() { - sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this); - if (enterTransition != null) { - removeTargets(enterTransition, enteringViews); - } - if (exitTransition != null) { - removeTargets(exitTransition, exitingViews); - } - if (sharedElementTransition != null) { - removeTargets(sharedElementTransition, sharedElementTargets); - } - for (Map.Entry entry : renamedViews.entrySet()) { - View view = entry.getValue(); - String name = entry.getKey(); - view.setTransitionName(name); - } - int numViews = hiddenViews.size(); - for (int i = 0; i < numViews; i++) { - overallTransition.excludeTarget(hiddenViews.get(i), false); - } - overallTransition.excludeTarget(nonExistentView, false); - return true; - } - }); - } - } - - /** - * This method removes the views from transitions that target ONLY those views. - * The views list should match those added in addTargets and should contain - * one view that is not in the view hierarchy (state.nonExistentView). - */ - public static void removeTargets(Object transitionObject, ArrayList views) { - Transition transition = (Transition) transitionObject; - if (transition instanceof TransitionSet) { - TransitionSet set = (TransitionSet) transition; - int numTransitions = set.getTransitionCount(); - for (int i = 0; i < numTransitions; i++) { - Transition child = set.getTransitionAt(i); - removeTargets(child, views); - } - } else if (!hasSimpleTarget(transition)) { - List targets = transition.getTargets(); - if (targets != null && targets.size() == views.size() && - targets.containsAll(views)) { - // We have an exact match. We must have added these earlier in addTargets - for (int i = views.size() - 1; i >= 0; i--) { - transition.removeTarget(views.get(i)); - } - } - } - } - - /** - * This method adds views as targets to the transition, but only if the transition - * doesn't already have a target. It is best for views to contain one View object - * that does not exist in the view hierarchy (state.nonExistentView) so that - * when they are removed later, a list match will suffice to remove the targets. - * Otherwise, if you happened to have targeted the exact views for the transition, - * the removeTargets call will remove them unexpectedly. - */ - public static void addTargets(Object transitionObject, ArrayList views) { - Transition transition = (Transition) transitionObject; - if (transition instanceof TransitionSet) { - TransitionSet set = (TransitionSet) transition; - int numTransitions = set.getTransitionCount(); - for (int i = 0; i < numTransitions; i++) { - Transition child = set.getTransitionAt(i); - addTargets(child, views); - } - } else if (!hasSimpleTarget(transition)) { - List targets = transition.getTargets(); - if (isNullOrEmpty(targets)) { - // We can just add the target views - int numViews = views.size(); - for (int i = 0; i < numViews; i++) { - transition.addTarget(views.get(i)); - } - } - } - } - - private static boolean hasSimpleTarget(Transition transition) { - return !isNullOrEmpty(transition.getTargetIds()) || - !isNullOrEmpty(transition.getTargetNames()) || - !isNullOrEmpty(transition.getTargetTypes()); - } - - private static boolean isNullOrEmpty(List list) { - return list == null || list.isEmpty(); - } - - public interface ViewRetriever { - View getView(); - } - - public static class EpicenterView { - public View epicenter; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/INotificationSideChannel.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/INotificationSideChannel.aidl deleted file mode 100644 index c5f6243..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/INotificationSideChannel.aidl +++ /dev/null @@ -1,42 +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 android.plug.v4.app; - -import android.app.Notification; - -/** - * Interface used for delivering notifications via a side channel that bypasses - * the NotificationManagerService. - * - * @hide - */ -oneway interface INotificationSideChannel { - /** - * Send an ambient notification to the service. - */ - void notify(String packageName, int id, String tag, in Notification notification); - - /** - * Cancel an already-notified notification. - */ - void cancel(String packageName, int id, String tag); - - /** - * Cancel all notifications for the given package. - */ - void cancelAll(String packageName); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/INotificationSideChannel.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/INotificationSideChannel.java deleted file mode 100644 index d06f1d0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/INotificationSideChannel.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * This file is auto-generated. DO NOT MODIFY. - * Original file: /Users/user/Documents/dev/android/projects/oss/oss-android-sdk/libraries/src/main/aidl/android/plug/v4/app/INotificationSideChannel.aidl - */ -package p.android.support.v4.app; -/** - * Interface used for delivering notifications via a side channel that bypasses - * the NotificationManagerService. - * - * @hide - */ -public interface INotificationSideChannel extends android.os.IInterface -{ -/** Local-side IPC implementation stub class. */ -public static abstract class Stub extends android.os.Binder implements INotificationSideChannel -{ -private static final java.lang.String DESCRIPTOR = "android.plug.v4.app.INotificationSideChannel"; -/** Construct the stub at attach it to the interface. */ -public Stub() -{ -this.attachInterface(this, DESCRIPTOR); -} -/** - * Cast an IBinder object into an android.plug.v4.app.INotificationSideChannel interface, - * generating a proxy if needed. - */ -public static INotificationSideChannel asInterface(android.os.IBinder obj) -{ -if ((obj==null)) { -return null; -} -android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); -if (((iin!=null)&&(iin instanceof INotificationSideChannel))) { -return ((INotificationSideChannel)iin); -} -return new INotificationSideChannel.Stub.Proxy(obj); -} -@Override public android.os.IBinder asBinder() -{ -return this; -} -@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException -{ -java.lang.String descriptor = DESCRIPTOR; -switch (code) -{ -case INTERFACE_TRANSACTION: -{ -reply.writeString(descriptor); -return true; -} -case TRANSACTION_notify: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -int _arg1; -_arg1 = data.readInt(); -java.lang.String _arg2; -_arg2 = data.readString(); -android.app.Notification _arg3; -if ((0!=data.readInt())) { -_arg3 = android.app.Notification.CREATOR.createFromParcel(data); -} -else { -_arg3 = null; -} -this.notify(_arg0, _arg1, _arg2, _arg3); -return true; -} -case TRANSACTION_cancel: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -int _arg1; -_arg1 = data.readInt(); -java.lang.String _arg2; -_arg2 = data.readString(); -this.cancel(_arg0, _arg1, _arg2); -return true; -} -case TRANSACTION_cancelAll: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -this.cancelAll(_arg0); -return true; -} -default: -{ -return super.onTransact(code, data, reply, flags); -} -} -} -private static class Proxy implements INotificationSideChannel -{ -private android.os.IBinder mRemote; -Proxy(android.os.IBinder remote) -{ -mRemote = remote; -} -@Override public android.os.IBinder asBinder() -{ -return mRemote; -} -public java.lang.String getInterfaceDescriptor() -{ -return DESCRIPTOR; -} -/** - * Send an ambient notification to the service. - */ -@Override public void notify(java.lang.String packageName, int id, java.lang.String tag, android.app.Notification notification) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(packageName); -_data.writeInt(id); -_data.writeString(tag); -if ((notification!=null)) { -_data.writeInt(1); -notification.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_notify, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -/** - * Cancel an already-notified notification. - */ -@Override public void cancel(java.lang.String packageName, int id, java.lang.String tag) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(packageName); -_data.writeInt(id); -_data.writeString(tag); -mRemote.transact(Stub.TRANSACTION_cancel, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -/** - * Cancel all notifications for the given package. - */ -@Override public void cancelAll(java.lang.String packageName) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(packageName); -mRemote.transact(Stub.TRANSACTION_cancelAll, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -} -static final int TRANSACTION_notify = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); -static final int TRANSACTION_cancel = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); -static final int TRANSACTION_cancelAll = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); -} -/** - * Send an ambient notification to the service. - */ -public void notify(java.lang.String packageName, int id, java.lang.String tag, android.app.Notification notification) throws android.os.RemoteException; -/** - * Cancel an already-notified notification. - */ -public void cancel(java.lang.String packageName, int id, java.lang.String tag) throws android.os.RemoteException; -/** - * Cancel all notifications for the given package. - */ -public void cancelAll(java.lang.String packageName) throws android.os.RemoteException; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ListFragment.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ListFragment.java deleted file mode 100644 index 367a1a3..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ListFragment.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.AnimationUtils; -import android.widget.AdapterView; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.ProgressBar; -import android.widget.TextView; - -/** - * Static library support version of the framework's {@link android.app.ListFragment}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework SDK - * documentation for a class overview. - */ -public class ListFragment extends Fragment { - static final int INTERNAL_EMPTY_ID = 0x00ff0001; - static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002; - static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003; - - final private Handler mHandler = new Handler(); - - final private Runnable mRequestFocus = new Runnable() { - public void run() { - mList.focusableViewAvailable(mList); - } - }; - - final private AdapterView.OnItemClickListener mOnClickListener - = new AdapterView.OnItemClickListener() { - public void onItemClick(AdapterView parent, View v, int position, long id) { - onListItemClick((ListView)parent, v, position, id); - } - }; - - ListAdapter mAdapter; - ListView mList; - View mEmptyView; - TextView mStandardEmptyView; - View mProgressContainer; - View mListContainer; - CharSequence mEmptyText; - boolean mListShown; - - public ListFragment() { - } - - /** - * Provide default implementation to return a simple list view. Subclasses - * can override to replace with their own layout. If doing so, the - * returned view hierarchy must have a ListView whose id - * is {@link android.R.id#list android.R.id.list} and can optionally - * have a sibling view id {@link android.R.id#empty android.R.id.empty} - * that is to be shown when the list is empty. - * - *

If you are overriding this method with your own custom content, - * consider including the standard layout {@link android.R.layout#list_content} - * in your layout file, so that you continue to retain all of the standard - * behavior of ListFragment. In particular, this is currently the only - * way to have the built-in indeterminant progress state be shown. - */ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - final Context context = getActivity(); - - FrameLayout root = new FrameLayout(context); - - // ------------------------------------------------------------------ - - LinearLayout pframe = new LinearLayout(context); - pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID); - pframe.setOrientation(LinearLayout.VERTICAL); - pframe.setVisibility(View.GONE); - pframe.setGravity(Gravity.CENTER); - - ProgressBar progress = new ProgressBar(context, null, - android.R.attr.progressBarStyleLarge); - pframe.addView(progress, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - - root.addView(pframe, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); - - // ------------------------------------------------------------------ - - FrameLayout lframe = new FrameLayout(context); - lframe.setId(INTERNAL_LIST_CONTAINER_ID); - - TextView tv = new TextView(getActivity()); - tv.setId(INTERNAL_EMPTY_ID); - tv.setGravity(Gravity.CENTER); - lframe.addView(tv, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); - - ListView lv = new ListView(getActivity()); - lv.setId(android.R.id.list); - lv.setDrawSelectorOnTop(false); - lframe.addView(lv, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); - - root.addView(lframe, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); - - // ------------------------------------------------------------------ - - root.setLayoutParams(new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); - - return root; - } - - /** - * Attach to list view once the view hierarchy has been created. - */ - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - ensureList(); - } - - /** - * Detach from list view. - */ - @Override - public void onDestroyView() { - mHandler.removeCallbacks(mRequestFocus); - mList = null; - mListShown = false; - mEmptyView = mProgressContainer = mListContainer = null; - mStandardEmptyView = null; - super.onDestroyView(); - } - - /** - * This method will be called when an item in the list is selected. - * Subclasses should override. Subclasses can call - * getListView().getItemAtPosition(position) if they need to access the - * data associated with the selected item. - * - * @param l The ListView where the click happened - * @param v The view that was clicked within the ListView - * @param position The position of the view in the list - * @param id The row id of the item that was clicked - */ - public void onListItemClick(ListView l, View v, int position, long id) { - } - - /** - * Provide the cursor for the list view. - */ - public void setListAdapter(ListAdapter adapter) { - boolean hadAdapter = mAdapter != null; - mAdapter = adapter; - if (mList != null) { - mList.setAdapter(adapter); - if (!mListShown && !hadAdapter) { - // The list was hidden, and previously didn't have an - // adapter. It is now time to show it. - setListShown(true, getView().getWindowToken() != null); - } - } - } - - /** - * Set the currently selected list item to the specified - * position with the adapter's data - * - * @param position - */ - public void setSelection(int position) { - ensureList(); - mList.setSelection(position); - } - - /** - * Get the position of the currently selected list item. - */ - public int getSelectedItemPosition() { - ensureList(); - return mList.getSelectedItemPosition(); - } - - /** - * Get the cursor row ID of the currently selected list item. - */ - public long getSelectedItemId() { - ensureList(); - return mList.getSelectedItemId(); - } - - /** - * Get the activity's list view widget. - */ - public ListView getListView() { - ensureList(); - return mList; - } - - /** - * The default content for a ListFragment has a TextView that can - * be shown when the list is empty. If you would like to have it - * shown, call this method to supply the text it should use. - */ - public void setEmptyText(CharSequence text) { - ensureList(); - if (mStandardEmptyView == null) { - throw new IllegalStateException("Can't be used with a custom content view"); - } - mStandardEmptyView.setText(text); - if (mEmptyText == null) { - mList.setEmptyView(mStandardEmptyView); - } - mEmptyText = text; - } - - /** - * Control whether the list is being displayed. You can make it not - * displayed if you are waiting for the initial data to show in it. During - * this time an indeterminant progress indicator will be shown instead. - * - *

Applications do not normally need to use this themselves. The default - * behavior of ListFragment is to start with the list not being shown, only - * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}. - * If the list at that point had not been shown, when it does get shown - * it will be do without the user ever seeing the hidden state. - * - * @param shown If true, the list view is shown; if false, the progress - * indicator. The initial value is true. - */ - public void setListShown(boolean shown) { - setListShown(shown, true); - } - - /** - * Like {@link #setListShown(boolean)}, but no animation is used when - * transitioning from the previous state. - */ - public void setListShownNoAnimation(boolean shown) { - setListShown(shown, false); - } - - /** - * Control whether the list is being displayed. You can make it not - * displayed if you are waiting for the initial data to show in it. During - * this time an indeterminant progress indicator will be shown instead. - * - * @param shown If true, the list view is shown; if false, the progress - * indicator. The initial value is true. - * @param animate If true, an animation will be used to transition to the - * new state. - */ - private void setListShown(boolean shown, boolean animate) { - ensureList(); - if (mProgressContainer == null) { - throw new IllegalStateException("Can't be used with a custom content view"); - } - if (mListShown == shown) { - return; - } - mListShown = shown; - if (shown) { - if (animate) { - mProgressContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_out)); - mListContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_in)); - } else { - mProgressContainer.clearAnimation(); - mListContainer.clearAnimation(); - } - mProgressContainer.setVisibility(View.GONE); - mListContainer.setVisibility(View.VISIBLE); - } else { - if (animate) { - mProgressContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_in)); - mListContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_out)); - } else { - mProgressContainer.clearAnimation(); - mListContainer.clearAnimation(); - } - mProgressContainer.setVisibility(View.VISIBLE); - mListContainer.setVisibility(View.GONE); - } - } - - /** - * Get the ListAdapter associated with this activity's ListView. - */ - public ListAdapter getListAdapter() { - return mAdapter; - } - - private void ensureList() { - if (mList != null) { - return; - } - View root = getView(); - if (root == null) { - throw new IllegalStateException("Content view not yet created"); - } - if (root instanceof ListView) { - mList = (ListView)root; - } else { - mStandardEmptyView = (TextView)root.findViewById(INTERNAL_EMPTY_ID); - if (mStandardEmptyView == null) { - mEmptyView = root.findViewById(android.R.id.empty); - } else { - mStandardEmptyView.setVisibility(View.GONE); - } - mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID); - mListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID); - View rawListView = root.findViewById(android.R.id.list); - if (!(rawListView instanceof ListView)) { - if (rawListView == null) { - throw new RuntimeException( - "Your content must have a ListView whose id attribute is " + - "'android.R.id.list'"); - } - throw new RuntimeException( - "Content has view with id attribute 'android.R.id.list' " - + "that is not a ListView class"); - } - mList = (ListView)rawListView; - if (mEmptyView != null) { - mList.setEmptyView(mEmptyView); - } else if (mEmptyText != null) { - mStandardEmptyView.setText(mEmptyText); - mList.setEmptyView(mStandardEmptyView); - } - } - mListShown = true; - mList.setOnItemClickListener(mOnClickListener); - if (mAdapter != null) { - ListAdapter adapter = mAdapter; - mAdapter = null; - setListAdapter(adapter); - } else { - // We are starting without an adapter, so assume we won't - // have our data right away and start with the progress indicator. - if (mProgressContainer != null) { - setListShown(false, false); - } - } - mHandler.post(mRequestFocus); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/LoaderManager.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/LoaderManager.java deleted file mode 100644 index c9d024c..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/LoaderManager.java +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.os.Bundle; -import p.android.support.v4.content.Loader; -import p.android.support.v4.util.DebugUtils; -import p.android.support.v4.util.SparseArrayCompat; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.reflect.Modifier; - -/** - * Static library support version of the framework's {@link android.app.LoaderManager}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework SDK - * documentation for a class overview. - * - *

Your activity must derive from {@link FragmentActivity} to use this. - */ -public abstract class LoaderManager { - /** - * Callback interface for a client to interact with the manager. - */ - public interface LoaderCallbacks { - /** - * Instantiate and return a new Loader for the given ID. - * - * @param id The ID whose loader is to be created. - * @param args Any arguments supplied by the caller. - * @return Return a new Loader instance that is ready to start loading. - */ - public Loader onCreateLoader(int id, Bundle args); - - /** - * Called when a previously created loader has finished its load. Note - * that normally an application is not allowed to commit fragment - * transactions while in this call, since it can happen after an - * activity's state is saved. See {@link FragmentManager#beginTransaction() - * FragmentManager.openTransaction()} for further discussion on this. - * - *

This function is guaranteed to be called prior to the release of - * the last data that was supplied for this Loader. At this point - * you should remove all use of the old data (since it will be released - * soon), but should not do your own release of the data since its Loader - * owns it and will take care of that. The Loader will take care of - * management of its data so you don't have to. In particular: - * - *

    - *
  • The Loader will monitor for changes to the data, and report - * them to you through new calls here. You should not monitor the - * data yourself. For example, if the data is a {@link android.database.Cursor} - * and you place it in a {@link android.widget.CursorAdapter}, use - * the {@link android.widget.CursorAdapter#CursorAdapter(android.content.Context, - * android.database.Cursor, int)} constructor without passing - * in either {@link android.widget.CursorAdapter#FLAG_AUTO_REQUERY} - * or {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER} - * (that is, use 0 for the flags argument). This prevents the CursorAdapter - * from doing its own observing of the Cursor, which is not needed since - * when a change happens you will get a new Cursor throw another call - * here. - *

  • The Loader will release the data once it knows the application - * is no longer using it. For example, if the data is - * a {@link android.database.Cursor} from a {@link android.content.CursorLoader}, - * you should not call close() on it yourself. If the Cursor is being placed in a - * {@link android.widget.CursorAdapter}, you should use the - * {@link android.widget.CursorAdapter#swapCursor(android.database.Cursor)} - * method so that the old Cursor is not closed. - *
- * - * @param loader The Loader that has finished. - * @param data The data generated by the Loader. - */ - public void onLoadFinished(Loader loader, D data); - - /** - * Called when a previously created loader is being reset, and thus - * making its data unavailable. The application should at this point - * remove any references it has to the Loader's data. - * - * @param loader The Loader that is being reset. - */ - public void onLoaderReset(Loader loader); - } - - /** - * Ensures a loader is initialized and active. If the loader doesn't - * already exist, one is created and (if the activity/fragment is currently - * started) starts the loader. Otherwise the last created - * loader is re-used. - * - *

In either case, the given callback is associated with the loader, and - * will be called as the loader state changes. If at the point of call - * the caller is in its started state, and the requested loader - * already exists and has generated its data, then - * callback {@link LoaderCallbacks#onLoadFinished} will - * be called immediately (inside of this function), so you must be prepared - * for this to happen. - * - * @param id A unique identifier for this loader. Can be whatever you want. - * Identifiers are scoped to a particular LoaderManager instance. - * @param args Optional arguments to supply to the loader at construction. - * If a loader already exists (a new one does not need to be created), this - * parameter will be ignored and the last arguments continue to be used. - * @param callback Interface the LoaderManager will call to report about - * changes in the state of the loader. Required. - */ - public abstract Loader initLoader(int id, Bundle args, - LoaderCallbacks callback); - - /** - * Starts a new or restarts an existing {@link android.content.Loader} in - * this manager, registers the callbacks to it, - * and (if the activity/fragment is currently started) starts loading it. - * If a loader with the same id has previously been - * started it will automatically be destroyed when the new loader completes - * its work. The callback will be delivered before the old loader - * is destroyed. - * - * @param id A unique identifier for this loader. Can be whatever you want. - * Identifiers are scoped to a particular LoaderManager instance. - * @param args Optional arguments to supply to the loader at construction. - * @param callback Interface the LoaderManager will call to report about - * changes in the state of the loader. Required. - */ - public abstract Loader restartLoader(int id, Bundle args, - LoaderCallbacks callback); - - /** - * Stops and removes the loader with the given ID. If this loader - * had previously reported data to the client through - * {@link LoaderCallbacks#onLoadFinished(Loader, Object)}, a call - * will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}. - */ - public abstract void destroyLoader(int id); - - /** - * Return the Loader with the given id or null if no matching Loader - * is found. - */ - public abstract Loader getLoader(int id); - - /** - * Print the LoaderManager's state into the given stream. - * - * @param prefix Text to print at the front of each line. - * @param fd The raw file descriptor that the dump is being sent to. - * @param writer A PrintWriter to which the dump is to be set. - * @param args Additional arguments to the dump request. - */ - public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args); - - /** - * Control whether the framework's internal loader manager debugging - * logs are turned on. If enabled, you will see output in logcat as - * the framework performs loader operations. - */ - public static void enableDebugLogging(boolean enabled) { - LoaderManagerImpl.DEBUG = enabled; - } - - /** - * Returns true if any loaders managed are currently running and have not - * returned data to the application yet. - */ - public boolean hasRunningLoaders() { return false; } -} - -/** - * @hide - */ -class LoaderManagerImpl extends LoaderManager { - static final String TAG = "LoaderManager"; - static boolean DEBUG = false; - - // These are the currently active loaders. A loader is here - // from the time its load is started until it has been explicitly - // stopped or restarted by the application. - final SparseArrayCompat mLoaders = new SparseArrayCompat(); - - // These are previously run loaders. This list is maintained internally - // to avoid destroying a loader while an application is still using it. - // It allows an application to restart a loader, but continue using its - // previously run loader until the new loader's data is available. - final SparseArrayCompat mInactiveLoaders = new SparseArrayCompat(); - - final String mWho; - - boolean mStarted; - boolean mRetaining; - boolean mRetainingStarted; - - boolean mCreatingLoader; - private FragmentHostCallback mHost; - - final class LoaderInfo implements Loader.OnLoadCompleteListener, - Loader.OnLoadCanceledListener { - final int mId; - final Bundle mArgs; - LoaderCallbacks mCallbacks; - Loader mLoader; - boolean mHaveData; - boolean mDeliveredData; - Object mData; - @SuppressWarnings("hiding") - boolean mStarted; - @SuppressWarnings("hiding") - boolean mRetaining; - @SuppressWarnings("hiding") - boolean mRetainingStarted; - boolean mReportNextStart; - boolean mDestroyed; - boolean mListenerRegistered; - - LoaderInfo mPendingLoader; - - public LoaderInfo(int id, Bundle args, LoaderCallbacks callbacks) { - mId = id; - mArgs = args; - mCallbacks = callbacks; - } - - void start() { - if (mRetaining && mRetainingStarted) { - // Our owner is started, but we were being retained from a - // previous instance in the started state... so there is really - // nothing to do here, since the loaders are still started. - mStarted = true; - return; - } - - if (mStarted) { - // If loader already started, don't restart. - return; - } - - mStarted = true; - - if (DEBUG) Log.v(TAG, " Starting: " + this); - if (mLoader == null && mCallbacks != null) { - mLoader = mCallbacks.onCreateLoader(mId, mArgs); - } - if (mLoader != null) { - if (mLoader.getClass().isMemberClass() - && !Modifier.isStatic(mLoader.getClass().getModifiers())) { - throw new IllegalArgumentException( - "Object returned from onCreateLoader must not be a non-static inner member class: " - + mLoader); - } - if (!mListenerRegistered) { - mLoader.registerListener(mId, this); - mLoader.registerOnLoadCanceledListener(this); - mListenerRegistered = true; - } - mLoader.startLoading(); - } - } - - void retain() { - if (DEBUG) Log.v(TAG, " Retaining: " + this); - mRetaining = true; - mRetainingStarted = mStarted; - mStarted = false; - mCallbacks = null; - } - - void finishRetain() { - if (mRetaining) { - if (DEBUG) Log.v(TAG, " Finished Retaining: " + this); - mRetaining = false; - if (mStarted != mRetainingStarted) { - if (!mStarted) { - // This loader was retained in a started state, but - // at the end of retaining everything our owner is - // no longer started... so make it stop. - stop(); - } - } - } - - if (mStarted && mHaveData && !mReportNextStart) { - // This loader has retained its data, either completely across - // a configuration change or just whatever the last data set - // was after being restarted from a stop, and now at the point of - // finishing the retain we find we remain started, have - // our data, and the owner has a new callback... so - // let's deliver the data now. - callOnLoadFinished(mLoader, mData); - } - } - - void reportStart() { - if (mStarted) { - if (mReportNextStart) { - mReportNextStart = false; - if (mHaveData) { - callOnLoadFinished(mLoader, mData); - } - } - } - } - - void stop() { - if (DEBUG) Log.v(TAG, " Stopping: " + this); - mStarted = false; - if (!mRetaining) { - if (mLoader != null && mListenerRegistered) { - // Let the loader know we're done with it - mListenerRegistered = false; - mLoader.unregisterListener(this); - mLoader.unregisterOnLoadCanceledListener(this); - mLoader.stopLoading(); - } - } - } - - void cancel() { - if (DEBUG) Log.v(TAG, " Canceling: " + this); - if (mStarted && mLoader != null && mListenerRegistered) { - if (!mLoader.cancelLoad()) { - onLoadCanceled(mLoader); - } - } - } - - void destroy() { - if (DEBUG) Log.v(TAG, " Destroying: " + this); - mDestroyed = true; - boolean needReset = mDeliveredData; - mDeliveredData = false; - if (mCallbacks != null && mLoader != null && mHaveData && needReset) { - if (DEBUG) Log.v(TAG, " Reseting: " + this); - String lastBecause = null; - if (mHost != null) { - lastBecause = mHost.mFragmentManager.mNoTransactionsBecause; - mHost.mFragmentManager.mNoTransactionsBecause = "onLoaderReset"; - } - try { - mCallbacks.onLoaderReset(mLoader); - } finally { - if (mHost != null) { - mHost.mFragmentManager.mNoTransactionsBecause = lastBecause; - } - } - } - mCallbacks = null; - mData = null; - mHaveData = false; - if (mLoader != null) { - if (mListenerRegistered) { - mListenerRegistered = false; - mLoader.unregisterListener(this); - mLoader.unregisterOnLoadCanceledListener(this); - } - mLoader.reset(); - } - if (mPendingLoader != null) { - mPendingLoader.destroy(); - } - } - - @Override - public void onLoadCanceled(Loader loader) { - if (DEBUG) Log.v(TAG, "onLoadCanceled: " + this); - - if (mDestroyed) { - if (DEBUG) Log.v(TAG, " Ignoring load canceled -- destroyed"); - return; - } - - if (mLoaders.get(mId) != this) { - // This cancellation message is not coming from the current active loader. - // We don't care about it. - if (DEBUG) Log.v(TAG, " Ignoring load canceled -- not active"); - return; - } - - LoaderInfo pending = mPendingLoader; - if (pending != null) { - // There is a new request pending and we were just - // waiting for the old one to cancel or complete before starting - // it. So now it is time, switch over to the new loader. - if (DEBUG) Log.v(TAG, " Switching to pending loader: " + pending); - mPendingLoader = null; - mLoaders.put(mId, null); - destroy(); - installLoader(pending); - } - } - - @Override - public void onLoadComplete(Loader loader, Object data) { - if (DEBUG) Log.v(TAG, "onLoadComplete: " + this); - - if (mDestroyed) { - if (DEBUG) Log.v(TAG, " Ignoring load complete -- destroyed"); - return; - } - - if (mLoaders.get(mId) != this) { - // This data is not coming from the current active loader. - // We don't care about it. - if (DEBUG) Log.v(TAG, " Ignoring load complete -- not active"); - return; - } - - LoaderInfo pending = mPendingLoader; - if (pending != null) { - // There is a new request pending and we were just - // waiting for the old one to complete before starting - // it. So now it is time, switch over to the new loader. - if (DEBUG) Log.v(TAG, " Switching to pending loader: " + pending); - mPendingLoader = null; - mLoaders.put(mId, null); - destroy(); - installLoader(pending); - return; - } - - // Notify of the new data so the app can switch out the old data before - // we try to destroy it. - if (mData != data || !mHaveData) { - mData = data; - mHaveData = true; - if (mStarted) { - callOnLoadFinished(loader, data); - } - } - - //if (DEBUG) Log.v(TAG, " onLoadFinished returned: " + this); - - // We have now given the application the new loader with its - // loaded data, so it should have stopped using the previous - // loader. If there is a previous loader on the inactive list, - // clean it up. - LoaderInfo info = mInactiveLoaders.get(mId); - if (info != null && info != this) { - info.mDeliveredData = false; - info.destroy(); - mInactiveLoaders.remove(mId); - } - - if (mHost != null && !hasRunningLoaders()) { - mHost.mFragmentManager.startPendingDeferredFragments(); - } - } - - void callOnLoadFinished(Loader loader, Object data) { - if (mCallbacks != null) { - String lastBecause = null; - if (mHost != null) { - lastBecause = mHost.mFragmentManager.mNoTransactionsBecause; - mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished"; - } - try { - if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": " - + loader.dataToString(data)); - mCallbacks.onLoadFinished(loader, data); - } finally { - if (mHost != null) { - mHost.mFragmentManager.mNoTransactionsBecause = lastBecause; - } - } - mDeliveredData = true; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - sb.append("LoaderInfo{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" #"); - sb.append(mId); - sb.append(" : "); - DebugUtils.buildShortClassTag(mLoader, sb); - sb.append("}}"); - return sb.toString(); - } - - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - writer.print(prefix); writer.print("mId="); writer.print(mId); - writer.print(" mArgs="); writer.println(mArgs); - writer.print(prefix); writer.print("mCallbacks="); writer.println(mCallbacks); - writer.print(prefix); writer.print("mLoader="); writer.println(mLoader); - if (mLoader != null) { - mLoader.dump(prefix + " ", fd, writer, args); - } - if (mHaveData || mDeliveredData) { - writer.print(prefix); writer.print("mHaveData="); writer.print(mHaveData); - writer.print(" mDeliveredData="); writer.println(mDeliveredData); - writer.print(prefix); writer.print("mData="); writer.println(mData); - } - writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); - writer.print(" mReportNextStart="); writer.print(mReportNextStart); - writer.print(" mDestroyed="); writer.println(mDestroyed); - writer.print(prefix); writer.print("mRetaining="); writer.print(mRetaining); - writer.print(" mRetainingStarted="); writer.print(mRetainingStarted); - writer.print(" mListenerRegistered="); writer.println(mListenerRegistered); - if (mPendingLoader != null) { - writer.print(prefix); writer.println("Pending Loader "); - writer.print(mPendingLoader); writer.println(":"); - mPendingLoader.dump(prefix + " ", fd, writer, args); - } - } - } - - LoaderManagerImpl(String who, FragmentHostCallback host, boolean started) { - mWho = who; - mHost = host; - mStarted = started; - } - - void updateHostController(FragmentHostCallback host) { - mHost = host; - } - - private LoaderInfo createLoader(int id, Bundle args, - LoaderCallbacks callback) { - LoaderInfo info = new LoaderInfo(id, args, callback); - Loader loader = callback.onCreateLoader(id, args); - info.mLoader = loader; - return info; - } - - private LoaderInfo createAndInstallLoader(int id, Bundle args, - LoaderCallbacks callback) { - try { - mCreatingLoader = true; - LoaderInfo info = createLoader(id, args, callback); - installLoader(info); - return info; - } finally { - mCreatingLoader = false; - } - } - - void installLoader(LoaderInfo info) { - mLoaders.put(info.mId, info); - if (mStarted) { - // The activity will start all existing loaders in it's onStart(), - // so only start them here if we're past that point of the activitiy's - // life cycle - info.start(); - } - } - - /** - * Call to initialize a particular ID with a Loader. If this ID already - * has a Loader associated with it, it is left unchanged and any previous - * callbacks replaced with the newly provided ones. If there is not currently - * a Loader for the ID, a new one is created and started. - * - *

This function should generally be used when a component is initializing, - * to ensure that a Loader it relies on is created. This allows it to re-use - * an existing Loader's data if there already is one, so that for example - * when an {@link Activity} is re-created after a configuration change it - * does not need to re-create its loaders. - * - *

Note that in the case where an existing Loader is re-used, the - * args given here will be ignored because you will - * continue using the previous Loader. - * - * @param id A unique (to this LoaderManager instance) identifier under - * which to manage the new Loader. - * @param args Optional arguments that will be propagated to - * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}. - * @param callback Interface implementing management of this Loader. Required. - * Its onCreateLoader() method will be called while inside of the function to - * instantiate the Loader object. - */ - @SuppressWarnings("unchecked") - public Loader initLoader(int id, Bundle args, LoaderCallbacks callback) { - if (mCreatingLoader) { - throw new IllegalStateException("Called while creating a loader"); - } - - LoaderInfo info = mLoaders.get(id); - - if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args); - - if (info == null) { - // Loader doesn't already exist; create. - info = createAndInstallLoader(id, args, (LoaderCallbacks)callback); - if (DEBUG) Log.v(TAG, " Created new loader " + info); - } else { - if (DEBUG) Log.v(TAG, " Re-using existing loader " + info); - info.mCallbacks = (LoaderCallbacks)callback; - } - - if (info.mHaveData && mStarted) { - // If the loader has already generated its data, report it now. - info.callOnLoadFinished(info.mLoader, info.mData); - } - - return (Loader)info.mLoader; - } - - /** - * Call to re-create the Loader associated with a particular ID. If there - * is currently a Loader associated with this ID, it will be - * canceled/stopped/destroyed as appropriate. A new Loader with the given - * arguments will be created and its data delivered to you once available. - * - *

This function does some throttling of Loaders. If too many Loaders - * have been created for the given ID but not yet generated their data, - * new calls to this function will create and return a new Loader but not - * actually start it until some previous loaders have completed. - * - *

After calling this function, any previous Loaders associated with - * this ID will be considered invalid, and you will receive no further - * data updates from them. - * - * @param id A unique (to this LoaderManager instance) identifier under - * which to manage the new Loader. - * @param args Optional arguments that will be propagated to - * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}. - * @param callback Interface implementing management of this Loader. Required. - * Its onCreateLoader() method will be called while inside of the function to - * instantiate the Loader object. - */ - @SuppressWarnings("unchecked") - public Loader restartLoader(int id, Bundle args, LoaderCallbacks callback) { - if (mCreatingLoader) { - throw new IllegalStateException("Called while creating a loader"); - } - - LoaderInfo info = mLoaders.get(id); - if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args); - if (info != null) { - LoaderInfo inactive = mInactiveLoaders.get(id); - if (inactive != null) { - if (info.mHaveData) { - // This loader now has data... we are probably being - // called from within onLoadComplete, where we haven't - // yet destroyed the last inactive loader. So just do - // that now. - if (DEBUG) Log.v(TAG, " Removing last inactive loader: " + info); - inactive.mDeliveredData = false; - inactive.destroy(); - info.mLoader.abandon(); - mInactiveLoaders.put(id, info); - } else { - // We already have an inactive loader for this ID that we are - // waiting for! What to do, what to do... - if (!info.mStarted) { - // The current Loader has not been started... we thus - // have no reason to keep it around, so bam, slam, - // thank-you-ma'am. - if (DEBUG) Log.v(TAG, " Current loader is stopped; replacing"); - mLoaders.put(id, null); - info.destroy(); - } else { - // Now we have three active loaders... we'll queue - // up this request to be processed once one of the other loaders - // finishes or is canceled. - if (DEBUG) Log.v(TAG, " Current loader is running; attempting to cancel"); - info.cancel(); - if (info.mPendingLoader != null) { - if (DEBUG) Log.v(TAG, " Removing pending loader: " + info.mPendingLoader); - info.mPendingLoader.destroy(); - info.mPendingLoader = null; - } - if (DEBUG) Log.v(TAG, " Enqueuing as new pending loader"); - info.mPendingLoader = createLoader(id, args, - (LoaderCallbacks)callback); - return (Loader)info.mPendingLoader.mLoader; - } - } - } else { - // Keep track of the previous instance of this loader so we can destroy - // it when the new one completes. - if (DEBUG) Log.v(TAG, " Making last loader inactive: " + info); - info.mLoader.abandon(); - mInactiveLoaders.put(id, info); - } - } - - info = createAndInstallLoader(id, args, (LoaderCallbacks)callback); - return (Loader)info.mLoader; - } - - /** - * Rip down, tear apart, shred to pieces a current Loader ID. After returning - * from this function, any Loader objects associated with this ID are - * destroyed. Any data associated with them is destroyed. You better not - * be using it when you do this. - * @param id Identifier of the Loader to be destroyed. - */ - public void destroyLoader(int id) { - if (mCreatingLoader) { - throw new IllegalStateException("Called while creating a loader"); - } - - if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id); - int idx = mLoaders.indexOfKey(id); - if (idx >= 0) { - LoaderInfo info = mLoaders.valueAt(idx); - mLoaders.removeAt(idx); - info.destroy(); - } - idx = mInactiveLoaders.indexOfKey(id); - if (idx >= 0) { - LoaderInfo info = mInactiveLoaders.valueAt(idx); - mInactiveLoaders.removeAt(idx); - info.destroy(); - } - if (mHost != null && !hasRunningLoaders()) { - mHost.mFragmentManager.startPendingDeferredFragments(); - } - } - - /** - * Return the most recent Loader object associated with the - * given ID. - */ - @SuppressWarnings("unchecked") - public Loader getLoader(int id) { - if (mCreatingLoader) { - throw new IllegalStateException("Called while creating a loader"); - } - - LoaderInfo loaderInfo = mLoaders.get(id); - if (loaderInfo != null) { - if (loaderInfo.mPendingLoader != null) { - return (Loader)loaderInfo.mPendingLoader.mLoader; - } - return (Loader)loaderInfo.mLoader; - } - return null; - } - - void doStart() { - if (DEBUG) Log.v(TAG, "Starting in " + this); - if (mStarted) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Log.w(TAG, "Called doStart when already started: " + this, e); - return; - } - - mStarted = true; - - // Call out to sub classes so they can start their loaders - // Let the existing loaders know that we want to be notified when a load is complete - for (int i = mLoaders.size()-1; i >= 0; i--) { - mLoaders.valueAt(i).start(); - } - } - - void doStop() { - if (DEBUG) Log.v(TAG, "Stopping in " + this); - if (!mStarted) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Log.w(TAG, "Called doStop when not started: " + this, e); - return; - } - - for (int i = mLoaders.size()-1; i >= 0; i--) { - mLoaders.valueAt(i).stop(); - } - mStarted = false; - } - - void doRetain() { - if (DEBUG) Log.v(TAG, "Retaining in " + this); - if (!mStarted) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Log.w(TAG, "Called doRetain when not started: " + this, e); - return; - } - - mRetaining = true; - mStarted = false; - for (int i = mLoaders.size()-1; i >= 0; i--) { - mLoaders.valueAt(i).retain(); - } - } - - void finishRetain() { - if (mRetaining) { - if (DEBUG) Log.v(TAG, "Finished Retaining in " + this); - - mRetaining = false; - for (int i = mLoaders.size()-1; i >= 0; i--) { - mLoaders.valueAt(i).finishRetain(); - } - } - } - - void doReportNextStart() { - for (int i = mLoaders.size()-1; i >= 0; i--) { - mLoaders.valueAt(i).mReportNextStart = true; - } - } - - void doReportStart() { - for (int i = mLoaders.size()-1; i >= 0; i--) { - mLoaders.valueAt(i).reportStart(); - } - } - - void doDestroy() { - if (!mRetaining) { - if (DEBUG) Log.v(TAG, "Destroying Active in " + this); - for (int i = mLoaders.size()-1; i >= 0; i--) { - mLoaders.valueAt(i).destroy(); - } - mLoaders.clear(); - } - - if (DEBUG) Log.v(TAG, "Destroying Inactive in " + this); - for (int i = mInactiveLoaders.size()-1; i >= 0; i--) { - mInactiveLoaders.valueAt(i).destroy(); - } - mInactiveLoaders.clear(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(128); - sb.append("LoaderManager{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" in "); - DebugUtils.buildShortClassTag(mHost, sb); - sb.append("}}"); - return sb.toString(); - } - - @Override - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - if (mLoaders.size() > 0) { - writer.print(prefix); writer.println("Active Loaders:"); - String innerPrefix = prefix + " "; - for (int i=0; i < mLoaders.size(); i++) { - LoaderInfo li = mLoaders.valueAt(i); - writer.print(prefix); writer.print(" #"); writer.print(mLoaders.keyAt(i)); - writer.print(": "); writer.println(li.toString()); - li.dump(innerPrefix, fd, writer, args); - } - } - if (mInactiveLoaders.size() > 0) { - writer.print(prefix); writer.println("Inactive Loaders:"); - String innerPrefix = prefix + " "; - for (int i=0; i < mInactiveLoaders.size(); i++) { - LoaderInfo li = mInactiveLoaders.valueAt(i); - writer.print(prefix); writer.print(" #"); writer.print(mInactiveLoaders.keyAt(i)); - writer.print(": "); writer.println(li.toString()); - li.dump(innerPrefix, fd, writer, args); - } - } - } - - @Override - public boolean hasRunningLoaders() { - boolean loadersRunning = false; - final int count = mLoaders.size(); - for (int i = 0; i < count; i++) { - final LoaderInfo li = mLoaders.valueAt(i); - loadersRunning |= li.mStarted && !li.mDeliveredData; - } - return loadersRunning; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NavUtils.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NavUtils.java deleted file mode 100644 index da7851f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NavUtils.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import p.android.support.v4.content.IntentCompat; -import p.android.support.annotation.Nullable; -import android.util.Log; - -/** - * NavUtils provides helper functionality for applications implementing - * recommended Android UI navigation patterns. For information about recommended - * navigation patterns see - * Tasks and Back Stack - * from the developer guide and Navigation - * from the design guide. - */ -public final class NavUtils { - private static final String TAG = "NavUtils"; - public static final String PARENT_ACTIVITY = "android.support.PARENT_ACTIVITY"; - - interface NavUtilsImpl { - Intent getParentActivityIntent(Activity activity); - boolean shouldUpRecreateTask(Activity activity, Intent targetIntent); - void navigateUpTo(Activity activity, Intent upIntent); - String getParentActivityName(Context context, ActivityInfo info); - } - - static class NavUtilsImplBase implements NavUtilsImpl { - - @Override - public Intent getParentActivityIntent(Activity activity) { - String parentName = NavUtils.getParentActivityName(activity); - if (parentName == null) return null; - - // If the parent itself has no parent, generate a main activity intent. - final ComponentName target = new ComponentName(activity, parentName); - try { - final String grandparent = NavUtils.getParentActivityName(activity, target); - final Intent parentIntent = grandparent == null - ? IntentCompat.makeMainActivity(target) - : new Intent().setComponent(target); - return parentIntent; - } catch (NameNotFoundException e) { - Log.e(TAG, "getParentActivityIntent: bad parentActivityName '" + parentName + - "' in manifest"); - return null; - } - } - - @Override - public boolean shouldUpRecreateTask(Activity activity, Intent targetIntent) { - String action = activity.getIntent().getAction(); - return action != null && !action.equals(Intent.ACTION_MAIN); - } - - @Override - public void navigateUpTo(Activity activity, Intent upIntent) { - upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - activity.startActivity(upIntent); - activity.finish(); - } - - @Override - public String getParentActivityName(Context context, ActivityInfo info) { - if (info.metaData == null) return null; - String parentActivity = info.metaData.getString(PARENT_ACTIVITY); - if (parentActivity == null) return null; - if (parentActivity.charAt(0) == '.') { - parentActivity = context.getPackageName() + parentActivity; - } - return parentActivity; - } - } - - static class NavUtilsImplJB extends NavUtilsImplBase { - - @Override - public Intent getParentActivityIntent(Activity activity) { - // Prefer the "real" JB definition if available, - // else fall back to the meta-data element. - Intent result = NavUtilsJB.getParentActivityIntent(activity); - if (result == null) { - result = superGetParentActivityIntent(activity); - } - return result; - } - - Intent superGetParentActivityIntent(Activity activity) { - return super.getParentActivityIntent(activity); - } - - @Override - public boolean shouldUpRecreateTask(Activity activity, Intent targetIntent) { - return NavUtilsJB.shouldUpRecreateTask(activity, targetIntent); - } - - @Override - public void navigateUpTo(Activity activity, Intent upIntent) { - NavUtilsJB.navigateUpTo(activity, upIntent); - } - - @Override - public String getParentActivityName(Context context, ActivityInfo info) { - String result = NavUtilsJB.getParentActivityName(info); - if (result == null) { - result = super.getParentActivityName(context, info); - } - return result; - } - } - - private static final NavUtilsImpl IMPL; - - static { - final int version = android.os.Build.VERSION.SDK_INT; - if (version >= 16) { - IMPL = new NavUtilsImplJB(); - } else { - IMPL = new NavUtilsImplBase(); - } - } - - /** - * Returns true if sourceActivity should recreate the task when navigating 'up' - * by using targetIntent. - * - *

If this method returns false the app can trivially call - * {@link #navigateUpTo(Activity, Intent)} using the same parameters to correctly perform - * up navigation. If this method returns true, the app should synthesize a new task stack - * by using {@link TaskStackBuilder} or another similar mechanism to perform up navigation.

- * - * @param sourceActivity The current activity from which the user is attempting to navigate up - * @param targetIntent An intent representing the target destination for up navigation - * @return true if navigating up should recreate a new task stack, false if the same task - * should be used for the destination - */ - public static boolean shouldUpRecreateTask(Activity sourceActivity, Intent targetIntent) { - return IMPL.shouldUpRecreateTask(sourceActivity, targetIntent); - } - - /** - * Convenience method that is equivalent to calling - * {@link #navigateUpTo(Activity, Intent) navigateUpTo}(sourceActivity, - * {@link #getParentActivityIntent(Activity) getParentActivityIntent} (sourceActivity)). - * sourceActivity will be finished by this call. - * - *

Note: This method should only be used when sourceActivity and the corresponding - * parent are within the same task. If up navigation should cross tasks in some cases, see - * {@link #shouldUpRecreateTask(Activity, Intent)}.

- * - * @param sourceActivity The current activity from which the user is attempting to navigate up - */ - public static void navigateUpFromSameTask(Activity sourceActivity) { - Intent upIntent = getParentActivityIntent(sourceActivity); - - if (upIntent == null) { - throw new IllegalArgumentException("Activity " + - sourceActivity.getClass().getSimpleName() + - " does not have a parent activity name specified." + - " (Did you forget to add the android.support.PARENT_ACTIVITY " + - " element in your manifest?)"); - } - - navigateUpTo(sourceActivity, upIntent); - } - - /** - * Navigate from sourceActivity to the activity specified by upIntent, finishing sourceActivity - * in the process. upIntent will have the flag {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} set - * by this method, along with any others required for proper up navigation as outlined - * in the Android Design Guide. - * - *

This method should be used when performing up navigation from within the same task - * as the destination. If up navigation should cross tasks in some cases, see - * {@link #shouldUpRecreateTask(Activity, Intent)}.

- * - * @param sourceActivity The current activity from which the user is attempting to navigate up - * @param upIntent An intent representing the target destination for up navigation - */ - public static void navigateUpTo(Activity sourceActivity, Intent upIntent) { - IMPL.navigateUpTo(sourceActivity, upIntent); - } - - /** - * Obtain an {@link Intent} that will launch an explicit target activity - * specified by sourceActivity's {@link #PARENT_ACTIVITY} <meta-data> - * element in the application's manifest. If the device is running - * Jellybean or newer, the android:parentActivityName attribute will be preferred - * if it is present. - * - * @param sourceActivity Activity to fetch a parent intent for - * @return a new Intent targeting the defined parent activity of sourceActivity - */ - public static Intent getParentActivityIntent(Activity sourceActivity) { - return IMPL.getParentActivityIntent(sourceActivity); - } - - /** - * Obtain an {@link Intent} that will launch an explicit target activity - * specified by sourceActivityClass's {@link #PARENT_ACTIVITY} <meta-data> - * element in the application's manifest. - * - * @param context Context for looking up the activity component for sourceActivityClass - * @param sourceActivityClass {@link Class} object for an Activity class - * @return a new Intent targeting the defined parent activity of sourceActivity - * @throws NameNotFoundException if the ComponentName for sourceActivityClass is invalid - */ - public static Intent getParentActivityIntent(Context context, Class sourceActivityClass) - throws NameNotFoundException { - String parentActivity = getParentActivityName(context, - new ComponentName(context, sourceActivityClass)); - if (parentActivity == null) return null; - - // If the parent itself has no parent, generate a main activity intent. - final ComponentName target = new ComponentName(context, parentActivity); - final String grandparent = getParentActivityName(context, target); - final Intent parentIntent = grandparent == null - ? IntentCompat.makeMainActivity(target) - : new Intent().setComponent(target); - return parentIntent; - } - - /** - * Obtain an {@link Intent} that will launch an explicit target activity - * specified by sourceActivityClass's {@link #PARENT_ACTIVITY} <meta-data> - * element in the application's manifest. - * - * @param context Context for looking up the activity component for the source activity - * @param componentName ComponentName for the source Activity - * @return a new Intent targeting the defined parent activity of sourceActivity - * @throws NameNotFoundException if the ComponentName for sourceActivityClass is invalid - */ - public static Intent getParentActivityIntent(Context context, ComponentName componentName) - throws NameNotFoundException { - String parentActivity = getParentActivityName(context, componentName); - if (parentActivity == null) return null; - - // If the parent itself has no parent, generate a main activity intent. - final ComponentName target = new ComponentName( - componentName.getPackageName(), parentActivity); - final String grandparent = getParentActivityName(context, target); - final Intent parentIntent = grandparent == null - ? IntentCompat.makeMainActivity(target) - : new Intent().setComponent(target); - return parentIntent; - } - - /** - * Return the fully qualified class name of sourceActivity's parent activity as specified by - * a {@link #PARENT_ACTIVITY} <meta-data> element within the activity element in - * the application's manifest. - * - * @param sourceActivity Activity to fetch a parent class name for - * @return The fully qualified class name of sourceActivity's parent activity or null if - * it was not specified - */ - @Nullable - public static String getParentActivityName(Activity sourceActivity) { - try { - return getParentActivityName(sourceActivity, sourceActivity.getComponentName()); - } catch (NameNotFoundException e) { - // Component name of supplied activity does not exist...? - throw new IllegalArgumentException(e); - } - } - /** - * Return the fully qualified class name of a source activity's parent activity as specified by - * a {@link #PARENT_ACTIVITY} <meta-data> element within the activity element in - * the application's manifest. The source activity is provided by componentName. - * - * @param context Context for looking up the activity component for the source activity - * @param componentName ComponentName for the source Activity - * @return The fully qualified class name of sourceActivity's parent activity or null if - * it was not specified - */ - @Nullable - public static String getParentActivityName(Context context, ComponentName componentName) - throws NameNotFoundException { - PackageManager pm = context.getPackageManager(); - ActivityInfo info = pm.getActivityInfo(componentName, PackageManager.GET_META_DATA); - String parentActivity = IMPL.getParentActivityName(context, info); - return parentActivity; - } - - /** No instances! */ - private NavUtils() { - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NavUtilsJB.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NavUtilsJB.java deleted file mode 100644 index 250343c..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NavUtilsJB.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Intent; -import android.content.pm.ActivityInfo; - -class NavUtilsJB { - public static Intent getParentActivityIntent(Activity activity) { - return activity.getParentActivityIntent(); - } - - public static boolean shouldUpRecreateTask(Activity activity, Intent targetIntent) { - return activity.shouldUpRecreateTask(targetIntent); - } - - public static void navigateUpTo(Activity activity, Intent upIntent) { - activity.navigateUpTo(upIntent); - } - - public static String getParentActivityName(ActivityInfo info) { - return info.parentActivityName; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NoSaveStateFrameLayout.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NoSaveStateFrameLayout.java deleted file mode 100644 index e9c05ba..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NoSaveStateFrameLayout.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.content.Context; -import android.os.Parcelable; -import android.util.SparseArray; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -/** - * Pre-Honeycomb versions of the platform don't have {@link View#setSaveFromParentEnabled(boolean)}, - * so instead we insert this between the view and its parent. - */ -class NoSaveStateFrameLayout extends FrameLayout { - static ViewGroup wrap(View child) { - NoSaveStateFrameLayout wrapper = new NoSaveStateFrameLayout(child.getContext()); - ViewGroup.LayoutParams childParams = child.getLayoutParams(); - if (childParams != null) { - wrapper.setLayoutParams(childParams); - } - LayoutParams lp = new LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); - child.setLayoutParams(lp); - wrapper.addView(child); - return wrapper; - } - - public NoSaveStateFrameLayout(Context context) { - super(context); - } - - /** - * Override to prevent freezing of any child views. - */ - @Override - protected void dispatchSaveInstanceState(SparseArray container) { - dispatchFreezeSelfOnly(container); - } - - /** - * Override to prevent thawing of any child views. - */ - @Override - protected void dispatchRestoreInstanceState(SparseArray container) { - dispatchThawSelfOnly(container); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationBuilderWithActions.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationBuilderWithActions.java deleted file mode 100644 index 48d38f7..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationBuilderWithActions.java +++ /dev/null @@ -1,24 +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 p.android.support.v4.app; - -/** - * Interface implemented by notification compat builders that support adding actions. - */ -interface NotificationBuilderWithActions { - public void addAction(NotificationCompatBase.Action action); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationBuilderWithBuilderAccessor.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationBuilderWithBuilderAccessor.java deleted file mode 100644 index ce1d8bd..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationBuilderWithBuilderAccessor.java +++ /dev/null @@ -1,31 +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 p.android.support.v4.app; - -import android.app.Notification; - -/** - * Interface implemented by notification compat builders that support - * an accessor for {@link Notification.Builder}. {@link Notification.Builder} - * was introduced in HoneyComb. - * - * @hide - */ -public interface NotificationBuilderWithBuilderAccessor { - public Notification.Builder getBuilder(); - public Notification build(); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompat.java deleted file mode 100644 index 041e3bc..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompat.java +++ /dev/null @@ -1,3361 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Parcelable; -import p.android.support.annotation.ColorInt; -import p.android.support.v4.view.GravityCompat; -import android.view.Gravity; -import android.widget.RemoteViews; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Helper for accessing features in {@link Notification} - * introduced after API level 4 in a backwards compatible fashion. - */ -public class NotificationCompat { - - /** - * Use all default values (where applicable). - */ - public static final int DEFAULT_ALL = ~0; - - /** - * Use the default notification sound. This will ignore any sound set using - * {@link Builder#setSound} - * - *

- * A notification that is noisy is more likely to be presented as a heads-up notification, - * on some platforms. - *

- * - * @see Builder#setDefaults - */ - public static final int DEFAULT_SOUND = 1; - - /** - * Use the default notification vibrate. This will ignore any vibrate set using - * {@link Builder#setVibrate}. Using phone vibration requires the - * {@link android.Manifest.permission#VIBRATE VIBRATE} permission. - * - *

- * A notification that vibrates is more likely to be presented as a heads-up notification, - * on some platforms. - *

- * - * @see Builder#setDefaults - */ - public static final int DEFAULT_VIBRATE = 2; - - /** - * Use the default notification lights. This will ignore the - * {@link #FLAG_SHOW_LIGHTS} bit, and values set with {@link Builder#setLights}. - * - * @see Builder#setDefaults - */ - public static final int DEFAULT_LIGHTS = 4; - - /** - * Use this constant as the value for audioStreamType to request that - * the default stream type for notifications be used. Currently the - * default stream type is {@link AudioManager#STREAM_NOTIFICATION}. - */ - public static final int STREAM_DEFAULT = -1; - - /** - * Bit set in the Notification flags field when LEDs should be turned on - * for this notification. - */ - public static final int FLAG_SHOW_LIGHTS = 0x00000001; - - /** - * Bit set in the Notification flags field if this notification is in - * reference to something that is ongoing, like a phone call. It should - * not be set if this notification is in reference to something that - * happened at a particular point in time, like a missed phone call. - */ - public static final int FLAG_ONGOING_EVENT = 0x00000002; - - /** - * Bit set in the Notification flags field if - * the audio will be repeated until the notification is - * cancelled or the notification window is opened. - */ - public static final int FLAG_INSISTENT = 0x00000004; - - /** - * Bit set in the Notification flags field if the notification's sound, - * vibrate and ticker should only be played if the notification is not already showing. - */ - public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008; - - /** - * Bit set in the Notification flags field if the notification should be canceled when - * it is clicked by the user. - */ - public static final int FLAG_AUTO_CANCEL = 0x00000010; - - /** - * Bit set in the Notification flags field if the notification should not be canceled - * when the user clicks the Clear all button. - */ - public static final int FLAG_NO_CLEAR = 0x00000020; - - /** - * Bit set in the Notification flags field if this notification represents a currently - * running service. This will normally be set for you by - * {@link android.app.Service#startForeground}. - */ - public static final int FLAG_FOREGROUND_SERVICE = 0x00000040; - - /** - * Obsolete flag indicating high-priority notifications; use the priority field instead. - * - * @deprecated Use {@link Builder#setPriority(int)} with a positive value. - */ - public static final int FLAG_HIGH_PRIORITY = 0x00000080; - - /** - * Bit set in the Notification flags field if this notification is relevant to the current - * device only and it is not recommended that it bridge to other devices. - */ - public static final int FLAG_LOCAL_ONLY = 0x00000100; - - /** - * Bit set in the Notification flags field if this notification is the group summary for a - * group of notifications. Grouped notifications may display in a cluster or stack on devices - * which support such rendering. Requires a group key also be set using - * {@link Builder#setGroup}. - */ - public static final int FLAG_GROUP_SUMMARY = 0x00000200; - - /** - * Default notification priority for {@link Builder#setPriority(int)}. - * If your application does not prioritize its own notifications, - * use this value for all notifications. - */ - public static final int PRIORITY_DEFAULT = 0; - - /** - * Lower notification priority for {@link Builder#setPriority(int)}, - * for items that are less important. The UI may choose to show - * these items smaller, or at a different position in the list, - * compared with your app's {@link #PRIORITY_DEFAULT} items. - */ - public static final int PRIORITY_LOW = -1; - - /** - * Lowest notification priority for {@link Builder#setPriority(int)}; - * these items might not be shown to the user except under - * special circumstances, such as detailed notification logs. - */ - public static final int PRIORITY_MIN = -2; - - /** - * Higher notification priority for {@link Builder#setPriority(int)}, - * for more important notifications or alerts. The UI may choose - * to show these items larger, or at a different position in - * notification lists, compared with your app's {@link #PRIORITY_DEFAULT} items. - */ - public static final int PRIORITY_HIGH = 1; - - /** - * Highest notification priority for {@link Builder#setPriority(int)}, - * for your application's most important items that require the user's - * prompt attention or input. - */ - public static final int PRIORITY_MAX = 2; - - /** - * Notification extras key: this is the title of the notification, - * as supplied to {@link Builder#setContentTitle(CharSequence)}. - */ - public static final String EXTRA_TITLE = "android.title"; - - /** - * Notification extras key: this is the title of the notification when shown in expanded form, - * e.g. as supplied to {@link BigTextStyle#setBigContentTitle(CharSequence)}. - */ - public static final String EXTRA_TITLE_BIG = EXTRA_TITLE + ".big"; - - /** - * Notification extras key: this is the main text payload, as supplied to - * {@link Builder#setContentText(CharSequence)}. - */ - public static final String EXTRA_TEXT = "android.text"; - - /** - * Notification extras key: this is a third line of text, as supplied to - * {@link Builder#setSubText(CharSequence)}. - */ - public static final String EXTRA_SUB_TEXT = "android.subText"; - - /** - * Notification extras key: this is a small piece of additional text as supplied to - * {@link Builder#setContentInfo(CharSequence)}. - */ - public static final String EXTRA_INFO_TEXT = "android.infoText"; - - /** - * Notification extras key: this is a line of summary information intended to be shown - * alongside expanded notifications, as supplied to (e.g.) - * {@link BigTextStyle#setSummaryText(CharSequence)}. - */ - public static final String EXTRA_SUMMARY_TEXT = "android.summaryText"; - - /** - * Notification extras key: this is the longer text shown in the big form of a - * {@link BigTextStyle} notification, as supplied to - * {@link BigTextStyle#bigText(CharSequence)}. - */ - public static final String EXTRA_BIG_TEXT = "android.bigText"; - - /** - * Notification extras key: this is the resource ID of the notification's main small icon, as - * supplied to {@link Builder#setSmallIcon(int)}. - */ - public static final String EXTRA_SMALL_ICON = "android.icon"; - - /** - * Notification extras key: this is a bitmap to be used instead of the small icon when showing the - * notification payload, as - * supplied to {@link Builder#setLargeIcon(Bitmap)}. - */ - public static final String EXTRA_LARGE_ICON = "android.largeIcon"; - - /** - * Notification extras key: this is a bitmap to be used instead of the one from - * {@link Builder#setLargeIcon(Bitmap)} when the notification is - * shown in its expanded form, as supplied to - * {@link BigPictureStyle#bigLargeIcon(Bitmap)}. - */ - public static final String EXTRA_LARGE_ICON_BIG = EXTRA_LARGE_ICON + ".big"; - - /** - * Notification extras key: this is the progress value supplied to - * {@link Builder#setProgress(int, int, boolean)}. - */ - public static final String EXTRA_PROGRESS = "android.progress"; - - /** - * Notification extras key: this is the maximum value supplied to - * {@link Builder#setProgress(int, int, boolean)}. - */ - public static final String EXTRA_PROGRESS_MAX = "android.progressMax"; - - /** - * Notification extras key: whether the progress bar is indeterminate, supplied to - * {@link Builder#setProgress(int, int, boolean)}. - */ - public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate"; - - /** - * Notification extras key: whether the when field set using {@link Builder#setWhen} should - * be shown as a count-up timer (specifically a {@link android.widget.Chronometer}) instead - * of a timestamp, as supplied to {@link Builder#setUsesChronometer(boolean)}. - */ - public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer"; - - /** - * Notification extras key: whether the when field set using {@link Builder#setWhen} should - * be shown, as supplied to {@link Builder#setShowWhen(boolean)}. - */ - public static final String EXTRA_SHOW_WHEN = "android.showWhen"; - - /** - * Notification extras key: this is a bitmap to be shown in {@link BigPictureStyle} expanded - * notifications, supplied to {@link BigPictureStyle#bigPicture(Bitmap)}. - */ - public static final String EXTRA_PICTURE = "android.picture"; - - /** - * Notification extras key: An array of CharSequences to show in {@link InboxStyle} expanded - * notifications, each of which was supplied to {@link InboxStyle#addLine(CharSequence)}. - */ - public static final String EXTRA_TEXT_LINES = "android.textLines"; - - /** - * Notification extras key: A string representing the name of the specific - * {@link Notification.Style} used to create this notification. - */ - public static final String EXTRA_TEMPLATE = "android.template"; - - /** - * Notification extras key: A String array containing the people that this - * notification relates to, each of which was supplied to - * {@link Builder#addPerson(String)}. - */ - public static final String EXTRA_PEOPLE = "android.people"; - - /** - * Notification extras key: A - * {@link android.content.ContentUris content URI} pointing to an image that can be displayed - * in the background when the notification is selected. The URI must point to an image stream - * suitable for passing into - * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream) - * BitmapFactory.decodeStream}; all other content types will be ignored. The content provider - * URI used for this purpose must require no permissions to read the image data. - */ - public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri"; - - /** - * Notification key: A - * {@link android.media.session.MediaSession.Token} associated with a - * {@link Notification.MediaStyle} notification. - */ - public static final String EXTRA_MEDIA_SESSION = "android.mediaSession"; - - /** - * Notification extras key: the indices of actions to be shown in the compact view, - * as supplied to (e.g.) {@link Notification.MediaStyle#setShowActionsInCompactView(int...)}. - */ - public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions"; - - /** - * Value of {@link Notification#color} equal to 0 (also known as - * {@link Color#TRANSPARENT Color.TRANSPARENT}), - * telling the system not to decorate this notification with any special color but instead use - * default colors when presenting this notification. - */ - @ColorInt - public static final int COLOR_DEFAULT = Color.TRANSPARENT; - - /** - * Notification visibility: Show this notification in its entirety on all lockscreens. - * - * {@see android.app.Notification#visibility} - */ - public static final int VISIBILITY_PUBLIC = 1; - - /** - * Notification visibility: Show this notification on all lockscreens, but conceal sensitive or - * private information on secure lockscreens. - * - * {@see android.app.Notification#visibility} - */ - public static final int VISIBILITY_PRIVATE = 0; - - /** - * Notification visibility: Do not reveal any part of this notification on a secure lockscreen. - * - * {@see android.app.Notification#visibility} - */ - public static final int VISIBILITY_SECRET = -1; - - /** - * Notification category: incoming call (voice or video) or similar synchronous communication request. - */ - public static final String CATEGORY_CALL = NotificationCompatApi21.CATEGORY_CALL; - - /** - * Notification category: incoming direct message (SMS, instant message, etc.). - */ - public static final String CATEGORY_MESSAGE = NotificationCompatApi21.CATEGORY_MESSAGE; - - /** - * Notification category: asynchronous bulk message (email). - */ - public static final String CATEGORY_EMAIL = NotificationCompatApi21.CATEGORY_EMAIL; - - /** - * Notification category: calendar event. - */ - public static final String CATEGORY_EVENT = NotificationCompatApi21.CATEGORY_EVENT; - - /** - * Notification category: promotion or advertisement. - */ - public static final String CATEGORY_PROMO = NotificationCompatApi21.CATEGORY_PROMO; - - /** - * Notification category: alarm or timer. - */ - public static final String CATEGORY_ALARM = NotificationCompatApi21.CATEGORY_ALARM; - - /** - * Notification category: progress of a long-running background operation. - */ - public static final String CATEGORY_PROGRESS = NotificationCompatApi21.CATEGORY_PROGRESS; - - /** - * Notification category: social network or sharing update. - */ - public static final String CATEGORY_SOCIAL = NotificationCompatApi21.CATEGORY_SOCIAL; - - /** - * Notification category: error in background operation or authentication status. - */ - public static final String CATEGORY_ERROR = NotificationCompatApi21.CATEGORY_ERROR; - - /** - * Notification category: media transport control for playback. - */ - public static final String CATEGORY_TRANSPORT = NotificationCompatApi21.CATEGORY_TRANSPORT; - - /** - * Notification category: system or device status update. Reserved for system use. - */ - public static final String CATEGORY_SYSTEM = NotificationCompatApi21.CATEGORY_SYSTEM; - - /** - * Notification category: indication of running background service. - */ - public static final String CATEGORY_SERVICE = NotificationCompatApi21.CATEGORY_SERVICE; - - /** - * Notification category: a specific, timely recommendation for a single thing. - * For example, a news app might want to recommend a news story it believes the user will - * want to read next. - */ - public static final String CATEGORY_RECOMMENDATION = - NotificationCompatApi21.CATEGORY_RECOMMENDATION; - - /** - * Notification category: ongoing information about device or contextual status. - */ - public static final String CATEGORY_STATUS = NotificationCompatApi21.CATEGORY_STATUS; - - private static final NotificationCompatImpl IMPL; - - interface NotificationCompatImpl { - public Notification build(Builder b, BuilderExtender extender); - public Bundle getExtras(Notification n); - public int getActionCount(Notification n); - public Action getAction(Notification n, int actionIndex); - public Action[] getActionsFromParcelableArrayList(ArrayList parcelables); - public ArrayList getParcelableArrayListForActions(Action[] actions); - public String getCategory(Notification n); - public boolean getLocalOnly(Notification n); - public String getGroup(Notification n); - public boolean isGroupSummary(Notification n); - public String getSortKey(Notification n); - Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc); - NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle( - Bundle b, NotificationCompatBase.UnreadConversation.Factory factory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory); - } - - /** - * Interface for appcompat to extend v4 builder with media style. - * - * @hide - */ - protected static class BuilderExtender { - public Notification build(Builder b, NotificationBuilderWithBuilderAccessor builder) { - return builder.build(); - } - } - - static class NotificationCompatImplBase implements NotificationCompatImpl { - @Override - public Notification build(Builder b, BuilderExtender extender) { - Notification result = b.mNotification; - result = NotificationCompatBase.add(result, b.mContext, - b.mContentTitle, b.mContentText, b.mContentIntent); - // translate high priority requests into legacy flag - if (b.mPriority > PRIORITY_DEFAULT) { - result.flags |= FLAG_HIGH_PRIORITY; - } - return result; - } - - @Override - public Bundle getExtras(Notification n) { - return null; - } - - @Override - public int getActionCount(Notification n) { - return 0; - } - - @Override - public Action getAction(Notification n, int actionIndex) { - return null; - } - - @Override - public Action[] getActionsFromParcelableArrayList( - ArrayList parcelables) { - return null; - } - - @Override - public ArrayList getParcelableArrayListForActions(Action[] actions) { - return null; - } - - @Override - public String getCategory(Notification n) { - return null; - } - - @Override - public boolean getLocalOnly(Notification n) { - return false; - } - - @Override - public String getGroup(Notification n) { - return null; - } - - @Override - public boolean isGroupSummary(Notification n) { - return false; - } - - @Override - public String getSortKey(Notification n) { - return null; - } - - @Override - public Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) { - return null; - } - - @Override - public NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle( - Bundle b, NotificationCompatBase.UnreadConversation.Factory factory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - return null; - } - } - - static class NotificationCompatImplGingerbread extends NotificationCompatImplBase { - @Override - public Notification build(Builder b, BuilderExtender extender) { - Notification result = b.mNotification; - result = NotificationCompatGingerbread.add(result, b.mContext, - b.mContentTitle, b.mContentText, b.mContentIntent, b.mFullScreenIntent); - // translate high priority requests into legacy flag - if (b.mPriority > PRIORITY_DEFAULT) { - result.flags |= FLAG_HIGH_PRIORITY; - } - return result; - } - } - - static class NotificationCompatImplHoneycomb extends NotificationCompatImplBase { - @Override - public Notification build(Builder b, BuilderExtender extender) { - return NotificationCompatHoneycomb.add(b.mContext, b.mNotification, - b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, - b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon); - } - } - - static class NotificationCompatImplIceCreamSandwich extends NotificationCompatImplBase { - @Override - public Notification build(Builder b, BuilderExtender extender) { - NotificationCompatIceCreamSandwich.Builder builder = - new NotificationCompatIceCreamSandwich.Builder( - b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, - b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, - b.mProgressMax, b.mProgress, b.mProgressIndeterminate); - return extender.build(b, builder); - } - } - - static class NotificationCompatImplJellybean extends NotificationCompatImplBase { - @Override - public Notification build(Builder b, BuilderExtender extender) { - NotificationCompatJellybean.Builder builder = new NotificationCompatJellybean.Builder( - b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, - b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, - b.mProgressMax, b.mProgress, b.mProgressIndeterminate, - b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras, - b.mGroupKey, b.mGroupSummary, b.mSortKey); - addActionsToBuilder(builder, b.mActions); - addStyleToBuilderJellybean(builder, b.mStyle); - return extender.build(b, builder); - } - - @Override - public Bundle getExtras(Notification n) { - return NotificationCompatJellybean.getExtras(n); - } - - @Override - public int getActionCount(Notification n) { - return NotificationCompatJellybean.getActionCount(n); - } - - @Override - public Action getAction(Notification n, int actionIndex) { - return (Action) NotificationCompatJellybean.getAction(n, actionIndex, Action.FACTORY, - RemoteInput.FACTORY); - } - - @Override - public Action[] getActionsFromParcelableArrayList( - ArrayList parcelables) { - return (Action[]) NotificationCompatJellybean.getActionsFromParcelableArrayList( - parcelables, Action.FACTORY, RemoteInput.FACTORY); - } - - @Override - public ArrayList getParcelableArrayListForActions( - Action[] actions) { - return NotificationCompatJellybean.getParcelableArrayListForActions(actions); - } - - @Override - public boolean getLocalOnly(Notification n) { - return NotificationCompatJellybean.getLocalOnly(n); - } - - @Override - public String getGroup(Notification n) { - return NotificationCompatJellybean.getGroup(n); - } - - @Override - public boolean isGroupSummary(Notification n) { - return NotificationCompatJellybean.isGroupSummary(n); - } - - @Override - public String getSortKey(Notification n) { - return NotificationCompatJellybean.getSortKey(n); - } - } - - static class NotificationCompatImplKitKat extends NotificationCompatImplJellybean { - @Override - public Notification build(Builder b, BuilderExtender extender) { - NotificationCompatKitKat.Builder builder = new NotificationCompatKitKat.Builder( - b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, - b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, - b.mProgressMax, b.mProgress, b.mProgressIndeterminate, b.mShowWhen, - b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, - b.mPeople, b.mExtras, b.mGroupKey, b.mGroupSummary, b.mSortKey); - addActionsToBuilder(builder, b.mActions); - addStyleToBuilderJellybean(builder, b.mStyle); - return extender.build(b, builder); - } - - @Override - public Bundle getExtras(Notification n) { - return NotificationCompatKitKat.getExtras(n); - } - - @Override - public int getActionCount(Notification n) { - return NotificationCompatKitKat.getActionCount(n); - } - - @Override - public Action getAction(Notification n, int actionIndex) { - return (Action) NotificationCompatKitKat.getAction(n, actionIndex, Action.FACTORY, - RemoteInput.FACTORY); - } - - @Override - public boolean getLocalOnly(Notification n) { - return NotificationCompatKitKat.getLocalOnly(n); - } - - @Override - public String getGroup(Notification n) { - return NotificationCompatKitKat.getGroup(n); - } - - @Override - public boolean isGroupSummary(Notification n) { - return NotificationCompatKitKat.isGroupSummary(n); - } - - @Override - public String getSortKey(Notification n) { - return NotificationCompatKitKat.getSortKey(n); - } - } - - static class NotificationCompatImplApi20 extends NotificationCompatImplKitKat { - @Override - public Notification build(Builder b, BuilderExtender extender) { - NotificationCompatApi20.Builder builder = new NotificationCompatApi20.Builder( - b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, - b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, - b.mProgressMax, b.mProgress, b.mProgressIndeterminate, b.mShowWhen, - b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mPeople, b.mExtras, - b.mGroupKey, b.mGroupSummary, b.mSortKey); - addActionsToBuilder(builder, b.mActions); - addStyleToBuilderJellybean(builder, b.mStyle); - return extender.build(b, builder); - } - - @Override - public Action getAction(Notification n, int actionIndex) { - return (Action) NotificationCompatApi20.getAction(n, actionIndex, Action.FACTORY, - RemoteInput.FACTORY); - } - - @Override - public Action[] getActionsFromParcelableArrayList( - ArrayList parcelables) { - return (Action[]) NotificationCompatApi20.getActionsFromParcelableArrayList( - parcelables, Action.FACTORY, RemoteInput.FACTORY); - } - - @Override - public ArrayList getParcelableArrayListForActions( - Action[] actions) { - return NotificationCompatApi20.getParcelableArrayListForActions(actions); - } - - @Override - public boolean getLocalOnly(Notification n) { - return NotificationCompatApi20.getLocalOnly(n); - } - - @Override - public String getGroup(Notification n) { - return NotificationCompatApi20.getGroup(n); - } - - @Override - public boolean isGroupSummary(Notification n) { - return NotificationCompatApi20.isGroupSummary(n); - } - - @Override - public String getSortKey(Notification n) { - return NotificationCompatApi20.getSortKey(n); - } - } - - static class NotificationCompatImplApi21 extends NotificationCompatImplApi20 { - @Override - public Notification build(Builder b, BuilderExtender extender) { - NotificationCompatApi21.Builder builder = new NotificationCompatApi21.Builder( - b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, - b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, - b.mProgressMax, b.mProgress, b.mProgressIndeterminate, b.mShowWhen, - b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mCategory, - b.mPeople, b.mExtras, b.mColor, b.mVisibility, b.mPublicVersion, - b.mGroupKey, b.mGroupSummary, b.mSortKey); - addActionsToBuilder(builder, b.mActions); - addStyleToBuilderJellybean(builder, b.mStyle); - return extender.build(b, builder); - } - - @Override - public String getCategory(Notification notif) { - return NotificationCompatApi21.getCategory(notif); - } - - @Override - public Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) { - return NotificationCompatApi21.getBundleForUnreadConversation(uc); - } - - @Override - public NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle( - Bundle b, NotificationCompatBase.UnreadConversation.Factory factory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - return NotificationCompatApi21.getUnreadConversationFromBundle( - b, factory, remoteInputFactory); - } - } - - private static void addActionsToBuilder(NotificationBuilderWithActions builder, - ArrayList actions) { - for (Action action : actions) { - builder.addAction(action); - } - } - - private static void addStyleToBuilderJellybean(NotificationBuilderWithBuilderAccessor builder, - Style style) { - if (style != null) { - if (style instanceof BigTextStyle) { - BigTextStyle bigTextStyle = (BigTextStyle) style; - NotificationCompatJellybean.addBigTextStyle(builder, - bigTextStyle.mBigContentTitle, - bigTextStyle.mSummaryTextSet, - bigTextStyle.mSummaryText, - bigTextStyle.mBigText); - } else if (style instanceof InboxStyle) { - InboxStyle inboxStyle = (InboxStyle) style; - NotificationCompatJellybean.addInboxStyle(builder, - inboxStyle.mBigContentTitle, - inboxStyle.mSummaryTextSet, - inboxStyle.mSummaryText, - inboxStyle.mTexts); - } else if (style instanceof BigPictureStyle) { - BigPictureStyle bigPictureStyle = (BigPictureStyle) style; - NotificationCompatJellybean.addBigPictureStyle(builder, - bigPictureStyle.mBigContentTitle, - bigPictureStyle.mSummaryTextSet, - bigPictureStyle.mSummaryText, - bigPictureStyle.mPicture, - bigPictureStyle.mBigLargeIcon, - bigPictureStyle.mBigLargeIconSet); - } - } - } - - static { - if (Build.VERSION.SDK_INT >= 21) { - IMPL = new NotificationCompatImplApi21(); - } else if (Build.VERSION.SDK_INT >= 20) { - IMPL = new NotificationCompatImplApi20(); - } else if (Build.VERSION.SDK_INT >= 19) { - IMPL = new NotificationCompatImplKitKat(); - } else if (Build.VERSION.SDK_INT >= 16) { - IMPL = new NotificationCompatImplJellybean(); - } else if (Build.VERSION.SDK_INT >= 14) { - IMPL = new NotificationCompatImplIceCreamSandwich(); - } else if (Build.VERSION.SDK_INT >= 11) { - IMPL = new NotificationCompatImplHoneycomb(); - } else if (Build.VERSION.SDK_INT >= 9) { - IMPL = new NotificationCompatImplGingerbread(); - } else { - IMPL = new NotificationCompatImplBase(); - } - } - - /** - * Builder class for {@link NotificationCompat} objects. Allows easier control over - * all the flags, as well as help constructing the typical notification layouts. - *

- * On platform versions that don't offer expanded notifications, methods that depend on - * expanded notifications have no effect. - *

- *

- * For example, action buttons won't appear on platforms prior to Android 4.1. Action - * buttons depend on expanded notifications, which are only available in Android 4.1 - * and later. - *

- * For this reason, you should always ensure that UI controls in a notification are also - * available in an {@link android.app.Activity} in your app, and you should always start that - * {@link android.app.Activity} when users click the notification. To do this, use the - * {@link Builder#setContentIntent setContentIntent()} - * method. - *

- * - */ - public static class Builder { - /** - * Maximum length of CharSequences accepted by Builder and friends. - * - *

- * Avoids spamming the system with overly large strings such as full e-mails. - */ - private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024; - - // All these variables are declared public/hidden so they can be accessed by a builder - // extender. - - /** @hide */ - public Context mContext; - - /** @hide */ - public CharSequence mContentTitle; - /** @hide */ - public CharSequence mContentText; - PendingIntent mContentIntent; - PendingIntent mFullScreenIntent; - RemoteViews mTickerView; - /** @hide */ - public Bitmap mLargeIcon; - /** @hide */ - public CharSequence mContentInfo; - /** @hide */ - public int mNumber; - int mPriority; - boolean mShowWhen = true; - /** @hide */ - public boolean mUseChronometer; - /** @hide */ - public Style mStyle; - /** @hide */ - public CharSequence mSubText; - int mProgressMax; - int mProgress; - boolean mProgressIndeterminate; - String mGroupKey; - boolean mGroupSummary; - String mSortKey; - /** @hide */ - public ArrayList mActions = new ArrayList(); - boolean mLocalOnly = false; - String mCategory; - Bundle mExtras; - int mColor = COLOR_DEFAULT; - int mVisibility = VISIBILITY_PRIVATE; - Notification mPublicVersion; - - /** @hide */ - public Notification mNotification = new Notification(); - public ArrayList mPeople; - - /** - * Constructor. - * - * Automatically sets the when field to {@link System#currentTimeMillis() - * System.currentTimeMillis()} and the audio stream to the - * {@link Notification#STREAM_DEFAULT}. - * - * @param context A {@link Context} that will be used to construct the - * RemoteViews. The Context will not be held past the lifetime of this - * Builder object. - */ - public Builder(Context context) { - mContext = context; - - // Set defaults to match the defaults of a Notification - mNotification.when = System.currentTimeMillis(); - mNotification.audioStreamType = Notification.STREAM_DEFAULT; - mPriority = PRIORITY_DEFAULT; - mPeople = new ArrayList(); - } - - /** - * Set the time that the event occurred. Notifications in the panel are - * sorted by this time. - */ - public Builder setWhen(long when) { - mNotification.when = when; - return this; - } - - /** - * Control whether the timestamp set with {@link #setWhen(long) setWhen} is shown - * in the content view. - */ - public Builder setShowWhen(boolean show) { - mShowWhen = show; - return this; - } - - /** - * Show the {@link Notification#when} field as a stopwatch. - * - * Instead of presenting when as a timestamp, the notification will show an - * automatically updating display of the minutes and seconds since when. - * - * Useful when showing an elapsed time (like an ongoing phone call). - * - * @see android.widget.Chronometer - * @see Notification#when - */ - public Builder setUsesChronometer(boolean b) { - mUseChronometer = b; - return this; - } - - /** - * Set the small icon to use in the notification layouts. Different classes of devices - * may return different sizes. See the UX guidelines for more information on how to - * design these icons. - * - * @param icon A resource ID in the application's package of the drawble to use. - */ - public Builder setSmallIcon(int icon) { - mNotification.icon = icon; - return this; - } - - /** - * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional - * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable - * LevelListDrawable}. - * - * @param icon A resource ID in the application's package of the drawble to use. - * @param level The level to use for the icon. - * - * @see android.graphics.drawable.LevelListDrawable - */ - public Builder setSmallIcon(int icon, int level) { - mNotification.icon = icon; - mNotification.iconLevel = level; - return this; - } - - /** - * Set the title (first row) of the notification, in a standard notification. - */ - public Builder setContentTitle(CharSequence title) { - mContentTitle = limitCharSequenceLength(title); - return this; - } - - /** - * Set the text (second row) of the notification, in a standard notification. - */ - public Builder setContentText(CharSequence text) { - mContentText = limitCharSequenceLength(text); - return this; - } - - /** - * Set the third line of text in the platform notification template. - * Don't use if you're also using {@link #setProgress(int, int, boolean)}; - * they occupy the same location in the standard template. - *
- * If the platform does not provide large-format notifications, this method has no effect. - * The third line of text only appears in expanded view. - *
- */ - public Builder setSubText(CharSequence text) { - mSubText = limitCharSequenceLength(text); - return this; - } - - /** - * Set the large number at the right-hand side of the notification. This is - * equivalent to setContentInfo, although it might show the number in a different - * font size for readability. - */ - public Builder setNumber(int number) { - mNumber = number; - return this; - } - - /** - * Set the large text at the right-hand side of the notification. - */ - public Builder setContentInfo(CharSequence info) { - mContentInfo = limitCharSequenceLength(info); - return this; - } - - /** - * Set the progress this notification represents, which may be - * represented as a {@link android.widget.ProgressBar}. - */ - public Builder setProgress(int max, int progress, boolean indeterminate) { - mProgressMax = max; - mProgress = progress; - mProgressIndeterminate = indeterminate; - return this; - } - - /** - * Supply a custom RemoteViews to use instead of the standard one. - */ - public Builder setContent(RemoteViews views) { - mNotification.contentView = views; - return this; - } - - /** - * Supply a {@link PendingIntent} to send when the notification is clicked. - * If you do not supply an intent, you can now add PendingIntents to individual - * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent - * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. Be sure to - * read {@link Notification#contentIntent Notification.contentIntent} for - * how to correctly use this. - */ - public Builder setContentIntent(PendingIntent intent) { - mContentIntent = intent; - return this; - } - - /** - * Supply a {@link PendingIntent} to send when the notification is cleared by the user - * directly from the notification panel. For example, this intent is sent when the user - * clicks the "Clear all" button, or the individual "X" buttons on notifications. This - * intent is not sent when the application calls - * {@link android.app.NotificationManager#cancel NotificationManager.cancel(int)}. - */ - public Builder setDeleteIntent(PendingIntent intent) { - mNotification.deleteIntent = intent; - return this; - } - - /** - * An intent to launch instead of posting the notification to the status bar. - * Only for use with extremely high-priority notifications demanding the user's - * immediate attention, such as an incoming phone call or - * alarm clock that the user has explicitly set to a particular time. - * If this facility is used for something else, please give the user an option - * to turn it off and use a normal notification, as this can be extremely - * disruptive. - * - *

- * On some platforms, the system UI may choose to display a heads-up notification, - * instead of launching this intent, while the user is using the device. - *

- * - * @param intent The pending intent to launch. - * @param highPriority Passing true will cause this notification to be sent - * even if other notifications are suppressed. - */ - public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { - mFullScreenIntent = intent; - setFlag(FLAG_HIGH_PRIORITY, highPriority); - return this; - } - - /** - * Set the text that is displayed in the status bar when the notification first - * arrives. - */ - public Builder setTicker(CharSequence tickerText) { - mNotification.tickerText = limitCharSequenceLength(tickerText); - return this; - } - - /** - * Set the text that is displayed in the status bar when the notification first - * arrives, and also a RemoteViews object that may be displayed instead on some - * devices. - */ - public Builder setTicker(CharSequence tickerText, RemoteViews views) { - mNotification.tickerText = limitCharSequenceLength(tickerText); - mTickerView = views; - return this; - } - - /** - * Set the large icon that is shown in the ticker and notification. - */ - public Builder setLargeIcon(Bitmap icon) { - mLargeIcon = icon; - return this; - } - - /** - * Set the sound to play. It will play on the default stream. - * - *

- * On some platforms, a notification that is noisy is more likely to be presented - * as a heads-up notification. - *

- */ - public Builder setSound(Uri sound) { - mNotification.sound = sound; - mNotification.audioStreamType = Notification.STREAM_DEFAULT; - return this; - } - - /** - * Set the sound to play. It will play on the stream you supply. - * - *

- * On some platforms, a notification that is noisy is more likely to be presented - * as a heads-up notification. - *

- * - * @see Notification#STREAM_DEFAULT - * @see AudioManager for the STREAM_ constants. - */ - public Builder setSound(Uri sound, int streamType) { - mNotification.sound = sound; - mNotification.audioStreamType = streamType; - return this; - } - - /** - * Set the vibration pattern to use. - * - *

- * On some platforms, a notification that vibrates is more likely to be presented - * as a heads-up notification. - *

- * - * @see android.os.Vibrator for a discussion of the pattern - * parameter. - */ - public Builder setVibrate(long[] pattern) { - mNotification.vibrate = pattern; - return this; - } - - /** - * Set the argb value that you would like the LED on the device to blnk, as well as the - * rate. The rate is specified in terms of the number of milliseconds to be on - * and then the number of milliseconds to be off. - */ - public Builder setLights(@ColorInt int argb, int onMs, int offMs) { - mNotification.ledARGB = argb; - mNotification.ledOnMS = onMs; - mNotification.ledOffMS = offMs; - boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0; - mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) | - (showLights ? Notification.FLAG_SHOW_LIGHTS : 0); - return this; - } - - /** - * Set whether this is an ongoing notification. - * - *

Ongoing notifications differ from regular notifications in the following ways: - *

    - *
  • Ongoing notifications are sorted above the regular notifications in the - * notification panel.
  • - *
  • Ongoing notifications do not have an 'X' close button, and are not affected - * by the "Clear all" button. - *
- */ - public Builder setOngoing(boolean ongoing) { - setFlag(Notification.FLAG_ONGOING_EVENT, ongoing); - return this; - } - - /** - * Set this flag if you would only like the sound, vibrate - * and ticker to be played if the notification is not already showing. - */ - public Builder setOnlyAlertOnce(boolean onlyAlertOnce) { - setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce); - return this; - } - - /** - * Setting this flag will make it so the notification is automatically - * canceled when the user clicks it in the panel. The PendingIntent - * set with {@link #setDeleteIntent} will be broadcast when the notification - * is canceled. - */ - public Builder setAutoCancel(boolean autoCancel) { - setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel); - return this; - } - - /** - * Set whether or not this notification is only relevant to the current device. - * - *

Some notifications can be bridged to other devices for remote display. - * This hint can be set to recommend this notification not be bridged. - */ - public Builder setLocalOnly(boolean b) { - mLocalOnly = b; - return this; - } - - /** - * Set the notification category. - * - *

Must be one of the predefined notification categories (see the CATEGORY_* - * constants in {@link Notification}) that best describes this notification. - * May be used by the system for ranking and filtering. - */ - public Builder setCategory(String category) { - mCategory = category; - return this; - } - - /** - * Set the default notification options that will be used. - *

- * The value should be one or more of the following fields combined with - * bitwise-or: - * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE}, - * {@link Notification#DEFAULT_LIGHTS}. - *

- * For all default values, use {@link Notification#DEFAULT_ALL}. - */ - public Builder setDefaults(int defaults) { - mNotification.defaults = defaults; - if ((defaults & Notification.DEFAULT_LIGHTS) != 0) { - mNotification.flags |= Notification.FLAG_SHOW_LIGHTS; - } - return this; - } - - private void setFlag(int mask, boolean value) { - if (value) { - mNotification.flags |= mask; - } else { - mNotification.flags &= ~mask; - } - } - - /** - * Set the relative priority for this notification. - * - * Priority is an indication of how much of the user's - * valuable attention should be consumed by this - * notification. Low-priority notifications may be hidden from - * the user in certain situations, while the user might be - * interrupted for a higher-priority notification. - * The system sets a notification's priority based on various factors including the - * setPriority value. The effect may differ slightly on different platforms. - * - * @param pri Relative priority for this notification. Must be one of - * the priority constants defined by {@link NotificationCompat}. - * Acceptable values range from {@link - * NotificationCompat#PRIORITY_MIN} (-2) to {@link - * NotificationCompat#PRIORITY_MAX} (2). - */ - public Builder setPriority(int pri) { - mPriority = pri; - return this; - } - - /** - * Add a person that is relevant to this notification. - * - *

- * Depending on user preferences, this annotation may allow the notification to pass - * through interruption filters, and to appear more prominently in the user interface. - *

- * - *

- * The person should be specified by the {@code String} representation of a - * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}. - *

- * - *

The system will also attempt to resolve {@code mailto:} and {@code tel:} schema - * URIs. The path part of these URIs must exist in the contacts database, in the - * appropriate column, or the reference will be discarded as invalid. Telephone schema - * URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}. - *

- * - * @param uri A URI for the person. - * @see Notification#EXTRA_PEOPLE - */ - public Builder addPerson(String uri) { - mPeople.add(uri); - return this; - } - - /** - * Set this notification to be part of a group of notifications sharing the same key. - * Grouped notifications may display in a cluster or stack on devices which - * support such rendering. - * - *

To make this notification the summary for its group, also call - * {@link #setGroupSummary}. A sort order can be specified for group members by using - * {@link #setSortKey}. - * @param groupKey The group key of the group. - * @return this object for method chaining - */ - public Builder setGroup(String groupKey) { - mGroupKey = groupKey; - return this; - } - - /** - * Set this notification to be the group summary for a group of notifications. - * Grouped notifications may display in a cluster or stack on devices which - * support such rendering. Requires a group key also be set using {@link #setGroup}. - * @param isGroupSummary Whether this notification should be a group summary. - * @return this object for method chaining - */ - public Builder setGroupSummary(boolean isGroupSummary) { - mGroupSummary = isGroupSummary; - return this; - } - - /** - * Set a sort key that orders this notification among other notifications from the - * same package. This can be useful if an external sort was already applied and an app - * would like to preserve this. Notifications will be sorted lexicographically using this - * value, although providing different priorities in addition to providing sort key may - * cause this value to be ignored. - * - *

This sort key can also be used to order members of a notification group. See - * {@link Builder#setGroup}. - * - * @see String#compareTo(String) - */ - public Builder setSortKey(String sortKey) { - mSortKey = sortKey; - return this; - } - - /** - * Merge additional metadata into this notification. - * - *

Values within the Bundle will replace existing extras values in this Builder. - * - * @see Notification#extras - */ - public Builder addExtras(Bundle extras) { - if (extras != null) { - if (mExtras == null) { - mExtras = new Bundle(extras); - } else { - mExtras.putAll(extras); - } - } - return this; - } - - /** - * Set metadata for this notification. - * - *

A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's - * current contents are copied into the Notification each time {@link #build()} is - * called. - * - *

Replaces any existing extras values with those from the provided Bundle. - * Use {@link #addExtras} to merge in metadata instead. - * - * @see Notification#extras - */ - public Builder setExtras(Bundle extras) { - mExtras = extras; - return this; - } - - /** - * Get the current metadata Bundle used by this notification Builder. - * - *

The returned Bundle is shared with this Builder. - * - *

The current contents of this Bundle are copied into the Notification each time - * {@link #build()} is called. - * - * @see Notification#extras - */ - public Bundle getExtras() { - if (mExtras == null) { - mExtras = new Bundle(); - } - return mExtras; - } - - /** - * Add an action to this notification. Actions are typically displayed by - * the system as a button adjacent to the notification content. - *
- * Action buttons won't appear on platforms prior to Android 4.1. Action - * buttons depend on expanded notifications, which are only available in Android 4.1 - * and later. To ensure that an action button's functionality is always available, first - * implement the functionality in the {@link android.app.Activity} that starts when a user - * clicks the notification (see {@link #setContentIntent setContentIntent()}), and then - * enhance the notification by implementing the same functionality with - * {@link #addAction addAction()}. - * - * @param icon Resource ID of a drawable that represents the action. - * @param title Text describing the action. - * @param intent {@link PendingIntent} to be fired when the action is invoked. - */ - public Builder addAction(int icon, CharSequence title, PendingIntent intent) { - mActions.add(new Action(icon, title, intent)); - return this; - } - - /** - * Add an action to this notification. Actions are typically displayed by - * the system as a button adjacent to the notification content. - *
- * Action buttons won't appear on platforms prior to Android 4.1. Action - * buttons depend on expanded notifications, which are only available in Android 4.1 - * and later. To ensure that an action button's functionality is always available, first - * implement the functionality in the {@link android.app.Activity} that starts when a user - * clicks the notification (see {@link #setContentIntent setContentIntent()}), and then - * enhance the notification by implementing the same functionality with - * {@link #addAction addAction()}. - * - * @param action The action to add. - */ - public Builder addAction(Action action) { - mActions.add(action); - return this; - } - - /** - * Add a rich notification style to be applied at build time. - *
- * If the platform does not provide rich notification styles, this method has no effect. The - * user will always see the normal notification style. - * - * @param style Object responsible for modifying the notification style. - */ - public Builder setStyle(Style style) { - if (mStyle != style) { - mStyle = style; - if (mStyle != null) { - mStyle.setBuilder(this); - } - } - return this; - } - - /** - * Sets {@link Notification#color}. - * - * @param argb The accent color to use - * - * @return The same Builder. - */ - public Builder setColor(@ColorInt int argb) { - mColor = argb; - return this; - } - - /** - * Sets {@link Notification#visibility}. - * - * @param visibility One of {@link Notification#VISIBILITY_PRIVATE} (the default), - * {@link Notification#VISIBILITY_PUBLIC}, or - * {@link Notification#VISIBILITY_SECRET}. - */ - public Builder setVisibility(int visibility) { - mVisibility = visibility; - return this; - } - - /** - * Supply a replacement Notification whose contents should be shown in insecure contexts - * (i.e. atop the secure lockscreen). See {@link Notification#visibility} and - * {@link #VISIBILITY_PUBLIC}. - * - * @param n A replacement notification, presumably with some or all info redacted. - * @return The same Builder. - */ - public Builder setPublicVersion(Notification n) { - mPublicVersion = n; - return this; - } - - /** - * Apply an extender to this notification builder. Extenders may be used to add - * metadata or change options on this builder. - */ - public Builder extend(Extender extender) { - extender.extend(this); - return this; - } - - /** - * @deprecated Use {@link #build()} instead. - */ - @Deprecated - public Notification getNotification() { - return build(); - } - - /** - * Combine all of the options that have been set and return a new {@link Notification} - * object. - */ - public Notification build() { - return IMPL.build(this, getExtender()); - } - - /** - * @hide - */ - protected BuilderExtender getExtender() { - return new BuilderExtender(); - } - - protected static CharSequence limitCharSequenceLength(CharSequence cs) { - if (cs == null) return cs; - if (cs.length() > MAX_CHARSEQUENCE_LENGTH) { - cs = cs.subSequence(0, MAX_CHARSEQUENCE_LENGTH); - } - return cs; - } - } - - /** - * An object that can apply a rich notification style to a {@link Notification.Builder} - * object. - *
- * If the platform does not provide rich notification styles, methods in this class have no - * effect. - */ - public static abstract class Style { - Builder mBuilder; - CharSequence mBigContentTitle; - CharSequence mSummaryText; - boolean mSummaryTextSet = false; - - public void setBuilder(Builder builder) { - if (mBuilder != builder) { - mBuilder = builder; - if (mBuilder != null) { - mBuilder.setStyle(this); - } - } - } - - public Notification build() { - Notification notification = null; - if (mBuilder != null) { - notification = mBuilder.build(); - } - return notification; - } - } - - /** - * Helper class for generating large-format notifications that include a large image attachment. - *
- * If the platform does not provide large-format notifications, this method has no effect. The - * user will always see the normal notification view. - *
- * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: - *

-     * Notification notif = new Notification.Builder(mContext)
-     *     .setContentTitle("New photo from " + sender.toString())
-     *     .setContentText(subject)
-     *     .setSmallIcon(R.drawable.new_post)
-     *     .setLargeIcon(aBitmap)
-     *     .setStyle(new Notification.BigPictureStyle()
-     *         .bigPicture(aBigBitmap))
-     *     .build();
-     * 
- * - * @see Notification#bigContentView - */ - public static class BigPictureStyle extends Style { - Bitmap mPicture; - Bitmap mBigLargeIcon; - boolean mBigLargeIconSet; - - public BigPictureStyle() { - } - - public BigPictureStyle(Builder builder) { - setBuilder(builder); - } - - /** - * Overrides ContentTitle in the big form of the template. - * This defaults to the value passed to setContentTitle(). - */ - public BigPictureStyle setBigContentTitle(CharSequence title) { - mBigContentTitle = Builder.limitCharSequenceLength(title); - return this; - } - - /** - * Set the first line of text after the detail section in the big form of the template. - */ - public BigPictureStyle setSummaryText(CharSequence cs) { - mSummaryText = Builder.limitCharSequenceLength(cs); - mSummaryTextSet = true; - return this; - } - - /** - * Provide the bitmap to be used as the payload for the BigPicture notification. - */ - public BigPictureStyle bigPicture(Bitmap b) { - mPicture = b; - return this; - } - - /** - * Override the large icon when the big notification is shown. - */ - public BigPictureStyle bigLargeIcon(Bitmap b) { - mBigLargeIcon = b; - mBigLargeIconSet = true; - return this; - } - } - - /** - * Helper class for generating large-format notifications that include a lot of text. - * - *
- * If the platform does not provide large-format notifications, this method has no effect. The - * user will always see the normal notification view. - *
- * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: - *
-     * Notification notif = new Notification.Builder(mContext)
-     *     .setContentTitle("New mail from " + sender.toString())
-     *     .setContentText(subject)
-     *     .setSmallIcon(R.drawable.new_mail)
-     *     .setLargeIcon(aBitmap)
-     *     .setStyle(new Notification.BigTextStyle()
-     *         .bigText(aVeryLongString))
-     *     .build();
-     * 
- * - * @see Notification#bigContentView - */ - public static class BigTextStyle extends Style { - CharSequence mBigText; - - public BigTextStyle() { - } - - public BigTextStyle(Builder builder) { - setBuilder(builder); - } - - /** - * Overrides ContentTitle in the big form of the template. - * This defaults to the value passed to setContentTitle(). - */ - public BigTextStyle setBigContentTitle(CharSequence title) { - mBigContentTitle = Builder.limitCharSequenceLength(title); - return this; - } - - /** - * Set the first line of text after the detail section in the big form of the template. - */ - public BigTextStyle setSummaryText(CharSequence cs) { - mSummaryText = Builder.limitCharSequenceLength(cs); - mSummaryTextSet = true; - return this; - } - - /** - * Provide the longer text to be displayed in the big form of the - * template in place of the content text. - */ - public BigTextStyle bigText(CharSequence cs) { - mBigText = Builder.limitCharSequenceLength(cs); - return this; - } - } - - /** - * Helper class for generating large-format notifications that include a list of (up to 5) strings. - * - *
- * If the platform does not provide large-format notifications, this method has no effect. The - * user will always see the normal notification view. - *
- * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so: - *
-     * Notification noti = new Notification.Builder()
-     *     .setContentTitle("5 New mails from " + sender.toString())
-     *     .setContentText(subject)
-     *     .setSmallIcon(R.drawable.new_mail)
-     *     .setLargeIcon(aBitmap)
-     *     .setStyle(new Notification.InboxStyle()
-     *         .addLine(str1)
-     *         .addLine(str2)
-     *         .setContentTitle("")
-     *         .setSummaryText("+3 more"))
-     *     .build();
-     * 
- * - * @see Notification#bigContentView - */ - public static class InboxStyle extends Style { - ArrayList mTexts = new ArrayList(); - - public InboxStyle() { - } - - public InboxStyle(Builder builder) { - setBuilder(builder); - } - - /** - * Overrides ContentTitle in the big form of the template. - * This defaults to the value passed to setContentTitle(). - */ - public InboxStyle setBigContentTitle(CharSequence title) { - mBigContentTitle = Builder.limitCharSequenceLength(title); - return this; - } - - /** - * Set the first line of text after the detail section in the big form of the template. - */ - public InboxStyle setSummaryText(CharSequence cs) { - mSummaryText = Builder.limitCharSequenceLength(cs); - mSummaryTextSet = true; - return this; - } - - /** - * Append a line to the digest section of the Inbox notification. - */ - public InboxStyle addLine(CharSequence cs) { - mTexts.add(Builder.limitCharSequenceLength(cs)); - return this; - } - } - - /** - * Structure to encapsulate a named action that can be shown as part of this notification. - * It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is - * selected by the user. Action buttons won't appear on platforms prior to Android 4.1. - *

- * Apps should use {@link NotificationCompat.Builder#addAction(int, CharSequence, PendingIntent)} - * or {@link NotificationCompat.Builder#addAction(Action)} - * to attach actions. - */ - public static class Action extends NotificationCompatBase.Action { - private final Bundle mExtras; - private final RemoteInput[] mRemoteInputs; - - /** - * Small icon representing the action. - */ - public int icon; - /** - * Title of the action. - */ - public CharSequence title; - /** - * Intent to send when the user invokes this action. May be null, in which case the action - * may be rendered in a disabled presentation. - */ - public PendingIntent actionIntent; - - public Action(int icon, CharSequence title, PendingIntent intent) { - this(icon, title, intent, new Bundle(), null); - } - - private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras, - RemoteInput[] remoteInputs) { - this.icon = icon; - this.title = NotificationCompat.Builder.limitCharSequenceLength(title); - this.actionIntent = intent; - this.mExtras = extras != null ? extras : new Bundle(); - this.mRemoteInputs = remoteInputs; - } - - @Override - public int getIcon() { - return icon; - } - - @Override - public CharSequence getTitle() { - return title; - } - - @Override - public PendingIntent getActionIntent() { - return actionIntent; - } - - /** - * Get additional metadata carried around with this Action. - */ - @Override - public Bundle getExtras() { - return mExtras; - } - - /** - * Get the list of inputs to be collected from the user when this action is sent. - * May return null if no remote inputs were added. - */ - @Override - public RemoteInput[] getRemoteInputs() { - return mRemoteInputs; - } - - /** - * Builder class for {@link Action} objects. - */ - public static final class Builder { - private final int mIcon; - private final CharSequence mTitle; - private final PendingIntent mIntent; - private final Bundle mExtras; - private ArrayList mRemoteInputs; - - /** - * Construct a new builder for {@link Action} object. - * @param icon icon to show for this action - * @param title the title of the action - * @param intent the {@link PendingIntent} to fire when users trigger this action - */ - public Builder(int icon, CharSequence title, PendingIntent intent) { - this(icon, title, intent, new Bundle()); - } - - /** - * Construct a new builder for {@link Action} object using the fields from an - * {@link Action}. - * @param action the action to read fields from. - */ - public Builder(Action action) { - this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras)); - } - - private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras) { - mIcon = icon; - mTitle = NotificationCompat.Builder.limitCharSequenceLength(title); - mIntent = intent; - mExtras = extras; - } - - /** - * Merge additional metadata into this builder. - * - *

Values within the Bundle will replace existing extras values in this Builder. - * - * @see Action#getExtras - */ - public Builder addExtras(Bundle extras) { - if (extras != null) { - mExtras.putAll(extras); - } - return this; - } - - /** - * Get the metadata Bundle used by this Builder. - * - *

The returned Bundle is shared with this Builder. - */ - public Bundle getExtras() { - return mExtras; - } - - /** - * Add an input to be collected from the user when this action is sent. - * Response values can be retrieved from the fired intent by using the - * {@link RemoteInput#getResultsFromIntent} function. - * @param remoteInput a {@link RemoteInput} to add to the action - * @return this object for method chaining - */ - public Builder addRemoteInput(RemoteInput remoteInput) { - if (mRemoteInputs == null) { - mRemoteInputs = new ArrayList(); - } - mRemoteInputs.add(remoteInput); - return this; - } - - /** - * Apply an extender to this action builder. Extenders may be used to add - * metadata or change options on this builder. - */ - public Builder extend(Extender extender) { - extender.extend(this); - return this; - } - - /** - * Combine all of the options that have been set and return a new {@link Action} - * object. - * @return the built action - */ - public Action build() { - RemoteInput[] remoteInputs = mRemoteInputs != null - ? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null; - return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs); - } - } - - - /** - * Extender interface for use with {@link Builder#extend}. Extenders may be used to add - * metadata or change options on an action builder. - */ - public interface Extender { - /** - * Apply this extender to a notification action builder. - * @param builder the builder to be modified. - * @return the build object for chaining. - */ - public Builder extend(Builder builder); - } - - /** - * Wearable extender for notification actions. To add extensions to an action, - * create a new {@link WearableExtender} object using - * the {@code WearableExtender()} constructor and apply it to a - * {@link Builder} using - * {@link Builder#extend}. - * - *

-         * NotificationCompat.Action action = new NotificationCompat.Action.Builder(
-         *         R.drawable.archive_all, "Archive all", actionIntent)
-         *         .extend(new NotificationCompat.Action.WearableExtender()
-         *                 .setAvailableOffline(false))
-         *         .build();
- */ - public static final class WearableExtender implements Extender { - /** Notification action extra which contains wearable extensions */ - private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS"; - - // Keys within EXTRA_WEARABLE_EXTENSIONS for wearable options. - private static final String KEY_FLAGS = "flags"; - private static final String KEY_IN_PROGRESS_LABEL = "inProgressLabel"; - private static final String KEY_CONFIRM_LABEL = "confirmLabel"; - private static final String KEY_CANCEL_LABEL = "cancelLabel"; - - // Flags bitwise-ored to mFlags - private static final int FLAG_AVAILABLE_OFFLINE = 0x1; - - // Default value for flags integer - private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE; - - private int mFlags = DEFAULT_FLAGS; - - private CharSequence mInProgressLabel; - private CharSequence mConfirmLabel; - private CharSequence mCancelLabel; - - /** - * Create a {@link WearableExtender} with default - * options. - */ - public WearableExtender() { - } - - /** - * Create a {@link WearableExtender} by reading - * wearable options present in an existing notification action. - * @param action the notification action to inspect. - */ - public WearableExtender(Action action) { - Bundle wearableBundle = action.getExtras().getBundle(EXTRA_WEARABLE_EXTENSIONS); - if (wearableBundle != null) { - mFlags = wearableBundle.getInt(KEY_FLAGS, DEFAULT_FLAGS); - mInProgressLabel = wearableBundle.getCharSequence(KEY_IN_PROGRESS_LABEL); - mConfirmLabel = wearableBundle.getCharSequence(KEY_CONFIRM_LABEL); - mCancelLabel = wearableBundle.getCharSequence(KEY_CANCEL_LABEL); - } - } - - /** - * Apply wearable extensions to a notification action that is being built. This is - * typically called by the {@link Builder#extend} - * method of {@link Builder}. - */ - @Override - public Builder extend(Builder builder) { - Bundle wearableBundle = new Bundle(); - - if (mFlags != DEFAULT_FLAGS) { - wearableBundle.putInt(KEY_FLAGS, mFlags); - } - if (mInProgressLabel != null) { - wearableBundle.putCharSequence(KEY_IN_PROGRESS_LABEL, mInProgressLabel); - } - if (mConfirmLabel != null) { - wearableBundle.putCharSequence(KEY_CONFIRM_LABEL, mConfirmLabel); - } - if (mCancelLabel != null) { - wearableBundle.putCharSequence(KEY_CANCEL_LABEL, mCancelLabel); - } - - builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle); - return builder; - } - - @Override - public WearableExtender clone() { - WearableExtender that = new WearableExtender(); - that.mFlags = this.mFlags; - that.mInProgressLabel = this.mInProgressLabel; - that.mConfirmLabel = this.mConfirmLabel; - that.mCancelLabel = this.mCancelLabel; - return that; - } - - /** - * Set whether this action is available when the wearable device is not connected to - * a companion device. The user can still trigger this action when the wearable device - * is offline, but a visual hint will indicate that the action may not be available. - * Defaults to true. - */ - public WearableExtender setAvailableOffline(boolean availableOffline) { - setFlag(FLAG_AVAILABLE_OFFLINE, availableOffline); - return this; - } - - /** - * Get whether this action is available when the wearable device is not connected to - * a companion device. The user can still trigger this action when the wearable device - * is offline, but a visual hint will indicate that the action may not be available. - * Defaults to true. - */ - public boolean isAvailableOffline() { - return (mFlags & FLAG_AVAILABLE_OFFLINE) != 0; - } - - private void setFlag(int mask, boolean value) { - if (value) { - mFlags |= mask; - } else { - mFlags &= ~mask; - } - } - - /** - * Set a label to display while the wearable is preparing to automatically execute the - * action. This is usually a 'ing' verb ending in ellipsis like "Sending..." - * - * @param label the label to display while the action is being prepared to execute - * @return this object for method chaining - */ - public WearableExtender setInProgressLabel(CharSequence label) { - mInProgressLabel = label; - return this; - } - - /** - * Get the label to display while the wearable is preparing to automatically execute - * the action. This is usually a 'ing' verb ending in ellipsis like "Sending..." - * - * @return the label to display while the action is being prepared to execute - */ - public CharSequence getInProgressLabel() { - return mInProgressLabel; - } - - /** - * Set a label to display to confirm that the action should be executed. - * This is usually an imperative verb like "Send". - * - * @param label the label to confirm the action should be executed - * @return this object for method chaining - */ - public WearableExtender setConfirmLabel(CharSequence label) { - mConfirmLabel = label; - return this; - } - - /** - * Get the label to display to confirm that the action should be executed. - * This is usually an imperative verb like "Send". - * - * @return the label to confirm the action should be executed - */ - public CharSequence getConfirmLabel() { - return mConfirmLabel; - } - - /** - * Set a label to display to cancel the action. - * This is usually an imperative verb, like "Cancel". - * - * @param label the label to display to cancel the action - * @return this object for method chaining - */ - public WearableExtender setCancelLabel(CharSequence label) { - mCancelLabel = label; - return this; - } - - /** - * Get the label to display to cancel the action. - * This is usually an imperative verb like "Cancel". - * - * @return the label to display to cancel the action - */ - public CharSequence getCancelLabel() { - return mCancelLabel; - } - } - - /** @hide */ - public static final Factory FACTORY = new Factory() { - @Override - public Action build(int icon, CharSequence title, - PendingIntent actionIntent, Bundle extras, - RemoteInputCompatBase.RemoteInput[] remoteInputs) { - return new Action(icon, title, actionIntent, extras, - (RemoteInput[]) remoteInputs); - } - - @Override - public Action[] newArray(int length) { - return new Action[length]; - } - }; - } - - - /** - * Extender interface for use with {@link Builder#extend}. Extenders may be used to add - * metadata or change options on a notification builder. - */ - public interface Extender { - /** - * Apply this extender to a notification builder. - * @param builder the builder to be modified. - * @return the build object for chaining. - */ - public Builder extend(Builder builder); - } - - /** - * Helper class to add wearable extensions to notifications. - *

See - * Creating Notifications - * for Android Wear for more information on how to use this class. - *

- * To create a notification with wearable extensions: - *

    - *
  1. Create a {@link Builder}, setting any desired - * properties. - *
  2. Create a {@link WearableExtender}. - *
  3. Set wearable-specific properties using the - * {@code add} and {@code set} methods of {@link WearableExtender}. - *
  4. Call {@link Builder#extend} to apply the extensions to a - * notification. - *
  5. Post the notification to the notification - * system with the {@code NotificationManagerCompat.notify(...)} methods - * and not the {@code NotificationManager.notify(...)} methods. - *
- * - *
-     * Notification notif = new NotificationCompat.Builder(mContext)
-     *         .setContentTitle("New mail from " + sender.toString())
-     *         .setContentText(subject)
-     *         .setSmallIcon(R.drawable.new_mail)
-     *         .extend(new NotificationCompat.WearableExtender()
-     *                 .setContentIcon(R.drawable.new_mail))
-     *         .build();
-     * NotificationManagerCompat.from(mContext).notify(0, notif);
- * - *

Wearable extensions can be accessed on an existing notification by using the - * {@code WearableExtender(Notification)} constructor, - * and then using the {@code get} methods to access values. - * - *

-     * NotificationCompat.WearableExtender wearableExtender =
-     *         new NotificationCompat.WearableExtender(notification);
-     * List<Notification> pages = wearableExtender.getPages();
- */ - public static final class WearableExtender implements Extender { - /** - * Sentinel value for an action index that is unset. - */ - public static final int UNSET_ACTION_INDEX = -1; - - /** - * Size value for use with {@link #setCustomSizePreset} to show this notification with - * default sizing. - *

For custom display notifications created using {@link #setDisplayIntent}, - * the default is {@link #SIZE_MEDIUM}. All other notifications size automatically based - * on their content. - */ - public static final int SIZE_DEFAULT = 0; - - /** - * Size value for use with {@link #setCustomSizePreset} to show this notification - * with an extra small size. - *

This value is only applicable for custom display notifications created using - * {@link #setDisplayIntent}. - */ - public static final int SIZE_XSMALL = 1; - - /** - * Size value for use with {@link #setCustomSizePreset} to show this notification - * with a small size. - *

This value is only applicable for custom display notifications created using - * {@link #setDisplayIntent}. - */ - public static final int SIZE_SMALL = 2; - - /** - * Size value for use with {@link #setCustomSizePreset} to show this notification - * with a medium size. - *

This value is only applicable for custom display notifications created using - * {@link #setDisplayIntent}. - */ - public static final int SIZE_MEDIUM = 3; - - /** - * Size value for use with {@link #setCustomSizePreset} to show this notification - * with a large size. - *

This value is only applicable for custom display notifications created using - * {@link #setDisplayIntent}. - */ - public static final int SIZE_LARGE = 4; - - /** - * Size value for use with {@link #setCustomSizePreset} to show this notification - * full screen. - *

This value is only applicable for custom display notifications created using - * {@link #setDisplayIntent}. - */ - public static final int SIZE_FULL_SCREEN = 5; - - /** - * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on for a - * short amount of time when this notification is displayed on the screen. This - * is the default value. - */ - public static final int SCREEN_TIMEOUT_SHORT = 0; - - /** - * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on - * for a longer amount of time when this notification is displayed on the screen. - */ - public static final int SCREEN_TIMEOUT_LONG = -1; - - /** Notification extra which contains wearable extensions */ - private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS"; - - // Keys within EXTRA_WEARABLE_EXTENSIONS for wearable options. - private static final String KEY_ACTIONS = "actions"; - private static final String KEY_FLAGS = "flags"; - private static final String KEY_DISPLAY_INTENT = "displayIntent"; - private static final String KEY_PAGES = "pages"; - private static final String KEY_BACKGROUND = "background"; - private static final String KEY_CONTENT_ICON = "contentIcon"; - private static final String KEY_CONTENT_ICON_GRAVITY = "contentIconGravity"; - private static final String KEY_CONTENT_ACTION_INDEX = "contentActionIndex"; - private static final String KEY_CUSTOM_SIZE_PRESET = "customSizePreset"; - private static final String KEY_CUSTOM_CONTENT_HEIGHT = "customContentHeight"; - private static final String KEY_GRAVITY = "gravity"; - private static final String KEY_HINT_SCREEN_TIMEOUT = "hintScreenTimeout"; - - // Flags bitwise-ored to mFlags - private static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 0x1; - private static final int FLAG_HINT_HIDE_ICON = 1 << 1; - private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2; - private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3; - private static final int FLAG_HINT_AVOID_BACKGROUND_CLIPPING = 1 << 4; - - // Default value for flags integer - private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE; - - private static final int DEFAULT_CONTENT_ICON_GRAVITY = GravityCompat.END; - private static final int DEFAULT_GRAVITY = Gravity.BOTTOM; - - private ArrayList mActions = new ArrayList(); - private int mFlags = DEFAULT_FLAGS; - private PendingIntent mDisplayIntent; - private ArrayList mPages = new ArrayList(); - private Bitmap mBackground; - private int mContentIcon; - private int mContentIconGravity = DEFAULT_CONTENT_ICON_GRAVITY; - private int mContentActionIndex = UNSET_ACTION_INDEX; - private int mCustomSizePreset = SIZE_DEFAULT; - private int mCustomContentHeight; - private int mGravity = DEFAULT_GRAVITY; - private int mHintScreenTimeout; - - /** - * Create a {@link WearableExtender} with default - * options. - */ - public WearableExtender() { - } - - public WearableExtender(Notification notif) { - Bundle extras = getExtras(notif); - Bundle wearableBundle = extras != null ? extras.getBundle(EXTRA_WEARABLE_EXTENSIONS) - : null; - if (wearableBundle != null) { - Action[] actions = IMPL.getActionsFromParcelableArrayList( - wearableBundle.getParcelableArrayList(KEY_ACTIONS)); - if (actions != null) { - Collections.addAll(mActions, actions); - } - - mFlags = wearableBundle.getInt(KEY_FLAGS, DEFAULT_FLAGS); - mDisplayIntent = wearableBundle.getParcelable(KEY_DISPLAY_INTENT); - - Notification[] pages = getNotificationArrayFromBundle( - wearableBundle, KEY_PAGES); - if (pages != null) { - Collections.addAll(mPages, pages); - } - - mBackground = wearableBundle.getParcelable(KEY_BACKGROUND); - mContentIcon = wearableBundle.getInt(KEY_CONTENT_ICON); - mContentIconGravity = wearableBundle.getInt(KEY_CONTENT_ICON_GRAVITY, - DEFAULT_CONTENT_ICON_GRAVITY); - mContentActionIndex = wearableBundle.getInt(KEY_CONTENT_ACTION_INDEX, - UNSET_ACTION_INDEX); - mCustomSizePreset = wearableBundle.getInt(KEY_CUSTOM_SIZE_PRESET, - SIZE_DEFAULT); - mCustomContentHeight = wearableBundle.getInt(KEY_CUSTOM_CONTENT_HEIGHT); - mGravity = wearableBundle.getInt(KEY_GRAVITY, DEFAULT_GRAVITY); - mHintScreenTimeout = wearableBundle.getInt(KEY_HINT_SCREEN_TIMEOUT); - } - } - - /** - * Apply wearable extensions to a notification that is being built. This is typically - * called by the {@link Builder#extend} method of - * {@link Builder}. - */ - @Override - public Builder extend(Builder builder) { - Bundle wearableBundle = new Bundle(); - - if (!mActions.isEmpty()) { - wearableBundle.putParcelableArrayList(KEY_ACTIONS, - IMPL.getParcelableArrayListForActions(mActions.toArray( - new Action[mActions.size()]))); - } - if (mFlags != DEFAULT_FLAGS) { - wearableBundle.putInt(KEY_FLAGS, mFlags); - } - if (mDisplayIntent != null) { - wearableBundle.putParcelable(KEY_DISPLAY_INTENT, mDisplayIntent); - } - if (!mPages.isEmpty()) { - wearableBundle.putParcelableArray(KEY_PAGES, mPages.toArray( - new Notification[mPages.size()])); - } - if (mBackground != null) { - wearableBundle.putParcelable(KEY_BACKGROUND, mBackground); - } - if (mContentIcon != 0) { - wearableBundle.putInt(KEY_CONTENT_ICON, mContentIcon); - } - if (mContentIconGravity != DEFAULT_CONTENT_ICON_GRAVITY) { - wearableBundle.putInt(KEY_CONTENT_ICON_GRAVITY, mContentIconGravity); - } - if (mContentActionIndex != UNSET_ACTION_INDEX) { - wearableBundle.putInt(KEY_CONTENT_ACTION_INDEX, - mContentActionIndex); - } - if (mCustomSizePreset != SIZE_DEFAULT) { - wearableBundle.putInt(KEY_CUSTOM_SIZE_PRESET, mCustomSizePreset); - } - if (mCustomContentHeight != 0) { - wearableBundle.putInt(KEY_CUSTOM_CONTENT_HEIGHT, mCustomContentHeight); - } - if (mGravity != DEFAULT_GRAVITY) { - wearableBundle.putInt(KEY_GRAVITY, mGravity); - } - if (mHintScreenTimeout != 0) { - wearableBundle.putInt(KEY_HINT_SCREEN_TIMEOUT, mHintScreenTimeout); - } - - builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle); - return builder; - } - - @Override - public WearableExtender clone() { - WearableExtender that = new WearableExtender(); - that.mActions = new ArrayList(this.mActions); - that.mFlags = this.mFlags; - that.mDisplayIntent = this.mDisplayIntent; - that.mPages = new ArrayList(this.mPages); - that.mBackground = this.mBackground; - that.mContentIcon = this.mContentIcon; - that.mContentIconGravity = this.mContentIconGravity; - that.mContentActionIndex = this.mContentActionIndex; - that.mCustomSizePreset = this.mCustomSizePreset; - that.mCustomContentHeight = this.mCustomContentHeight; - that.mGravity = this.mGravity; - that.mHintScreenTimeout = this.mHintScreenTimeout; - return that; - } - - /** - * Add a wearable action to this notification. - * - *

When wearable actions are added using this method, the set of actions that - * show on a wearable device splits from devices that only show actions added - * using {@link Builder#addAction}. This allows for customization - * of which actions display on different devices. - * - * @param action the action to add to this notification - * @return this object for method chaining - * @see Action - */ - public WearableExtender addAction(Action action) { - mActions.add(action); - return this; - } - - /** - * Adds wearable actions to this notification. - * - *

When wearable actions are added using this method, the set of actions that - * show on a wearable device splits from devices that only show actions added - * using {@link Builder#addAction}. This allows for customization - * of which actions display on different devices. - * - * @param actions the actions to add to this notification - * @return this object for method chaining - * @see Action - */ - public WearableExtender addActions(List actions) { - mActions.addAll(actions); - return this; - } - - /** - * Clear all wearable actions present on this builder. - * @return this object for method chaining. - * @see #addAction - */ - public WearableExtender clearActions() { - mActions.clear(); - return this; - } - - /** - * Get the wearable actions present on this notification. - */ - public List getActions() { - return mActions; - } - - /** - * Set an intent to launch inside of an activity view when displaying - * this notification. The {@link PendingIntent} provided should be for an activity. - * - *

-         * Intent displayIntent = new Intent(context, MyDisplayActivity.class);
-         * PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
-         *         0, displayIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-         * Notification notif = new NotificationCompat.Builder(context)
-         *         .extend(new NotificationCompat.WearableExtender()
-         *                 .setDisplayIntent(displayPendingIntent)
-         *                 .setCustomSizePreset(NotificationCompat.WearableExtender.SIZE_MEDIUM))
-         *         .build();
- * - *

The activity to launch needs to allow embedding, must be exported, and - * should have an empty task affinity. It is also recommended to use the device - * default light theme. - * - *

Example AndroidManifest.xml entry: - *

-         * <activity android:name="com.example.MyDisplayActivity"
-         *     android:exported="true"
-         *     android:allowEmbedded="true"
-         *     android:taskAffinity=""
-         *     android:theme="@android:style/Theme.DeviceDefault.Light" />
- * - * @param intent the {@link PendingIntent} for an activity - * @return this object for method chaining - * @see WearableExtender#getDisplayIntent - */ - public WearableExtender setDisplayIntent(PendingIntent intent) { - mDisplayIntent = intent; - return this; - } - - /** - * Get the intent to launch inside of an activity view when displaying this - * notification. This {@code PendingIntent} should be for an activity. - */ - public PendingIntent getDisplayIntent() { - return mDisplayIntent; - } - - /** - * Add an additional page of content to display with this notification. The current - * notification forms the first page, and pages added using this function form - * subsequent pages. This field can be used to separate a notification into multiple - * sections. - * - * @param page the notification to add as another page - * @return this object for method chaining - * @see WearableExtender#getPages - */ - public WearableExtender addPage(Notification page) { - mPages.add(page); - return this; - } - - /** - * Add additional pages of content to display with this notification. The current - * notification forms the first page, and pages added using this function form - * subsequent pages. This field can be used to separate a notification into multiple - * sections. - * - * @param pages a list of notifications - * @return this object for method chaining - * @see WearableExtender#getPages - */ - public WearableExtender addPages(List pages) { - mPages.addAll(pages); - return this; - } - - /** - * Clear all additional pages present on this builder. - * @return this object for method chaining. - * @see #addPage - */ - public WearableExtender clearPages() { - mPages.clear(); - return this; - } - - /** - * Get the array of additional pages of content for displaying this notification. The - * current notification forms the first page, and elements within this array form - * subsequent pages. This field can be used to separate a notification into multiple - * sections. - * @return the pages for this notification - */ - public List getPages() { - return mPages; - } - - /** - * Set a background image to be displayed behind the notification content. - * Contrary to the {@link BigPictureStyle}, this background - * will work with any notification style. - * - * @param background the background bitmap - * @return this object for method chaining - * @see WearableExtender#getBackground - */ - public WearableExtender setBackground(Bitmap background) { - mBackground = background; - return this; - } - - /** - * Get a background image to be displayed behind the notification content. - * Contrary to the {@link BigPictureStyle}, this background - * will work with any notification style. - * - * @return the background image - * @see WearableExtender#setBackground - */ - public Bitmap getBackground() { - return mBackground; - } - - /** - * Set an icon that goes with the content of this notification. - */ - public WearableExtender setContentIcon(int icon) { - mContentIcon = icon; - return this; - } - - /** - * Get an icon that goes with the content of this notification. - */ - public int getContentIcon() { - return mContentIcon; - } - - /** - * Set the gravity that the content icon should have within the notification display. - * Supported values include {@link Gravity#START} and - * {@link Gravity#END}. The default value is {@link Gravity#END}. - * @see #setContentIcon - */ - public WearableExtender setContentIconGravity(int contentIconGravity) { - mContentIconGravity = contentIconGravity; - return this; - } - - /** - * Get the gravity that the content icon should have within the notification display. - * Supported values include {@link Gravity#START} and - * {@link Gravity#END}. The default value is {@link Gravity#END}. - * @see #getContentIcon - */ - public int getContentIconGravity() { - return mContentIconGravity; - } - - /** - * Set an action from this notification's actions to be clickable with the content of - * this notification. This action will no longer display separately from the - * notification's content. - * - *

For notifications with multiple pages, child pages can also have content actions - * set, although the list of available actions comes from the main notification and not - * from the child page's notification. - * - * @param actionIndex The index of the action to hoist onto the current notification page. - * If wearable actions were added to the main notification, this index - * will apply to that list, otherwise it will apply to the regular - * actions list. - */ - public WearableExtender setContentAction(int actionIndex) { - mContentActionIndex = actionIndex; - return this; - } - - /** - * Get the index of the notification action, if any, that was specified as being clickable - * with the content of this notification. This action will no longer display separately - * from the notification's content. - * - *

For notifications with multiple pages, child pages can also have content actions - * set, although the list of available actions comes from the main notification and not - * from the child page's notification. - * - *

If wearable specific actions were added to the main notification, this index will - * apply to that list, otherwise it will apply to the regular actions list. - * - * @return the action index or {@link #UNSET_ACTION_INDEX} if no action was selected. - */ - public int getContentAction() { - return mContentActionIndex; - } - - /** - * Set the gravity that this notification should have within the available viewport space. - * Supported values include {@link Gravity#TOP}, - * {@link Gravity#CENTER_VERTICAL} and {@link Gravity#BOTTOM}. - * The default value is {@link Gravity#BOTTOM}. - */ - public WearableExtender setGravity(int gravity) { - mGravity = gravity; - return this; - } - - /** - * Get the gravity that this notification should have within the available viewport space. - * Supported values include {@link Gravity#TOP}, - * {@link Gravity#CENTER_VERTICAL} and {@link Gravity#BOTTOM}. - * The default value is {@link Gravity#BOTTOM}. - */ - public int getGravity() { - return mGravity; - } - - /** - * Set the custom size preset for the display of this notification out of the available - * presets found in {@link WearableExtender}, e.g. - * {@link #SIZE_LARGE}. - *

Some custom size presets are only applicable for custom display notifications created - * using {@link WearableExtender#setDisplayIntent}. Check the - * documentation for the preset in question. See also - * {@link #setCustomContentHeight} and {@link #getCustomSizePreset}. - */ - public WearableExtender setCustomSizePreset(int sizePreset) { - mCustomSizePreset = sizePreset; - return this; - } - - /** - * Get the custom size preset for the display of this notification out of the available - * presets found in {@link WearableExtender}, e.g. - * {@link #SIZE_LARGE}. - *

Some custom size presets are only applicable for custom display notifications created - * using {@link #setDisplayIntent}. Check the documentation for the preset in question. - * See also {@link #setCustomContentHeight} and {@link #setCustomSizePreset}. - */ - public int getCustomSizePreset() { - return mCustomSizePreset; - } - - /** - * Set the custom height in pixels for the display of this notification's content. - *

This option is only available for custom display notifications created - * using {@link WearableExtender#setDisplayIntent}. See also - * {@link WearableExtender#setCustomSizePreset} and - * {@link #getCustomContentHeight}. - */ - public WearableExtender setCustomContentHeight(int height) { - mCustomContentHeight = height; - return this; - } - - /** - * Get the custom height in pixels for the display of this notification's content. - *

This option is only available for custom display notifications created - * using {@link #setDisplayIntent}. See also {@link #setCustomSizePreset} and - * {@link #setCustomContentHeight}. - */ - public int getCustomContentHeight() { - return mCustomContentHeight; - } - - /** - * Set whether the scrolling position for the contents of this notification should start - * at the bottom of the contents instead of the top when the contents are too long to - * display within the screen. Default is false (start scroll at the top). - */ - public WearableExtender setStartScrollBottom(boolean startScrollBottom) { - setFlag(FLAG_START_SCROLL_BOTTOM, startScrollBottom); - return this; - } - - /** - * Get whether the scrolling position for the contents of this notification should start - * at the bottom of the contents instead of the top when the contents are too long to - * display within the screen. Default is false (start scroll at the top). - */ - public boolean getStartScrollBottom() { - return (mFlags & FLAG_START_SCROLL_BOTTOM) != 0; - } - - /** - * Set whether the content intent is available when the wearable device is not connected - * to a companion device. The user can still trigger this intent when the wearable device - * is offline, but a visual hint will indicate that the content intent may not be available. - * Defaults to true. - */ - public WearableExtender setContentIntentAvailableOffline( - boolean contentIntentAvailableOffline) { - setFlag(FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE, contentIntentAvailableOffline); - return this; - } - - /** - * Get whether the content intent is available when the wearable device is not connected - * to a companion device. The user can still trigger this intent when the wearable device - * is offline, but a visual hint will indicate that the content intent may not be available. - * Defaults to true. - */ - public boolean getContentIntentAvailableOffline() { - return (mFlags & FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE) != 0; - } - - /** - * Set a hint that this notification's icon should not be displayed. - * @param hintHideIcon {@code true} to hide the icon, {@code false} otherwise. - * @return this object for method chaining - */ - public WearableExtender setHintHideIcon(boolean hintHideIcon) { - setFlag(FLAG_HINT_HIDE_ICON, hintHideIcon); - return this; - } - - /** - * Get a hint that this notification's icon should not be displayed. - * @return {@code true} if this icon should not be displayed, false otherwise. - * The default value is {@code false} if this was never set. - */ - public boolean getHintHideIcon() { - return (mFlags & FLAG_HINT_HIDE_ICON) != 0; - } - - /** - * Set a visual hint that only the background image of this notification should be - * displayed, and other semantic content should be hidden. This hint is only applicable - * to sub-pages added using {@link #addPage}. - */ - public WearableExtender setHintShowBackgroundOnly(boolean hintShowBackgroundOnly) { - setFlag(FLAG_HINT_SHOW_BACKGROUND_ONLY, hintShowBackgroundOnly); - return this; - } - - /** - * Get a visual hint that only the background image of this notification should be - * displayed, and other semantic content should be hidden. This hint is only applicable - * to sub-pages added using {@link WearableExtender#addPage}. - */ - public boolean getHintShowBackgroundOnly() { - return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0; - } - - /** - * Set a hint that this notification's background should not be clipped if possible, - * and should instead be resized to fully display on the screen, retaining the aspect - * ratio of the image. This can be useful for images like barcodes or qr codes. - * @param hintAvoidBackgroundClipping {@code true} to avoid clipping if possible. - * @return this object for method chaining - */ - public WearableExtender setHintAvoidBackgroundClipping( - boolean hintAvoidBackgroundClipping) { - setFlag(FLAG_HINT_AVOID_BACKGROUND_CLIPPING, hintAvoidBackgroundClipping); - return this; - } - - /** - * Get a hint that this notification's background should not be clipped if possible, - * and should instead be resized to fully display on the screen, retaining the aspect - * ratio of the image. This can be useful for images like barcodes or qr codes. - * @return {@code true} if it's ok if the background is clipped on the screen, false - * otherwise. The default value is {@code false} if this was never set. - */ - public boolean getHintAvoidBackgroundClipping() { - return (mFlags & FLAG_HINT_AVOID_BACKGROUND_CLIPPING) != 0; - } - - /** - * Set a hint that the screen should remain on for at least this duration when - * this notification is displayed on the screen. - * @param timeout The requested screen timeout in milliseconds. Can also be either - * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}. - * @return this object for method chaining - */ - public WearableExtender setHintScreenTimeout(int timeout) { - mHintScreenTimeout = timeout; - return this; - } - - /** - * Get the duration, in milliseconds, that the screen should remain on for - * when this notification is displayed. - * @return the duration in milliseconds if > 0, or either one of the sentinel values - * {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}. - */ - public int getHintScreenTimeout() { - return mHintScreenTimeout; - } - - private void setFlag(int mask, boolean value) { - if (value) { - mFlags |= mask; - } else { - mFlags &= ~mask; - } - } - } - - /** - *

Helper class to add Android Auto extensions to notifications. To create a notification - * with car extensions: - * - *

    - *
  1. Create an {@link Builder}, setting any desired - * properties. - *
  2. Create a {@link CarExtender}. - *
  3. Set car-specific properties using the {@code add} and {@code set} methods of - * {@link CarExtender}. - *
  4. Call {@link Builder#extend(Extender)} - * to apply the extensions to a notification. - *
  5. Post the notification to the notification system with the - * {@code NotificationManagerCompat.notify(...)} methods and not the - * {@code NotificationManager.notify(...)} methods. - *
- * - *
-     * Notification notification = new NotificationCompat.Builder(context)
-     *         ...
-     *         .extend(new CarExtender()
-     *                 .set*(...))
-     *         .build();
-     * 
- * - *

Car extensions can be accessed on an existing notification by using the - * {@code CarExtender(Notification)} constructor, and then using the {@code get} methods - * to access values. - */ - public static final class CarExtender implements Extender { - private static final String TAG = "CarExtender"; - - private static final String EXTRA_CAR_EXTENDER = "android.car.EXTENSIONS"; - private static final String EXTRA_LARGE_ICON = "large_icon"; - private static final String EXTRA_CONVERSATION = "car_conversation"; - private static final String EXTRA_COLOR = "app_color"; - - private Bitmap mLargeIcon; - private UnreadConversation mUnreadConversation; - private int mColor = NotificationCompat.COLOR_DEFAULT; - - /** - * Create a {@link CarExtender} with default options. - */ - public CarExtender() { - } - - /** - * Create a {@link CarExtender} from the CarExtender options of an existing Notification. - * - * @param notif The notification from which to copy options. - */ - public CarExtender(Notification notif) { - if (Build.VERSION.SDK_INT < 21) { - return; - } - - Bundle carBundle = getExtras(notif)==null ? - null : getExtras(notif).getBundle(EXTRA_CAR_EXTENDER); - if (carBundle != null) { - mLargeIcon = carBundle.getParcelable(EXTRA_LARGE_ICON); - mColor = carBundle.getInt(EXTRA_COLOR, NotificationCompat.COLOR_DEFAULT); - - Bundle b = carBundle.getBundle(EXTRA_CONVERSATION); - mUnreadConversation = (UnreadConversation) IMPL.getUnreadConversationFromBundle( - b, UnreadConversation.FACTORY, RemoteInput.FACTORY); - } - } - - /** - * Apply car extensions to a notification that is being built. This is typically called by - * the {@link Builder#extend(Extender)} - * method of {@link Builder}. - */ - @Override - public Builder extend(Builder builder) { - if (Build.VERSION.SDK_INT < 21) { - return builder; - } - - Bundle carExtensions = new Bundle(); - - if (mLargeIcon != null) { - carExtensions.putParcelable(EXTRA_LARGE_ICON, mLargeIcon); - } - if (mColor != NotificationCompat.COLOR_DEFAULT) { - carExtensions.putInt(EXTRA_COLOR, mColor); - } - - if (mUnreadConversation != null) { - Bundle b = IMPL.getBundleForUnreadConversation(mUnreadConversation); - carExtensions.putBundle(EXTRA_CONVERSATION, b); - } - - builder.getExtras().putBundle(EXTRA_CAR_EXTENDER, carExtensions); - return builder; - } - - /** - * Sets the accent color to use when Android Auto presents the notification. - * - * Android Auto uses the color set with {@link Builder#setColor(int)} - * to accent the displayed notification. However, not all colors are acceptable in an - * automotive setting. This method can be used to override the color provided in the - * notification in such a situation. - */ - public CarExtender setColor(@ColorInt int color) { - mColor = color; - return this; - } - - /** - * Gets the accent color. - * - * @see setColor - */ - @ColorInt - public int getColor() { - return mColor; - } - - /** - * Sets the large icon of the car notification. - * - * If no large icon is set in the extender, Android Auto will display the icon - * specified by {@link Builder#setLargeIcon(Bitmap)} - * - * @param largeIcon The large icon to use in the car notification. - * @return This object for method chaining. - */ - public CarExtender setLargeIcon(Bitmap largeIcon) { - mLargeIcon = largeIcon; - return this; - } - - /** - * Gets the large icon used in this car notification, or null if no icon has been set. - * - * @return The large icon for the car notification. - * @see CarExtender#setLargeIcon - */ - public Bitmap getLargeIcon() { - return mLargeIcon; - } - - /** - * Sets the unread conversation in a message notification. - * - * @param unreadConversation The unread part of the conversation this notification conveys. - * @return This object for method chaining. - */ - public CarExtender setUnreadConversation(UnreadConversation unreadConversation) { - mUnreadConversation = unreadConversation; - return this; - } - - /** - * Returns the unread conversation conveyed by this notification. - * @see #setUnreadConversation(UnreadConversation) - */ - public UnreadConversation getUnreadConversation() { - return mUnreadConversation; - } - - /** - * A class which holds the unread messages from a conversation. - */ - public static class UnreadConversation extends NotificationCompatBase.UnreadConversation { - private final String[] mMessages; - private final RemoteInput mRemoteInput; - private final PendingIntent mReplyPendingIntent; - private final PendingIntent mReadPendingIntent; - private final String[] mParticipants; - private final long mLatestTimestamp; - - UnreadConversation(String[] messages, RemoteInput remoteInput, - PendingIntent replyPendingIntent, PendingIntent readPendingIntent, - String[] participants, long latestTimestamp) { - mMessages = messages; - mRemoteInput = remoteInput; - mReadPendingIntent = readPendingIntent; - mReplyPendingIntent = replyPendingIntent; - mParticipants = participants; - mLatestTimestamp = latestTimestamp; - } - - /** - * Gets the list of messages conveyed by this notification. - */ - @Override - public String[] getMessages() { - return mMessages; - } - - /** - * Gets the remote input that will be used to convey the response to a message list, or - * null if no such remote input exists. - */ - @Override - public RemoteInput getRemoteInput() { - return mRemoteInput; - } - - /** - * Gets the pending intent that will be triggered when the user replies to this - * notification. - */ - @Override - public PendingIntent getReplyPendingIntent() { - return mReplyPendingIntent; - } - - /** - * Gets the pending intent that Android Auto will send after it reads aloud all messages - * in this object's message list. - */ - @Override - public PendingIntent getReadPendingIntent() { - return mReadPendingIntent; - } - - /** - * Gets the participants in the conversation. - */ - @Override - public String[] getParticipants() { - return mParticipants; - } - - /** - * Gets the firs participant in the conversation. - */ - @Override - public String getParticipant() { - return mParticipants.length > 0 ? mParticipants[0] : null; - } - - /** - * Gets the timestamp of the conversation. - */ - @Override - public long getLatestTimestamp() { - return mLatestTimestamp; - } - - /** @hide */ - static final Factory FACTORY = new Factory() { - @Override - public UnreadConversation build( - String[] messages, RemoteInputCompatBase.RemoteInput remoteInput, - PendingIntent replyPendingIntent, PendingIntent readPendingIntent, - String[] participants, long latestTimestamp) { - return new UnreadConversation( - messages, (RemoteInput) remoteInput, replyPendingIntent, - readPendingIntent, - participants, latestTimestamp); - } - }; - - /** - * Builder class for {@link UnreadConversation} objects. - */ - public static class Builder { - private final List mMessages = new ArrayList(); - private final String mParticipant; - private RemoteInput mRemoteInput; - private PendingIntent mReadPendingIntent; - private PendingIntent mReplyPendingIntent; - private long mLatestTimestamp; - - /** - * Constructs a new builder for {@link UnreadConversation}. - * - * @param name The name of the other participant in the conversation. - */ - public Builder(String name) { - mParticipant = name; - } - - /** - * Appends a new unread message to the list of messages for this conversation. - * - * The messages should be added from oldest to newest. - * - * @param message The text of the new unread message. - * @return This object for method chaining. - */ - public Builder addMessage(String message) { - mMessages.add(message); - return this; - } - - /** - * Sets the pending intent and remote input which will convey the reply to this - * notification. - * - * @param pendingIntent The pending intent which will be triggered on a reply. - * @param remoteInput The remote input parcelable which will carry the reply. - * @return This object for method chaining. - * - * @see UnreadConversation#getRemoteInput - * @see UnreadConversation#getReplyPendingIntent - */ - public Builder setReplyAction( - PendingIntent pendingIntent, RemoteInput remoteInput) { - mRemoteInput = remoteInput; - mReplyPendingIntent = pendingIntent; - - return this; - } - - /** - * Sets the pending intent that will be sent once the messages in this notification - * are read. - * - * @param pendingIntent The pending intent to use. - * @return This object for method chaining. - */ - public Builder setReadPendingIntent(PendingIntent pendingIntent) { - mReadPendingIntent = pendingIntent; - return this; - } - - /** - * Sets the timestamp of the most recent message in an unread conversation. - * - * If a messaging notification has been posted by your application and has not - * yet been cancelled, posting a later notification with the same id and tag - * but without a newer timestamp may result in Android Auto not displaying a - * heads up notification for the later notification. - * - * @param timestamp The timestamp of the most recent message in the conversation. - * @return This object for method chaining. - */ - public Builder setLatestTimestamp(long timestamp) { - mLatestTimestamp = timestamp; - return this; - } - - /** - * Builds a new unread conversation object. - * - * @return The new unread conversation object. - */ - public UnreadConversation build() { - String[] messages = mMessages.toArray(new String[mMessages.size()]); - String[] participants = { mParticipant }; - return new UnreadConversation(messages, mRemoteInput, mReplyPendingIntent, - mReadPendingIntent, participants, mLatestTimestamp); - } - } - } - } - - - /** - * Get an array of Notification objects from a parcelable array bundle field. - * Update the bundle to have a typed array so fetches in the future don't need - * to do an array copy. - */ - private static Notification[] getNotificationArrayFromBundle(Bundle bundle, String key) { - Parcelable[] array = bundle.getParcelableArray(key); - if (array instanceof Notification[] || array == null) { - return (Notification[]) array; - } - Notification[] typedArray = new Notification[array.length]; - for (int i = 0; i < array.length; i++) { - typedArray[i] = (Notification) array[i]; - } - bundle.putParcelableArray(key, typedArray); - return typedArray; - } - - /** - * Gets the {@link Notification#extras} field from a notification in a backwards - * compatible manner. Extras field was supported from JellyBean (Api level 16) - * forwards. This function will return null on older api levels. - */ - public static Bundle getExtras(Notification notif) { - return IMPL.getExtras(notif); - } - - /** - * Get the number of actions in this notification in a backwards compatible - * manner. Actions were supported from JellyBean (Api level 16) forwards. - */ - public static int getActionCount(Notification notif) { - return IMPL.getActionCount(notif); - } - - /** - * Get an action on this notification in a backwards compatible - * manner. Actions were supported from JellyBean (Api level 16) forwards. - * @param notif The notification to inspect. - * @param actionIndex The index of the action to retrieve. - */ - public static Action getAction(Notification notif, int actionIndex) { - return IMPL.getAction(notif, actionIndex); - } - - /** - * Get the category of this notification in a backwards compatible - * manner. - * @param notif The notification to inspect. - */ - public static String getCategory(Notification notif) { - return IMPL.getCategory(notif); - } - - /** - * Get whether or not this notification is only relevant to the current device. - * - *

Some notifications can be bridged to other devices for remote display. - * If this hint is set, it is recommend that this notification not be bridged. - */ - public static boolean getLocalOnly(Notification notif) { - return IMPL.getLocalOnly(notif); - } - - /** - * Get the key used to group this notification into a cluster or stack - * with other notifications on devices which support such rendering. - */ - public static String getGroup(Notification notif) { - return IMPL.getGroup(notif); - } - - /** - * Get whether this notification to be the group summary for a group of notifications. - * Grouped notifications may display in a cluster or stack on devices which - * support such rendering. Requires a group key also be set using {@link Builder#setGroup}. - * @return Whether this notification is a group summary. - */ - public static boolean isGroupSummary(Notification notif) { - return IMPL.isGroupSummary(notif); - } - - /** - * Get a sort key that orders this notification among other notifications from the - * same package. This can be useful if an external sort was already applied and an app - * would like to preserve this. Notifications will be sorted lexicographically using this - * value, although providing different priorities in addition to providing sort key may - * cause this value to be ignored. - * - *

This sort key can also be used to order members of a notification group. See - * {@link Builder#setGroup}. - * - * @see String#compareTo(String) - */ - public static String getSortKey(Notification notif) { - return IMPL.getSortKey(notif); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatApi20.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatApi20.java deleted file mode 100644 index c75af32..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatApi20.java +++ /dev/null @@ -1,199 +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 p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.app.RemoteInput; -import android.content.Context; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.os.Parcelable; -import android.widget.RemoteViews; - -import java.util.ArrayList; - -class NotificationCompatApi20 { - public static class Builder implements NotificationBuilderWithBuilderAccessor, - NotificationBuilderWithActions { - private Notification.Builder b; - private Bundle mExtras; - - public Builder(Context context, Notification n, - CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, - RemoteViews tickerView, int number, - PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, - int progressMax, int progress, boolean progressIndeterminate, boolean showWhen, - boolean useChronometer, int priority, CharSequence subText, boolean localOnly, - ArrayList people, Bundle extras, String groupKey, boolean groupSummary, - String sortKey) { - b = new Notification.Builder(context) - .setWhen(n.when) - .setShowWhen(showWhen) - .setSmallIcon(n.icon, n.iconLevel) - .setContent(n.contentView) - .setTicker(n.tickerText, tickerView) - .setSound(n.sound, n.audioStreamType) - .setVibrate(n.vibrate) - .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) - .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) - .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) - .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) - .setDefaults(n.defaults) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setSubText(subText) - .setContentInfo(contentInfo) - .setContentIntent(contentIntent) - .setDeleteIntent(n.deleteIntent) - .setFullScreenIntent(fullScreenIntent, - (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) - .setLargeIcon(largeIcon) - .setNumber(number) - .setUsesChronometer(useChronometer) - .setPriority(priority) - .setProgress(progressMax, progress, progressIndeterminate) - .setLocalOnly(localOnly) - .setGroup(groupKey) - .setGroupSummary(groupSummary) - .setSortKey(sortKey); - mExtras = new Bundle(); - if (extras != null) { - mExtras.putAll(extras); - } - if (people != null && !people.isEmpty()) { - mExtras.putStringArray(Notification.EXTRA_PEOPLE, - people.toArray(new String[people.size()])); - } - } - - @Override - public void addAction(NotificationCompatBase.Action action) { - NotificationCompatApi20.addAction(b, action); - } - - @Override - public Notification.Builder getBuilder() { - return b; - } - - @Override - public Notification build() { - b.setExtras(mExtras); - return b.build(); - } - } - - public static void addAction(Notification.Builder b, NotificationCompatBase.Action action) { - Notification.Action.Builder actionBuilder = new Notification.Action.Builder( - action.getIcon(), action.getTitle(), action.getActionIntent()); - if (action.getRemoteInputs() != null) { - for (RemoteInput remoteInput : RemoteInputCompatApi20.fromCompat( - action.getRemoteInputs())) { - actionBuilder.addRemoteInput(remoteInput); - } - } - if (action.getExtras() != null) { - actionBuilder.addExtras(action.getExtras()); - } - b.addAction(actionBuilder.build()); - } - - public static NotificationCompatBase.Action getAction(Notification notif, - int actionIndex, NotificationCompatBase.Action.Factory actionFactory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - return getActionCompatFromAction(notif.actions[actionIndex], actionFactory, remoteInputFactory); - } - - private static NotificationCompatBase.Action getActionCompatFromAction( - Notification.Action action, NotificationCompatBase.Action.Factory actionFactory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - RemoteInputCompatBase.RemoteInput[] remoteInputs = RemoteInputCompatApi20.toCompat( - action.getRemoteInputs(), remoteInputFactory); - return actionFactory.build(action.icon, action.title, action.actionIntent, - action.getExtras(), remoteInputs); - } - - private static Notification.Action getActionFromActionCompat( - NotificationCompatBase.Action actionCompat) { - Notification.Action.Builder actionBuilder = new Notification.Action.Builder( - actionCompat.getIcon(), actionCompat.getTitle(), actionCompat.getActionIntent()) - .addExtras(actionCompat.getExtras()); - RemoteInputCompatBase.RemoteInput[] remoteInputCompats = actionCompat.getRemoteInputs(); - if (remoteInputCompats != null) { - RemoteInput[] remoteInputs = RemoteInputCompatApi20.fromCompat(remoteInputCompats); - for (RemoteInput remoteInput : remoteInputs) { - actionBuilder.addRemoteInput(remoteInput); - } - } - return actionBuilder.build(); - } - - /** - * Get a list of notification compat actions by parsing actions stored within a list of - * parcelables using the {@link Bundle#getParcelableArrayList} function in the same - * manner that framework code would do so. In API20, Using Action parcelable directly - * is correct. - */ - public static NotificationCompatBase.Action[] getActionsFromParcelableArrayList( - ArrayList parcelables, - NotificationCompatBase.Action.Factory actionFactory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - if (parcelables == null) { - return null; - } - NotificationCompatBase.Action[] actions = actionFactory.newArray(parcelables.size()); - for (int i = 0; i < actions.length; i++) { - Notification.Action action = (Notification.Action) parcelables.get(i); - actions[i] = getActionCompatFromAction(action, actionFactory, remoteInputFactory); - } - return actions; - } - - /** - * Get an array list of parcelables, suitable for {@link Bundle#putParcelableArrayList}, - * that matches what framework code would do to store an actions list in this way. In API20, - * action parcelables were directly placed as entries in the array list. - */ - public static ArrayList getParcelableArrayListForActions( - NotificationCompatBase.Action[] actions) { - if (actions == null) { - return null; - } - ArrayList parcelables = new ArrayList(actions.length); - for (NotificationCompatBase.Action action : actions) { - parcelables.add(getActionFromActionCompat(action)); - } - return parcelables; - } - - public static boolean getLocalOnly(Notification notif) { - return (notif.flags & Notification.FLAG_LOCAL_ONLY) != 0; - } - - public static String getGroup(Notification notif) { - return notif.getGroup(); - } - - public static boolean isGroupSummary(Notification notif) { - return (notif.flags & Notification.FLAG_GROUP_SUMMARY) != 0; - } - - public static String getSortKey(Notification notif) { - return notif.getSortKey(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatApi21.java deleted file mode 100644 index 0fc0966..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatApi21.java +++ /dev/null @@ -1,223 +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 p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.os.Parcelable; -import android.widget.RemoteViews; - -import java.util.ArrayList; - -class NotificationCompatApi21 { - - public static final String CATEGORY_CALL = Notification.CATEGORY_CALL; - public static final String CATEGORY_MESSAGE = Notification.CATEGORY_MESSAGE; - public static final String CATEGORY_EMAIL = Notification.CATEGORY_EMAIL; - public static final String CATEGORY_EVENT = Notification.CATEGORY_EVENT; - public static final String CATEGORY_PROMO = Notification.CATEGORY_PROMO; - public static final String CATEGORY_ALARM = Notification.CATEGORY_ALARM; - public static final String CATEGORY_PROGRESS = Notification.CATEGORY_PROGRESS; - public static final String CATEGORY_SOCIAL = Notification.CATEGORY_SOCIAL; - public static final String CATEGORY_ERROR = Notification.CATEGORY_ERROR; - public static final String CATEGORY_TRANSPORT = Notification.CATEGORY_TRANSPORT; - public static final String CATEGORY_SYSTEM = Notification.CATEGORY_SYSTEM; - public static final String CATEGORY_SERVICE = Notification.CATEGORY_SERVICE; - public static final String CATEGORY_RECOMMENDATION = Notification.CATEGORY_RECOMMENDATION; - public static final String CATEGORY_STATUS = Notification.CATEGORY_STATUS; - - private static final String KEY_AUTHOR = "author"; - private static final String KEY_TEXT = "text"; - private static final String KEY_MESSAGES = "messages"; - private static final String KEY_REMOTE_INPUT = "remote_input"; - private static final String KEY_ON_REPLY = "on_reply"; - private static final String KEY_ON_READ = "on_read"; - private static final String KEY_PARTICIPANTS = "participants"; - private static final String KEY_TIMESTAMP = "timestamp"; - - public static class Builder implements NotificationBuilderWithBuilderAccessor, - NotificationBuilderWithActions { - private Notification.Builder b; - - public Builder(Context context, Notification n, - CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, - RemoteViews tickerView, int number, - PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, - int progressMax, int progress, boolean progressIndeterminate, boolean showWhen, - boolean useChronometer, int priority, CharSequence subText, boolean localOnly, - String category, ArrayList people, Bundle extras, int color, - int visibility, Notification publicVersion, String groupKey, boolean groupSummary, - String sortKey) { - b = new Notification.Builder(context) - .setWhen(n.when) - .setShowWhen(showWhen) - .setSmallIcon(n.icon, n.iconLevel) - .setContent(n.contentView) - .setTicker(n.tickerText, tickerView) - .setSound(n.sound, n.audioStreamType) - .setVibrate(n.vibrate) - .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) - .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) - .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) - .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) - .setDefaults(n.defaults) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setSubText(subText) - .setContentInfo(contentInfo) - .setContentIntent(contentIntent) - .setDeleteIntent(n.deleteIntent) - .setFullScreenIntent(fullScreenIntent, - (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) - .setLargeIcon(largeIcon) - .setNumber(number) - .setUsesChronometer(useChronometer) - .setPriority(priority) - .setProgress(progressMax, progress, progressIndeterminate) - .setLocalOnly(localOnly) - .setExtras(extras) - .setGroup(groupKey) - .setGroupSummary(groupSummary) - .setSortKey(sortKey) - .setCategory(category) - .setColor(color) - .setVisibility(visibility) - .setPublicVersion(publicVersion); - for (String person: people) { - b.addPerson(person); - } - } - - @Override - public void addAction(NotificationCompatBase.Action action) { - NotificationCompatApi20.addAction(b, action); - } - - @Override - public Notification.Builder getBuilder() { - return b; - } - - @Override - public Notification build() { - return b.build(); - } - } - - public static String getCategory(Notification notif) { - return notif.category; - } - - static Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) { - if (uc == null) { - return null; - } - Bundle b = new Bundle(); - String author = null; - if (uc.getParticipants() != null && uc.getParticipants().length > 1) { - author = uc.getParticipants()[0]; - } - Parcelable[] messages = new Parcelable[uc.getMessages().length]; - for (int i = 0; i < messages.length; i++) { - Bundle m = new Bundle(); - m.putString(KEY_TEXT, uc.getMessages()[i]); - m.putString(KEY_AUTHOR, author); - messages[i] = m; - } - b.putParcelableArray(KEY_MESSAGES, messages); - RemoteInputCompatBase.RemoteInput remoteInput = uc.getRemoteInput(); - if (remoteInput != null) { - b.putParcelable(KEY_REMOTE_INPUT, fromCompatRemoteInput(remoteInput)); - } - b.putParcelable(KEY_ON_REPLY, uc.getReplyPendingIntent()); - b.putParcelable(KEY_ON_READ, uc.getReadPendingIntent()); - b.putStringArray(KEY_PARTICIPANTS, uc.getParticipants()); - b.putLong(KEY_TIMESTAMP, uc.getLatestTimestamp()); - return b; - } - - static NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle( - Bundle b, NotificationCompatBase.UnreadConversation.Factory factory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - if (b == null) { - return null; - } - Parcelable[] parcelableMessages = b.getParcelableArray(KEY_MESSAGES); - String[] messages = null; - if (parcelableMessages != null) { - String[] tmp = new String[parcelableMessages.length]; - boolean success = true; - for (int i = 0; i < tmp.length; i++) { - if (!(parcelableMessages[i] instanceof Bundle)) { - success = false; - break; - } - tmp[i] = ((Bundle) parcelableMessages[i]).getString(KEY_TEXT); - if (tmp[i] == null) { - success = false; - break; - } - } - if (success) { - messages = tmp; - } else { - return null; - } - } - - PendingIntent onRead = b.getParcelable(KEY_ON_READ); - PendingIntent onReply = b.getParcelable(KEY_ON_REPLY); - - android.app.RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT); - - String[] participants = b.getStringArray(KEY_PARTICIPANTS); - if (participants == null || participants.length != 1) { - return null; - } - - - return factory.build( - messages, - remoteInput != null ? toCompatRemoteInput(remoteInput, remoteInputFactory) : null, - onReply, - onRead, - participants, b.getLong(KEY_TIMESTAMP)); - } - - private static android.app.RemoteInput fromCompatRemoteInput( - RemoteInputCompatBase.RemoteInput src) { - return new android.app.RemoteInput.Builder(src.getResultKey()) - .setLabel(src.getLabel()) - .setChoices(src.getChoices()) - .setAllowFreeFormInput(src.getAllowFreeFormInput()) - .addExtras(src.getExtras()) - .build(); - } - - private static RemoteInputCompatBase.RemoteInput toCompatRemoteInput( - android.app.RemoteInput remoteInput, - RemoteInputCompatBase.RemoteInput.Factory factory) { - return factory.build(remoteInput.getResultKey(), - remoteInput.getLabel(), - remoteInput.getChoices(), - remoteInput.getAllowFreeFormInput(), - remoteInput.getExtras()); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatBase.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatBase.java deleted file mode 100644 index 9a22b6f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatBase.java +++ /dev/null @@ -1,65 +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 p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.os.Bundle; - -/** - * @hide - */ -public class NotificationCompatBase { - - public static abstract class Action { - public abstract int getIcon(); - public abstract CharSequence getTitle(); - public abstract PendingIntent getActionIntent(); - public abstract Bundle getExtras(); - public abstract RemoteInputCompatBase.RemoteInput[] getRemoteInputs(); - - public interface Factory { - Action build(int icon, CharSequence title, PendingIntent actionIntent, - Bundle extras, RemoteInputCompatBase.RemoteInput[] remoteInputs); - public Action[] newArray(int length); - } - } - - public static abstract class UnreadConversation { - abstract String[] getParticipants(); - abstract String getParticipant(); - abstract String[] getMessages(); - abstract RemoteInputCompatBase.RemoteInput getRemoteInput(); - abstract PendingIntent getReplyPendingIntent(); - abstract PendingIntent getReadPendingIntent(); - abstract long getLatestTimestamp(); - - public interface Factory { - UnreadConversation build(String[] messages, - RemoteInputCompatBase.RemoteInput remoteInput, - PendingIntent replyPendingIntent, PendingIntent readPendingIntent, - String[] participants, long latestTimestamp); - } - } - - public static Notification add(Notification notification, Context context, - CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) { - //notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); - return notification; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatExtras.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatExtras.java deleted file mode 100644 index 42c528d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatExtras.java +++ /dev/null @@ -1,70 +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 p.android.support.v4.app; - -/** - * Well-known extras used by {@link NotificationCompat} for backwards compatibility. - */ -public final class NotificationCompatExtras { - /** - * Extras key used internally by {@link NotificationCompat} to store the value of - * the {@link android.app.Notification#FLAG_LOCAL_ONLY} field before it was available. - * If possible, use {@link NotificationCompat#getLocalOnly} to access this field. - */ - public static final String EXTRA_LOCAL_ONLY = NotificationCompatJellybean.EXTRA_LOCAL_ONLY; - - /** - * Extras key used internally by {@link NotificationCompat} to store the value set - * by {@link android.app.Notification.Builder#setGroup} before it was available. - * If possible, use {@link NotificationCompat#getGroup} to access this value. - */ - public static final String EXTRA_GROUP_KEY = NotificationCompatJellybean.EXTRA_GROUP_KEY; - - /** - * Extras key used internally by {@link NotificationCompat} to store the value set - * by {@link android.app.Notification.Builder#setGroupSummary} before it was available. - * If possible, use {@link NotificationCompat#isGroupSummary} to access this value. - */ - public static final String EXTRA_GROUP_SUMMARY = - NotificationCompatJellybean.EXTRA_GROUP_SUMMARY; - - /** - * Extras key used internally by {@link NotificationCompat} to store the value set - * by {@link android.app.Notification.Builder#setSortKey} before it was available. - * If possible, use {@link NotificationCompat#getSortKey} to access this value. - */ - public static final String EXTRA_SORT_KEY = NotificationCompatJellybean.EXTRA_SORT_KEY; - - /** - * Extras key used internally by {@link NotificationCompat} to store the value of - * the {@link android.app.Notification.Action#extras} field before it was available. - * If possible, use {@link NotificationCompat#getAction} to access this field. - */ - public static final String EXTRA_ACTION_EXTRAS = - NotificationCompatJellybean.EXTRA_ACTION_EXTRAS; - - /** - * Extras key used internally by {@link NotificationCompat} to store the value of - * the {@link android.app.Notification.Action#getRemoteInputs} before the field - * was available. - * If possible, use {@link NotificationCompat.Action#getRemoteInputs to access this field. - */ - public static final String EXTRA_REMOTE_INPUTS = - NotificationCompatJellybean.EXTRA_REMOTE_INPUTS; - - private NotificationCompatExtras() {} -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatGingerbread.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatGingerbread.java deleted file mode 100644 index 13d4486..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatGingerbread.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; - -class NotificationCompatGingerbread { - public static Notification add(Notification notification, Context context, - CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent, - PendingIntent fullScreenIntent) { - //notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); - notification.fullScreenIntent = fullScreenIntent; - return notification; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatHoneycomb.java deleted file mode 100644 index 985bc3a..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatHoneycomb.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.Bitmap; -import android.widget.RemoteViews; - -class NotificationCompatHoneycomb { - static Notification add(Context context, Notification n, - CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, - RemoteViews tickerView, int number, - PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon) { - Notification.Builder b = new Notification.Builder(context) - .setWhen(n.when) - .setSmallIcon(n.icon, n.iconLevel) - .setContent(n.contentView) - .setTicker(n.tickerText, tickerView) - .setSound(n.sound, n.audioStreamType) - .setVibrate(n.vibrate) - .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) - .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) - .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) - .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) - .setDefaults(n.defaults) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setContentInfo(contentInfo) - .setContentIntent(contentIntent) - .setDeleteIntent(n.deleteIntent) - .setFullScreenIntent(fullScreenIntent, - (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) - .setLargeIcon(largeIcon) - .setNumber(number); - - return b.getNotification(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatIceCreamSandwich.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatIceCreamSandwich.java deleted file mode 100644 index 467a587..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatIceCreamSandwich.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.Bitmap; -import android.widget.RemoteViews; - -class NotificationCompatIceCreamSandwich { - - public static class Builder implements NotificationBuilderWithBuilderAccessor { - - private Notification.Builder b; - - public Builder(Context context, Notification n, CharSequence contentTitle, - CharSequence contentText, CharSequence contentInfo, RemoteViews tickerView, - int number, PendingIntent contentIntent, PendingIntent fullScreenIntent, - Bitmap largeIcon, int progressMax, int progress, boolean progressIndeterminate) { - b = new Notification.Builder(context) - .setWhen(n.when) - .setSmallIcon(n.icon, n.iconLevel) - .setContent(n.contentView) - .setTicker(n.tickerText, tickerView) - .setSound(n.sound, n.audioStreamType) - .setVibrate(n.vibrate) - .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) - .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) - .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) - .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) - .setDefaults(n.defaults) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setContentInfo(contentInfo) - .setContentIntent(contentIntent) - .setDeleteIntent(n.deleteIntent) - .setFullScreenIntent(fullScreenIntent, - (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) - .setLargeIcon(largeIcon) - .setNumber(number) - .setProgress(progressMax, progress, progressIndeterminate); - } - - @Override - public Notification.Builder getBuilder() { - return b; - } - - @Override - public Notification build() { - return b.getNotification(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatJellybean.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatJellybean.java deleted file mode 100644 index 35d02ad..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatJellybean.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.os.Parcelable; -import android.util.Log; -import android.util.SparseArray; -import android.widget.RemoteViews; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -class NotificationCompatJellybean { - public static final String TAG = "NotificationCompat"; - - // Extras keys used for Jellybean SDK and above. - static final String EXTRA_LOCAL_ONLY = "android.support.localOnly"; - static final String EXTRA_ACTION_EXTRAS = "android.support.actionExtras"; - static final String EXTRA_REMOTE_INPUTS = "android.support.remoteInputs"; - static final String EXTRA_GROUP_KEY = "android.support.groupKey"; - static final String EXTRA_GROUP_SUMMARY = "android.support.isGroupSummary"; - static final String EXTRA_SORT_KEY = "android.support.sortKey"; - static final String EXTRA_USE_SIDE_CHANNEL = "android.support.useSideChannel"; - - // Bundle keys for storing action fields in a bundle - private static final String KEY_ICON = "icon"; - private static final String KEY_TITLE = "title"; - private static final String KEY_ACTION_INTENT = "actionIntent"; - private static final String KEY_EXTRAS = "extras"; - private static final String KEY_REMOTE_INPUTS = "remoteInputs"; - - private static final Object sExtrasLock = new Object(); - private static Field sExtrasField; - private static boolean sExtrasFieldAccessFailed; - - private static final Object sActionsLock = new Object(); - private static Class sActionClass; - private static Field sActionsField; - private static Field sActionIconField; - private static Field sActionTitleField; - private static Field sActionIntentField; - private static boolean sActionsAccessFailed; - - public static class Builder implements NotificationBuilderWithBuilderAccessor, - NotificationBuilderWithActions { - private Notification.Builder b; - private final Bundle mExtras; - private List mActionExtrasList = new ArrayList(); - - public Builder(Context context, Notification n, - CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, - RemoteViews tickerView, int number, - PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, - int progressMax, int progress, boolean progressIndeterminate, - boolean useChronometer, int priority, CharSequence subText, boolean localOnly, - Bundle extras, String groupKey, boolean groupSummary, String sortKey) { - b = new Notification.Builder(context) - .setWhen(n.when) - .setSmallIcon(n.icon, n.iconLevel) - .setContent(n.contentView) - .setTicker(n.tickerText, tickerView) - .setSound(n.sound, n.audioStreamType) - .setVibrate(n.vibrate) - .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) - .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) - .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) - .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) - .setDefaults(n.defaults) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setSubText(subText) - .setContentInfo(contentInfo) - .setContentIntent(contentIntent) - .setDeleteIntent(n.deleteIntent) - .setFullScreenIntent(fullScreenIntent, - (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) - .setLargeIcon(largeIcon) - .setNumber(number) - .setUsesChronometer(useChronometer) - .setPriority(priority) - .setProgress(progressMax, progress, progressIndeterminate); - mExtras = new Bundle(); - if (extras != null) { - mExtras.putAll(extras); - } - if (localOnly) { - mExtras.putBoolean(EXTRA_LOCAL_ONLY, true); - } - if (groupKey != null) { - mExtras.putString(EXTRA_GROUP_KEY, groupKey); - if (groupSummary) { - mExtras.putBoolean(EXTRA_GROUP_SUMMARY, true); - } else { - mExtras.putBoolean(EXTRA_USE_SIDE_CHANNEL, true); - } - } - if (sortKey != null) { - mExtras.putString(EXTRA_SORT_KEY, sortKey); - } - } - - @Override - public void addAction(NotificationCompatBase.Action action) { - mActionExtrasList.add(writeActionAndGetExtras(b, action)); - } - - @Override - public Notification.Builder getBuilder() { - return b; - } - - public Notification build() { - Notification notif = b.build(); - // Merge in developer provided extras, but let the values already set - // for keys take precedence. - Bundle extras = getExtras(notif); - Bundle mergeBundle = new Bundle(mExtras); - for (String key : mExtras.keySet()) { - if (extras.containsKey(key)) { - mergeBundle.remove(key); - } - } - extras.putAll(mergeBundle); - SparseArray actionExtrasMap = buildActionExtrasMap(mActionExtrasList); - if (actionExtrasMap != null) { - // Add the action extras sparse array if any action was added with extras. - getExtras(notif).putSparseParcelableArray(EXTRA_ACTION_EXTRAS, actionExtrasMap); - } - return notif; - } - } - - public static void addBigTextStyle(NotificationBuilderWithBuilderAccessor b, - CharSequence bigContentTitle, boolean useSummary, - CharSequence summaryText, CharSequence bigText) { - Notification.BigTextStyle style = new Notification.BigTextStyle(b.getBuilder()) - .setBigContentTitle(bigContentTitle) - .bigText(bigText); - if (useSummary) { - style.setSummaryText(summaryText); - } - } - - public static void addBigPictureStyle(NotificationBuilderWithBuilderAccessor b, - CharSequence bigContentTitle, boolean useSummary, - CharSequence summaryText, Bitmap bigPicture, Bitmap bigLargeIcon, - boolean bigLargeIconSet) { - Notification.BigPictureStyle style = new Notification.BigPictureStyle(b.getBuilder()) - .setBigContentTitle(bigContentTitle) - .bigPicture(bigPicture); - if (bigLargeIconSet) { - style.bigLargeIcon(bigLargeIcon); - } - if (useSummary) { - style.setSummaryText(summaryText); - } - } - - public static void addInboxStyle(NotificationBuilderWithBuilderAccessor b, - CharSequence bigContentTitle, boolean useSummary, - CharSequence summaryText, ArrayList texts) { - Notification.InboxStyle style = new Notification.InboxStyle(b.getBuilder()) - .setBigContentTitle(bigContentTitle); - if (useSummary) { - style.setSummaryText(summaryText); - } - for (CharSequence text: texts) { - style.addLine(text); - } - } - - /** Return an SparseArray for action extras or null if none was needed. */ - public static SparseArray buildActionExtrasMap(List actionExtrasList) { - SparseArray actionExtrasMap = null; - for (int i = 0, count = actionExtrasList.size(); i < count; i++) { - Bundle actionExtras = actionExtrasList.get(i); - if (actionExtras != null) { - if (actionExtrasMap == null) { - actionExtrasMap = new SparseArray(); - } - actionExtrasMap.put(i, actionExtras); - } - } - return actionExtrasMap; - } - - /** - * Get the extras Bundle from a notification using reflection. Extras were present in - * Jellybean notifications, but the field was private until KitKat. - */ - public static Bundle getExtras(Notification notif) { - synchronized (sExtrasLock) { - if (sExtrasFieldAccessFailed) { - return null; - } - try { - if (sExtrasField == null) { - Field extrasField = Notification.class.getDeclaredField("extras"); - if (!Bundle.class.isAssignableFrom(extrasField.getType())) { - Log.e(TAG, "Notification.extras field is not of type Bundle"); - sExtrasFieldAccessFailed = true; - return null; - } - extrasField.setAccessible(true); - sExtrasField = extrasField; - } - Bundle extras = (Bundle) sExtrasField.get(notif); - if (extras == null) { - extras = new Bundle(); - sExtrasField.set(notif, extras); - } - return extras; - } catch (IllegalAccessException e) { - Log.e(TAG, "Unable to access notification extras", e); - } catch (NoSuchFieldException e) { - Log.e(TAG, "Unable to access notification extras", e); - } - sExtrasFieldAccessFailed = true; - return null; - } - } - - public static NotificationCompatBase.Action readAction( - NotificationCompatBase.Action.Factory factory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory, int icon, - CharSequence title, PendingIntent actionIntent, Bundle extras) { - RemoteInputCompatBase.RemoteInput[] remoteInputs = null; - if (extras != null) { - remoteInputs = RemoteInputCompatJellybean.fromBundleArray( - BundleUtil.getBundleArrayFromBundle(extras, EXTRA_REMOTE_INPUTS), - remoteInputFactory); - } - return factory.build(icon, title, actionIntent, extras, remoteInputs); - } - - public static Bundle writeActionAndGetExtras( - Notification.Builder builder, NotificationCompatBase.Action action) { - builder.addAction(action.getIcon(), action.getTitle(), action.getActionIntent()); - Bundle actionExtras = new Bundle(action.getExtras()); - if (action.getRemoteInputs() != null) { - actionExtras.putParcelableArray(EXTRA_REMOTE_INPUTS, - RemoteInputCompatJellybean.toBundleArray(action.getRemoteInputs())); - } - return actionExtras; - } - - public static int getActionCount(Notification notif) { - synchronized (sActionsLock) { - Object[] actionObjects = getActionObjectsLocked(notif); - return actionObjects != null ? actionObjects.length : 0; - } - } - - public static NotificationCompatBase.Action getAction(Notification notif, int actionIndex, - NotificationCompatBase.Action.Factory factory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - synchronized (sActionsLock) { - try { - Object actionObject = getActionObjectsLocked(notif)[actionIndex]; - Bundle actionExtras = null; - Bundle extras = getExtras(notif); - if (extras != null) { - SparseArray actionExtrasMap = extras.getSparseParcelableArray( - EXTRA_ACTION_EXTRAS); - if (actionExtrasMap != null) { - actionExtras = actionExtrasMap.get(actionIndex); - } - } - return readAction(factory, remoteInputFactory, - sActionIconField.getInt(actionObject), - (CharSequence) sActionTitleField.get(actionObject), - (PendingIntent) sActionIntentField.get(actionObject), - actionExtras); - } catch (IllegalAccessException e) { - Log.e(TAG, "Unable to access notification actions", e); - sActionsAccessFailed = true; - } - } - return null; - } - - private static Object[] getActionObjectsLocked(Notification notif) { - synchronized (sActionsLock) { - if (!ensureActionReflectionReadyLocked()) { - return null; - } - try { - return (Object[]) sActionsField.get(notif); - } catch (IllegalAccessException e) { - Log.e(TAG, "Unable to access notification actions", e); - sActionsAccessFailed = true; - return null; - } - } - } - - private static boolean ensureActionReflectionReadyLocked() { - if (sActionsAccessFailed) { - return false; - } - try { - if (sActionsField == null) { - sActionClass = Class.forName("android.app.Notification$Action"); - sActionIconField = sActionClass.getDeclaredField("icon"); - sActionTitleField = sActionClass.getDeclaredField("title"); - sActionIntentField = sActionClass.getDeclaredField("actionIntent"); - sActionsField = Notification.class.getDeclaredField("actions"); - sActionsField.setAccessible(true); - } - } catch (ClassNotFoundException e) { - Log.e(TAG, "Unable to access notification actions", e); - sActionsAccessFailed = true; - } catch (NoSuchFieldException e) { - Log.e(TAG, "Unable to access notification actions", e); - sActionsAccessFailed = true; - } - return !sActionsAccessFailed; - } - - public static NotificationCompatBase.Action[] getActionsFromParcelableArrayList( - ArrayList parcelables, - NotificationCompatBase.Action.Factory actionFactory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - if (parcelables == null) { - return null; - } - NotificationCompatBase.Action[] actions = actionFactory.newArray(parcelables.size()); - for (int i = 0; i < actions.length; i++) { - actions[i] = getActionFromBundle((Bundle) parcelables.get(i), - actionFactory, remoteInputFactory); - } - return actions; - } - - private static NotificationCompatBase.Action getActionFromBundle(Bundle bundle, - NotificationCompatBase.Action.Factory actionFactory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - return actionFactory.build( - bundle.getInt(KEY_ICON), - bundle.getCharSequence(KEY_TITLE), - bundle.getParcelable(KEY_ACTION_INTENT), - bundle.getBundle(KEY_EXTRAS), - RemoteInputCompatJellybean.fromBundleArray( - BundleUtil.getBundleArrayFromBundle(bundle, KEY_REMOTE_INPUTS), - remoteInputFactory)); - } - - public static ArrayList getParcelableArrayListForActions( - NotificationCompatBase.Action[] actions) { - if (actions == null) { - return null; - } - ArrayList parcelables = new ArrayList(actions.length); - for (NotificationCompatBase.Action action : actions) { - parcelables.add(getBundleForAction(action)); - } - return parcelables; - } - - private static Bundle getBundleForAction(NotificationCompatBase.Action action) { - Bundle bundle = new Bundle(); - bundle.putInt(KEY_ICON, action.getIcon()); - bundle.putCharSequence(KEY_TITLE, action.getTitle()); - bundle.putParcelable(KEY_ACTION_INTENT, action.getActionIntent()); - bundle.putBundle(KEY_EXTRAS, action.getExtras()); - bundle.putParcelableArray(KEY_REMOTE_INPUTS, RemoteInputCompatJellybean.toBundleArray( - action.getRemoteInputs())); - return bundle; - } - - public static boolean getLocalOnly(Notification notif) { - return getExtras(notif).getBoolean(EXTRA_LOCAL_ONLY); - } - - public static String getGroup(Notification n) { - return getExtras(n).getString(EXTRA_GROUP_KEY); - } - - public static boolean isGroupSummary(Notification n) { - return getExtras(n).getBoolean(EXTRA_GROUP_SUMMARY); - } - - public static String getSortKey(Notification n) { - return getExtras(n).getString(EXTRA_SORT_KEY); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatKitKat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatKitKat.java deleted file mode 100644 index 1b00008..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatKitKat.java +++ /dev/null @@ -1,156 +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 p.android.support.v4.app; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.util.SparseArray; -import android.widget.RemoteViews; - -import java.util.ArrayList; -import java.util.List; - -class NotificationCompatKitKat { - public static class Builder implements NotificationBuilderWithBuilderAccessor, - NotificationBuilderWithActions { - private Notification.Builder b; - private Bundle mExtras; - private List mActionExtrasList = new ArrayList(); - - public Builder(Context context, Notification n, - CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo, - RemoteViews tickerView, int number, - PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon, - int progressMax, int progress, boolean progressIndeterminate, boolean showWhen, - boolean useChronometer, int priority, CharSequence subText, boolean localOnly, - ArrayList people, Bundle extras, String groupKey, boolean groupSummary, - String sortKey) { - b = new Notification.Builder(context) - .setWhen(n.when) - .setShowWhen(showWhen) - .setSmallIcon(n.icon, n.iconLevel) - .setContent(n.contentView) - .setTicker(n.tickerText, tickerView) - .setSound(n.sound, n.audioStreamType) - .setVibrate(n.vibrate) - .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) - .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) - .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) - .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) - .setDefaults(n.defaults) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setSubText(subText) - .setContentInfo(contentInfo) - .setContentIntent(contentIntent) - .setDeleteIntent(n.deleteIntent) - .setFullScreenIntent(fullScreenIntent, - (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) - .setLargeIcon(largeIcon) - .setNumber(number) - .setUsesChronometer(useChronometer) - .setPriority(priority) - .setProgress(progressMax, progress, progressIndeterminate); - mExtras = new Bundle(); - if (extras != null) { - mExtras.putAll(extras); - } - if (people != null && !people.isEmpty()) { - mExtras.putStringArray(Notification.EXTRA_PEOPLE, - people.toArray(new String[people.size()])); - } - if (localOnly) { - mExtras.putBoolean(NotificationCompatJellybean.EXTRA_LOCAL_ONLY, true); - } - if (groupKey != null) { - mExtras.putString(NotificationCompatJellybean.EXTRA_GROUP_KEY, groupKey); - if (groupSummary) { - mExtras.putBoolean(NotificationCompatJellybean.EXTRA_GROUP_SUMMARY, true); - } else { - mExtras.putBoolean(NotificationCompatJellybean.EXTRA_USE_SIDE_CHANNEL, true); - } - } - if (sortKey != null) { - mExtras.putString(NotificationCompatJellybean.EXTRA_SORT_KEY, sortKey); - } - } - - @Override - public void addAction(NotificationCompatBase.Action action) { - mActionExtrasList.add(NotificationCompatJellybean.writeActionAndGetExtras(b, action)); - } - - @Override - public Notification.Builder getBuilder() { - return b; - } - - @Override - public Notification build() { - SparseArray actionExtrasMap = NotificationCompatJellybean.buildActionExtrasMap( - mActionExtrasList); - if (actionExtrasMap != null) { - // Add the action extras sparse array if any action was added with extras. - mExtras.putSparseParcelableArray( - NotificationCompatJellybean.EXTRA_ACTION_EXTRAS, actionExtrasMap); - } - b.setExtras(mExtras); - return b.build(); - } - } - - public static Bundle getExtras(Notification notif) { - return notif.extras; - } - - public static int getActionCount(Notification notif) { - return notif.actions != null ? notif.actions.length : 0; - } - - public static NotificationCompatBase.Action getAction(Notification notif, - int actionIndex, NotificationCompatBase.Action.Factory factory, - RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) { - Notification.Action action = notif.actions[actionIndex]; - Bundle actionExtras = null; - SparseArray actionExtrasMap = notif.extras.getSparseParcelableArray( - NotificationCompatJellybean.EXTRA_ACTION_EXTRAS); - if (actionExtrasMap != null) { - actionExtras = actionExtrasMap.get(actionIndex); - } - return NotificationCompatJellybean.readAction(factory, remoteInputFactory, - action.icon, action.title, action.actionIntent, actionExtras); - } - - public static boolean getLocalOnly(Notification notif) { - return notif.extras.getBoolean(NotificationCompatJellybean.EXTRA_LOCAL_ONLY); - } - - public static String getGroup(Notification notif) { - return notif.extras.getString(NotificationCompatJellybean.EXTRA_GROUP_KEY); - } - - public static boolean isGroupSummary(Notification notif) { - return notif.extras.getBoolean(NotificationCompatJellybean.EXTRA_GROUP_SUMMARY); - } - - public static String getSortKey(Notification notif) { - return notif.extras.getString(NotificationCompatJellybean.EXTRA_SORT_KEY); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatSideChannelService.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatSideChannelService.java deleted file mode 100644 index e081008..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationCompatSideChannelService.java +++ /dev/null @@ -1,118 +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 p.android.support.v4.app; - -import android.app.Notification; -import android.app.Service; -import android.content.Intent; -import android.os.Build; -import android.os.IBinder; -import android.os.RemoteException; - -/** - * Abstract service to receive side channel notifications sent from - * {@link NotificationManagerCompat}. - * - *

To receive side channel notifications, extend this service and register it in your - * android manifest with an intent filter for the BIND_NOTIFICATION_SIDE_CHANNEL action. - * Note: you must also have an enabled - * {@link android.service.notification.NotificationListenerService} within your package. - * - *

Example AndroidManifest.xml addition: - *

- * <service android:name="com.example.NotificationSideChannelService">
- *     <intent-filter>
- *         <action android:name="android.support.BIND_NOTIFICATION_SIDE_CHANNEL" />
- *     </intent-filter>
- * </service>
- * - */ -public abstract class NotificationCompatSideChannelService extends Service { - @Override - public IBinder onBind(Intent intent) { - if (intent.getAction().equals(NotificationManagerCompat.ACTION_BIND_SIDE_CHANNEL)) { - // Block side channel service connections if the current sdk has no need for - // side channeling. - if (Build.VERSION.SDK_INT > NotificationManagerCompat.MAX_SIDE_CHANNEL_SDK_VERSION) { - return null; - } - return new NotificationSideChannelStub(); - } - return null; - } - - /** - * Handle a side-channeled notification being posted. - */ - public abstract void notify(String packageName, int id, String tag, Notification notification); - - /** - * Handle a side-channelled notification being cancelled. - */ - public abstract void cancel(String packageName, int id, String tag); - - /** - * Handle the side-channelled cancelling of all notifications for a package. - */ - public abstract void cancelAll(String packageName); - - private class NotificationSideChannelStub extends INotificationSideChannel.Stub { - @Override - public void notify(String packageName, int id, String tag, Notification notification) - throws RemoteException { - checkPermission(getCallingUid(), packageName); - long idToken = clearCallingIdentity(); - try { - NotificationCompatSideChannelService.this.notify(packageName, id, tag, notification); - } finally { - restoreCallingIdentity(idToken); - } - } - - @Override - public void cancel(String packageName, int id, String tag) throws RemoteException { - checkPermission(getCallingUid(), packageName); - long idToken = clearCallingIdentity(); - try { - NotificationCompatSideChannelService.this.cancel(packageName, id, tag); - } finally { - restoreCallingIdentity(idToken); - } - } - - @Override - public void cancelAll(String packageName) { - checkPermission(getCallingUid(), packageName); - long idToken = clearCallingIdentity(); - try { - NotificationCompatSideChannelService.this.cancelAll(packageName); - } finally { - restoreCallingIdentity(idToken); - } - } - } - - private void checkPermission(int callingUid, String packageName) { - for (String validPackage : getPackageManager().getPackagesForUid(callingUid)) { - if (validPackage.equals(packageName)) { - return; - } - } - throw new SecurityException("NotificationSideChannelService: Uid " + callingUid - + " is not authorized for package " + packageName); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompat.java deleted file mode 100644 index 64ac1f0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompat.java +++ /dev/null @@ -1,628 +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 p.android.support.v4.app; - -import android.app.Notification; -import android.app.NotificationManager; -import android.app.Service; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.os.Build; -import android.os.Bundle; -import android.os.DeadObjectException; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Message; -import android.os.RemoteException; -import android.provider.Settings; -import android.util.Log; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Compatibility library for NotificationManager with fallbacks for older platforms. - * - *

To use this class, call the static function {@link #from} to get a - * {@link NotificationManagerCompat} object, and then call one of its - * methods to post or cancel notifications. - */ -public final class NotificationManagerCompat { - private static final String TAG = "NotifManCompat"; - - /** - * Notification extras key: if set to true, the posted notification should use - * the side channel for delivery instead of using notification manager. - */ - public static final String EXTRA_USE_SIDE_CHANNEL = - NotificationCompatJellybean.EXTRA_USE_SIDE_CHANNEL; - - /** - * Intent action to register for on a service to receive side channel - * notifications. The listening service must be in the same package as an enabled - * {@link android.service.notification.NotificationListenerService}. - */ - public static final String ACTION_BIND_SIDE_CHANNEL = - "android.support.BIND_NOTIFICATION_SIDE_CHANNEL"; - - /** - * Maximum sdk build version which needs support for side channeled notifications. - * Currently the only needed use is for side channeling group children before KITKAT_WATCH. - */ - static final int MAX_SIDE_CHANNEL_SDK_VERSION = 19; - - /** Base time delay for a side channel listener queue retry. */ - private static final int SIDE_CHANNEL_RETRY_BASE_INTERVAL_MS = 1000; - /** Maximum retries for a side channel listener before dropping tasks. */ - private static final int SIDE_CHANNEL_RETRY_MAX_COUNT = 6; - /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */ - private static final String SETTING_ENABLED_NOTIFICATION_LISTENERS = - "enabled_notification_listeners"; - private static final int SIDE_CHANNEL_BIND_FLAGS; - - /** Cache of enabled notification listener components */ - private static final Object sEnabledNotificationListenersLock = new Object(); - /** Guarded by {@link #sEnabledNotificationListenersLock} */ - private static String sEnabledNotificationListeners; - /** Guarded by {@link #sEnabledNotificationListenersLock} */ - private static Set sEnabledNotificationListenerPackages = new HashSet(); - - private final Context mContext; - private final NotificationManager mNotificationManager; - /** Lock for mutable static fields */ - private static final Object sLock = new Object(); - /** Guarded by {@link #sLock} */ - private static SideChannelManager sSideChannelManager; - - /** Get a {@link NotificationManagerCompat} instance for a provided context. */ - public static NotificationManagerCompat from(Context context) { - return new NotificationManagerCompat(context); - } - - private NotificationManagerCompat(Context context) { - mContext = context; - mNotificationManager = (NotificationManager) mContext.getSystemService( - Context.NOTIFICATION_SERVICE); - } - - private static final Impl IMPL; - - interface Impl { - void cancelNotification(NotificationManager notificationManager, String tag, int id); - - void postNotification(NotificationManager notificationManager, String tag, int id, - Notification notification); - - int getSideChannelBindFlags(); - } - - static class ImplBase implements Impl { - @Override - public void cancelNotification(NotificationManager notificationManager, String tag, - int id) { - notificationManager.cancel(id); - } - - @Override - public void postNotification(NotificationManager notificationManager, String tag, int id, - Notification notification) { - notificationManager.notify(id, notification); - } - - @Override - public int getSideChannelBindFlags() { - return Service.BIND_AUTO_CREATE; - } - } - - static class ImplEclair extends ImplBase { - @Override - public void cancelNotification(NotificationManager notificationManager, String tag, - int id) { - NotificationManagerCompatEclair.cancelNotification(notificationManager, tag, id); - } - - @Override - public void postNotification(NotificationManager notificationManager, String tag, int id, - Notification notification) { - NotificationManagerCompatEclair.postNotification(notificationManager, tag, id, - notification); - } - } - - static class ImplIceCreamSandwich extends ImplEclair { - @Override - public int getSideChannelBindFlags() { - return NotificationManagerCompatIceCreamSandwich.SIDE_CHANNEL_BIND_FLAGS; - } - } - - static { - if (Build.VERSION.SDK_INT >= 14) { - IMPL = new ImplIceCreamSandwich(); - } else if (Build.VERSION.SDK_INT >= 5) { - IMPL = new ImplEclair(); - } else { - IMPL = new ImplBase(); - } - SIDE_CHANNEL_BIND_FLAGS = IMPL.getSideChannelBindFlags(); - } - - /** - * Cancel a previously shown notification. - * @param id the ID of the notification - */ - public void cancel(int id) { - cancel(null, id); - } - - /** - * Cancel a previously shown notification. - * @param tag the string identifier of the notification. - * @param id the ID of the notification - */ - public void cancel(String tag, int id) { - IMPL.cancelNotification(mNotificationManager, tag, id); - if (Build.VERSION.SDK_INT <= MAX_SIDE_CHANNEL_SDK_VERSION) { - pushSideChannelQueue(new CancelTask(mContext.getPackageName(), id, tag)); - } - } - - /** Cancel all previously shown notifications. */ - public void cancelAll() { - mNotificationManager.cancelAll(); - if (Build.VERSION.SDK_INT <= MAX_SIDE_CHANNEL_SDK_VERSION) { - pushSideChannelQueue(new CancelTask(mContext.getPackageName())); - } - } - - /** - * Post a notification to be shown in the status bar, stream, etc. - * @param id the ID of the notification - * @param notification the notification to post to the system - */ - public void notify(int id, Notification notification) { - notify(null, id, notification); - } - - /** - * Post a notification to be shown in the status bar, stream, etc. - * @param tag the string identifier for a notification. Can be {@code null}. - * @param id the ID of the notification. The pair (tag, id) must be unique within your app. - * @param notification the notification to post to the system - */ - public void notify(String tag, int id, Notification notification) { - if (useSideChannelForNotification(notification)) { - pushSideChannelQueue(new NotifyTask(mContext.getPackageName(), id, tag, notification)); - // Cancel this notification in notification manager if it just transitioned to being - // side channelled. - IMPL.cancelNotification(mNotificationManager, tag, id); - } else { - IMPL.postNotification(mNotificationManager, tag, id, notification); - } - } - - /** - * Get the set of packages that have an enabled notification listener component within them. - */ - public static Set getEnabledListenerPackages(Context context) { - final String enabledNotificationListeners = Settings.Secure.getString( - context.getContentResolver(), - SETTING_ENABLED_NOTIFICATION_LISTENERS); - // Parse the string again if it is different from the last time this method was called. - if (enabledNotificationListeners != null - && !enabledNotificationListeners.equals(sEnabledNotificationListeners)) { - final String[] components = enabledNotificationListeners.split(":"); - Set packageNames = new HashSet(components.length); - for (String component : components) { - ComponentName componentName = ComponentName.unflattenFromString(component); - if (componentName != null) { - packageNames.add(componentName.getPackageName()); - } - } - synchronized (sEnabledNotificationListenersLock) { - sEnabledNotificationListenerPackages = packageNames; - sEnabledNotificationListeners = enabledNotificationListeners; - } - } - return sEnabledNotificationListenerPackages; - } - - /** - * Returns true if this notification should use the side channel for delivery. - */ - private static boolean useSideChannelForNotification(Notification notification) { - Bundle extras = NotificationCompat.getExtras(notification); - return extras != null && extras.getBoolean(EXTRA_USE_SIDE_CHANNEL); - } - - /** - * Push a notification task for distribution to notification side channels. - */ - private void pushSideChannelQueue(Task task) { - synchronized (sLock) { - if (sSideChannelManager == null) { - sSideChannelManager = new SideChannelManager(mContext.getApplicationContext()); - } - } - sSideChannelManager.queueTask(task); - } - - /** - * Helper class to manage a queue of pending tasks to send to notification side channel - * listeners. - */ - private static class SideChannelManager implements Handler.Callback, ServiceConnection { - private static final int MSG_QUEUE_TASK = 0; - private static final int MSG_SERVICE_CONNECTED = 1; - private static final int MSG_SERVICE_DISCONNECTED = 2; - private static final int MSG_RETRY_LISTENER_QUEUE = 3; - - private static final String KEY_BINDER = "binder"; - - private final Context mContext; - private final HandlerThread mHandlerThread; - private final Handler mHandler; - private final Map mRecordMap = - new HashMap(); - private Set mCachedEnabledPackages = new HashSet(); - - public SideChannelManager(Context context) { - mContext = context; - mHandlerThread = new HandlerThread("NotificationManagerCompat"); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper(), this); - } - - /** - * Queue a new task to be sent to all listeners. This function can be called - * from any thread. - */ - public void queueTask(Task task) { - mHandler.obtainMessage(MSG_QUEUE_TASK, task).sendToTarget(); - } - - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_QUEUE_TASK: - handleQueueTask((Task) msg.obj); - return true; - case MSG_SERVICE_CONNECTED: - ServiceConnectedEvent event = (ServiceConnectedEvent) msg.obj; - handleServiceConnected(event.componentName, event.iBinder); - return true; - case MSG_SERVICE_DISCONNECTED: - handleServiceDisconnected((ComponentName) msg.obj); - return true; - case MSG_RETRY_LISTENER_QUEUE: - handleRetryListenerQueue((ComponentName) msg.obj); - return true; - } - return false; - } - - private void handleQueueTask(Task task) { - updateListenerMap(); - for (ListenerRecord record : mRecordMap.values()) { - record.taskQueue.add(task); - processListenerQueue(record); - } - } - - private void handleServiceConnected(ComponentName componentName, IBinder iBinder) { - ListenerRecord record = mRecordMap.get(componentName); - if (record != null) { - record.service = INotificationSideChannel.Stub.asInterface(iBinder); - record.retryCount = 0; - processListenerQueue(record); - } - } - - private void handleServiceDisconnected(ComponentName componentName) { - ListenerRecord record = mRecordMap.get(componentName); - if (record != null) { - ensureServiceUnbound(record); - } - } - - private void handleRetryListenerQueue(ComponentName componentName) { - ListenerRecord record = mRecordMap.get(componentName); - if (record != null) { - processListenerQueue(record); - } - } - - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Connected to service " + componentName); - } - mHandler.obtainMessage(MSG_SERVICE_CONNECTED, - new ServiceConnectedEvent(componentName, iBinder)) - .sendToTarget(); - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Disconnected from service " + componentName); - } - mHandler.obtainMessage(MSG_SERVICE_DISCONNECTED, componentName).sendToTarget(); - } - - /** - * Check the current list of enabled listener packages and update the records map - * accordingly. - */ - private void updateListenerMap() { - Set enabledPackages = getEnabledListenerPackages(mContext); - if (enabledPackages.equals(mCachedEnabledPackages)) { - // Short-circuit when the list of enabled packages has not changed. - return; - } - mCachedEnabledPackages = enabledPackages; - List resolveInfos = mContext.getPackageManager().queryIntentServices( - new Intent().setAction(ACTION_BIND_SIDE_CHANNEL), PackageManager.GET_SERVICES); - Set enabledComponents = new HashSet(); - for (ResolveInfo resolveInfo : resolveInfos) { - if (!enabledPackages.contains(resolveInfo.serviceInfo.packageName)) { - continue; - } - ComponentName componentName = new ComponentName( - resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); - if (resolveInfo.serviceInfo.permission != null) { - Log.w(TAG, "Permission present on component " + componentName - + ", not adding listener record."); - continue; - } - enabledComponents.add(componentName); - } - // Ensure all enabled components have a record in the listener map. - for (ComponentName componentName : enabledComponents) { - if (!mRecordMap.containsKey(componentName)) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Adding listener record for " + componentName); - } - mRecordMap.put(componentName, new ListenerRecord(componentName)); - } - } - // Remove listener records that are no longer for enabled components. - Iterator> it = - mRecordMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (!enabledComponents.contains(entry.getKey())) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Removing listener record for " + entry.getKey()); - } - ensureServiceUnbound(entry.getValue()); - it.remove(); - } - } - } - - /** - * Ensure we are already attempting to bind to a service, or start a new binding if not. - * @return Whether the service bind attempt was successful. - */ - private boolean ensureServiceBound(ListenerRecord record) { - if (record.bound) { - return true; - } - Intent intent = new Intent(ACTION_BIND_SIDE_CHANNEL).setComponent(record.componentName); - record.bound = mContext.bindService(intent, this, SIDE_CHANNEL_BIND_FLAGS); - if (record.bound) { - record.retryCount = 0; - } else { - Log.w(TAG, "Unable to bind to listener " + record.componentName); - mContext.unbindService(this); - } - return record.bound; - } - - /** - * Ensure we have unbound from a service. - */ - private void ensureServiceUnbound(ListenerRecord record) { - if (record.bound) { - mContext.unbindService(this); - record.bound = false; - } - record.service = null; - } - - /** - * Schedule a delayed retry to communicate with a listener service. - * After a maximum number of attempts (with exponential back-off), start - * dropping pending tasks for this listener. - */ - private void scheduleListenerRetry(ListenerRecord record) { - if (mHandler.hasMessages(MSG_RETRY_LISTENER_QUEUE, record.componentName)) { - return; - } - record.retryCount++; - if (record.retryCount > SIDE_CHANNEL_RETRY_MAX_COUNT) { - Log.w(TAG, "Giving up on delivering " + record.taskQueue.size() + " tasks to " - + record.componentName + " after " + record.retryCount + " retries"); - record.taskQueue.clear(); - return; - } - int delayMs = SIDE_CHANNEL_RETRY_BASE_INTERVAL_MS * (1 << (record.retryCount - 1)); - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Scheduling retry for " + delayMs + " ms"); - } - Message msg = mHandler.obtainMessage(MSG_RETRY_LISTENER_QUEUE, record.componentName); - mHandler.sendMessageDelayed(msg, delayMs); - } - - /** - * Perform a processing step for a listener. First check the bind state, then attempt - * to flush the task queue, and if an error is encountered, schedule a retry. - */ - private void processListenerQueue(ListenerRecord record) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Processing component " + record.componentName + ", " - + record.taskQueue.size() + " queued tasks"); - } - if (record.taskQueue.isEmpty()) { - return; - } - if (!ensureServiceBound(record) || record.service == null) { - // Ensure bind has started and that a service interface is ready to use. - scheduleListenerRetry(record); - return; - } - // Attempt to flush all items in the task queue. - while (true) { - Task task = record.taskQueue.peek(); - if (task == null) { - break; - } - try { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Sending task " + task); - } - task.send(record.service); - record.taskQueue.remove(); - } catch (DeadObjectException e) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Remote service has died: " + record.componentName); - } - break; - } catch (RemoteException e) { - Log.w(TAG, "RemoteException communicating with " + record.componentName, e); - break; - } - } - if (!record.taskQueue.isEmpty()) { - // Some tasks were not sent, meaning an error was encountered, schedule a retry. - scheduleListenerRetry(record); - } - } - - /** A per-side-channel-service listener state record */ - private static class ListenerRecord { - public final ComponentName componentName; - /** Whether the service is currently bound to. */ - public boolean bound = false; - /** The service stub provided by onServiceConnected */ - public INotificationSideChannel service; - /** Queue of pending tasks to send to this listener service */ - public LinkedList taskQueue = new LinkedList(); - /** Number of retries attempted while connecting to this listener service */ - public int retryCount = 0; - - public ListenerRecord(ComponentName componentName) { - this.componentName = componentName; - } - } - } - - private static class ServiceConnectedEvent { - final ComponentName componentName; - final IBinder iBinder; - - public ServiceConnectedEvent(ComponentName componentName, - final IBinder iBinder) { - this.componentName = componentName; - this.iBinder = iBinder; - } - } - - private interface Task { - public void send(INotificationSideChannel service) throws RemoteException; - } - - private static class NotifyTask implements Task { - final String packageName; - final int id; - final String tag; - final Notification notif; - - public NotifyTask(String packageName, int id, String tag, Notification notif) { - this.packageName = packageName; - this.id = id; - this.tag = tag; - this.notif = notif; - } - - @Override - public void send(INotificationSideChannel service) throws RemoteException { - service.notify(packageName, id, tag, notif); - } - - public String toString() { - StringBuilder sb = new StringBuilder("NotifyTask["); - sb.append("packageName:").append(packageName); - sb.append(", id:").append(id); - sb.append(", tag:").append(tag); - sb.append("]"); - return sb.toString(); - } - } - - private static class CancelTask implements Task { - final String packageName; - final int id; - final String tag; - final boolean all; - - public CancelTask(String packageName) { - this.packageName = packageName; - this.id = 0; - this.tag = null; - this.all = true; - } - - public CancelTask(String packageName, int id, String tag) { - this.packageName = packageName; - this.id = id; - this.tag = tag; - this.all = false; - } - - @Override - public void send(INotificationSideChannel service) throws RemoteException { - if (all) { - service.cancelAll(packageName); - } else { - service.cancel(packageName, id, tag); - } - } - - public String toString() { - StringBuilder sb = new StringBuilder("CancelTask["); - sb.append("packageName:").append(packageName); - sb.append(", id:").append(id); - sb.append(", tag:").append(tag); - sb.append(", all:").append(all); - sb.append("]"); - return sb.toString(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompatEclair.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompatEclair.java deleted file mode 100644 index 0fa00de..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompatEclair.java +++ /dev/null @@ -1,32 +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 p.android.support.v4.app; - -import android.app.Notification; -import android.app.NotificationManager; - -class NotificationManagerCompatEclair { - static void cancelNotification(NotificationManager notificationManager, String tag, - int id) { - notificationManager.cancel(tag, id); - } - - public static void postNotification(NotificationManager notificationManager, String tag, int id, - Notification notification) { - notificationManager.notify(tag, id, notification); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompatIceCreamSandwich.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompatIceCreamSandwich.java deleted file mode 100644 index 23b8dd9..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/NotificationManagerCompatIceCreamSandwich.java +++ /dev/null @@ -1,24 +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 p.android.support.v4.app; - -import android.app.Service; - -class NotificationManagerCompatIceCreamSandwich { - static final int SIDE_CHANNEL_BIND_FLAGS = Service.BIND_AUTO_CREATE - | Service.BIND_WAIVE_PRIORITY; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInput.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInput.java deleted file mode 100644 index 5791bfe..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInput.java +++ /dev/null @@ -1,276 +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 p.android.support.v4.app; - -import android.content.Intent; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; - -/** - * Helper for using the {@link android.app.RemoteInput} API - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class RemoteInput extends RemoteInputCompatBase.RemoteInput { - private static final String TAG = "RemoteInput"; - - /** Label used to denote the clip data type used for remote input transport */ - public static final String RESULTS_CLIP_LABEL = RemoteInputCompatJellybean.RESULTS_CLIP_LABEL; - - /** Extra added to a clip data intent object to hold the results bundle. */ - public static final String EXTRA_RESULTS_DATA = RemoteInputCompatJellybean.EXTRA_RESULTS_DATA; - - private final String mResultKey; - private final CharSequence mLabel; - private final CharSequence[] mChoices; - private final boolean mAllowFreeFormInput; - private final Bundle mExtras; - - private RemoteInput(String resultKey, CharSequence label, CharSequence[] choices, - boolean allowFreeFormInput, Bundle extras) { - this.mResultKey = resultKey; - this.mLabel = label; - this.mChoices = choices; - this.mAllowFreeFormInput = allowFreeFormInput; - this.mExtras = extras; - } - - /** - * Get the key that the result of this input will be set in from the Bundle returned by - * {@link #getResultsFromIntent} when the {@link android.app.PendingIntent} is sent. - */ - public String getResultKey() { - return mResultKey; - } - - /** - * Get the label to display to users when collecting this input. - */ - public CharSequence getLabel() { - return mLabel; - } - - /** - * Get possible input choices. This can be {@code null} if there are no choices to present. - */ - public CharSequence[] getChoices() { - return mChoices; - } - - /** - * Get whether or not users can provide an arbitrary value for - * input. If you set this to {@code false}, users must select one of the - * choices in {@link #getChoices}. An {@link IllegalArgumentException} is thrown - * if you set this to false and {@link #getChoices} returns {@code null} or empty. - */ - public boolean getAllowFreeFormInput() { - return mAllowFreeFormInput; - } - - /** - * Get additional metadata carried around with this remote input. - */ - public Bundle getExtras() { - return mExtras; - } - - /** - * Builder class for {@link RemoteInput} objects. - */ - public static final class Builder { - private final String mResultKey; - private CharSequence mLabel; - private CharSequence[] mChoices; - private boolean mAllowFreeFormInput = true; - private Bundle mExtras = new Bundle(); - - /** - * Create a builder object for {@link RemoteInput} objects. - * @param resultKey the Bundle key that refers to this input when collected from the user - */ - public Builder(String resultKey) { - if (resultKey == null) { - throw new IllegalArgumentException("Result key can't be null"); - } - mResultKey = resultKey; - } - - /** - * Set a label to be displayed to the user when collecting this input. - * @param label The label to show to users when they input a response. - * @return this object for method chaining - */ - public Builder setLabel(CharSequence label) { - mLabel = label; - return this; - } - - /** - * Specifies choices available to the user to satisfy this input. - * @param choices an array of pre-defined choices for users input. - * You must provide a non-null and non-empty array if - * you disabled free form input using {@link #setAllowFreeFormInput}. - * @return this object for method chaining - */ - public Builder setChoices(CharSequence[] choices) { - mChoices = choices; - return this; - } - - /** - * Specifies whether the user can provide arbitrary values. - * - * @param allowFreeFormInput The default is {@code true}. - * If you specify {@code false}, you must provide a non-null - * and non-empty array to {@link #setChoices} or an - * {@link IllegalArgumentException} is thrown. - * @return this object for method chaining - */ - public Builder setAllowFreeFormInput(boolean allowFreeFormInput) { - mAllowFreeFormInput = allowFreeFormInput; - return this; - } - - /** - * Merge additional metadata into this builder. - * - *

Values within the Bundle will replace existing extras values in this Builder. - * - * @see RemoteInput#getExtras - */ - public Builder addExtras(Bundle extras) { - if (extras != null) { - mExtras.putAll(extras); - } - return this; - } - - /** - * Get the metadata Bundle used by this Builder. - * - *

The returned Bundle is shared with this Builder. - */ - public Bundle getExtras() { - return mExtras; - } - - /** - * Combine all of the options that have been set and return a new - * {@link RemoteInput} object. - */ - public RemoteInput build() { - return new RemoteInput(mResultKey, mLabel, mChoices, mAllowFreeFormInput, mExtras); - } - } - - /** - * Get the remote input results bundle from an intent. The returned Bundle will - * contain a key/value for every result key populated by remote input collector. - * Use the {@link Bundle#getCharSequence(String)} method to retrieve a value. - * @param intent The intent object that fired in response to an action or content intent - * which also had one or more remote input requested. - */ - public static Bundle getResultsFromIntent(Intent intent) { - return IMPL.getResultsFromIntent(intent); - } - - /** - * Populate an intent object with the results gathered from remote input. This method - * should only be called by remote input collection services when sending results to a - * pending intent. - * @param remoteInputs The remote inputs for which results are being provided - * @param intent The intent to add remote inputs to. The {@link android.content.ClipData} - * field of the intent will be modified to contain the results. - * @param results A bundle holding the remote input results. This bundle should - * be populated with keys matching the result keys specified in - * {@code remoteInputs} with values being the result per key. - */ - public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, - Bundle results) { - IMPL.addResultsToIntent(remoteInputs, intent, results); - } - - private static final Impl IMPL; - - interface Impl { - Bundle getResultsFromIntent(Intent intent); - void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, - Bundle results); - } - - static class ImplBase implements Impl { - @Override - public Bundle getResultsFromIntent(Intent intent) { - Log.w(TAG, "RemoteInput is only supported from API Level 16"); - return null; - } - - @Override - public void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results) { - Log.w(TAG, "RemoteInput is only supported from API Level 16"); - } - } - - static class ImplJellybean implements Impl { - @Override - public Bundle getResultsFromIntent(Intent intent) { - return RemoteInputCompatJellybean.getResultsFromIntent(intent); - } - - @Override - public void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results) { - RemoteInputCompatJellybean.addResultsToIntent(remoteInputs, intent, results); - } - } - - static class ImplApi20 implements Impl { - @Override - public Bundle getResultsFromIntent(Intent intent) { - return RemoteInputCompatApi20.getResultsFromIntent(intent); - } - - @Override - public void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent, Bundle results) { - RemoteInputCompatApi20.addResultsToIntent(remoteInputs, intent, results); - } - } - - static { - if (Build.VERSION.SDK_INT >= 20) { - IMPL = new ImplApi20(); - } else if (Build.VERSION.SDK_INT >= 16) { - IMPL = new ImplJellybean(); - } else { - IMPL = new ImplBase(); - } - } - - /** @hide */ - public static final Factory FACTORY = new Factory() { - @Override - public RemoteInput build(String resultKey, - CharSequence label, CharSequence[] choices, boolean allowFreeFormInput, - Bundle extras) { - return new RemoteInput(resultKey, label, choices, allowFreeFormInput, extras); - } - - @Override - public RemoteInput[] newArray(int size) { - return new RemoteInput[size]; - } - }; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatApi20.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatApi20.java deleted file mode 100644 index 17ca63b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatApi20.java +++ /dev/null @@ -1,63 +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 p.android.support.v4.app; - -import android.app.RemoteInput; -import android.content.Intent; -import android.os.Bundle; - -class RemoteInputCompatApi20 { - static RemoteInputCompatBase.RemoteInput[] toCompat(RemoteInput[] srcArray, - RemoteInputCompatBase.RemoteInput.Factory factory) { - if (srcArray == null) { - return null; - } - RemoteInputCompatBase.RemoteInput[] result = factory.newArray(srcArray.length); - for (int i = 0; i < srcArray.length; i++) { - RemoteInput src = srcArray[i]; - result[i] = factory.build(src.getResultKey(), src.getLabel(), src.getChoices(), - src.getAllowFreeFormInput(), src.getExtras()); - } - return result; - } - - static RemoteInput[] fromCompat(RemoteInputCompatBase.RemoteInput[] srcArray) { - if (srcArray == null) { - return null; - } - RemoteInput[] result = new RemoteInput[srcArray.length]; - for (int i = 0; i < srcArray.length; i++) { - RemoteInputCompatBase.RemoteInput src = srcArray[i]; - result[i] = new RemoteInput.Builder(src.getResultKey()) - .setLabel(src.getLabel()) - .setChoices(src.getChoices()) - .setAllowFreeFormInput(src.getAllowFreeFormInput()) - .addExtras(src.getExtras()) - .build(); - } - return result; - } - - static Bundle getResultsFromIntent(Intent intent) { - return RemoteInput.getResultsFromIntent(intent); - } - - static void addResultsToIntent(RemoteInputCompatBase.RemoteInput[] remoteInputs, - Intent intent, Bundle results) { - RemoteInput.addResultsToIntent(fromCompat(remoteInputs), intent, results); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatBase.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatBase.java deleted file mode 100644 index 2c692cb..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatBase.java +++ /dev/null @@ -1,36 +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 p.android.support.v4.app; - -import android.os.Bundle; - -class RemoteInputCompatBase { - - public static abstract class RemoteInput { - protected abstract String getResultKey(); - protected abstract CharSequence getLabel(); - protected abstract CharSequence[] getChoices(); - protected abstract boolean getAllowFreeFormInput(); - protected abstract Bundle getExtras(); - - public interface Factory { - public RemoteInput build(String resultKey, CharSequence label, - CharSequence[] choices, boolean allowFreeFormInput, Bundle extras); - public RemoteInput[] newArray(int length); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatJellybean.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatJellybean.java deleted file mode 100644 index 47ed5c1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/RemoteInputCompatJellybean.java +++ /dev/null @@ -1,107 +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 p.android.support.v4.app; - -import android.content.ClipData; -import android.content.ClipDescription; -import android.content.Intent; -import android.os.Bundle; - -class RemoteInputCompatJellybean { - /** Label used to denote the clip data type used for remote input transport */ - public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results"; - - /** Extra added to a clip data intent object to hold the results bundle. */ - public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData"; - - private static final String KEY_RESULT_KEY = "resultKey"; - private static final String KEY_LABEL = "label"; - private static final String KEY_CHOICES = "choices"; - private static final String KEY_ALLOW_FREE_FORM_INPUT = "allowFreeFormInput"; - private static final String KEY_EXTRAS = "extras"; - - static RemoteInputCompatBase.RemoteInput fromBundle(Bundle data, - RemoteInputCompatBase.RemoteInput.Factory factory) { - return factory.build(data.getString(KEY_RESULT_KEY), - data.getCharSequence(KEY_LABEL), - data.getCharSequenceArray(KEY_CHOICES), - data.getBoolean(KEY_ALLOW_FREE_FORM_INPUT), - data.getBundle(KEY_EXTRAS)); - } - - static Bundle toBundle(RemoteInputCompatBase.RemoteInput remoteInput) { - Bundle data = new Bundle(); - data.putString(KEY_RESULT_KEY, remoteInput.getResultKey()); - data.putCharSequence(KEY_LABEL, remoteInput.getLabel()); - data.putCharSequenceArray(KEY_CHOICES, remoteInput.getChoices()); - data.putBoolean(KEY_ALLOW_FREE_FORM_INPUT, remoteInput.getAllowFreeFormInput()); - data.putBundle(KEY_EXTRAS, remoteInput.getExtras()); - return data; - } - - static RemoteInputCompatBase.RemoteInput[] fromBundleArray(Bundle[] bundles, - RemoteInputCompatBase.RemoteInput.Factory factory) { - if (bundles == null) { - return null; - } - RemoteInputCompatBase.RemoteInput[] remoteInputs = factory.newArray(bundles.length); - for (int i = 0; i < bundles.length; i++) { - remoteInputs[i] = fromBundle(bundles[i], factory); - } - return remoteInputs; - } - - static Bundle[] toBundleArray(RemoteInputCompatBase.RemoteInput[] remoteInputs) { - if (remoteInputs == null) { - return null; - } - Bundle[] bundles = new Bundle[remoteInputs.length]; - for (int i = 0; i < remoteInputs.length; i++) { - bundles[i] = toBundle(remoteInputs[i]); - } - return bundles; - } - - static Bundle getResultsFromIntent(Intent intent) { - ClipData clipData = intent.getClipData(); - if (clipData == null) { - return null; - } - ClipDescription clipDescription = clipData.getDescription(); - if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) { - return null; - } - if (clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) { - return clipData.getItemAt(0).getIntent().getExtras().getParcelable(EXTRA_RESULTS_DATA); - } - return null; - } - - static void addResultsToIntent(RemoteInputCompatBase.RemoteInput[] remoteInputs, Intent intent, - Bundle results) { - Bundle resultsBundle = new Bundle(); - for (RemoteInputCompatBase.RemoteInput remoteInput : remoteInputs) { - Object result = results.get(remoteInput.getResultKey()); - if (result instanceof CharSequence) { - resultsBundle.putCharSequence(remoteInput.getResultKey(), (CharSequence) result); - } - } - Intent clipIntent = new Intent(); - clipIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle); - intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipIntent)); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ServiceCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ServiceCompat.java deleted file mode 100644 index d96c4c2..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ServiceCompat.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -/** - * Helper for accessing features in {@link android.app.Service} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class ServiceCompat { - - private ServiceCompat() { - /* Hide constructor */ - } - - /** - * Constant to return from {@link android.app.Service#onStartCommand}: if this - * service's process is killed while it is started (after returning from - * {@link android.app.Service#onStartCommand}), then leave it in the started - * state but don't retain this delivered intent. Later the system will try to - * re-create the service. Because it is in the started state, it will - * guarantee to call {@link android.app.Service#onStartCommand} after creating - * the new service instance; if there are not any pending start commands to be - * delivered to the service, it will be called with a null intent - * object, so you must take care to check for this. - * - *

This mode makes sense for things that will be explicitly started - * and stopped to run for arbitrary periods of time, such as a service - * performing background music playback. - */ - public static final int START_STICKY = 1; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompat.java deleted file mode 100644 index a3341e4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompat.java +++ /dev/null @@ -1,959 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import p.android.support.v4.content.IntentCompat; -import p.android.support.annotation.StringRes; -import p.android.support.v4.view.MenuItemCompat; -import android.text.Html; -import android.text.Spanned; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; - -import java.util.ArrayList; - -/** - * Extra helper functionality for sharing data between activities. - * - * ShareCompat provides functionality to extend the {@link Intent#ACTION_SEND}/ - * {@link Intent#ACTION_SEND_MULTIPLE} protocol and support retrieving more info - * about the activity that invoked a social sharing action. - * - * {@link IntentBuilder} provides helper functions for constructing a sharing - * intent that always includes data about the calling activity and app. - * This lets the called activity provide attribution for the app that shared - * content. Constructing an intent this way can be done in a method-chaining style. - * To obtain an IntentBuilder with info about your calling activity, use the static - * method {@link IntentBuilder#from(Activity)}. - * - * {@link IntentReader} provides helper functions for parsing the defined extras - * within an {@link Intent#ACTION_SEND} or {@link Intent#ACTION_SEND_MULTIPLE} intent - * used to launch an activity. You can also obtain a Drawable for the caller's - * application icon and the application's localized label (the app's human-readable name). - * Social apps that enable sharing content are encouraged to use this information - * to call out the app that the content was shared from. - */ -public final class ShareCompat { - /** - * Intent extra that stores the name of the calling package for an ACTION_SEND intent. - * When an activity is started using startActivityForResult this is redundant info. - * (It is also provided by {@link Activity#getCallingPackage()}.) - * - * Instead of using this constant directly, consider using {@link #getCallingPackage(Activity)} - * or {@link IntentReader#getCallingPackage()}. - */ - public static final String EXTRA_CALLING_PACKAGE = - "android.support.v4.app.EXTRA_CALLING_PACKAGE"; - - /** - * Intent extra that stores the {@link ComponentName} of the calling activity for - * an ACTION_SEND intent. - */ - public static final String EXTRA_CALLING_ACTIVITY = - "android.support.v4.app.EXTRA_CALLING_ACTIVITY"; - - /** - * Compatibility shims for sharing operations - */ - interface ShareCompatImpl { - void configureMenuItem(MenuItem item, IntentBuilder shareIntent); - String escapeHtml(CharSequence text); - } - - static class ShareCompatImplBase implements ShareCompatImpl { - public void configureMenuItem(MenuItem item, IntentBuilder shareIntent) { - item.setIntent(shareIntent.createChooserIntent()); - } - - public String escapeHtml(CharSequence text) { - StringBuilder out = new StringBuilder(); - withinStyle(out, text, 0, text.length()); - return out.toString(); - } - - private static void withinStyle(StringBuilder out, CharSequence text, - int start, int end) { - for (int i = start; i < end; i++) { - char c = text.charAt(i); - - if (c == '<') { - out.append("<"); - } else if (c == '>') { - out.append(">"); - } else if (c == '&') { - out.append("&"); - } else if (c > 0x7E || c < ' ') { - out.append("&#" + ((int) c) + ";"); - } else if (c == ' ') { - while (i + 1 < end && text.charAt(i + 1) == ' ') { - out.append(" "); - i++; - } - - out.append(' '); - } else { - out.append(c); - } - } - } - } - - static class ShareCompatImplICS extends ShareCompatImplBase { - public void configureMenuItem(MenuItem item, IntentBuilder shareIntent) { - ShareCompatICS.configureMenuItem(item, shareIntent.getActivity(), - shareIntent.getIntent()); - if (shouldAddChooserIntent(item)) { - item.setIntent(shareIntent.createChooserIntent()); - } - } - - boolean shouldAddChooserIntent(MenuItem item) { - return !item.hasSubMenu(); - } - } - - static class ShareCompatImplJB extends ShareCompatImplICS { - public String escapeHtml(CharSequence html) { - return ShareCompatJB.escapeHtml(html); - } - - @Override - boolean shouldAddChooserIntent(MenuItem item) { - return false; - } - } - - private static ShareCompatImpl IMPL; - - static { - if (Build.VERSION.SDK_INT >= 16) { - IMPL = new ShareCompatImplJB(); - } else if (Build.VERSION.SDK_INT >= 14) { - IMPL = new ShareCompatImplICS(); - } else { - IMPL = new ShareCompatImplBase(); - } - } - - private ShareCompat() {} - - /** - * Retrieve the name of the package that launched calledActivity from a share intent. - * Apps that provide social sharing functionality can use this to provide attribution - * for the app that shared the content. - * - *

Note: This data may have been provided voluntarily by the calling - * application. As such it should not be trusted for accuracy in the context of - * security or verification.

- * - * @param calledActivity Current activity that was launched to share content - * @return Name of the calling package - */ - public static String getCallingPackage(Activity calledActivity) { - String result = calledActivity.getCallingPackage(); - if (result == null) { - result = calledActivity.getIntent().getStringExtra(EXTRA_CALLING_PACKAGE); - } - return result; - } - - /** - * Retrieve the ComponentName of the activity that launched calledActivity from a share intent. - * Apps that provide social sharing functionality can use this to provide attribution - * for the app that shared the content. - * - *

Note: This data may have been provided voluntarily by the calling - * application. As such it should not be trusted for accuracy in the context of - * security or verification.

- * - * @param calledActivity Current activity that was launched to share content - * @return ComponentName of the calling activity - */ - public static ComponentName getCallingActivity(Activity calledActivity) { - ComponentName result = calledActivity.getCallingActivity(); - if (result == null) { - result = calledActivity.getIntent().getParcelableExtra(EXTRA_CALLING_ACTIVITY); - } - return result; - } - - /** - * Configure a {@link MenuItem} to act as a sharing action. - * - *

If the app is running on API level 14 or higher (Android 4.0/Ice Cream Sandwich) - * this method will configure a ShareActionProvider to provide a more robust UI - * for selecting the target of the share. History will be tracked for each calling - * activity in a file named with the prefix ".sharecompat_" in the application's - * private data directory. If the application wishes to set this MenuItem to show - * as an action in the Action Bar it should use - * {@link MenuItemCompat#setShowAsAction(MenuItem, int)} to request that behavior - * in addition to calling this method.

- * - *

If the app is running on an older platform version this method will configure - * a standard activity chooser dialog for the menu item.

- * - *

During the calling activity's lifecycle, if data within the share intent must - * change the app should change that state in one of several ways:

- *
    - *
  • Call {@link ActivityCompat#invalidateOptionsMenu(Activity)}. If the app is running - * on API level 11 or above and uses the Action Bar its menu will be recreated and rebuilt. - * If not, the activity will receive a call to {@link Activity#onPrepareOptionsMenu(Menu)} - * the next time the user presses the menu key to open the options menu panel. The activity - * can then call configureMenuItem again with a new or altered IntentBuilder to reconfigure - * the share menu item.
  • - *
  • Keep a reference to the MenuItem object for the share item once it has been created - * and call configureMenuItem to update the associated sharing intent as needed.
  • - *
- * - * @param item MenuItem to configure for sharing - * @param shareIntent IntentBuilder with data about the content to share - */ - public static void configureMenuItem(MenuItem item, IntentBuilder shareIntent) { - IMPL.configureMenuItem(item, shareIntent); - } - - /** - * Configure a menu item to act as a sharing action. - * - * @param menu Menu containing the item to use for sharing - * @param menuItemId ID of the share item within menu - * @param shareIntent IntentBuilder with data about the content to share - * @see #configureMenuItem(MenuItem, IntentBuilder) - */ - public static void configureMenuItem(Menu menu, int menuItemId, IntentBuilder shareIntent) { - MenuItem item = menu.findItem(menuItemId); - if (item == null) { - throw new IllegalArgumentException("Could not find menu item with id " + menuItemId + - " in the supplied menu"); - } - configureMenuItem(item, shareIntent); - } - - /** - * IntentBuilder is a helper for constructing {@link Intent#ACTION_SEND} and - * {@link Intent#ACTION_SEND_MULTIPLE} sharing intents and starting activities - * to share content. The ComponentName and package name of the calling activity - * will be included. - */ - public static class IntentBuilder { - private Activity mActivity; - private Intent mIntent; - private CharSequence mChooserTitle; - private ArrayList mToAddresses; - private ArrayList mCcAddresses; - private ArrayList mBccAddresses; - - private ArrayList mStreams; - - /** - * Create a new IntentBuilder for launching a sharing action from launchingActivity. - * - * @param launchingActivity Activity that the share will be launched from - * @return a new IntentBuilder instance - */ - public static IntentBuilder from(Activity launchingActivity) { - return new IntentBuilder(launchingActivity); - } - - private IntentBuilder(Activity launchingActivity) { - mActivity = launchingActivity; - mIntent = new Intent().setAction(Intent.ACTION_SEND); - mIntent.putExtra(EXTRA_CALLING_PACKAGE, launchingActivity.getPackageName()); - mIntent.putExtra(EXTRA_CALLING_ACTIVITY, launchingActivity.getComponentName()); - mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - } - - /** - * Retrieve the Intent as configured so far by the IntentBuilder. This Intent - * is suitable for use in a ShareActionProvider or chooser dialog. - * - *

To create an intent that will launch the activity chooser so that the user - * may select a target for the share, see {@link #createChooserIntent()}. - * - * @return The current Intent being configured by this builder - */ - public Intent getIntent() { - if (mToAddresses != null) { - combineArrayExtra(Intent.EXTRA_EMAIL, mToAddresses); - mToAddresses = null; - } - if (mCcAddresses != null) { - combineArrayExtra(Intent.EXTRA_CC, mCcAddresses); - mCcAddresses = null; - } - if (mBccAddresses != null) { - combineArrayExtra(Intent.EXTRA_BCC, mBccAddresses); - mBccAddresses = null; - } - - // Check if we need to change the action. - boolean needsSendMultiple = mStreams != null && mStreams.size() > 1; - boolean isSendMultiple = mIntent.getAction().equals(Intent.ACTION_SEND_MULTIPLE); - - if (!needsSendMultiple && isSendMultiple) { - // Change back to a single send action; place the first stream into the - // intent for single sharing. - mIntent.setAction(Intent.ACTION_SEND); - if (mStreams != null && !mStreams.isEmpty()) { - mIntent.putExtra(Intent.EXTRA_STREAM, mStreams.get(0)); - } else { - mIntent.removeExtra(Intent.EXTRA_STREAM); - } - mStreams = null; - } - - if (needsSendMultiple && !isSendMultiple) { - // Change to a multiple send action; place the relevant ArrayList into the - // intent for multiple sharing. - mIntent.setAction(Intent.ACTION_SEND_MULTIPLE); - if (mStreams != null && !mStreams.isEmpty()) { - mIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, mStreams); - } else { - mIntent.removeExtra(Intent.EXTRA_STREAM); - } - } - - return mIntent; - } - - Activity getActivity() { - return mActivity; - } - - private void combineArrayExtra(String extra, ArrayList add) { - String[] currentAddresses = mIntent.getStringArrayExtra(extra); - int currentLength = currentAddresses != null ? currentAddresses.length : 0; - String[] finalAddresses = new String[currentLength + add.size()]; - add.toArray(finalAddresses); - if (currentAddresses != null) { - System.arraycopy(currentAddresses, 0, finalAddresses, add.size(), currentLength); - } - mIntent.putExtra(extra, finalAddresses); - } - - private void combineArrayExtra(String extra, String[] add) { - // Add any items still pending - Intent intent = getIntent(); - String[] old = intent.getStringArrayExtra(extra); - int oldLength = old != null ? old.length : 0; - String[] result = new String[oldLength + add.length]; - if (old != null) System.arraycopy(old, 0, result, 0, oldLength); - System.arraycopy(add, 0, result, oldLength, add.length); - intent.putExtra(extra, result); - } - - /** - * Create an Intent that will launch the standard Android activity chooser, - * allowing the user to pick what activity/app on the system should handle - * the share. - * - * @return A chooser Intent for the currently configured sharing action - */ - public Intent createChooserIntent() { - return Intent.createChooser(getIntent(), mChooserTitle); - } - - /** - * Start a chooser activity for the current share intent. - * - *

Note that under most circumstances you should use - * {@link ShareCompat#configureMenuItem(MenuItem, IntentBuilder) - * ShareCompat.configureMenuItem()} to add a Share item to the menu while - * presenting a detail view of the content to be shared instead - * of invoking this directly.

- */ - public void startChooser() { - mActivity.startActivity(createChooserIntent()); - } - - /** - * Set the title that will be used for the activity chooser for this share. - * - * @param title Title string - * @return This IntentBuilder for method chaining - */ - public IntentBuilder setChooserTitle(CharSequence title) { - mChooserTitle = title; - return this; - } - - /** - * Set the title that will be used for the activity chooser for this share. - * - * @param resId Resource ID of the title string to use - * @return This IntentBuilder for method chaining - */ - public IntentBuilder setChooserTitle(@StringRes int resId) { - return setChooserTitle(mActivity.getText(resId)); - } - - /** - * Set the type of data being shared - * - * @param mimeType mimetype of the shared data - * @return This IntentBuilder for method chaining - * @see Intent#setType(String) - */ - public IntentBuilder setType(String mimeType) { - mIntent.setType(mimeType); - return this; - } - - /** - * Set the literal text data to be sent as part of the share. - * This may be a styled CharSequence. - * - * @param text Text to share - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_TEXT - */ - public IntentBuilder setText(CharSequence text) { - mIntent.putExtra(Intent.EXTRA_TEXT, text); - return this; - } - - /** - * Set an HTML string to be sent as part of the share. - * If {@link Intent#EXTRA_TEXT EXTRA_TEXT} has not already been supplied, - * a styled version of the supplied HTML text will be added as EXTRA_TEXT as - * parsed by {@link Html#fromHtml(String) Html.fromHtml}. - * - * @param htmlText A string containing HTML markup as a richer version of the text - * provided by EXTRA_TEXT. - * @return This IntentBuilder for method chaining - * @see #setText(CharSequence) - */ - public IntentBuilder setHtmlText(String htmlText) { - mIntent.putExtra(IntentCompat.EXTRA_HTML_TEXT, htmlText); - if (!mIntent.hasExtra(Intent.EXTRA_TEXT)) { - // Supply a default if EXTRA_TEXT isn't set - setText(Html.fromHtml(htmlText)); - } - return this; - } - - /** - * Set a stream URI to the data that should be shared. - * - *

This replaces all currently set stream URIs and will produce a single-stream - * ACTION_SEND intent.

- * - * @param streamUri URI of the stream to share - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_STREAM - */ - public IntentBuilder setStream(Uri streamUri) { - if (!mIntent.getAction().equals(Intent.ACTION_SEND)) { - mIntent.setAction(Intent.ACTION_SEND); - } - mStreams = null; - mIntent.putExtra(Intent.EXTRA_STREAM, streamUri); - return this; - } - - /** - * Add a stream URI to the data that should be shared. If this is not the first - * stream URI added the final intent constructed will become an ACTION_SEND_MULTIPLE - * intent. Not all apps will handle both ACTION_SEND and ACTION_SEND_MULTIPLE. - * - * @param streamUri URI of the stream to share - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_STREAM - * @see Intent#ACTION_SEND - * @see Intent#ACTION_SEND_MULTIPLE - */ - public IntentBuilder addStream(Uri streamUri) { - Uri currentStream = mIntent.getParcelableExtra(Intent.EXTRA_STREAM); - if (mStreams == null && currentStream == null) { - return setStream(streamUri); - } - if (mStreams == null) { - mStreams = new ArrayList(); - } - if (currentStream != null) { - mIntent.removeExtra(Intent.EXTRA_STREAM); - mStreams.add(currentStream); - } - mStreams.add(streamUri); - return this; - } - - /** - * Set an array of email addresses as recipients of this share. - * This replaces all current "to" recipients that have been set so far. - * - * @param addresses Email addresses to send to - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_EMAIL - */ - public IntentBuilder setEmailTo(String[] addresses) { - if (mToAddresses != null) { - mToAddresses = null; - } - mIntent.putExtra(Intent.EXTRA_EMAIL, addresses); - return this; - } - - /** - * Add an email address to be used in the "to" field of the final Intent. - * - * @param address Email address to send to - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_EMAIL - */ - public IntentBuilder addEmailTo(String address) { - if (mToAddresses == null) { - mToAddresses = new ArrayList(); - } - mToAddresses.add(address); - return this; - } - - /** - * Add an array of email addresses to be used in the "to" field of the final Intent. - * - * @param addresses Email addresses to send to - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_EMAIL - */ - public IntentBuilder addEmailTo(String[] addresses) { - combineArrayExtra(Intent.EXTRA_EMAIL, addresses); - return this; - } - - /** - * Set an array of email addresses to CC on this share. - * This replaces all current "CC" recipients that have been set so far. - * - * @param addresses Email addresses to CC on the share - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_CC - */ - public IntentBuilder setEmailCc(String[] addresses) { - mIntent.putExtra(Intent.EXTRA_CC, addresses); - return this; - } - - /** - * Add an email address to be used in the "cc" field of the final Intent. - * - * @param address Email address to CC - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_CC - */ - public IntentBuilder addEmailCc(String address) { - if (mCcAddresses == null) { - mCcAddresses = new ArrayList(); - } - mCcAddresses.add(address); - return this; - } - - /** - * Add an array of email addresses to be used in the "cc" field of the final Intent. - * - * @param addresses Email addresses to CC - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_CC - */ - public IntentBuilder addEmailCc(String[] addresses) { - combineArrayExtra(Intent.EXTRA_CC, addresses); - return this; - } - - /** - * Set an array of email addresses to BCC on this share. - * This replaces all current "BCC" recipients that have been set so far. - * - * @param addresses Email addresses to BCC on the share - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_BCC - */ - public IntentBuilder setEmailBcc(String[] addresses) { - mIntent.putExtra(Intent.EXTRA_BCC, addresses); - return this; - } - - /** - * Add an email address to be used in the "bcc" field of the final Intent. - * - * @param address Email address to BCC - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_BCC - */ - public IntentBuilder addEmailBcc(String address) { - if (mBccAddresses == null) { - mBccAddresses = new ArrayList(); - } - mBccAddresses.add(address); - return this; - } - - /** - * Add an array of email addresses to be used in the "bcc" field of the final Intent. - * - * @param addresses Email addresses to BCC - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_BCC - */ - public IntentBuilder addEmailBcc(String[] addresses) { - combineArrayExtra(Intent.EXTRA_BCC, addresses); - return this; - } - - /** - * Set a subject heading for this share; useful for sharing via email. - * - * @param subject Subject heading for this share - * @return This IntentBuilder for method chaining - * @see Intent#EXTRA_SUBJECT - */ - public IntentBuilder setSubject(String subject) { - mIntent.putExtra(Intent.EXTRA_SUBJECT, subject); - return this; - } - } - - /** - * IntentReader is a helper for reading the data contained within a sharing (ACTION_SEND) - * Intent. It provides methods to parse standard elements included with a share - * in addition to extra metadata about the app that shared the content. - * - *

Social sharing apps are encouraged to provide attribution for the app that shared - * the content. IntentReader offers access to the application label, calling activity info, - * and application icon of the app that shared the content. This data may have been provided - * voluntarily by the calling app and should always be displayed to the user before submission - * for manual verification. The user should be offered the option to omit this information - * from shared posts if desired.

- * - *

Activities that intend to receive sharing intents should configure an intent-filter - * to accept {@link Intent#ACTION_SEND} intents ("android.intent.action.SEND") and optionally - * accept {@link Intent#ACTION_SEND_MULTIPLE} ("android.intent.action.SEND_MULTIPLE") if - * the activity is equipped to handle multiple data streams.

- */ - public static class IntentReader { - private static final String TAG = "IntentReader"; - - private Activity mActivity; - private Intent mIntent; - private String mCallingPackage; - private ComponentName mCallingActivity; - - private ArrayList mStreams; - - /** - * Get an IntentReader for parsing and interpreting the sharing intent - * used to start the given activity. - * - * @param activity Activity that was started to share content - * @return IntentReader for parsing sharing data - */ - public static IntentReader from(Activity activity) { - return new IntentReader(activity); - } - - private IntentReader(Activity activity) { - mActivity = activity; - mIntent = activity.getIntent(); - mCallingPackage = ShareCompat.getCallingPackage(activity); - mCallingActivity = ShareCompat.getCallingActivity(activity); - } - - /** - * Returns true if the activity this reader was obtained for was - * started with an {@link Intent#ACTION_SEND} or {@link Intent#ACTION_SEND_MULTIPLE} - * sharing Intent. - * - * @return true if the activity was started with an ACTION_SEND - * or ACTION_SEND_MULTIPLE Intent - */ - public boolean isShareIntent() { - final String action = mIntent.getAction(); - return Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action); - } - - /** - * Returns true if the activity this reader was obtained for was started with an - * {@link Intent#ACTION_SEND} intent and contains a single shared item. - * The shared content should be obtained using either the {@link #getText()} - * or {@link #getStream()} methods depending on the type of content shared. - * - * @return true if the activity was started with an ACTION_SEND intent - */ - public boolean isSingleShare() { - return Intent.ACTION_SEND.equals(mIntent.getAction()); - } - - /** - * Returns true if the activity this reader was obtained for was started with an - * {@link Intent#ACTION_SEND_MULTIPLE} intent. The Intent may contain more than - * one stream item. - * - * @return true if the activity was started with an ACTION_SEND_MULTIPLE intent - */ - public boolean isMultipleShare() { - return Intent.ACTION_SEND_MULTIPLE.equals(mIntent.getAction()); - } - - /** - * Get the mimetype of the data shared to this activity. - * - * @return mimetype of the shared data - * @see Intent#getType() - */ - public String getType() { - return mIntent.getType(); - } - - /** - * Get the literal text shared with the target activity. - * - * @return Literal shared text or null if none was supplied - * @see Intent#EXTRA_TEXT - */ - public CharSequence getText() { - return mIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); - } - - /** - * Get the styled HTML text shared with the target activity. - * If no HTML text was supplied but {@link Intent#EXTRA_TEXT} contained - * styled text, it will be converted to HTML if possible and returned. - * If the text provided by {@link Intent#EXTRA_TEXT} was not styled text, - * it will be escaped by {@link Html#escapeHtml(CharSequence)} - * and returned. If no text was provided at all, this method will return null. - * - * @return Styled text provided by the sender as HTML. - */ - public String getHtmlText() { - String result = mIntent.getStringExtra(IntentCompat.EXTRA_HTML_TEXT); - if (result == null) { - CharSequence text = getText(); - if (text instanceof Spanned) { - result = Html.toHtml((Spanned) text); - } else if (text != null) { - result = IMPL.escapeHtml(text); - } - } - return result; - } - - /** - * Get a URI referring to a data stream shared with the target activity. - * - *

This call will fail if the share intent contains multiple stream items. - * If {@link #isMultipleShare()} returns true the application should use - * {@link #getStream(int)} and {@link #getStreamCount()} to retrieve the - * included stream items.

- * - * @return A URI referring to a data stream to be shared or null if one was not supplied - * @see Intent#EXTRA_STREAM - */ - public Uri getStream() { - return mIntent.getParcelableExtra(Intent.EXTRA_STREAM); - } - - /** - * Get the URI of a stream item shared with the target activity. - * Index should be in the range [0-getStreamCount()). - * - * @param index Index of text item to retrieve - * @return Requested stream item URI - * @see Intent#EXTRA_STREAM - * @see Intent#ACTION_SEND_MULTIPLE - */ - public Uri getStream(int index) { - if (mStreams == null && isMultipleShare()) { - mStreams = mIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); - } - if (mStreams != null) { - return mStreams.get(index); - } - if (index == 0) { - return mIntent.getParcelableExtra(Intent.EXTRA_STREAM); - } - throw new IndexOutOfBoundsException("Stream items available: " + getStreamCount() + - " index requested: " + index); - } - - /** - * Return the number of stream items shared. The return value will be 0 or 1 if - * this was an {@link Intent#ACTION_SEND} intent, or 0 or more if it was an - * {@link Intent#ACTION_SEND_MULTIPLE} intent. - * - * @return Count of text items contained within the Intent - */ - public int getStreamCount() { - if (mStreams == null && isMultipleShare()) { - mStreams = mIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); - } - if (mStreams != null) { - return mStreams.size(); - } - return mIntent.hasExtra(Intent.EXTRA_STREAM) ? 1 : 0; - } - - /** - * Get an array of Strings, each an email address to share to. - * - * @return An array of email addresses or null if none were supplied. - * @see Intent#EXTRA_EMAIL - */ - public String[] getEmailTo() { - return mIntent.getStringArrayExtra(Intent.EXTRA_EMAIL); - } - - /** - * Get an array of Strings, each an email address to CC on this share. - * - * @return An array of email addresses or null if none were supplied. - * @see Intent#EXTRA_CC - */ - public String[] getEmailCc() { - return mIntent.getStringArrayExtra(Intent.EXTRA_CC); - } - - /** - * Get an array of Strings, each an email address to BCC on this share. - * - * @return An array of email addresses or null if none were supplied. - * @see Intent#EXTRA_BCC - */ - public String[] getEmailBcc() { - return mIntent.getStringArrayExtra(Intent.EXTRA_BCC); - } - - /** - * Get a subject heading for this share; useful when sharing via email. - * - * @return The subject heading for this share or null if one was not supplied. - * @see Intent#EXTRA_SUBJECT - */ - public String getSubject() { - return mIntent.getStringExtra(Intent.EXTRA_SUBJECT); - } - - /** - * Get the name of the package that invoked this sharing intent. If the activity - * was not started for a result, IntentBuilder will read this from extra metadata placed - * in the Intent by ShareBuilder. - * - *

Note: This data may have been provided voluntarily by the calling - * application. As such it should not be trusted for accuracy in the context of - * security or verification.

- * - * @return Name of the package that started this activity or null if unknown - * @see Activity#getCallingPackage() - * @see ShareCompat#EXTRA_CALLING_PACKAGE - */ - public String getCallingPackage() { - return mCallingPackage; - } - - /** - * Get the {@link ComponentName} of the Activity that invoked this sharing intent. - * If the target sharing activity was not started for a result, IntentBuilder will read - * this from extra metadata placed in the intent by ShareBuilder. - * - *

Note: This data may have been provided voluntarily by the calling - * application. As such it should not be trusted for accuracy in the context of - * security or verification.

- * - * @return ComponentName of the calling Activity or null if unknown - * @see Activity#getCallingActivity() - * @see ShareCompat#EXTRA_CALLING_ACTIVITY - */ - public ComponentName getCallingActivity() { - return mCallingActivity; - } - - /** - * Get the icon of the calling activity as a Drawable if data about - * the calling activity is available. - * - *

Note: This data may have been provided voluntarily by the calling - * application. As such it should not be trusted for accuracy in the context of - * security or verification.

- * - * @return The calling Activity's icon or null if unknown - */ - public Drawable getCallingActivityIcon() { - if (mCallingActivity == null) return null; - - PackageManager pm = mActivity.getPackageManager(); - try { - return pm.getActivityIcon(mCallingActivity); - } catch (NameNotFoundException e) { - Log.e(TAG, "Could not retrieve icon for calling activity", e); - } - return null; - } - - /** - * Get the icon of the calling application as a Drawable if data - * about the calling package is available. - * - *

Note: This data may have been provided voluntarily by the calling - * application. As such it should not be trusted for accuracy in the context of - * security or verification.

- * - * @return The calling application's icon or null if unknown - */ - public Drawable getCallingApplicationIcon() { - if (mCallingPackage == null) return null; - - PackageManager pm = mActivity.getPackageManager(); - try { - return pm.getApplicationIcon(mCallingPackage); - } catch (NameNotFoundException e) { - Log.e(TAG, "Could not retrieve icon for calling application", e); - } - return null; - } - - /** - * Get the human-readable label (title) of the calling application if - * data about the calling package is available. - * - *

Note: This data may have been provided voluntarily by the calling - * application. As such it should not be trusted for accuracy in the context of - * security or verification.

- * - * @return The calling application's label or null if unknown - */ - public CharSequence getCallingApplicationLabel() { - if (mCallingPackage == null) return null; - - PackageManager pm = mActivity.getPackageManager(); - try { - return pm.getApplicationLabel(pm.getApplicationInfo(mCallingPackage, 0)); - } catch (NameNotFoundException e) { - Log.e(TAG, "Could not retrieve label for calling application", e); - } - return null; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompatICS.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompatICS.java deleted file mode 100644 index 94e5513..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompatICS.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.content.Intent; -import android.view.ActionProvider; -import android.view.MenuItem; -import android.widget.ShareActionProvider; - -class ShareCompatICS { - private static final String HISTORY_FILENAME_PREFIX = ".sharecompat_"; - - public static void configureMenuItem(MenuItem item, Activity callingActivity, Intent intent) { - ActionProvider itemProvider = item.getActionProvider(); - ShareActionProvider provider = null; - if (!(itemProvider instanceof ShareActionProvider)) { - provider = new ShareActionProvider(callingActivity); - } else { - provider = (ShareActionProvider) itemProvider; - } - provider.setShareHistoryFileName(HISTORY_FILENAME_PREFIX + - callingActivity.getClass().getName()); - provider.setShareIntent(intent); - item.setActionProvider(provider); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompatJB.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompatJB.java deleted file mode 100644 index a57b212..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/ShareCompatJB.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.text.Html; - -class ShareCompatJB { - public static String escapeHtml(CharSequence html) { - return Html.escapeHtml(html); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/SharedElementCallback.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/SharedElementCallback.java deleted file mode 100644 index c6c7eb3..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/SharedElementCallback.java +++ /dev/null @@ -1,283 +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 p.android.support.v4.app; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Parcelable; -import android.view.View; -import android.widget.ImageView; -import android.widget.ImageView.ScaleType; - -import java.util.List; -import java.util.Map; - -/** - * Listener provided in - * {@link FragmentActivity#setEnterSharedElementCallback(SharedElementCallback)} and - * {@link FragmentActivity#setExitSharedElementCallback(SharedElementCallback)} - * to monitor the Activity transitions. The events can be used to customize Activity - * Transition behavior. - */ -public abstract class SharedElementCallback { - private Matrix mTempMatrix; - private static int MAX_IMAGE_SIZE = (1024 * 1024); - private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap"; - private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType"; - private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix"; - - /** - * In Activity Transitions, onSharedElementStart is called immediately before - * capturing the start of the shared element state on enter and reenter transitions and - * immediately before capturing the end of the shared element state for exit and return - * transitions. - *

- * In Fragment Transitions, onSharedElementStart is called immediately before capturing the - * start state of all shared element transitions. - *

- * This call can be used to adjust the transition start state by modifying the shared - * element Views. Note that no layout step will be executed between onSharedElementStart - * and the transition state capture. - *

- * For Activity Transitions, any changes made in {@link #onSharedElementEnd(List, List, List)} - * that are not updated during layout should be corrected in onSharedElementStart for exit and - * return transitions. For example, rotation or scale will not be affected by layout and - * if changed in {@link #onSharedElementEnd(List, List, List)}, it will also have to be reset - * in onSharedElementStart again to correct the end state. - * - * @param sharedElementNames The names of the shared elements that were accepted into - * the View hierarchy. - * @param sharedElements The shared elements that are part of the View hierarchy. - * @param sharedElementSnapshots The Views containing snap shots of the shared element - * from the launching Window. These elements will not - * be part of the scene, but will be positioned relative - * to the Window decor View. This list is null for Fragment - * Transitions. - */ - public void onSharedElementStart(List sharedElementNames, - List sharedElements, List sharedElementSnapshots) {} - - /** - * In Activity Transitions, onSharedElementEnd is called immediately before - * capturing the end of the shared element state on enter and reenter transitions and - * immediately before capturing the start of the shared element state for exit and return - * transitions. - *

- * In Fragment Transitions, onSharedElementEnd is called immediately before capturing the - * end state of all shared element transitions. - *

- * This call can be used to adjust the transition end state by modifying the shared - * element Views. Note that no layout step will be executed between onSharedElementEnd - * and the transition state capture. - *

- * Any changes made in {@link #onSharedElementStart(List, List, List)} that are not updated - * during layout should be corrected in onSharedElementEnd. For example, rotation or scale - * will not be affected by layout and if changed in - * {@link #onSharedElementStart(List, List, List)}, it will also have to be reset in - * onSharedElementEnd again to correct the end state. - * - * @param sharedElementNames The names of the shared elements that were accepted into - * the View hierarchy. - * @param sharedElements The shared elements that are part of the View hierarchy. - * @param sharedElementSnapshots The Views containing snap shots of the shared element - * from the launching Window. These elements will not - * be part of the scene, but will be positioned relative - * to the Window decor View. This list will be null for - * Fragment Transitions. - */ - public void onSharedElementEnd(List sharedElementNames, - List sharedElements, List sharedElementSnapshots) {} - - /** - * Called after {@link #onMapSharedElements(List, Map)} when - * transferring shared elements in. Any shared elements that have no mapping will be in - * rejectedSharedElements. The elements remaining in - * rejectedSharedElements will be transitioned out of the Scene. If a - * View is removed from rejectedSharedElements, it must be handled by the - * SharedElementListener. - *

- * Views in rejectedSharedElements will have their position and size set to the - * position of the calling shared element, relative to the Window decor View and contain - * snapshots of the View from the calling Activity or Fragment. This - * view may be safely added to the decor View's overlay to remain in position. - *

- *

This method is not called for Fragment Transitions. All rejected shared elements - * will be handled by the exit transition.

- * - * @param rejectedSharedElements Views containing visual information of shared elements - * that are not part of the entering scene. These Views - * are positioned relative to the Window decor View. A - * View removed from this list will not be transitioned - * automatically. - */ - public void onRejectSharedElements(List rejectedSharedElements) {} - - /** - * Lets the SharedElementCallback adjust the mapping of shared element names to - * Views. - * - * @param names The names of all shared elements transferred from the calling Activity - * or Fragment in the order they were provided. - * @param sharedElements The mapping of shared element names to Views. The best guess - * will be filled into sharedElements based on the transitionNames. - */ - public void onMapSharedElements(List names, Map sharedElements) {} - - - /** - * Creates a snapshot of a shared element to be used by the remote Activity and reconstituted - * with {@link #onCreateSnapshotView(Context, Parcelable)}. A - * null return value will mean that the remote Activity will have a null snapshot View in - * {@link #onSharedElementStart(List, List, List)} and - * {@link #onSharedElementEnd(List, List, List)}. - * - *

This is not called for Fragment Transitions.

- * - * @param sharedElement The shared element View to create a snapshot for. - * @param viewToGlobalMatrix A matrix containing a transform from the view to the screen - * coordinates. - * @param screenBounds The bounds of shared element in screen coordinate space. This is - * the bounds of the view with the viewToGlobalMatrix applied. - * @return A snapshot to send to the remote Activity to be reconstituted with - * {@link #onCreateSnapshotView(Context, Parcelable)} and passed - * into {@link #onSharedElementStart(List, List, List)} and - * {@link #onSharedElementEnd(List, List, List)}. - */ - public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix, - RectF screenBounds) { - if (sharedElement instanceof ImageView) { - ImageView imageView = ((ImageView) sharedElement); - Drawable d = imageView.getDrawable(); - Drawable bg = imageView.getBackground(); - if (d != null && bg == null) { - Bitmap bitmap = createDrawableBitmap(d); - if (bitmap != null) { - Bundle bundle = new Bundle(); - bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap); - bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE, - imageView.getScaleType().toString()); - if (imageView.getScaleType() == ScaleType.MATRIX) { - Matrix matrix = imageView.getImageMatrix(); - float[] values = new float[9]; - matrix.getValues(values); - bundle.putFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX, values); - } - return bundle; - } - } - } - int bitmapWidth = Math.round(screenBounds.width()); - int bitmapHeight = Math.round(screenBounds.height()); - Bitmap bitmap = null; - if (bitmapWidth > 0 && bitmapHeight > 0) { - float scale = Math.min(1f, ((float)MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight)); - bitmapWidth *= scale; - bitmapHeight *= scale; - if (mTempMatrix == null) { - mTempMatrix = new Matrix(); - } - mTempMatrix.set(viewToGlobalMatrix); - mTempMatrix.postTranslate(-screenBounds.left, -screenBounds.top); - mTempMatrix.postScale(scale, scale); - bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - canvas.concat(mTempMatrix); - sharedElement.draw(canvas); - } - return bitmap; - } - - /** - * Get a copy of bitmap of given drawable. - */ - private static Bitmap createDrawableBitmap(Drawable drawable) { - int width = drawable.getIntrinsicWidth(); - int height = drawable.getIntrinsicHeight(); - if (width <= 0 || height <= 0) { - return null; - } - float scale = Math.min(1f, ((float)MAX_IMAGE_SIZE) / (width * height)); - if (drawable instanceof BitmapDrawable && scale == 1f) { - // return same bitmap if scale down not needed - return ((BitmapDrawable) drawable).getBitmap(); - } - int bitmapWidth = (int) (width * scale); - int bitmapHeight = (int) (height * scale); - Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - Rect existingBounds = drawable.getBounds(); - int left = existingBounds.left; - int top = existingBounds.top; - int right = existingBounds.right; - int bottom = existingBounds.bottom; - drawable.setBounds(0, 0, bitmapWidth, bitmapHeight); - drawable.draw(canvas); - drawable.setBounds(left, top, right, bottom); - return bitmap; - } - - /** - * Reconstitutes a snapshot View from a Parcelable returned in - * {@link #onCaptureSharedElementSnapshot(View, Matrix, - * RectF)} to be used in {@link #onSharedElementStart(List, - * List, List)} and {@link #onSharedElementEnd(List, - * List, List)}. The returned View will be sized and positioned after - * this call so that it is ready to be added to the decor View's overlay. - * - *

This is not called for Fragment Transitions.

- * - * @param context The Context used to create the snapshot View. - * @param snapshot The Parcelable returned by {@link #onCaptureSharedElementSnapshot( - * View, Matrix, RectF)}. - * @return A View to be sent in {@link #onSharedElementStart(List, List, - * List)} and {@link #onSharedElementEnd(List, List, - * List)}. A null value will produce a null snapshot value for those two methods. - */ - public View onCreateSnapshotView(Context context, Parcelable snapshot) { - ImageView view = null; - if (snapshot instanceof Bundle) { - Bundle bundle = (Bundle) snapshot; - Bitmap bitmap = (Bitmap) bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP); - if (bitmap == null) { - return null; - } - ImageView imageView = new ImageView(context); - view = imageView; - imageView.setImageBitmap(bitmap); - imageView.setScaleType( - ScaleType.valueOf(bundle.getString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE))); - if (imageView.getScaleType() == ScaleType.MATRIX) { - float[] values = bundle.getFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX); - Matrix matrix = new Matrix(); - matrix.setValues(values); - imageView.setImageMatrix(matrix); - } - } else if (snapshot instanceof Bitmap) { - Bitmap bitmap = (Bitmap) snapshot; - view = new ImageView(context); - view.setImageBitmap(bitmap); - } - return view; - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/SuperNotCalledException.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/SuperNotCalledException.java deleted file mode 100644 index af49712..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/SuperNotCalledException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.util.AndroidRuntimeException; - -final class SuperNotCalledException extends AndroidRuntimeException { - public SuperNotCalledException(String msg) { - super(msg); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilder.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilder.java deleted file mode 100644 index 3f55180..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilder.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Build; -import android.os.Bundle; -import p.android.support.v4.content.ContextCompat; -import p.android.support.v4.content.IntentCompat; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Iterator; - -/** - * Utility class for constructing synthetic back stacks for cross-task navigation - * on Android 3.0 and newer. - * - *

In API level 11 (Android 3.0/Honeycomb) the recommended conventions for - * app navigation using the back key changed. The back key's behavior is local - * to the current task and does not capture navigation across different tasks. - * Navigating across tasks and easily reaching the previous task is accomplished - * through the "recents" UI, accessible through the software-provided Recents key - * on the navigation or system bar. On devices with the older hardware button configuration - * the recents UI can be accessed with a long press on the Home key.

- * - *

When crossing from one task stack to another post-Android 3.0, - * the application should synthesize a back stack/history for the new task so that - * the user may navigate out of the new task and back to the Launcher by repeated - * presses of the back key. Back key presses should not navigate across task stacks.

- * - *

TaskStackBuilder provides a backward-compatible way to obey the correct conventions - * around cross-task navigation on the device's version of the platform. On devices running - * Android 3.0 or newer, calls to the {@link #startActivities()} method or sending the - * {@link PendingIntent} generated by {@link #getPendingIntent(int, int)} will construct - * the synthetic back stack as prescribed. On devices running older versions of the platform, - * these same calls will invoke the topmost activity in the supplied stack, ignoring - * the rest of the synthetic stack and allowing the back key to navigate back to the previous - * task.

- * - *
- *

About Navigation

- * For more detailed information about tasks, the back stack, and navigation design guidelines, - * please read - * Tasks and Back Stack - * from the developer guide and Navigation - * from the design guide. - *
- */ -public final class TaskStackBuilder implements Iterable { - private static final String TAG = "TaskStackBuilder"; - - public interface SupportParentable { - Intent getSupportParentActivityIntent(); - } - - interface TaskStackBuilderImpl { - PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, - int flags, Bundle options); - } - - static class TaskStackBuilderImplBase implements TaskStackBuilderImpl { - public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, - int flags, Bundle options) { - Intent topIntent = new Intent(intents[intents.length - 1]); - topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - return PendingIntent.getActivity(context, requestCode, topIntent, flags); - } - } - - static class TaskStackBuilderImplHoneycomb implements TaskStackBuilderImpl { - public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, - int flags, Bundle options) { - intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | - IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); - return TaskStackBuilderHoneycomb.getActivitiesPendingIntent(context, requestCode, - intents, flags); - } - } - - static class TaskStackBuilderImplJellybean implements TaskStackBuilderImpl { - public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode, - int flags, Bundle options) { - intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | - IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); - return TaskStackBuilderJellybean.getActivitiesPendingIntent(context, requestCode, - intents, flags, options); - } - } - - private static final TaskStackBuilderImpl IMPL; - - static { - if (Build.VERSION.SDK_INT >= 11) { - IMPL = new TaskStackBuilderImplHoneycomb(); - } else { - IMPL = new TaskStackBuilderImplBase(); - } - } - - private final ArrayList mIntents = new ArrayList(); - private final Context mSourceContext; - - private TaskStackBuilder(Context a) { - mSourceContext = a; - } - - /** - * Return a new TaskStackBuilder for launching a fresh task stack consisting - * of a series of activities. - * - * @param context The context that will launch the new task stack or generate a PendingIntent - * @return A new TaskStackBuilder - */ - public static TaskStackBuilder create(Context context) { - return new TaskStackBuilder(context); - } - - /** - * Return a new TaskStackBuilder for launching a fresh task stack consisting - * of a series of activities. - * - * @param context The context that will launch the new task stack or generate a PendingIntent - * @return A new TaskStackBuilder - * - * @deprecated use {@link #create(Context)} instead - */ - public static TaskStackBuilder from(Context context) { - return create(context); - } - - /** - * Add a new Intent to the task stack. The most recently added Intent will invoke - * the Activity at the top of the final task stack. - * - * @param nextIntent Intent for the next Activity in the synthesized task stack - * @return This TaskStackBuilder for method chaining - */ - public TaskStackBuilder addNextIntent(Intent nextIntent) { - mIntents.add(nextIntent); - return this; - } - - /** - * Add a new Intent with the resolved chain of parents for the target activity to - * the task stack. - * - *

This is equivalent to calling {@link #addParentStack(ComponentName) addParentStack} - * with the resolved ComponentName of nextIntent (if it can be resolved), followed by - * {@link #addNextIntent(Intent) addNextIntent} with nextIntent.

- * - * @param nextIntent Intent for the topmost Activity in the synthesized task stack. - * Its chain of parents as specified in the manifest will be added. - * @return This TaskStackBuilder for method chaining. - */ - public TaskStackBuilder addNextIntentWithParentStack(Intent nextIntent) { - ComponentName target = nextIntent.getComponent(); - if (target == null) { - target = nextIntent.resolveActivity(mSourceContext.getPackageManager()); - } - if (target != null) { - addParentStack(target); - } - addNextIntent(nextIntent); - return this; - } - - /** - * Add the activity parent chain as specified by manifest <meta-data> elements - * to the task stack builder. - * - * @param sourceActivity All parents of this activity will be added - * @return This TaskStackBuilder for method chaining - */ - public TaskStackBuilder addParentStack(Activity sourceActivity) { - Intent parent = null; - if (sourceActivity instanceof SupportParentable) { - parent = ((SupportParentable) sourceActivity).getSupportParentActivityIntent(); - } - if (parent == null) { - parent = NavUtils.getParentActivityIntent(sourceActivity); - } - - if (parent != null) { - // We have the actual parent intent, build the rest from static metadata - // then add the direct parent intent to the end. - ComponentName target = parent.getComponent(); - if (target == null) { - target = parent.resolveActivity(mSourceContext.getPackageManager()); - } - addParentStack(target); - addNextIntent(parent); - } - return this; - } - - /** - * Add the activity parent chain as specified by manifest <meta-data> elements - * to the task stack builder. - * - * @param sourceActivityClass All parents of this activity will be added - * @return This TaskStackBuilder for method chaining - */ - public TaskStackBuilder addParentStack(Class sourceActivityClass) { - return addParentStack(new ComponentName(mSourceContext, sourceActivityClass)); - } - - /** - * Add the activity parent chain as specified by manifest <meta-data> elements - * to the task stack builder. - * - * @param sourceActivityName Must specify an Activity component. All parents of - * this activity will be added - * @return This TaskStackBuilder for method chaining - */ - public TaskStackBuilder addParentStack(ComponentName sourceActivityName) { - final int insertAt = mIntents.size(); - try { - Intent parent = NavUtils.getParentActivityIntent(mSourceContext, sourceActivityName); - while (parent != null) { - mIntents.add(insertAt, parent); - parent = NavUtils.getParentActivityIntent(mSourceContext, parent.getComponent()); - } - } catch (NameNotFoundException e) { - Log.e(TAG, "Bad ComponentName while traversing activity parent metadata"); - throw new IllegalArgumentException(e); - } - return this; - } - - /** - * @return the number of intents added so far. - */ - public int getIntentCount() { - return mIntents.size(); - } - - /** - * Get the intent at the specified index. - * Useful if you need to modify the flags or extras of an intent that was previously added, - * for example with {@link #addParentStack(Activity)}. - * - * @param index Index from 0-getIntentCount() - * @return the intent at position index - * - * @deprecated Renamed to editIntentAt to better reflect intended usage - */ - public Intent getIntent(int index) { - return editIntentAt(index); - } - - /** - * Return the intent at the specified index for modification. - * Useful if you need to modify the flags or extras of an intent that was previously added, - * for example with {@link #addParentStack(Activity)}. - * - * @param index Index from 0-getIntentCount() - * @return the intent at position index - */ - public Intent editIntentAt(int index) { - return mIntents.get(index); - } - - /** - * @deprecated Use editIntentAt instead - */ - public Iterator iterator() { - return mIntents.iterator(); - } - - /** - * Start the task stack constructed by this builder. The Context used to obtain - * this builder must be an Activity. - * - *

On devices that do not support API level 11 or higher the topmost activity - * will be started as a new task. On devices that do support API level 11 or higher - * the new task stack will be created in its entirety.

- */ - public void startActivities() { - startActivities(null); - } - - /** - * Start the task stack constructed by this builder. The Context used to obtain - * this builder must be an Activity. - * - *

On devices that do not support API level 11 or higher the topmost activity - * will be started as a new task. On devices that do support API level 11 or higher - * the new task stack will be created in its entirety.

- * - * @param options Additional options for how the Activity should be started. - * See {@link Context#startActivity(Intent, Bundle) - */ - public void startActivities(Bundle options) { - if (mIntents.isEmpty()) { - throw new IllegalStateException( - "No intents added to TaskStackBuilder; cannot startActivities"); - } - - Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]); - intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | - IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); - if (!ContextCompat.startActivities(mSourceContext, intents, options)) { - Intent topIntent = new Intent(intents[intents.length - 1]); - topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mSourceContext.startActivity(topIntent); - } - } - - /** - * Obtain a {@link PendingIntent} for launching the task constructed by this builder so far. - * - * @param requestCode Private request code for the sender - * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT}, - * {@link PendingIntent#FLAG_NO_CREATE}, {@link PendingIntent#FLAG_CANCEL_CURRENT}, - * {@link PendingIntent#FLAG_UPDATE_CURRENT}, or any of the flags supported by - * {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the - * intent that can be supplied when the actual send happens. - * @return The obtained PendingIntent - */ - public PendingIntent getPendingIntent(int requestCode, int flags) { - return getPendingIntent(requestCode, flags, null); - } - - /** - * Obtain a {@link PendingIntent} for launching the task constructed by this builder so far. - * - * @param requestCode Private request code for the sender - * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT}, - * {@link PendingIntent#FLAG_NO_CREATE}, {@link PendingIntent#FLAG_CANCEL_CURRENT}, - * {@link PendingIntent#FLAG_UPDATE_CURRENT}, or any of the flags supported by - * {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the - * intent that can be supplied when the actual send happens. - * @param options Additional options for how the Activity should be started. - * See {@link Context#startActivity(Intent, Bundle) - * @return The obtained PendingIntent - */ - public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options) { - if (mIntents.isEmpty()) { - throw new IllegalStateException( - "No intents added to TaskStackBuilder; cannot getPendingIntent"); - } - - Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]); - intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | - IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); - // Appropriate flags will be added by the call below. - return IMPL.getPendingIntent(mSourceContext, intents, requestCode, flags, options); - } - - /** - * Return an array containing the intents added to this builder. The intent at the - * root of the task stack will appear as the first item in the array and the - * intent at the top of the stack will appear as the last item. - * - * @return An array containing the intents added to this builder. - */ - public Intent[] getIntents() { - Intent[] intents = new Intent[mIntents.size()]; - if (intents.length == 0) return intents; - - intents[0] = new Intent(mIntents.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - IntentCompat.FLAG_ACTIVITY_CLEAR_TASK | - IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME); - for (int i = 1; i < intents.length; i++) { - intents[i] = new Intent(mIntents.get(i)); - } - return intents; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilderHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilderHoneycomb.java deleted file mode 100644 index 433f045..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilderHoneycomb.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; - -/** - * Implementation of TaskStackBuilder that can call Honeycomb APIs. - */ -class TaskStackBuilderHoneycomb { - public static PendingIntent getActivitiesPendingIntent(Context context, int requestCode, - Intent[] intents, int flags) { - return PendingIntent.getActivities(context, requestCode, intents, flags); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilderJellybean.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilderJellybean.java deleted file mode 100644 index 1fa4d6d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/TaskStackBuilderJellybean.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.app; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; - -class TaskStackBuilderJellybean { - - public static PendingIntent getActivitiesPendingIntent(Context context, int requestCode, - Intent[] intents, int flags, Bundle options) { - return PendingIntent.getActivities(context, requestCode, intents, flags, options); - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/package.html b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/package.html deleted file mode 100755 index 02d1b79..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/app/package.html +++ /dev/null @@ -1,8 +0,0 @@ - - -Support android.app classes to assist with development of applications for -android API level 4 or later. The main features here are backwards-compatible -versions of {@link android.support.v4.app.FragmentManager} and -{@link android.support.v4.app.LoaderManager}. - - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/AsyncTaskLoader.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/AsyncTaskLoader.java deleted file mode 100644 index 3f8caf5..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/AsyncTaskLoader.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Context; -import android.os.Handler; -import android.os.SystemClock; -import p.android.support.v4.os.OperationCanceledException; -import p.android.support.v4.util.TimeUtils; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; - -/** - * Static library support version of the framework's {@link android.content.AsyncTaskLoader}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework SDK - * documentation for a class overview. - */ -public abstract class AsyncTaskLoader extends Loader { - static final String TAG = "AsyncTaskLoader"; - static final boolean DEBUG = false; - - final class LoadTask extends ModernAsyncTask implements Runnable { - private final CountDownLatch mDone = new CountDownLatch(1); - - // Set to true to indicate that the task has been posted to a handler for - // execution at a later time. Used to throttle updates. - boolean waiting; - - /* Runs on a worker thread */ - @Override - protected D doInBackground(Void... params) { - if (DEBUG) Log.v(TAG, this + " >>> doInBackground"); - try { - D data = AsyncTaskLoader.this.onLoadInBackground(); - if (DEBUG) Log.v(TAG, this + " <<< doInBackground"); - return data; - } catch (OperationCanceledException ex) { - if (!isCancelled()) { - // onLoadInBackground threw a canceled exception spuriously. - // This is problematic because it means that the LoaderManager did not - // cancel the Loader itself and still expects to receive a result. - // Additionally, the Loader's own state will not have been updated to - // reflect the fact that the task was being canceled. - // So we treat this case as an unhandled exception. - throw ex; - } - if (DEBUG) Log.v(TAG, this + " <<< doInBackground (was canceled)", ex); - return null; - } - } - - /* Runs on the UI thread */ - @Override - protected void onPostExecute(D data) { - if (DEBUG) Log.v(TAG, this + " onPostExecute"); - try { - AsyncTaskLoader.this.dispatchOnLoadComplete(this, data); - } finally { - mDone.countDown(); - } - } - - /* Runs on the UI thread */ - @Override - protected void onCancelled(D data) { - if (DEBUG) Log.v(TAG, this + " onCancelled"); - try { - AsyncTaskLoader.this.dispatchOnCancelled(this, data); - } finally { - mDone.countDown(); - } - } - - /* Runs on the UI thread, when the waiting task is posted to a handler. - * This method is only executed when task execution was deferred (waiting was true). */ - @Override - public void run() { - waiting = false; - AsyncTaskLoader.this.executePendingTask(); - } - - /* Used for testing purposes to wait for the task to complete. */ - public void waitForLoader() { - try { - mDone.await(); - } catch (InterruptedException e) { - // Ignore - } - } - } - - private final Executor mExecutor; - - volatile LoadTask mTask; - volatile LoadTask mCancellingTask; - - long mUpdateThrottle; - long mLastLoadCompleteTime = -10000; - Handler mHandler; - - public AsyncTaskLoader(Context context) { - this(context, ModernAsyncTask.THREAD_POOL_EXECUTOR); - } - - private AsyncTaskLoader(Context context, Executor executor) { - super(context); - mExecutor = executor; - } - - /** - * Set amount to throttle updates by. This is the minimum time from - * when the last {@link #loadInBackground()} call has completed until - * a new load is scheduled. - * - * @param delayMS Amount of delay, in milliseconds. - */ - public void setUpdateThrottle(long delayMS) { - mUpdateThrottle = delayMS; - if (delayMS != 0) { - mHandler = new Handler(); - } - } - - @Override - protected void onForceLoad() { - super.onForceLoad(); - cancelLoad(); - mTask = new LoadTask(); - if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask); - executePendingTask(); - } - - @Override - protected boolean onCancelLoad() { - if (DEBUG) Log.v(TAG, "onCancelLoad: mTask=" + mTask); - if (mTask != null) { - if (mCancellingTask != null) { - // There was a pending task already waiting for a previous - // one being canceled; just drop it. - if (DEBUG) Log.v(TAG, - "cancelLoad: still waiting for cancelled task; dropping next"); - if (mTask.waiting) { - mTask.waiting = false; - mHandler.removeCallbacks(mTask); - } - mTask = null; - return false; - } else if (mTask.waiting) { - // There is a task, but it is waiting for the time it should - // execute. We can just toss it. - if (DEBUG) Log.v(TAG, "cancelLoad: task is waiting, dropping it"); - mTask.waiting = false; - mHandler.removeCallbacks(mTask); - mTask = null; - return false; - } else { - boolean cancelled = mTask.cancel(false); - if (DEBUG) Log.v(TAG, "cancelLoad: cancelled=" + cancelled); - if (cancelled) { - mCancellingTask = mTask; - cancelLoadInBackground(); - } - mTask = null; - return cancelled; - } - } - return false; - } - - /** - * Called if the task was canceled before it was completed. Gives the class a chance - * to clean up post-cancellation and to properly dispose of the result. - * - * @param data The value that was returned by {@link #loadInBackground}, or null - * if the task threw {@link OperationCanceledException}. - */ - public void onCanceled(D data) { - } - - void executePendingTask() { - if (mCancellingTask == null && mTask != null) { - if (mTask.waiting) { - mTask.waiting = false; - mHandler.removeCallbacks(mTask); - } - if (mUpdateThrottle > 0) { - long now = SystemClock.uptimeMillis(); - if (now < (mLastLoadCompleteTime+mUpdateThrottle)) { - // Not yet time to do another load. - if (DEBUG) Log.v(TAG, "Waiting until " - + (mLastLoadCompleteTime+mUpdateThrottle) - + " to execute: " + mTask); - mTask.waiting = true; - mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle); - return; - } - } - if (DEBUG) Log.v(TAG, "Executing: " + mTask); - mTask.executeOnExecutor(mExecutor, (Void[]) null); - } - } - - void dispatchOnCancelled(LoadTask task, D data) { - onCanceled(data); - if (mCancellingTask == task) { - if (DEBUG) Log.v(TAG, "Cancelled task is now canceled!"); - rollbackContentChanged(); - mLastLoadCompleteTime = SystemClock.uptimeMillis(); - mCancellingTask = null; - if (DEBUG) Log.v(TAG, "Delivering cancellation"); - deliverCancellation(); - executePendingTask(); - } - } - - void dispatchOnLoadComplete(LoadTask task, D data) { - if (mTask != task) { - if (DEBUG) Log.v(TAG, "Load complete of old task, trying to cancel"); - dispatchOnCancelled(task, data); - } else { - if (isAbandoned()) { - // This cursor has been abandoned; just cancel the new data. - onCanceled(data); - } else { - commitContentChanged(); - mLastLoadCompleteTime = SystemClock.uptimeMillis(); - mTask = null; - if (DEBUG) Log.v(TAG, "Delivering result"); - deliverResult(data); - } - } - } - - /** - * Called on a worker thread to perform the actual load and to return - * the result of the load operation. - * - * Implementations should not deliver the result directly, but should return them - * from this method, which will eventually end up calling {@link #deliverResult} on - * the UI thread. If implementations need to process the results on the UI thread - * they may override {@link #deliverResult} and do so there. - * - * To support cancellation, this method should periodically check the value of - * {@link #isLoadInBackgroundCanceled} and terminate when it returns true. - * Subclasses may also override {@link #cancelLoadInBackground} to interrupt the load - * directly instead of polling {@link #isLoadInBackgroundCanceled}. - * - * When the load is canceled, this method may either return normally or throw - * {@link OperationCanceledException}. In either case, the {@link Loader} will - * call {@link #onCanceled} to perform post-cancellation cleanup and to dispose of the - * result object, if any. - * - * @return The result of the load operation. - * - * @throws OperationCanceledException if the load is canceled during execution. - * - * @see #isLoadInBackgroundCanceled - * @see #cancelLoadInBackground - * @see #onCanceled - */ - public abstract D loadInBackground(); - - /** - * Calls {@link #loadInBackground()}. - * - * This method is reserved for use by the loader framework. - * Subclasses should override {@link #loadInBackground} instead of this method. - * - * @return The result of the load operation. - * - * @throws OperationCanceledException if the load is canceled during execution. - * - * @see #loadInBackground - */ - protected D onLoadInBackground() { - return loadInBackground(); - } - - /** - * Called on the main thread to abort a load in progress. - * - * Override this method to abort the current invocation of {@link #loadInBackground} - * that is running in the background on a worker thread. - * - * This method should do nothing if {@link #loadInBackground} has not started - * running or if it has already finished. - * - * @see #loadInBackground - */ - public void cancelLoadInBackground() { - } - - /** - * Returns true if the current invocation of {@link #loadInBackground} is being canceled. - * - * @return True if the current invocation of {@link #loadInBackground} is being canceled. - * - * @see #loadInBackground - */ - public boolean isLoadInBackgroundCanceled() { - return mCancellingTask != null; - } - - /** - * Locks the current thread until the loader completes the current load - * operation. Returns immediately if there is no load operation running. - * Should not be called from the UI thread: calling it from the UI - * thread would cause a deadlock. - *

- * Use for testing only. Never call this from a UI thread. - * - * @hide - */ - public void waitForLoader() { - LoadTask task = mTask; - if (task != null) { - task.waitForLoader(); - } - } - - @Override - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - super.dump(prefix, fd, writer, args); - if (mTask != null) { - writer.print(prefix); writer.print("mTask="); writer.print(mTask); - writer.print(" waiting="); writer.println(mTask.waiting); - } - if (mCancellingTask != null) { - writer.print(prefix); writer.print("mCancellingTask="); writer.print(mCancellingTask); - writer.print(" waiting="); writer.println(mCancellingTask.waiting); - } - if (mUpdateThrottle != 0) { - writer.print(prefix); writer.print("mUpdateThrottle="); - TimeUtils.formatDuration(mUpdateThrottle, writer); - writer.print(" mLastLoadCompleteTime="); - TimeUtils.formatDuration(mLastLoadCompleteTime, - SystemClock.uptimeMillis(), writer); - writer.println(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContentResolverCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContentResolverCompat.java deleted file mode 100644 index c9e6b7f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContentResolverCompat.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.ContentResolver; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import p.android.support.v4.os.CancellationSignal; -import p.android.support.v4.os.OperationCanceledException; - -/** - * Helper for accessing features in {@link ContentResolver} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class ContentResolverCompat { - interface ContentResolverCompatImpl { - Cursor query(ContentResolver resolver, - Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder, CancellationSignal cancellationSignal); - } - - static class ContentResolverCompatImplBase implements ContentResolverCompatImpl { - @Override - public Cursor query(ContentResolver resolver, Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder, - CancellationSignal cancellationSignal) { - // Note that the cancellation signal cannot cancel the query in progress - // prior to Jellybean so we cancel it preemptively here if needed. - if (cancellationSignal != null) { - cancellationSignal.throwIfCanceled(); - } - return resolver.query(uri, projection, selection, selectionArgs, sortOrder); - } - } - - static class ContentResolverCompatImplJB extends ContentResolverCompatImplBase { - @Override - public Cursor query(ContentResolver resolver, Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder, - CancellationSignal cancellationSignal) { - try { - return ContentResolverCompatJellybean.query(resolver, - uri, projection, selection, selectionArgs, sortOrder, - cancellationSignal != null ? - cancellationSignal.getCancellationSignalObject() : null); - } catch (Exception e) { - if (ContentResolverCompatJellybean.isFrameworkOperationCanceledException(e)) { - // query() can throw a framework OperationCanceledException if it has been - // canceled. We catch that and throw the support version instead. - throw new OperationCanceledException(); - } else { - // If it's not a framework OperationCanceledException, re-throw the exception - throw e; - } - } - } - } - - private static final ContentResolverCompatImpl IMPL; - static { - final int version = Build.VERSION.SDK_INT; - if (version >= 16) { - IMPL = new ContentResolverCompatImplJB(); - } else { - IMPL = new ContentResolverCompatImplBase(); - } - } - - private ContentResolverCompat() { - /* Hide constructor */ - } - - /** - * Query the given URI, returning a {@link Cursor} over the result set - * with optional support for cancellation. - *

- * For best performance, the caller should follow these guidelines: - *

    - *
  • Provide an explicit projection, to prevent - * reading data from storage that aren't going to be used.
  • - *
  • Use question mark parameter markers such as 'phone=?' instead of - * explicit values in the {@code selection} parameter, so that queries - * that differ only by those values will be recognized as the same - * for caching purposes.
  • - *
- *

- * - * @param uri The URI, using the content:// scheme, for the content to - * retrieve. - * @param projection A list of which columns to return. Passing null will - * return all columns, which is inefficient. - * @param selection A filter declaring which rows to return, formatted as an - * SQL WHERE clause (excluding the WHERE itself). Passing null will - * return all rows for the given URI. - * @param selectionArgs You may include ?s in selection, which will be - * replaced by the values from selectionArgs, in the order that they - * appear in the selection. The values will be bound as Strings. - * @param sortOrder How to order the rows, formatted as an SQL ORDER BY - * clause (excluding the ORDER BY itself). Passing null will use the - * default sort order, which may be unordered. - * @param cancellationSignal A signal to cancel the operation in progress, or null if none. - * If the operation is canceled, then {@link OperationCanceledException} will be thrown - * when the query is executed. - * @return A Cursor object, which is positioned before the first entry, or null - * @see Cursor - */ - public static Cursor query(ContentResolver resolver, - Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder, CancellationSignal cancellationSignal) { - return IMPL.query(resolver, uri, projection, selection, selectionArgs, - sortOrder, cancellationSignal); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContentResolverCompatJellybean.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContentResolverCompatJellybean.java deleted file mode 100644 index 5b621fa..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContentResolverCompatJellybean.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.ContentResolver; -import android.database.Cursor; -import android.net.Uri; -import android.os.OperationCanceledException; - -class ContentResolverCompatJellybean { - - public static Cursor query(ContentResolver resolver, Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder, - Object cancellationSignalObj) { - return resolver.query(uri, projection, selection, selectionArgs, sortOrder, - (android.os.CancellationSignal)cancellationSignalObj); - } - - static boolean isFrameworkOperationCanceledException(Exception e) { - return e instanceof OperationCanceledException; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompat.java deleted file mode 100644 index 4d625c4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompat.java +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.res.ColorStateList; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.Bundle; -import android.os.Environment; -import android.os.Process; -import p.android.support.annotation.NonNull; -import p.android.support.v4.os.EnvironmentCompat; -import android.util.Log; - -import java.io.File; - -/** - * Helper for accessing features in {@link Context} - * introduced after API level 4 in a backwards compatible fashion. - */ -public class ContextCompat { - private static final String TAG = "ContextCompat"; - - private static final String DIR_ANDROID = "Android"; - private static final String DIR_DATA = "data"; - private static final String DIR_OBB = "obb"; - private static final String DIR_FILES = "files"; - private static final String DIR_CACHE = "cache"; - - /** - * Start a set of activities as a synthesized task stack, if able. - * - *

In API level 11 (Android 3.0/Honeycomb) the recommended conventions for - * app navigation using the back key changed. The back key's behavior is local - * to the current task and does not capture navigation across different tasks. - * Navigating across tasks and easily reaching the previous task is accomplished - * through the "recents" UI, accessible through the software-provided Recents key - * on the navigation or system bar. On devices with the older hardware button configuration - * the recents UI can be accessed with a long press on the Home key.

- * - *

When crossing from one task stack to another post-Android 3.0, - * the application should synthesize a back stack/history for the new task so that - * the user may navigate out of the new task and back to the Launcher by repeated - * presses of the back key. Back key presses should not navigate across task stacks.

- * - *

startActivities provides a mechanism for constructing a synthetic task stack of - * multiple activities. If the underlying API is not available on the system this method - * will return false.

- * - * @param context Start activities using this activity as the starting context - * @param intents Array of intents defining the activities that will be started. The element - * length-1 will correspond to the top activity on the resulting task stack. - * @return true if the underlying API was available and the call was successful, false otherwise - */ - public static boolean startActivities(Context context, Intent[] intents) { - return startActivities(context, intents, null); - } - - /** - * Start a set of activities as a synthesized task stack, if able. - * - *

In API level 11 (Android 3.0/Honeycomb) the recommended conventions for - * app navigation using the back key changed. The back key's behavior is local - * to the current task and does not capture navigation across different tasks. - * Navigating across tasks and easily reaching the previous task is accomplished - * through the "recents" UI, accessible through the software-provided Recents key - * on the navigation or system bar. On devices with the older hardware button configuration - * the recents UI can be accessed with a long press on the Home key.

- * - *

When crossing from one task stack to another post-Android 3.0, - * the application should synthesize a back stack/history for the new task so that - * the user may navigate out of the new task and back to the Launcher by repeated - * presses of the back key. Back key presses should not navigate across task stacks.

- * - *

startActivities provides a mechanism for constructing a synthetic task stack of - * multiple activities. If the underlying API is not available on the system this method - * will return false.

- * - * @param context Start activities using this activity as the starting context - * @param intents Array of intents defining the activities that will be started. The element - * length-1 will correspond to the top activity on the resulting task stack. - * @param options Additional options for how the Activity should be started. - * See {@link Context#startActivity(Intent, Bundle) - * @return true if the underlying API was available and the call was successful, false otherwise - */ - public static boolean startActivities(Context context, Intent[] intents, - Bundle options) { - final int version = Build.VERSION.SDK_INT; - if (version >= 16) { - ContextCompatJellybean.startActivities(context, intents, options); - return true; - } else if (version >= 11) { - ContextCompatHoneycomb.startActivities(context, intents); - return true; - } - return false; - } - - /** - * Returns absolute paths to application-specific directories on all - * external storage devices where the application's OBB files (if there are - * any) can be found. Note if the application does not have any OBB files, - * these directories may not exist. - *

- * This is like {@link Context#getFilesDir()} in that these files will be - * deleted when the application is uninstalled, however there are some - * important differences: - *

    - *
  • External files are not always available: they will disappear if the - * user mounts the external storage on a computer or removes it. - *
  • There is no security enforced with these files. - *
- *

- * External storage devices returned here are considered a permanent part of - * the device, including both emulated external storage and physical media - * slots, such as SD cards in a battery compartment. The returned paths do - * not include transient devices, such as USB flash drives. - *

- * An application may store data on any or all of the returned devices. For - * example, an app may choose to store large files on the device with the - * most available space, as measured by {@link android.os.StatFs}. - *

- * Starting in {@link Build.VERSION_CODES#KITKAT}, no permissions - * are required to write to the returned paths; they're always accessible to - * the calling app. Before then, - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to - * write. Write access outside of these paths on secondary external storage - * devices is not available. To request external storage access in a - * backwards compatible way, consider using {@code android:maxSdkVersion} - * like this: - * - *

<uses-permission
-     *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-     *     android:maxSdkVersion="18" />
- *

- * The first path returned is the same as {@link Context#getObbDir()}. - * Returned paths may be {@code null} if a storage device is unavailable. - * - * @see Context#getObbDir() - * @see EnvironmentCompat#getStorageState(File) - */ - public static File[] getObbDirs(Context context) { - final int version = Build.VERSION.SDK_INT; - if (version >= 19) { - return ContextCompatKitKat.getObbDirs(context); - } else { - final File single; - if (version >= 11) { - single = ContextCompatHoneycomb.getObbDir(context); - } else { - single = buildPath(Environment.getExternalStorageDirectory(), DIR_ANDROID, DIR_OBB, - context.getPackageName()); - } - return new File[] { single }; - } - } - - /** - * Returns absolute paths to application-specific directories on all - * external storage devices where the application can place persistent files - * it owns. These files are internal to the application, and not typically - * visible to the user as media. - *

- * This is like {@link Context#getFilesDir()} in that these files will be - * deleted when the application is uninstalled, however there are some - * important differences: - *

    - *
  • External files are not always available: they will disappear if the - * user mounts the external storage on a computer or removes it. - *
  • There is no security enforced with these files. - *
- *

- * External storage devices returned here are considered a permanent part of - * the device, including both emulated external storage and physical media - * slots, such as SD cards in a battery compartment. The returned paths do - * not include transient devices, such as USB flash drives. - *

- * An application may store data on any or all of the returned devices. For - * example, an app may choose to store large files on the device with the - * most available space, as measured by {@link android.os.StatFs}. - *

- * Starting in {@link Build.VERSION_CODES#KITKAT}, no permissions - * are required to write to the returned paths; they're always accessible to - * the calling app. Before then, - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to - * write. Write access outside of these paths on secondary external storage - * devices is not available. To request external storage access in a - * backwards compatible way, consider using {@code android:maxSdkVersion} - * like this: - * - *

<uses-permission
-     *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-     *     android:maxSdkVersion="18" />
- *

- * The first path returned is the same as - * {@link Context#getExternalFilesDir(String)}. Returned paths may be - * {@code null} if a storage device is unavailable. - * - * @see Context#getExternalFilesDir(String) - * @see EnvironmentCompat#getStorageState(File) - */ - public static File[] getExternalFilesDirs(Context context, String type) { - final int version = Build.VERSION.SDK_INT; - if (version >= 19) { - return ContextCompatKitKat.getExternalFilesDirs(context, type); - } else { - final File single; - if (version >= 8) { - single = ContextCompatFroyo.getExternalFilesDir(context, type); - } else { - single = buildPath(Environment.getExternalStorageDirectory(), DIR_ANDROID, DIR_DATA, - context.getPackageName(), DIR_FILES, type); - } - return new File[] { single }; - } - } - - /** - * Returns absolute paths to application-specific directories on all - * external storage devices where the application can place cache files it - * owns. These files are internal to the application, and not typically - * visible to the user as media. - *

- * This is like {@link Context#getCacheDir()} in that these files will be - * deleted when the application is uninstalled, however there are some - * important differences: - *

    - *
  • External files are not always available: they will disappear if the - * user mounts the external storage on a computer or removes it. - *
  • There is no security enforced with these files. - *
- *

- * External storage devices returned here are considered a permanent part of - * the device, including both emulated external storage and physical media - * slots, such as SD cards in a battery compartment. The returned paths do - * not include transient devices, such as USB flash drives. - *

- * An application may store data on any or all of the returned devices. For - * example, an app may choose to store large files on the device with the - * most available space, as measured by {@link android.os.StatFs}. - *

- * Starting in {@link Build.VERSION_CODES#KITKAT}, no permissions - * are required to write to the returned paths; they're always accessible to - * the calling app. Before then, - * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to - * write. Write access outside of these paths on secondary external storage - * devices is not available. To request external storage access in a - * backwards compatible way, consider using {@code android:maxSdkVersion} - * like this: - * - *

<uses-permission
-     *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-     *     android:maxSdkVersion="18" />
- *

- * The first path returned is the same as - * {@link Context#getExternalCacheDir()}. Returned paths may be {@code null} - * if a storage device is unavailable. - * - * @see Context#getExternalCacheDir() - * @see EnvironmentCompat#getStorageState(File) - */ - public static File[] getExternalCacheDirs(Context context) { - final int version = Build.VERSION.SDK_INT; - if (version >= 19) { - return ContextCompatKitKat.getExternalCacheDirs(context); - } else { - final File single; - if (version >= 8) { - single = ContextCompatFroyo.getExternalCacheDir(context); - } else { - single = buildPath(Environment.getExternalStorageDirectory(), DIR_ANDROID, DIR_DATA, - context.getPackageName(), DIR_CACHE); - } - return new File[] { single }; - } - } - - private static File buildPath(File base, String... segments) { - File cur = base; - for (String segment : segments) { - if (cur == null) { - cur = new File(segment); - } else if (segment != null) { - cur = new File(cur, segment); - } - } - return cur; - } - - /** - * Return a drawable object associated with a particular resource ID. - *

- * Starting in {@link Build.VERSION_CODES#LOLLIPOP}, the returned - * drawable will be styled for the specified Context's theme. - * - * @param id The desired resource identifier, as generated by the aapt tool. - * This integer encodes the package, type, and resource entry. - * The value 0 is an invalid identifier. - * @return Drawable An object that can be used to draw this resource. - */ - public static final Drawable getDrawable(Context context, int id) { - final int version = Build.VERSION.SDK_INT; - if (version >= 21) { - return ContextCompatApi21.getDrawable(context, id); - } else { - return context.getResources().getDrawable(id); - } - } - - /** - * Returns a color state list associated with a particular resource ID. - *

- * Starting in {@link Build.VERSION_CODES#M}, the returned - * color state list will be styled for the specified Context's theme. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @return A color state list, or {@code null} if the resource could not be - * resolved. - * @throws android.content.res.Resources.NotFoundException if the given ID - * does not exist. - */ - public static final ColorStateList getColorStateList(Context context, int id) { - final int version = Build.VERSION.SDK_INT; - if (version >= 23) { - return ContextCompatApi23.getColorStateList(context, id); - } else { - return context.getResources().getColorStateList(id); - } - } - - /** - * Returns a color associated with a particular resource ID - *

- * Starting in {@link Build.VERSION_CODES#M}, the returned - * color will be styled for the specified Context's theme. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @return A single color value in the form 0xAARRGGBB. - * @throws android.content.res.Resources.NotFoundException if the given ID - * does not exist. - */ - public static final int getColor(Context context, int id) { - final int version = Build.VERSION.SDK_INT; - if (version >= 23) { - return ContextCompatApi23.getColor(context, id); - } else { - return context.getResources().getColor(id); - } - } - - /** - * Determine whether you have been granted a particular permission. - * - * @param permission The name of the permission being checked. - * - * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if you have the - * permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} if not. - * - * @see android.content.pm.PackageManager#checkPermission(String, String) - */ - public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) { - if (permission == null) { - throw new IllegalArgumentException("permission is null"); - } - - return context.checkPermission(permission, Process.myPid(), Process.myUid()); - } - - /** - * Returns the absolute path to the directory on the filesystem similar to - * {@link Context#getFilesDir()}. The difference is that files placed under this - * directory will be excluded from automatic backup to remote storage on - * devices running {@link Build.VERSION_CODES#LOLLIPOP} or later. See - * {@link android.app.backup.BackupAgent BackupAgent} for a full discussion - * of the automatic backup mechanism in Android. - * - *

No permissions are required to read or write to the returned path, since this - * path is internal storage. - * - * @return The path of the directory holding application files that will not be - * automatically backed up to remote storage. - * - * @see Context.getFilesDir - */ - public final File getNoBackupFilesDir(Context context) { - final int version = Build.VERSION.SDK_INT; - if (version >= 21) { - return ContextCompatApi21.getNoBackupFilesDir(context); - } else { - ApplicationInfo appInfo = context.getApplicationInfo(); - return createFilesDir(new File(appInfo.dataDir, "no_backup")); - } - } - - /** - * Returns the absolute path to the application specific cache directory on - * the filesystem designed for storing cached code. On devices running - * {@link Build.VERSION_CODES#LOLLIPOP} or later, the system will delete - * any files stored in this location both when your specific application is - * upgraded, and when the entire platform is upgraded. - *

- * This location is optimal for storing compiled or optimized code generated - * by your application at runtime. - *

- * Apps require no extra permissions to read or write to the returned path, - * since this path lives in their private storage. - * - * @return The path of the directory holding application code cache files. - */ - public static File getCodeCacheDir(Context context) { - final int version = Build.VERSION.SDK_INT; - if (version >= 21) { - return ContextCompatApi21.getCodeCacheDir(context); - } else { - ApplicationInfo appInfo = context.getApplicationInfo(); - return createFilesDir(new File(appInfo.dataDir, "code_cache")); - } - } - - private synchronized static File createFilesDir(File file) { - if (!file.exists()) { - if (!file.mkdirs()) { - if (file.exists()) { - // spurious failure; probably racing with another process for this app - return file; - } - Log.w(TAG, "Unable to create files subdir " + file.getPath()); - return null; - } - } - return file; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatApi21.java deleted file mode 100644 index 650e076..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatApi21.java +++ /dev/null @@ -1,36 +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 p.android.support.v4.content; - -import android.content.Context; -import android.graphics.drawable.Drawable; - -import java.io.File; - -class ContextCompatApi21 { - public static Drawable getDrawable(Context context, int id) { - return context.getDrawable(id); - } - - public static File getNoBackupFilesDir(Context context) { - return context.getNoBackupFilesDir(); - } - - public static File getCodeCacheDir(Context context) { - return context.getCodeCacheDir(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatApi23.java deleted file mode 100644 index 572005a..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatApi23.java +++ /dev/null @@ -1,30 +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 p.android.support.v4.content; - -import android.content.Context; -import android.content.res.ColorStateList; - -class ContextCompatApi23 { - public static ColorStateList getColorStateList(Context context, int id) { - return context.getColorStateList(id); - } - - public static int getColor(Context context, int id) { - return context.getColor(id); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatFroyo.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatFroyo.java deleted file mode 100644 index 0bd4c3d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatFroyo.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Context; - -import java.io.File; - -class ContextCompatFroyo { - public static File getExternalCacheDir(Context context) { - return context.getExternalCacheDir(); - } - - public static File getExternalFilesDir(Context context, String type) { - return context.getExternalFilesDir(type); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatHoneycomb.java deleted file mode 100644 index 512ebb1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatHoneycomb.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Context; -import android.content.Intent; - -import java.io.File; - -/** - * Implementation of context compatibility that can call Honeycomb APIs. - */ -class ContextCompatHoneycomb { - - static void startActivities(Context context, Intent[] intents) { - context.startActivities(intents); - } - - public static File getObbDir(Context context) { - return context.getObbDir(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatJellybean.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatJellybean.java deleted file mode 100644 index 57088a7..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatJellybean.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; - -class ContextCompatJellybean { - - public static void startActivities(Context context, Intent[] intents, Bundle options) { - context.startActivities(intents, options); - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatKitKat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatKitKat.java deleted file mode 100644 index bfac85b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ContextCompatKitKat.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Context; - -import java.io.File; - -class ContextCompatKitKat { - public static File[] getExternalCacheDirs(Context context) { - return context.getExternalCacheDirs(); - } - - public static File[] getExternalFilesDirs(Context context, String type) { - return context.getExternalFilesDirs(type); - } - - public static File[] getObbDirs(Context context) { - return context.getObbDirs(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/CursorLoader.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/CursorLoader.java deleted file mode 100644 index 0e61f78..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/CursorLoader.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import p.android.support.v4.os.CancellationSignal; -import p.android.support.v4.os.OperationCanceledException; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Arrays; - -/** - * Static library support version of the framework's {@link android.content.CursorLoader}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework SDK - * documentation for a class overview. - */ -public class CursorLoader extends AsyncTaskLoader { - final ForceLoadContentObserver mObserver; - - Uri mUri; - String[] mProjection; - String mSelection; - String[] mSelectionArgs; - String mSortOrder; - - Cursor mCursor; - CancellationSignal mCancellationSignal; - - /* Runs on a worker thread */ - @Override - public Cursor loadInBackground() { - synchronized (this) { - if (isLoadInBackgroundCanceled()) { - throw new OperationCanceledException(); - } - mCancellationSignal = new CancellationSignal(); - } - try { - Cursor cursor = ContentResolverCompat.query(getContext().getContentResolver(), - mUri, mProjection, mSelection, mSelectionArgs, mSortOrder, - mCancellationSignal); - if (cursor != null) { - try { - // Ensure the cursor window is filled. - cursor.getCount(); - cursor.registerContentObserver(mObserver); - } catch (RuntimeException ex) { - cursor.close(); - throw ex; - } - } - return cursor; - } finally { - synchronized (this) { - mCancellationSignal = null; - } - } - } - - @Override - public void cancelLoadInBackground() { - super.cancelLoadInBackground(); - - synchronized (this) { - if (mCancellationSignal != null) { - mCancellationSignal.cancel(); - } - } - } - - /* Runs on the UI thread */ - @Override - public void deliverResult(Cursor cursor) { - if (isReset()) { - // An async query came in while the loader is stopped - if (cursor != null) { - cursor.close(); - } - return; - } - Cursor oldCursor = mCursor; - mCursor = cursor; - - if (isStarted()) { - super.deliverResult(cursor); - } - - if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { - oldCursor.close(); - } - } - - /** - * Creates an empty unspecified CursorLoader. You must follow this with - * calls to {@link #setUri(Uri)}, {@link #setSelection(String)}, etc - * to specify the query to perform. - */ - public CursorLoader(Context context) { - super(context); - mObserver = new ForceLoadContentObserver(); - } - - /** - * Creates a fully-specified CursorLoader. See - * {@link ContentResolver#query(Uri, String[], String, String[], String) - * ContentResolver.query()} for documentation on the meaning of the - * parameters. These will be passed as-is to that call. - */ - public CursorLoader(Context context, Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { - super(context); - mObserver = new ForceLoadContentObserver(); - mUri = uri; - mProjection = projection; - mSelection = selection; - mSelectionArgs = selectionArgs; - mSortOrder = sortOrder; - } - - /** - * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks - * will be called on the UI thread. If a previous load has been completed and is still valid - * the result may be passed to the callbacks immediately. - * - * Must be called from the UI thread - */ - @Override - protected void onStartLoading() { - if (mCursor != null) { - deliverResult(mCursor); - } - if (takeContentChanged() || mCursor == null) { - forceLoad(); - } - } - - /** - * Must be called from the UI thread - */ - @Override - protected void onStopLoading() { - // Attempt to cancel the current load task if possible. - cancelLoad(); - } - - @Override - public void onCanceled(Cursor cursor) { - if (cursor != null && !cursor.isClosed()) { - cursor.close(); - } - } - - @Override - protected void onReset() { - super.onReset(); - - // Ensure the loader is stopped - onStopLoading(); - - if (mCursor != null && !mCursor.isClosed()) { - mCursor.close(); - } - mCursor = null; - } - - public Uri getUri() { - return mUri; - } - - public void setUri(Uri uri) { - mUri = uri; - } - - public String[] getProjection() { - return mProjection; - } - - public void setProjection(String[] projection) { - mProjection = projection; - } - - public String getSelection() { - return mSelection; - } - - public void setSelection(String selection) { - mSelection = selection; - } - - public String[] getSelectionArgs() { - return mSelectionArgs; - } - - public void setSelectionArgs(String[] selectionArgs) { - mSelectionArgs = selectionArgs; - } - - public String getSortOrder() { - return mSortOrder; - } - - public void setSortOrder(String sortOrder) { - mSortOrder = sortOrder; - } - - @Override - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - super.dump(prefix, fd, writer, args); - writer.print(prefix); writer.print("mUri="); writer.println(mUri); - writer.print(prefix); writer.print("mProjection="); - writer.println(Arrays.toString(mProjection)); - writer.print(prefix); writer.print("mSelection="); writer.println(mSelection); - writer.print(prefix); writer.print("mSelectionArgs="); - writer.println(Arrays.toString(mSelectionArgs)); - writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder); - writer.print(prefix); writer.print("mCursor="); writer.println(mCursor); - writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/EditorCompatGingerbread.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/EditorCompatGingerbread.java deleted file mode 100644 index 6e81b30..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/EditorCompatGingerbread.java +++ /dev/null @@ -1,33 +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 p.android.support.v4.content; - -import android.content.SharedPreferences; -import p.android.support.annotation.NonNull; - -class EditorCompatGingerbread { - public static void apply(@NonNull SharedPreferences.Editor editor) { - try { - editor.apply(); - } catch (AbstractMethodError unused) { - // The app injected its own pre-Gingerbread - // SharedPreferences.Editor implementation without - // an apply method. - editor.commit(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ExecutorCompatHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ExecutorCompatHoneycomb.java deleted file mode 100644 index 6c3a909..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ExecutorCompatHoneycomb.java +++ /dev/null @@ -1,31 +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 p.android.support.v4.content; - -import android.os.AsyncTask; - -import java.util.concurrent.Executor; - -/** - * Implementation of parallel executor compatibility that can call Honeycomb APIs. - * @hide - */ -class ExecutorCompatHoneycomb { - public static Executor getParallelExecutor() { - return AsyncTask.THREAD_POOL_EXECUTOR; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/FileProvider.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/FileProvider.java deleted file mode 100644 index 1f26591..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/FileProvider.java +++ /dev/null @@ -1,773 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; -import static org.xmlpull.v1.XmlPullParser.START_TAG; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ProviderInfo; -import android.content.res.XmlResourceParser; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.net.Uri; -import android.os.Environment; -import android.os.ParcelFileDescriptor; -import android.provider.OpenableColumns; -import android.text.TextUtils; -import android.webkit.MimeTypeMap; - -import org.xmlpull.v1.XmlPullParserException; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * FileProvider is a special subclass of {@link ContentProvider} that facilitates secure sharing - * of files associated with an app by creating a content:// {@link Uri} for a file - * instead of a file:/// {@link Uri}. - *

- * A content URI allows you to grant read and write access using - * temporary access permissions. When you create an {@link Intent} containing - * a content URI, in order to send the content URI - * to a client app, you can also call {@link Intent#setFlags(int) Intent.setFlags()} to add - * permissions. These permissions are available to the client app for as long as the stack for - * a receiving {@link android.app.Activity} is active. For an {@link Intent} going to a - * {@link android.app.Service}, the permissions are available as long as the - * {@link android.app.Service} is running. - *

- * In comparison, to control access to a file:/// {@link Uri} you have to modify the - * file system permissions of the underlying file. The permissions you provide become available to - * any app, and remain in effect until you change them. This level of access is - * fundamentally insecure. - *

- * The increased level of file access security offered by a content URI - * makes FileProvider a key part of Android's security infrastructure. - *

- * This overview of FileProvider includes the following topics: - *

- *
    - *
  1. Defining a FileProvider
  2. - *
  3. Specifying Available Files
  4. - *
  5. Retrieving the Content URI for a File
  6. - *
  7. Granting Temporary Permissions to a URI
  8. - *
  9. Serving a Content URI to Another App
  10. - *
- *

Defining a FileProvider

- *

- * Since the default functionality of FileProvider includes content URI generation for files, you - * don't need to define a subclass in code. Instead, you can include a FileProvider in your app - * by specifying it entirely in XML. To specify the FileProvider component itself, add a - * <provider> - * element to your app manifest. Set the android:name attribute to - * FileProvider. Set the android:authorities - * attribute to a URI authority based on a domain you control; for example, if you control the - * domain mydomain.com you should use the authority - * com.mydomain.fileprovider. Set the android:exported attribute to - * false; the FileProvider does not need to be public. Set the - * android:grantUriPermissions attribute to true, to allow you - * to grant temporary access to files. For example: - *

- *<manifest>
- *    ...
- *    <application>
- *        ...
- *        <provider
- *            android:name="FileProvider"
- *            android:authorities="com.mydomain.fileprovider"
- *            android:exported="false"
- *            android:grantUriPermissions="true">
- *            ...
- *        </provider>
- *        ...
- *    </application>
- *</manifest>
- *

- * If you want to override any of the default behavior of FileProvider methods, extend - * the FileProvider class and use the fully-qualified class name in the android:name - * attribute of the <provider> element. - *

Specifying Available Files

- * A FileProvider can only generate a content URI for files in directories that you specify - * beforehand. To specify a directory, specify the its storage area and path in XML, using child - * elements of the <paths> element. - * For example, the following paths element tells FileProvider that you intend to - * request content URIs for the images/ subdirectory of your private file area. - *
- *<paths xmlns:android="http://schemas.android.com/apk/res/android">
- *    <files-path name="my_images" path="images/"/>
- *    ...
- *</paths>
- *
- *

- * The <paths> element must contain one or more of the following child elements: - *

- *
- *
- *
- *<files-path name="name" path="path" />
- *
- *
- *
- * Represents files in the files/ subdirectory of your app's internal storage - * area. This subdirectory is the same as the value returned by {@link Context#getFilesDir() - * Context.getFilesDir()}. - *
- *
- *<external-path name="name" path="path" />
- *
- *
- *
- * Represents files in the root of your app's external storage area. The path - * {@link Context#getExternalFilesDir(String) Context.getExternalFilesDir()} returns the - * files/ subdirectory of this this root. - *
- *
- *
- *<cache-path name="name" path="path" />
- *
- *
- *
- * Represents files in the cache subdirectory of your app's internal storage area. The root path - * of this subdirectory is the same as the value returned by {@link Context#getCacheDir() - * getCacheDir()}. - *
- *
- *

- * These child elements all use the same attributes: - *

- *
- *
- * name="name" - *
- *
- * A URI path segment. To enforce security, this value hides the name of the subdirectory - * you're sharing. The subdirectory name for this value is contained in the - * path attribute. - *
- *
- * path="path" - *
- *
- * The subdirectory you're sharing. While the name attribute is a URI path - * segment, the path value is an actual subdirectory name. Notice that the - * value refers to a subdirectory, not an individual file or files. You can't - * share a single file by its file name, nor can you specify a subset of files using - * wildcards. - *
- *
- *

- * You must specify a child element of <paths> for each directory that contains - * files for which you want content URIs. For example, these XML elements specify two directories: - *

- *<paths xmlns:android="http://schemas.android.com/apk/res/android">
- *    <files-path name="my_images" path="images/"/>
- *    <files-path name="my_docs" path="docs/"/>
- *</paths>
- *
- *

- * Put the <paths> element and its children in an XML file in your project. - * For example, you can add them to a new file called res/xml/file_paths.xml. - * To link this file to the FileProvider, add a - * <meta-data> element - * as a child of the <provider> element that defines the FileProvider. Set the - * <meta-data> element's "android:name" attribute to - * android.support.FILE_PROVIDER_PATHS. Set the element's "android:resource" attribute - * to @xml/file_paths (notice that you don't specify the .xml - * extension). For example: - *

- *<provider
- *    android:name="FileProvider"
- *    android:authorities="com.mydomain.fileprovider"
- *    android:exported="false"
- *    android:grantUriPermissions="true">
- *    <meta-data
- *        android:name="android.support.FILE_PROVIDER_PATHS"
- *        android:resource="@xml/file_paths" />
- *</provider>
- *
- *

Generating the Content URI for a File

- *

- * To share a file with another app using a content URI, your app has to generate the content URI. - * To generate the content URI, create a new {@link File} for the file, then pass the {@link File} - * to {@link #getUriForFile(Context, String, File) getUriForFile()}. You can send the content URI - * returned by {@link #getUriForFile(Context, String, File) getUriForFile()} to another app in an - * {@link Intent}. The client app that receives the content URI can open the file - * and access its contents by calling - * {@link android.content.ContentResolver#openFileDescriptor(Uri, String) - * ContentResolver.openFileDescriptor} to get a {@link ParcelFileDescriptor}. - *

- * For example, suppose your app is offering files to other apps with a FileProvider that has the - * authority com.mydomain.fileprovider. To get a content URI for the file - * default_image.jpg in the images/ subdirectory of your internal storage - * add the following code: - *

- *File imagePath = new File(Context.getFilesDir(), "images");
- *File newFile = new File(imagePath, "default_image.jpg");
- *Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
- *
- * As a result of the previous snippet, - * {@link #getUriForFile(Context, String, File) getUriForFile()} returns the content URI - * content://com.mydomain.fileprovider/my_images/default_image.jpg. - *

Granting Temporary Permissions to a URI

- * To grant an access permission to a content URI returned from - * {@link #getUriForFile(Context, String, File) getUriForFile()}, do one of the following: - *
    - *
  • - * Call the method - * {@link Context#grantUriPermission(String, Uri, int) - * Context.grantUriPermission(package, Uri, mode_flags)} for the content:// - * {@link Uri}, using the desired mode flags. This grants temporary access permission for the - * content URI to the specified package, according to the value of the - * the mode_flags parameter, which you can set to - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}, {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION} - * or both. The permission remains in effect until you revoke it by calling - * {@link Context#revokeUriPermission(Uri, int) revokeUriPermission()} or until the device - * reboots. - *
  • - *
  • - * Put the content URI in an {@link Intent} by calling {@link Intent#setData(Uri) setData()}. - *
  • - *
  • - * Next, call the method {@link Intent#setFlags(int) Intent.setFlags()} with either - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION} or both. - *
  • - *
  • - * Finally, send the {@link Intent} to - * another app. Most often, you do this by calling - * {@link android.app.Activity#setResult(int, Intent) setResult()}. - *

    - * Permissions granted in an {@link Intent} remain in effect while the stack of the receiving - * {@link android.app.Activity} is active. When the stack finishes, the permissions are - * automatically removed. Permissions granted to one {@link android.app.Activity} in a client - * app are automatically extended to other components of that app. - *

    - *
  • - *
- *

Serving a Content URI to Another App

- *

- * There are a variety of ways to serve the content URI for a file to a client app. One common way - * is for the client app to start your app by calling - * {@link android.app.Activity#startActivityForResult(Intent, int, Bundle) startActivityResult()}, - * which sends an {@link Intent} to your app to start an {@link android.app.Activity} in your app. - * In response, your app can immediately return a content URI to the client app or present a user - * interface that allows the user to pick a file. In the latter case, once the user picks the file - * your app can return its content URI. In both cases, your app returns the content URI in an - * {@link Intent} sent via {@link android.app.Activity#setResult(int, Intent) setResult()}. - *

- *

- * You can also put the content URI in a {@link android.content.ClipData} object and then add the - * object to an {@link Intent} you send to a client app. To do this, call - * {@link Intent#setClipData(ClipData) Intent.setClipData()}. When you use this approach, you can - * add multiple {@link android.content.ClipData} objects to the {@link Intent}, each with its own - * content URI. When you call {@link Intent#setFlags(int) Intent.setFlags()} on the {@link Intent} - * to set temporary access permissions, the same permissions are applied to all of the content - * URIs. - *

- *

- * Note: The {@link Intent#setClipData(ClipData) Intent.setClipData()} method is - * only available in platform version 16 (Android 4.1) and later. If you want to maintain - * compatibility with previous versions, you should send one content URI at a time in the - * {@link Intent}. Set the action to {@link Intent#ACTION_SEND} and put the URI in data by calling - * {@link Intent#setData setData()}. - *

- *

More Information

- *

- * To learn more about FileProvider, see the Android training class - * Sharing Files Securely with URIs. - *

- */ -public class FileProvider extends ContentProvider { - private static final String[] COLUMNS = { - OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE }; - - private static final String - META_DATA_FILE_PROVIDER_PATHS = "android.support.FILE_PROVIDER_PATHS"; - - private static final String TAG_ROOT_PATH = "root-path"; - private static final String TAG_FILES_PATH = "files-path"; - private static final String TAG_CACHE_PATH = "cache-path"; - private static final String TAG_EXTERNAL = "external-path"; - - private static final String ATTR_NAME = "name"; - private static final String ATTR_PATH = "path"; - - private static final File DEVICE_ROOT = new File("/"); - - // @GuardedBy("sCache") - private static HashMap sCache = new HashMap(); - - private PathStrategy mStrategy; - - /** - * The default FileProvider implementation does not need to be initialized. If you want to - * override this method, you must provide your own subclass of FileProvider. - */ - @Override - public boolean onCreate() { - return true; - } - - /** - * After the FileProvider is instantiated, this method is called to provide the system with - * information about the provider. - * - * @param context A {@link Context} for the current component. - * @param info A {@link ProviderInfo} for the new provider. - */ - @Override - public void attachInfo(Context context, ProviderInfo info) { - super.attachInfo(context, info); - - // Sanity check our security - if (info.exported) { - throw new SecurityException("Provider must not be exported"); - } - if (!info.grantUriPermissions) { - throw new SecurityException("Provider must grant uri permissions"); - } - - mStrategy = getPathStrategy(context, info.authority); - } - - /** - * Return a content URI for a given {@link File}. Specific temporary - * permissions for the content URI can be set with - * {@link Context#grantUriPermission(String, Uri, int)}, or added - * to an {@link Intent} by calling {@link Intent#setData(Uri) setData()} and then - * {@link Intent#setFlags(int) setFlags()}; in both cases, the applicable flags are - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}. A FileProvider can only return a - * content {@link Uri} for file paths defined in their <paths> - * meta-data element. See the Class Overview for more information. - * - * @param context A {@link Context} for the current component. - * @param authority The authority of a {@link FileProvider} defined in a - * {@code <provider>} element in your app's manifest. - * @param file A {@link File} pointing to the filename for which you want a - * content {@link Uri}. - * @return A content URI for the file. - * @throws IllegalArgumentException When the given {@link File} is outside - * the paths supported by the provider. - */ - public static Uri getUriForFile(Context context, String authority, File file) { - final PathStrategy strategy = getPathStrategy(context, authority); - return strategy.getUriForFile(file); - } - - /** - * Use a content URI returned by - * {@link #getUriForFile(Context, String, File) getUriForFile()} to get information about a file - * managed by the FileProvider. - * FileProvider reports the column names defined in {@link OpenableColumns}: - *
    - *
  • {@link OpenableColumns#DISPLAY_NAME}
  • - *
  • {@link OpenableColumns#SIZE}
  • - *
- * For more information, see - * {@link ContentProvider#query(Uri, String[], String, String[], String) - * ContentProvider.query()}. - * - * @param uri A content URI returned by {@link #getUriForFile}. - * @param projection The list of columns to put into the {@link Cursor}. If null all columns are - * included. - * @param selection Selection criteria to apply. If null then all data that matches the content - * URI is returned. - * @param selectionArgs An array of {@link String}, containing arguments to bind to - * the selection parameter. The query method scans selection from left to - * right and iterates through selectionArgs, replacing the current "?" character in - * selection with the value at the current position in selectionArgs. The - * values are bound to selection as {@link String} values. - * @param sortOrder A {@link String} containing the column name(s) on which to sort - * the resulting {@link Cursor}. - * @return A {@link Cursor} containing the results of the query. - * - */ - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - // ContentProvider has already checked granted permissions - final File file = mStrategy.getFileForUri(uri); - - if (projection == null) { - projection = COLUMNS; - } - - String[] cols = new String[projection.length]; - Object[] values = new Object[projection.length]; - int i = 0; - for (String col : projection) { - if (OpenableColumns.DISPLAY_NAME.equals(col)) { - cols[i] = OpenableColumns.DISPLAY_NAME; - values[i++] = file.getName(); - } else if (OpenableColumns.SIZE.equals(col)) { - cols[i] = OpenableColumns.SIZE; - values[i++] = file.length(); - } - } - - cols = copyOf(cols, i); - values = copyOf(values, i); - - final MatrixCursor cursor = new MatrixCursor(cols, 1); - cursor.addRow(values); - return cursor; - } - - /** - * Returns the MIME type of a content URI returned by - * {@link #getUriForFile(Context, String, File) getUriForFile()}. - * - * @param uri A content URI returned by - * {@link #getUriForFile(Context, String, File) getUriForFile()}. - * @return If the associated file has an extension, the MIME type associated with that - * extension; otherwise application/octet-stream. - */ - @Override - public String getType(Uri uri) { - // ContentProvider has already checked granted permissions - final File file = mStrategy.getFileForUri(uri); - - final int lastDot = file.getName().lastIndexOf('.'); - if (lastDot >= 0) { - final String extension = file.getName().substring(lastDot + 1); - final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - if (mime != null) { - return mime; - } - } - - return "application/octet-stream"; - } - - /** - * By default, this method throws an {@link UnsupportedOperationException}. You must - * subclass FileProvider if you want to provide different functionality. - */ - @Override - public Uri insert(Uri uri, ContentValues values) { - throw new UnsupportedOperationException("No external inserts"); - } - - /** - * By default, this method throws an {@link UnsupportedOperationException}. You must - * subclass FileProvider if you want to provide different functionality. - */ - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException("No external updates"); - } - - /** - * Deletes the file associated with the specified content URI, as - * returned by {@link #getUriForFile(Context, String, File) getUriForFile()}. Notice that this - * method does not throw an {@link IOException}; you must check its return value. - * - * @param uri A content URI for a file, as returned by - * {@link #getUriForFile(Context, String, File) getUriForFile()}. - * @param selection Ignored. Set to {@code null}. - * @param selectionArgs Ignored. Set to {@code null}. - * @return 1 if the delete succeeds; otherwise, 0. - */ - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - // ContentProvider has already checked granted permissions - final File file = mStrategy.getFileForUri(uri); - return file.delete() ? 1 : 0; - } - - /** - * By default, FileProvider automatically returns the - * {@link ParcelFileDescriptor} for a file associated with a content:// - * {@link Uri}. To get the {@link ParcelFileDescriptor}, call - * {@link android.content.ContentResolver#openFileDescriptor(Uri, String) - * ContentResolver.openFileDescriptor}. - * - * To override this method, you must provide your own subclass of FileProvider. - * - * @param uri A content URI associated with a file, as returned by - * {@link #getUriForFile(Context, String, File) getUriForFile()}. - * @param mode Access mode for the file. May be "r" for read-only access, "rw" for read and - * write access, or "rwt" for read and write access that truncates any existing file. - * @return A new {@link ParcelFileDescriptor} with which you can access the file. - */ - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - // ContentProvider has already checked granted permissions - final File file = mStrategy.getFileForUri(uri); - final int fileMode = modeToMode(mode); - return ParcelFileDescriptor.open(file, fileMode); - } - - /** - * Return {@link PathStrategy} for given authority, either by parsing or - * returning from cache. - */ - private static PathStrategy getPathStrategy(Context context, String authority) { - PathStrategy strat; - synchronized (sCache) { - strat = sCache.get(authority); - if (strat == null) { - try { - strat = parsePathStrategy(context, authority); - } catch (IOException e) { - throw new IllegalArgumentException( - "Failed to parse " + META_DATA_FILE_PROVIDER_PATHS + " meta-data", e); - } catch (XmlPullParserException e) { - throw new IllegalArgumentException( - "Failed to parse " + META_DATA_FILE_PROVIDER_PATHS + " meta-data", e); - } - sCache.put(authority, strat); - } - } - return strat; - } - - /** - * Parse and return {@link PathStrategy} for given authority as defined in - * {@link #META_DATA_FILE_PROVIDER_PATHS} {@code <meta-data>}. - * - * @see #getPathStrategy(Context, String) - */ - private static PathStrategy parsePathStrategy(Context context, String authority) - throws IOException, XmlPullParserException { - final SimplePathStrategy strat = new SimplePathStrategy(authority); - - final ProviderInfo info = context.getPackageManager() - .resolveContentProvider(authority, PackageManager.GET_META_DATA); - final XmlResourceParser in = info.loadXmlMetaData( - context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS); - if (in == null) { - throw new IllegalArgumentException( - "Missing " + META_DATA_FILE_PROVIDER_PATHS + " meta-data"); - } - - int type; - while ((type = in.next()) != END_DOCUMENT) { - if (type == START_TAG) { - final String tag = in.getName(); - - final String name = in.getAttributeValue(null, ATTR_NAME); - String path = in.getAttributeValue(null, ATTR_PATH); - - File target = null; - if (TAG_ROOT_PATH.equals(tag)) { - target = buildPath(DEVICE_ROOT, path); - } else if (TAG_FILES_PATH.equals(tag)) { - target = buildPath(context.getFilesDir(), path); - } else if (TAG_CACHE_PATH.equals(tag)) { - target = buildPath(context.getCacheDir(), path); - } else if (TAG_EXTERNAL.equals(tag)) { - target = buildPath(Environment.getExternalStorageDirectory(), path); - } - - if (target != null) { - strat.addRoot(name, target); - } - } - } - - return strat; - } - - /** - * Strategy for mapping between {@link File} and {@link Uri}. - *

- * Strategies must be symmetric so that mapping a {@link File} to a - * {@link Uri} and then back to a {@link File} points at the original - * target. - *

- * Strategies must remain consistent across app launches, and not rely on - * dynamic state. This ensures that any generated {@link Uri} can still be - * resolved if your process is killed and later restarted. - * - * @see SimplePathStrategy - */ - interface PathStrategy { - /** - * Return a {@link Uri} that represents the given {@link File}. - */ - public Uri getUriForFile(File file); - - /** - * Return a {@link File} that represents the given {@link Uri}. - */ - public File getFileForUri(Uri uri); - } - - /** - * Strategy that provides access to files living under a narrow whitelist of - * filesystem roots. It will throw {@link SecurityException} if callers try - * accessing files outside the configured roots. - *

- * For example, if configured with - * {@code addRoot("myfiles", context.getFilesDir())}, then - * {@code context.getFileStreamPath("foo.txt")} would map to - * {@code content://myauthority/myfiles/foo.txt}. - */ - static class SimplePathStrategy implements PathStrategy { - private final String mAuthority; - private final HashMap mRoots = new HashMap(); - - public SimplePathStrategy(String authority) { - mAuthority = authority; - } - - /** - * Add a mapping from a name to a filesystem root. The provider only offers - * access to files that live under configured roots. - */ - public void addRoot(String name, File root) { - if (TextUtils.isEmpty(name)) { - throw new IllegalArgumentException("Name must not be empty"); - } - - try { - // Resolve to canonical path to keep path checking fast - root = root.getCanonicalFile(); - } catch (IOException e) { - throw new IllegalArgumentException( - "Failed to resolve canonical path for " + root, e); - } - - mRoots.put(name, root); - } - - @Override - public Uri getUriForFile(File file) { - String path; - try { - path = file.getCanonicalPath(); - } catch (IOException e) { - throw new IllegalArgumentException("Failed to resolve canonical path for " + file); - } - - // Find the most-specific root path - Map.Entry mostSpecific = null; - for (Map.Entry root : mRoots.entrySet()) { - final String rootPath = root.getValue().getPath(); - if (path.startsWith(rootPath) && (mostSpecific == null - || rootPath.length() > mostSpecific.getValue().getPath().length())) { - mostSpecific = root; - } - } - - if (mostSpecific == null) { - throw new IllegalArgumentException( - "Failed to find configured root that contains " + path); - } - - // Start at first char of path under root - final String rootPath = mostSpecific.getValue().getPath(); - if (rootPath.endsWith("/")) { - path = path.substring(rootPath.length()); - } else { - path = path.substring(rootPath.length() + 1); - } - - // Encode the tag and path separately - path = Uri.encode(mostSpecific.getKey()) + '/' + Uri.encode(path, "/"); - return new Uri.Builder().scheme("content") - .authority(mAuthority).encodedPath(path).build(); - } - - @Override - public File getFileForUri(Uri uri) { - String path = uri.getEncodedPath(); - - final int splitIndex = path.indexOf('/', 1); - final String tag = Uri.decode(path.substring(1, splitIndex)); - path = Uri.decode(path.substring(splitIndex + 1)); - - final File root = mRoots.get(tag); - if (root == null) { - throw new IllegalArgumentException("Unable to find configured root for " + uri); - } - - File file = new File(root, path); - try { - file = file.getCanonicalFile(); - } catch (IOException e) { - throw new IllegalArgumentException("Failed to resolve canonical path for " + file); - } - - if (!file.getPath().startsWith(root.getPath())) { - throw new SecurityException("Resolved path jumped beyond configured root"); - } - - return file; - } - } - - /** - * Copied from ContentResolver.java - */ - private static int modeToMode(String mode) { - int modeBits; - if ("r".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_ONLY; - } else if ("w".equals(mode) || "wt".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY - | ParcelFileDescriptor.MODE_CREATE - | ParcelFileDescriptor.MODE_TRUNCATE; - } else if ("wa".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY - | ParcelFileDescriptor.MODE_CREATE - | ParcelFileDescriptor.MODE_APPEND; - } else if ("rw".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_WRITE - | ParcelFileDescriptor.MODE_CREATE; - } else if ("rwt".equals(mode)) { - modeBits = ParcelFileDescriptor.MODE_READ_WRITE - | ParcelFileDescriptor.MODE_CREATE - | ParcelFileDescriptor.MODE_TRUNCATE; - } else { - throw new IllegalArgumentException("Invalid mode: " + mode); - } - return modeBits; - } - - private static File buildPath(File base, String... segments) { - File cur = base; - for (String segment : segments) { - if (segment != null) { - cur = new File(cur, segment); - } - } - return cur; - } - - private static String[] copyOf(String[] original, int newLength) { - final String[] result = new String[newLength]; - System.arraycopy(original, 0, result, 0, newLength); - return result; - } - - private static Object[] copyOf(Object[] original, int newLength) { - final Object[] result = new Object[newLength]; - System.arraycopy(original, 0, result, 0, newLength); - return result; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompat.java deleted file mode 100644 index c15a970..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompat.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.os.Build; - -/** - * Helper for accessing features in {@link Intent} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class IntentCompat { - - interface IntentCompatImpl { - Intent makeMainActivity(ComponentName componentName); - Intent makeMainSelectorActivity(String selectorAction, String selectorCategory); - Intent makeRestartActivityTask(ComponentName mainActivity); - } - - static class IntentCompatImplBase implements IntentCompatImpl { - @Override - public Intent makeMainActivity(ComponentName componentName) { - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setComponent(componentName); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - return intent; - } - - @Override - public Intent makeMainSelectorActivity(String selectorAction, - String selectorCategory) { - // Before api 15 you couldn't set a selector intent. - // Fall back and just return an intent with the requested action/category, - // even though it won't be a proper "main" intent. - Intent intent = new Intent(selectorAction); - intent.addCategory(selectorCategory); - return intent; - } - - @Override - public Intent makeRestartActivityTask(ComponentName mainActivity) { - Intent intent = makeMainActivity(mainActivity); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK); - return intent; - } - } - - static class IntentCompatImplHC extends IntentCompatImplBase { - @Override - public Intent makeMainActivity(ComponentName componentName) { - return IntentCompatHoneycomb.makeMainActivity(componentName); - } - @Override - public Intent makeRestartActivityTask(ComponentName componentName) { - return IntentCompatHoneycomb.makeRestartActivityTask(componentName); - } - } - - static class IntentCompatImplIcsMr1 extends IntentCompatImplHC { - @Override - public Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) { - return IntentCompatIcsMr1.makeMainSelectorActivity(selectorAction, selectorCategory); - } - } - - private static final IntentCompatImpl IMPL; - static { - final int version = Build.VERSION.SDK_INT; - if (version >= 15) { - IMPL = new IntentCompatImplIcsMr1(); - } else if (version >= 11) { - IMPL = new IntentCompatImplHC(); - } else { - IMPL = new IntentCompatImplBase(); - } - } - - private IntentCompat() { - /* Hide constructor */ - } - - /** - * Broadcast Action: Resources for a set of packages (which were - * previously unavailable) are currently - * available since the media on which they exist is available. - * The extra data {@link #EXTRA_CHANGED_PACKAGE_LIST} contains a - * list of packages whose availability changed. - * The extra data {@link #EXTRA_CHANGED_UID_LIST} contains a - * list of uids of packages whose availability changed. - * Note that the - * packages in this list do not receive this broadcast. - * The specified set of packages are now available on the system. - *

Includes the following extras: - *

    - *
  • {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages - * whose resources(were previously unavailable) are currently available. - * {@link #EXTRA_CHANGED_UID_LIST} is the set of uids of the - * packages whose resources(were previously unavailable) - * are currently available. - *
- * - *

This is a protected intent that can only be sent - * by the system. - */ - public static final String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = - "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE"; - - /** - * Broadcast Action: Resources for a set of packages are currently - * unavailable since the media on which they exist is unavailable. - * The extra data {@link #EXTRA_CHANGED_PACKAGE_LIST} contains a - * list of packages whose availability changed. - * The extra data {@link #EXTRA_CHANGED_UID_LIST} contains a - * list of uids of packages whose availability changed. - * The specified set of packages can no longer be - * launched and are practically unavailable on the system. - *

Inclues the following extras: - *

    - *
  • {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages - * whose resources are no longer available. - * {@link #EXTRA_CHANGED_UID_LIST} is the set of packages - * whose resources are no longer available. - *
- * - *

This is a protected intent that can only be sent - * by the system. - */ - public static final String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = - "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE"; - - /** - * This field is part of - * {@link Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE}, - * {@link Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE} - * and contains a string array of all of the components that have changed. - */ - public static final String EXTRA_CHANGED_PACKAGE_LIST = - "android.intent.extra.changed_package_list"; - - /** - * This field is part of - * {@link Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE}, - * {@link Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE} - * and contains an integer array of uids of all of the components - * that have changed. - */ - public static final String EXTRA_CHANGED_UID_LIST = - "android.intent.extra.changed_uid_list"; - - /** - * A constant String that is associated with the Intent, used with - * {@link Intent#ACTION_SEND} to supply an alternative to - * {@link Intent#EXTRA_TEXT} - * as HTML formatted text. Note that you must also supply - * {@link Intent#EXTRA_TEXT}. - */ - public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT"; - - /** - * Indicates an activity optimized for Leanback mode, and that should - * be displayed in the Leanback launcher. - */ - public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER"; - - /** - * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, - * this flag will cause a newly launching task to be placed on top of the current - * home activity task (if there is one). That is, pressing back from the task - * will always return the user to home even if that was not the last activity they - * saw. This can only be used in conjunction with - * {@link Intent#FLAG_ACTIVITY_NEW_TASK}. - */ - public static final int FLAG_ACTIVITY_TASK_ON_HOME = 0x00004000; - - /** - * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, - * this flag will cause any existing task that would be associated with the - * activity to be cleared before the activity is started. That is, the activity - * becomes the new root of an otherwise empty task, and any old activities - * are finished. This can only be used in conjunction with - * {@link Intent#FLAG_ACTIVITY_NEW_TASK}. - * - *

This flag will only be obeyed on devices supporting API 11 or higher.

- */ - public static final int FLAG_ACTIVITY_CLEAR_TASK = 0x00008000; - - /** - * Create an intent to launch the main (root) activity of a task. This - * is the Intent that is started when the application's is launched from - * Home. For anything else that wants to launch an application in the - * same way, it is important that they use an Intent structured the same - * way, and can use this function to ensure this is the case. - * - *

The returned Intent has the given Activity component as its explicit - * component, {@link Intent#ACTION_MAIN ACTION_MAIN} as its action, and includes the - * category {@link Intent#CATEGORY_LAUNCHER CATEGORY_LAUNCHER}. This does not have - * {@link Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} set, - * though typically you will want to do that through {@link Intent#addFlags(int) addFlags(int)} - * on the returned Intent. - * - * @param mainActivity The main activity component that this Intent will - * launch. - * @return Returns a newly created Intent that can be used to launch the - * activity as a main application entry. - * - * @see Intent#setClass - * @see Intent#setComponent - */ - public static Intent makeMainActivity(ComponentName mainActivity) { - return IMPL.makeMainActivity(mainActivity); - } - - - /** - * Make an Intent for the main activity of an application, without - * specifying a specific activity to run but giving a selector to find - * the activity. This results in a final Intent that is structured - * the same as when the application is launched from - * Home. For anything else that wants to launch an application in the - * same way, it is important that they use an Intent structured the same - * way, and can use this function to ensure this is the case. - * - *

The returned Intent has {@link Intent#ACTION_MAIN} as its action, and includes the - * category {@link Intent#CATEGORY_LAUNCHER}. This does not have - * {@link Intent#FLAG_ACTIVITY_NEW_TASK} set, though typically you will want - * to do that through {@link Intent#addFlags(int)} on the returned Intent. - * - * @param selectorAction The action name of the Intent's selector. - * @param selectorCategory The name of a category to add to the Intent's - * selector. - * @return Returns a newly created Intent that can be used to launch the - * activity as a main application entry. - * - * @see #setSelector(Intent) - */ - public static Intent makeMainSelectorActivity(String selectorAction, - String selectorCategory) { - return IMPL.makeMainSelectorActivity(selectorAction, selectorCategory); - } - - /** - * Make an Intent that can be used to re-launch an application's task - * in its base state. This is like {@link #makeMainActivity(ComponentName)}, - * but also sets the flags {@link Intent#FLAG_ACTIVITY_NEW_TASK} and - * {@link IntentCompat#FLAG_ACTIVITY_CLEAR_TASK}. - * - * @param mainActivity The activity component that is the root of the - * task; this is the activity that has been published in the application's - * manifest as the main launcher icon. - * - * @return Returns a newly created Intent that can be used to relaunch the - * activity's task in its root state. - */ - public static Intent makeRestartActivityTask(ComponentName mainActivity) { - return IMPL.makeRestartActivityTask(mainActivity); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompatHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompatHoneycomb.java deleted file mode 100644 index a0a7ec6..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompatHoneycomb.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.ComponentName; -import android.content.Intent; - -class IntentCompatHoneycomb { - public static Intent makeMainActivity(ComponentName mainActivity) { - return Intent.makeMainActivity(mainActivity); - } - - public static Intent makeRestartActivityTask(ComponentName mainActivity) { - return Intent.makeRestartActivityTask(mainActivity); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompatIcsMr1.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompatIcsMr1.java deleted file mode 100644 index 365f728..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/IntentCompatIcsMr1.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Intent; - -class IntentCompatIcsMr1 { - - public static Intent makeMainSelectorActivity(String selectorAction, String selectorCategory) { - return Intent.makeMainSelectorActivity(selectorAction, selectorCategory); - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/Loader.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/Loader.java deleted file mode 100644 index 26b6fc0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/Loader.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.Context; -import android.database.ContentObserver; -import android.os.Handler; -import p.android.support.v4.app.LoaderManager; -import p.android.support.v4.util.DebugUtils; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Static library support version of the framework's {@link android.content.Loader}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework SDK - * documentation for a class overview. - */ -public class Loader { - int mId; - OnLoadCompleteListener mListener; - OnLoadCanceledListener mOnLoadCanceledListener; - Context mContext; - boolean mStarted = false; - boolean mAbandoned = false; - boolean mReset = true; - boolean mContentChanged = false; - boolean mProcessingChange = false; - - /** - * An implementation of a ContentObserver that takes care of connecting - * it to the Loader to have the loader re-load its data when the observer - * is told it has changed. You do not normally need to use this yourself; - * it is used for you by {@link CursorLoader} to take care of executing - * an update when the cursor's backing data changes. - */ - public final class ForceLoadContentObserver extends ContentObserver { - public ForceLoadContentObserver() { - super(new Handler()); - } - - @Override - public boolean deliverSelfNotifications() { - return true; - } - - @Override - public void onChange(boolean selfChange) { - onContentChanged(); - } - } - - /** - * Interface that is implemented to discover when a Loader has finished - * loading its data. You do not normally need to implement this yourself; - * it is used in the implementation of {@link LoaderManager} - * to find out when a Loader it is managing has completed so that this can - * be reported to its client. This interface should only be used if a - * Loader is not being used in conjunction with LoaderManager. - */ - public interface OnLoadCompleteListener { - /** - * Called on the thread that created the Loader when the load is complete. - * - * @param loader the loader that completed the load - * @param data the result of the load - */ - public void onLoadComplete(Loader loader, D data); - } - - /** - * Interface that is implemented to discover when a Loader has been canceled - * before it finished loading its data. You do not normally need to implement - * this yourself; it is used in the implementation of {@link LoaderManager} - * to find out when a Loader it is managing has been canceled so that it - * can schedule the next Loader. This interface should only be used if a - * Loader is not being used in conjunction with LoaderManager. - */ - public interface OnLoadCanceledListener { - /** - * Called on the thread that created the Loader when the load is canceled. - * - * @param loader the loader that canceled the load - */ - public void onLoadCanceled(Loader loader); - } - - /** - * Stores away the application context associated with context. - * Since Loaders can be used across multiple activities it's dangerous to - * store the context directly; always use {@link #getContext()} to retrieve - * the Loader's Context, don't use the constructor argument directly. - * The Context returned by {@link #getContext} is safe to use across - * Activity instances. - * - * @param context used to retrieve the application context. - */ - public Loader(Context context) { - mContext = context.getApplicationContext(); - } - - /** - * Sends the result of the load to the registered listener. Should only be called by subclasses. - * - * Must be called from the process's main thread. - * - * @param data the result of the load - */ - public void deliverResult(D data) { - if (mListener != null) { - mListener.onLoadComplete(this, data); - } - } - - /** - * Informs the registered {@link OnLoadCanceledListener} that the load has been canceled. - * Should only be called by subclasses. - * - * Must be called from the process's main thread. - */ - public void deliverCancellation() { - if (mOnLoadCanceledListener != null) { - mOnLoadCanceledListener.onLoadCanceled(this); - } - } - - /** - * @return an application context retrieved from the Context passed to the constructor. - */ - public Context getContext() { - return mContext; - } - - /** - * @return the ID of this loader - */ - public int getId() { - return mId; - } - - /** - * Registers a class that will receive callbacks when a load is complete. - * The callback will be called on the process's main thread so it's safe to - * pass the results to widgets. - * - *

Must be called from the process's main thread. - */ - public void registerListener(int id, OnLoadCompleteListener listener) { - if (mListener != null) { - throw new IllegalStateException("There is already a listener registered"); - } - mListener = listener; - mId = id; - } - - /** - * Remove a listener that was previously added with {@link #registerListener}. - * - * Must be called from the process's main thread. - */ - public void unregisterListener(OnLoadCompleteListener listener) { - if (mListener == null) { - throw new IllegalStateException("No listener register"); - } - if (mListener != listener) { - throw new IllegalArgumentException("Attempting to unregister the wrong listener"); - } - mListener = null; - } - - /** - * Registers a listener that will receive callbacks when a load is canceled. - * The callback will be called on the process's main thread so it's safe to - * pass the results to widgets. - * - * Must be called from the process's main thread. - * - * @param listener The listener to register. - */ - public void registerOnLoadCanceledListener(OnLoadCanceledListener listener) { - if (mOnLoadCanceledListener != null) { - throw new IllegalStateException("There is already a listener registered"); - } - mOnLoadCanceledListener = listener; - } - - /** - * Unregisters a listener that was previously added with - * {@link #registerOnLoadCanceledListener}. - * - * Must be called from the process's main thread. - * - * @param listener The listener to unregister. - */ - public void unregisterOnLoadCanceledListener(OnLoadCanceledListener listener) { - if (mOnLoadCanceledListener == null) { - throw new IllegalStateException("No listener register"); - } - if (mOnLoadCanceledListener != listener) { - throw new IllegalArgumentException("Attempting to unregister the wrong listener"); - } - mOnLoadCanceledListener = null; - } - - /** - * Return whether this load has been started. That is, its {@link #startLoading()} - * has been called and no calls to {@link #stopLoading()} or - * {@link #reset()} have yet been made. - */ - public boolean isStarted() { - return mStarted; - } - - /** - * Return whether this loader has been abandoned. In this state, the - * loader must not report any new data, and must keep - * its last reported data valid until it is finally reset. - */ - public boolean isAbandoned() { - return mAbandoned; - } - - /** - * Return whether this load has been reset. That is, either the loader - * has not yet been started for the first time, or its {@link #reset()} - * has been called. - */ - public boolean isReset() { - return mReset; - } - - /** - * This function will normally be called for you automatically by - * {@link LoaderManager} when the associated fragment/activity - * is being started. When using a Loader with {@link LoaderManager}, - * you must not call this method yourself, or you will conflict - * with its management of the Loader. - * - * Starts an asynchronous load of the Loader's data. When the result - * is ready the callbacks will be called on the process's main thread. - * If a previous load has been completed and is still valid - * the result may be passed to the callbacks immediately. - * The loader will monitor the source of - * the data set and may deliver future callbacks if the source changes. - * Calling {@link #stopLoading} will stop the delivery of callbacks. - * - *

This updates the Loader's internal state so that - * {@link #isStarted()} and {@link #isReset()} will return the correct - * values, and then calls the implementation's {@link #onStartLoading()}. - * - *

Must be called from the process's main thread. - */ - public final void startLoading() { - mStarted = true; - mReset = false; - mAbandoned = false; - onStartLoading(); - } - - /** - * Subclasses must implement this to take care of loading their data, - * as per {@link #startLoading()}. This is not called by clients directly, - * but as a result of a call to {@link #startLoading()}. - */ - protected void onStartLoading() { - } - - /** - * Attempt to cancel the current load task. - * Must be called on the main thread of the process. - * - *

Cancellation is not an immediate operation, since the load is performed - * in a background thread. If there is currently a load in progress, this - * method requests that the load be canceled, and notes this is the case; - * once the background thread has completed its work its remaining state - * will be cleared. If another load request comes in during this time, - * it will be held until the canceled load is complete. - * - * @return Returns false if the task could not be canceled, - * typically because it has already completed normally, or - * because {@link #startLoading()} hasn't been called; returns - * true otherwise. When true is returned, the task - * is still running and the {@link OnLoadCanceledListener} will be called - * when the task completes. - */ - public boolean cancelLoad() { - return onCancelLoad(); - } - - /** - * Subclasses must implement this to take care of requests to {@link #cancelLoad()}. - * This will always be called from the process's main thread. - * - * @return Returns false if the task could not be canceled, - * typically because it has already completed normally, or - * because {@link #startLoading()} hasn't been called; returns - * true otherwise. When true is returned, the task - * is still running and the {@link OnLoadCanceledListener} will be called - * when the task completes. - */ - protected boolean onCancelLoad() { - return false; - } - - /** - * Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously - * loaded data set and load a new one. This simply calls through to the - * implementation's {@link #onForceLoad()}. You generally should only call this - * when the loader is started -- that is, {@link #isStarted()} returns true. - * - *

Must be called from the process's main thread. - */ - public void forceLoad() { - onForceLoad(); - } - - /** - * Subclasses must implement this to take care of requests to {@link #forceLoad()}. - * This will always be called from the process's main thread. - */ - protected void onForceLoad() { - } - - /** - * This function will normally be called for you automatically by - * {@link LoaderManager} when the associated fragment/activity - * is being stopped. When using a Loader with {@link LoaderManager}, - * you must not call this method yourself, or you will conflict - * with its management of the Loader. - * - *

Stops delivery of updates until the next time {@link #startLoading()} is called. - * Implementations should not invalidate their data at this point -- - * clients are still free to use the last data the loader reported. They will, - * however, typically stop reporting new data if the data changes; they can - * still monitor for changes, but must not report them to the client until and - * if {@link #startLoading()} is later called. - * - *

This updates the Loader's internal state so that - * {@link #isStarted()} will return the correct - * value, and then calls the implementation's {@link #onStopLoading()}. - * - *

Must be called from the process's main thread. - */ - public void stopLoading() { - mStarted = false; - onStopLoading(); - } - - /** - * Subclasses must implement this to take care of stopping their loader, - * as per {@link #stopLoading()}. This is not called by clients directly, - * but as a result of a call to {@link #stopLoading()}. - * This will always be called from the process's main thread. - */ - protected void onStopLoading() { - } - - /** - * This function will normally be called for you automatically by - * {@link LoaderManager} when restarting a Loader. When using - * a Loader with {@link LoaderManager}, - * you must not call this method yourself, or you will conflict - * with its management of the Loader. - * - * Tell the Loader that it is being abandoned. This is called prior - * to {@link #reset} to have it retain its current data but not report - * any new data. - */ - public void abandon() { - mAbandoned = true; - onAbandon(); - } - - /** - * Subclasses implement this to take care of being abandoned. This is - * an optional intermediate state prior to {@link #onReset()} -- it means that - * the client is no longer interested in any new data from the loader, - * so the loader must not report any further updates. However, the - * loader must keep its last reported data valid until the final - * {@link #onReset()} happens. You can retrieve the current abandoned - * state with {@link #isAbandoned}. - */ - protected void onAbandon() { - } - - /** - * This function will normally be called for you automatically by - * {@link LoaderManager} when destroying a Loader. When using - * a Loader with {@link LoaderManager}, - * you must not call this method yourself, or you will conflict - * with its management of the Loader. - * - * Resets the state of the Loader. The Loader should at this point free - * all of its resources, since it may never be called again; however, its - * {@link #startLoading()} may later be called at which point it must be - * able to start running again. - * - *

This updates the Loader's internal state so that - * {@link #isStarted()} and {@link #isReset()} will return the correct - * values, and then calls the implementation's {@link #onReset()}. - * - *

Must be called from the process's main thread. - */ - public void reset() { - onReset(); - mReset = true; - mStarted = false; - mAbandoned = false; - mContentChanged = false; - mProcessingChange = false; - } - - /** - * Subclasses must implement this to take care of resetting their loader, - * as per {@link #reset()}. This is not called by clients directly, - * but as a result of a call to {@link #reset()}. - * This will always be called from the process's main thread. - */ - protected void onReset() { - } - - /** - * Take the current flag indicating whether the loader's content had - * changed while it was stopped. If it had, true is returned and the - * flag is cleared. - */ - public boolean takeContentChanged() { - boolean res = mContentChanged; - mContentChanged = false; - mProcessingChange |= res; - return res; - } - - /** - * Commit that you have actually fully processed a content change that - * was returned by {@link #takeContentChanged}. This is for use with - * {@link #rollbackContentChanged()} to handle situations where a load - * is cancelled. Call this when you have completely processed a load - * without it being cancelled. - */ - public void commitContentChanged() { - mProcessingChange = false; - } - - /** - * Report that you have abandoned the processing of a content change that - * was returned by {@link #takeContentChanged()} and would like to rollback - * to the state where there is again a pending content change. This is - * to handle the case where a data load due to a content change has been - * canceled before its data was delivered back to the loader. - */ - public void rollbackContentChanged() { - if (mProcessingChange) { - mContentChanged = true; - } - } - - /** - * Called when {@link ForceLoadContentObserver} detects a change. The - * default implementation checks to see if the loader is currently started; - * if so, it simply calls {@link #forceLoad()}; otherwise, it sets a flag - * so that {@link #takeContentChanged()} returns true. - * - *

Must be called from the process's main thread. - */ - public void onContentChanged() { - if (mStarted) { - forceLoad(); - } else { - // This loader has been stopped, so we don't want to load - // new data right now... but keep track of it changing to - // refresh later if we start again. - mContentChanged = true; - } - } - - /** - * For debugging, converts an instance of the Loader's data class to - * a string that can be printed. Must handle a null data. - */ - public String dataToString(D data) { - StringBuilder sb = new StringBuilder(64); - DebugUtils.buildShortClassTag(data, sb); - sb.append("}"); - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - DebugUtils.buildShortClassTag(this, sb); - sb.append(" id="); - sb.append(mId); - sb.append("}"); - return sb.toString(); - } - - /** - * Print the Loader's state into the given stream. - * - * @param prefix Text to print at the front of each line. - * @param fd The raw file descriptor that the dump is being sent to. - * @param writer A PrintWriter to which the dump is to be set. - * @param args Additional arguments to the dump request. - */ - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - writer.print(prefix); writer.print("mId="); writer.print(mId); - writer.print(" mListener="); writer.println(mListener); - if (mStarted || mContentChanged || mProcessingChange) { - writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); - writer.print(" mContentChanged="); writer.print(mContentChanged); - writer.print(" mProcessingChange="); writer.println(mProcessingChange); - } - if (mAbandoned || mReset) { - writer.print(prefix); writer.print("mAbandoned="); writer.print(mAbandoned); - writer.print(" mReset="); writer.println(mReset); - } - } -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/LocalBroadcastManager.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/LocalBroadcastManager.java deleted file mode 100644 index 203a25f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/LocalBroadcastManager.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Set; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.Uri; -import android.os.Handler; -import android.os.Message; -import android.util.Log; - -/** - * Helper to register for and send broadcasts of Intents to local objects - * within your process. This is has a number of advantages over sending - * global broadcasts with {@link Context#sendBroadcast}: - *

    - *
  • You know that the data you are broadcasting won't leave your app, so - * don't need to worry about leaking private data. - *
  • It is not possible for other applications to send these broadcasts to - * your app, so you don't need to worry about having security holes they can - * exploit. - *
  • It is more efficient than sending a global broadcast through the - * system. - *
- */ -public final class LocalBroadcastManager { - private static class ReceiverRecord { - final IntentFilter filter; - final BroadcastReceiver receiver; - boolean broadcasting; - - ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) { - filter = _filter; - receiver = _receiver; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(128); - builder.append("Receiver{"); - builder.append(receiver); - builder.append(" filter="); - builder.append(filter); - builder.append("}"); - return builder.toString(); - } - } - - private static class BroadcastRecord { - final Intent intent; - final ArrayList receivers; - - BroadcastRecord(Intent _intent, ArrayList _receivers) { - intent = _intent; - receivers = _receivers; - } - } - - private static final String TAG = "LocalBroadcastManager"; - private static final boolean DEBUG = false; - - private final Context mAppContext; - - private final HashMap> mReceivers - = new HashMap>(); - private final HashMap> mActions - = new HashMap>(); - - private final ArrayList mPendingBroadcasts - = new ArrayList(); - - static final int MSG_EXEC_PENDING_BROADCASTS = 1; - - private final Handler mHandler; - - private static final Object mLock = new Object(); - private static LocalBroadcastManager mInstance; - - public static LocalBroadcastManager getInstance(Context context) { - synchronized (mLock) { - if (mInstance == null) { - mInstance = new LocalBroadcastManager(context.getApplicationContext()); - } - return mInstance; - } - } - - private LocalBroadcastManager(Context context) { - mAppContext = context; - mHandler = new Handler(context.getMainLooper()) { - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_EXEC_PENDING_BROADCASTS: - executePendingBroadcasts(); - break; - default: - super.handleMessage(msg); - } - } - }; - } - - /** - * Register a receive for any local broadcasts that match the given IntentFilter. - * - * @param receiver The BroadcastReceiver to handle the broadcast. - * @param filter Selects the Intent broadcasts to be received. - * - * @see #unregisterReceiver - */ - public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { - synchronized (mReceivers) { - ReceiverRecord entry = new ReceiverRecord(filter, receiver); - ArrayList filters = mReceivers.get(receiver); - if (filters == null) { - filters = new ArrayList(1); - mReceivers.put(receiver, filters); - } - filters.add(filter); - for (int i=0; i entries = mActions.get(action); - if (entries == null) { - entries = new ArrayList(1); - mActions.put(action, entries); - } - entries.add(entry); - } - } - } - - /** - * Unregister a previously registered BroadcastReceiver. All - * filters that have been registered for this BroadcastReceiver will be - * removed. - * - * @param receiver The BroadcastReceiver to unregister. - * - * @see #registerReceiver - */ - public void unregisterReceiver(BroadcastReceiver receiver) { - synchronized (mReceivers) { - ArrayList filters = mReceivers.remove(receiver); - if (filters == null) { - return; - } - for (int i=0; i receivers = mActions.get(action); - if (receivers != null) { - for (int k=0; k categories = intent.getCategories(); - - final boolean debug = DEBUG || - ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); - if (debug) Log.v( - TAG, "Resolving type " + type + " scheme " + scheme - + " of intent " + intent); - - ArrayList entries = mActions.get(intent.getAction()); - if (entries != null) { - if (debug) Log.v(TAG, "Action list: " + entries); - - ArrayList receivers = null; - for (int i=0; i= 0) { - if (debug) Log.v(TAG, " Filter matched! match=0x" + - Integer.toHexString(match)); - if (receivers == null) { - receivers = new ArrayList(); - } - receivers.add(receiver); - receiver.broadcasting = true; - } else { - if (debug) { - String reason; - switch (match) { - case IntentFilter.NO_MATCH_ACTION: reason = "action"; break; - case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break; - case IntentFilter.NO_MATCH_DATA: reason = "data"; break; - case IntentFilter.NO_MATCH_TYPE: reason = "type"; break; - default: reason = "unknown reason"; break; - } - Log.v(TAG, " Filter did not match: " + reason); - } - } - } - - if (receivers != null) { - for (int i=0; iNote that for now this is not publicly available because it is not a - * complete implementation, only sufficient for the needs of - * {@link AsyncTaskLoader}. - */ -abstract class ModernAsyncTask { - private static final String LOG_TAG = "AsyncTask"; - - private static final int CORE_POOL_SIZE = 5; - private static final int MAXIMUM_POOL_SIZE = 128; - private static final int KEEP_ALIVE = 1; - - private static final ThreadFactory sThreadFactory = new ThreadFactory() { - private final AtomicInteger mCount = new AtomicInteger(1); - - public Thread newThread(Runnable r) { - return new Thread(r, "ModernAsyncTask #" + mCount.getAndIncrement()); - } - }; - - private static final BlockingQueue sPoolWorkQueue = - new LinkedBlockingQueue(10); - - /** - * An {@link Executor} that can be used to execute tasks in parallel. - */ - public static final Executor THREAD_POOL_EXECUTOR - = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, - TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); - - private static final int MESSAGE_POST_RESULT = 0x1; - private static final int MESSAGE_POST_PROGRESS = 0x2; - - private static InternalHandler sHandler; - - private static volatile Executor sDefaultExecutor = THREAD_POOL_EXECUTOR; - private final WorkerRunnable mWorker; - private final FutureTask mFuture; - - private volatile Status mStatus = Status.PENDING; - - private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); - - /** - * Indicates the current status of the task. Each status will be set only once - * during the lifetime of a task. - */ - public enum Status { - /** - * Indicates that the task has not been executed yet. - */ - PENDING, - /** - * Indicates that the task is running. - */ - RUNNING, - /** - * Indicates that {@link android.os.AsyncTask#onPostExecute(Object)} has finished. - */ - FINISHED, - } - - private static Handler getHandler() { - synchronized (ModernAsyncTask.class) { - if (sHandler == null) { - sHandler = new InternalHandler(); - } - return sHandler; - } - } - - /** @hide */ - public static void setDefaultExecutor(Executor exec) { - sDefaultExecutor = exec; - } - - /** - * Creates a new asynchronous task. This constructor must be invoked on the UI thread. - */ - public ModernAsyncTask() { - mWorker = new WorkerRunnable() { - public Result call() throws Exception { - mTaskInvoked.set(true); - - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - return postResult(doInBackground(mParams)); - } - }; - - mFuture = new FutureTask(mWorker) { - @Override - protected void done() { - try { - final Result result = get(); - - postResultIfNotInvoked(result); - } catch (InterruptedException e) { - android.util.Log.w(LOG_TAG, e); - } catch (ExecutionException e) { - throw new RuntimeException( - "An error occurred while executing doInBackground()", e.getCause()); - } catch (CancellationException e) { - postResultIfNotInvoked(null); - } catch (Throwable t) { - throw new RuntimeException( - "An error occurred while executing doInBackground()", t); - } - } - }; - } - - private void postResultIfNotInvoked(Result result) { - final boolean wasTaskInvoked = mTaskInvoked.get(); - if (!wasTaskInvoked) { - postResult(result); - } - } - - private Result postResult(Result result) { - Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, - new AsyncTaskResult(this, result)); - message.sendToTarget(); - return result; - } - - /** - * Returns the current status of this task. - * - * @return The current status. - */ - public final Status getStatus() { - return mStatus; - } - - /** - * Override this method to perform a computation on a background thread. The - * specified parameters are the parameters passed to {@link #execute} - * by the caller of this task. - * - * This method can call {@link #publishProgress} to publish updates - * on the UI thread. - * - * @param params The parameters of the task. - * - * @return A result, defined by the subclass of this task. - * - * @see #onPreExecute() - * @see #onPostExecute - * @see #publishProgress - */ - protected abstract Result doInBackground(Params... params); - - /** - * Runs on the UI thread before {@link #doInBackground}. - * - * @see #onPostExecute - * @see #doInBackground - */ - protected void onPreExecute() { - } - - /** - *

Runs on the UI thread after {@link #doInBackground}. The - * specified result is the value returned by {@link #doInBackground}.

- * - *

This method won't be invoked if the task was cancelled.

- * - * @param result The result of the operation computed by {@link #doInBackground}. - * - * @see #onPreExecute - * @see #doInBackground - * @see #onCancelled(Object) - */ - @SuppressWarnings({"UnusedDeclaration"}) - protected void onPostExecute(Result result) { - } - - /** - * Runs on the UI thread after {@link #publishProgress} is invoked. - * The specified values are the values passed to {@link #publishProgress}. - * - * @param values The values indicating progress. - * - * @see #publishProgress - * @see #doInBackground - */ - @SuppressWarnings({"UnusedDeclaration"}) - protected void onProgressUpdate(Progress... values) { - } - - /** - *

Runs on the UI thread after {@link #cancel(boolean)} is invoked and - * {@link #doInBackground(Object[])} has finished.

- * - *

The default implementation simply invokes {@link #onCancelled()} and - * ignores the result. If you write your own implementation, do not call - * super.onCancelled(result).

- * - * @param result The result, if any, computed in - * {@link #doInBackground(Object[])}, can be null - * - * @see #cancel(boolean) - * @see #isCancelled() - */ - @SuppressWarnings({"UnusedParameters"}) - protected void onCancelled(Result result) { - onCancelled(); - } - - /** - *

Applications should preferably override {@link #onCancelled(Object)}. - * This method is invoked by the default implementation of - * {@link #onCancelled(Object)}.

- * - *

Runs on the UI thread after {@link #cancel(boolean)} is invoked and - * {@link #doInBackground(Object[])} has finished.

- * - * @see #onCancelled(Object) - * @see #cancel(boolean) - * @see #isCancelled() - */ - protected void onCancelled() { - } - - /** - * Returns true if this task was cancelled before it completed - * normally. If you are calling {@link #cancel(boolean)} on the task, - * the value returned by this method should be checked periodically from - * {@link #doInBackground(Object[])} to end the task as soon as possible. - * - * @return true if task was cancelled before it completed - * - * @see #cancel(boolean) - */ - public final boolean isCancelled() { - return mFuture.isCancelled(); - } - - /** - *

Attempts to cancel execution of this task. This attempt will - * fail if the task has already completed, already been cancelled, - * or could not be cancelled for some other reason. If successful, - * and this task has not started when cancel is called, - * this task should never run. If the task has already started, - * then the mayInterruptIfRunning parameter determines - * whether the thread executing this task should be interrupted in - * an attempt to stop the task.

- * - *

Calling this method will result in {@link #onCancelled(Object)} being - * invoked on the UI thread after {@link #doInBackground(Object[])} - * returns. Calling this method guarantees that {@link #onPostExecute(Object)} - * is never invoked. After invoking this method, you should check the - * value returned by {@link #isCancelled()} periodically from - * {@link #doInBackground(Object[])} to finish the task as early as - * possible.

- * - * @param mayInterruptIfRunning true if the thread executing this - * task should be interrupted; otherwise, in-progress tasks are allowed - * to complete. - * - * @return false if the task could not be cancelled, - * typically because it has already completed normally; - * true otherwise - * - * @see #isCancelled() - * @see #onCancelled(Object) - */ - public final boolean cancel(boolean mayInterruptIfRunning) { - return mFuture.cancel(mayInterruptIfRunning); - } - - /** - * Waits if necessary for the computation to complete, and then - * retrieves its result. - * - * @return The computed result. - * - * @throws CancellationException If the computation was cancelled. - * @throws ExecutionException If the computation threw an exception. - * @throws InterruptedException If the current thread was interrupted - * while waiting. - */ - public final Result get() throws InterruptedException, ExecutionException { - return mFuture.get(); - } - - /** - * Waits if necessary for at most the given time for the computation - * to complete, and then retrieves its result. - * - * @param timeout Time to wait before cancelling the operation. - * @param unit The time unit for the timeout. - * - * @return The computed result. - * - * @throws CancellationException If the computation was cancelled. - * @throws ExecutionException If the computation threw an exception. - * @throws InterruptedException If the current thread was interrupted - * while waiting. - * @throws TimeoutException If the wait timed out. - */ - public final Result get(long timeout, TimeUnit unit) throws InterruptedException, - ExecutionException, TimeoutException { - return mFuture.get(timeout, unit); - } - - /** - * Executes the task with the specified parameters. The task returns - * itself (this) so that the caller can keep a reference to it. - * - *

Note: this function schedules the task on a queue for a single background - * thread or pool of threads depending on the platform version. When first - * introduced, AsyncTasks were executed serially on a single background thread. - * Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed - * to a pool of threads allowing multiple tasks to operate in parallel. After - * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, it is planned to change this - * back to a single thread to avoid common application errors caused - * by parallel execution. If you truly want parallel execution, you can use - * the {@link #executeOnExecutor} version of this method - * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings on - * its use. - * - *

This method must be invoked on the UI thread. - * - * @param params The parameters of the task. - * - * @return This instance of AsyncTask. - * - * @throws IllegalStateException If {@link #getStatus()} returns either - * {@link android.os.AsyncTask.Status#RUNNING} or - * {@link android.os.AsyncTask.Status#FINISHED}. - */ - public final ModernAsyncTask execute(Params... params) { - return executeOnExecutor(sDefaultExecutor, params); - } - - /** - * Executes the task with the specified parameters. The task returns - * itself (this) so that the caller can keep a reference to it. - * - *

This method is typically used with {@link #THREAD_POOL_EXECUTOR} to - * allow multiple tasks to run in parallel on a pool of threads managed by - * AsyncTask, however you can also use your own {@link Executor} for custom - * behavior. - * - *

Warning: Allowing multiple tasks to run in parallel from - * a thread pool is generally not what one wants, because the order - * of their operation is not defined. For example, if these tasks are used - * to modify any state in common (such as writing a file due to a button click), - * there are no guarantees on the order of the modifications. - * Without careful work it is possible in rare cases for the newer version - * of the data to be over-written by an older one, leading to obscure data - * loss and stability issues. - * - *

This method must be invoked on the UI thread. - * - * @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a - * convenient process-wide thread pool for tasks that are loosely coupled. - * @param params The parameters of the task. - * - * @return This instance of AsyncTask. - * - * @throws IllegalStateException If {@link #getStatus()} returns either - * {@link android.os.AsyncTask.Status#RUNNING} - * or {@link android.os.AsyncTask.Status#FINISHED}. - */ - public final ModernAsyncTask executeOnExecutor(Executor exec, - Params... params) { - if (mStatus != Status.PENDING) { - switch (mStatus) { - case RUNNING: - throw new IllegalStateException("Cannot execute task:" - + " the task is already running."); - case FINISHED: - throw new IllegalStateException("Cannot execute task:" - + " the task has already been executed " - + "(a task can be executed only once)"); - } - } - - mStatus = Status.RUNNING; - - onPreExecute(); - - mWorker.mParams = params; - exec.execute(mFuture); - - return this; - } - - /** - * Convenience version of {@link #execute(Object...)} for use with - * a simple Runnable object. - */ - public static void execute(Runnable runnable) { - sDefaultExecutor.execute(runnable); - } - - /** - * This method can be invoked from {@link #doInBackground} to - * publish updates on the UI thread while the background computation is - * still running. Each call to this method will trigger the execution of - * {@link #onProgressUpdate} on the UI thread. - * - * {@link #onProgressUpdate} will note be called if the task has been - * canceled. - * - * @param values The progress values to update the UI with. - * - * @see #onProgressUpdate - * @see #doInBackground - */ - protected final void publishProgress(Progress... values) { - if (!isCancelled()) { - getHandler().obtainMessage(MESSAGE_POST_PROGRESS, - new AsyncTaskResult(this, values)).sendToTarget(); - } - } - - private void finish(Result result) { - if (isCancelled()) { - onCancelled(result); - } else { - onPostExecute(result); - } - mStatus = Status.FINISHED; - } - - private static class InternalHandler extends Handler { - public InternalHandler() { - super(Looper.getMainLooper()); - } - - @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) - @Override - public void handleMessage(Message msg) { - AsyncTaskResult result = (AsyncTaskResult) msg.obj; - switch (msg.what) { - case MESSAGE_POST_RESULT: - // There is only one result - result.mTask.finish(result.mData[0]); - break; - case MESSAGE_POST_PROGRESS: - result.mTask.onProgressUpdate(result.mData); - break; - } - } - } - - private static abstract class WorkerRunnable implements Callable { - Params[] mParams; - } - - @SuppressWarnings({"RawUseOfParameterizedType"}) - private static class AsyncTaskResult { - final ModernAsyncTask mTask; - final Data[] mData; - - AsyncTaskResult(ModernAsyncTask task, Data... data) { - mTask = task; - mData = data; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ParallelExecutorCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ParallelExecutorCompat.java deleted file mode 100644 index 9db6fc1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/ParallelExecutorCompat.java +++ /dev/null @@ -1,38 +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 p.android.support.v4.content; - -import android.os.Build; - -import java.util.concurrent.Executor; - -/** - * Helper for accessing a shared parallel Executor instance - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class ParallelExecutorCompat { - public static Executor getParallelExecutor() { - if (Build.VERSION.SDK_INT >= 11) { - // From API 11 onwards, return AsyncTask.THREAD_POOL_EXECUTOR - return ExecutorCompatHoneycomb.getParallelExecutor(); - } else { - return ModernAsyncTask.THREAD_POOL_EXECUTOR; - } - } - - private ParallelExecutorCompat() {} -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/PermissionChecker.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/PermissionChecker.java deleted file mode 100644 index 3509c6f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/PermissionChecker.java +++ /dev/null @@ -1,165 +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 p.android.support.v4.content; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.os.Binder; -import android.os.Process; -import p.android.support.annotation.IntDef; -import p.android.support.annotation.NonNull; -import p.android.support.v4.app.AppOpsManagerCompat; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * This class provides permission check APIs that verify both the - * permission and the associated app op for this permission if - * such is defined. - *

- * In the new permission model permissions with protection level - * dangerous are runtime permissions. For apps targeting {@link android.os.Build.VERSION_CODES#M} - * and above the user may not grant such permissions or revoke - * them at any time. For apps targeting API lower than {@link android.os.Build.VERSION_CODES#M} - * these permissions are always granted as such apps do not expect - * permission revocations and would crash. Therefore, when the - * user disables a permission for a legacy app in the UI the - * platform disables the APIs guarded by this permission making - * them a no-op which is doing nothing or returning an empty - * result or default error. - *

- *

- * It is important that when you perform an operation on behalf of - * another app you use these APIs to check for permissions as the - * app may be a legacy app that does not participate in the new - * permission model for which the user had disabled the "permission" - * which is achieved by disallowing the corresponding app op. - *

- */ -public final class PermissionChecker { - /** Permission result: The permission is granted. */ - public static final int PERMISSION_GRANTED = PackageManager.PERMISSION_GRANTED; - - /** Permission result: The permission is denied. */ - public static final int PERMISSION_DENIED = PackageManager.PERMISSION_DENIED; - - /** Permission result: The permission is denied because the app op is not allowed. */ - public static final int PERMISSION_DENIED_APP_OP = PackageManager.PERMISSION_DENIED - 1; - - @IntDef({PERMISSION_GRANTED, - PERMISSION_DENIED, - PERMISSION_DENIED_APP_OP}) - @Retention(RetentionPolicy.SOURCE) - public @interface PermissionResult {} - - private PermissionChecker() { - /* do nothing */ - } - - /** - * Checks whether a given package in a UID and PID has a given permission - * and whether the app op that corresponds to this permission is allowed. - * - * @param context Context for accessing resources. - * @param permission The permission to check. - * @param pid The process id for which to check. - * @param uid The uid for which to check. - * @param packageName The package name for which to check. If null the - * the first package for the calling UID will be used. - * @return The permission check result which is either {@link #PERMISSION_GRANTED} - * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. - */ - public static int checkPermission(@NonNull Context context, @NonNull String permission, - int pid, int uid, String packageName) { - if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) { - return PERMISSION_DENIED; - } - - String op = AppOpsManagerCompat.permissionToOp(permission); - if (op == null) { - return PERMISSION_GRANTED; - } - - if (packageName == null) { - String[] packageNames = context.getPackageManager().getPackagesForUid(uid); - if (packageNames == null || packageNames.length <= 0) { - return PERMISSION_DENIED; - } - packageName = packageNames[0]; - } - - if (AppOpsManagerCompat.noteProxyOp(context, op, packageName) - != AppOpsManagerCompat.MODE_ALLOWED) { - return PERMISSION_DENIED_APP_OP; - } - - return PERMISSION_GRANTED; - } - - /** - * Checks whether your app has a given permission and whether the app op - * that corresponds to this permission is allowed. - * - * @param context Context for accessing resources. - * @param permission The permission to check. - * @return The permission check result which is either {@link #PERMISSION_GRANTED} - * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. - */ - public static int checkSelfPermission(@NonNull Context context, - @NonNull String permission) { - return checkPermission(context, permission, Process.myPid(), - Process.myUid(), context.getPackageName()); - } - - /** - * Checks whether the IPC you are handling has a given permission and whether - * the app op that corresponds to this permission is allowed. - * - * @param context Context for accessing resources. - * @param permission The permission to check. - * @param packageName The package name making the IPC. If null the - * the first package for the calling UID will be used. - * @return The permission check result which is either {@link #PERMISSION_GRANTED} - * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. - */ - public static int checkCallingPermission(@NonNull Context context, - @NonNull String permission, String packageName) { - if (Binder.getCallingPid() == Process.myPid()) { - return PackageManager.PERMISSION_DENIED; - } - return checkPermission(context, permission, Binder.getCallingPid(), - Binder.getCallingUid(), packageName); - } - - /** - * Checks whether the IPC you are handling or your app has a given permission - * and whether the app op that corresponds to this permission is allowed. - * - * @param context Context for accessing resources. - * @param permission The permission to check. - * @return The permission check result which is either {@link #PERMISSION_GRANTED} - * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}. - */ - public static int checkCallingOrSelfPermission(@NonNull Context context, - @NonNull String permission) { - String packageName = (Binder.getCallingPid() == Process.myPid()) - ? context.getPackageName() : null; - return checkPermission(context, permission, Binder.getCallingPid(), - Binder.getCallingUid(), packageName); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/SharedPreferencesCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/SharedPreferencesCompat.java deleted file mode 100644 index 23005c9..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/SharedPreferencesCompat.java +++ /dev/null @@ -1,73 +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 p.android.support.v4.content; - -import android.content.SharedPreferences; -import android.os.Build; -import p.android.support.annotation.NonNull; - -public final class SharedPreferencesCompat { - - public final static class EditorCompat { - - private static EditorCompat sInstance; - - private interface Helper { - void apply(@NonNull SharedPreferences.Editor editor); - } - - private static class EditorHelperBaseImpl implements Helper { - - @Override - public void apply(@NonNull SharedPreferences.Editor editor) { - editor.commit(); - } - } - - private static class EditorHelperApi9Impl implements Helper { - - @Override - public void apply(@NonNull SharedPreferences.Editor editor) { - EditorCompatGingerbread.apply(editor); - } - } - - private final Helper mHelper; - - private EditorCompat() { - if (Build.VERSION.SDK_INT >= 9) { - mHelper = new EditorHelperApi9Impl(); - } else { - mHelper = new EditorHelperBaseImpl(); - } - } - - public static EditorCompat getInstance() { - if (sInstance == null) { - sInstance = new EditorCompat(); - } - return sInstance; - } - - public void apply(@NonNull SharedPreferences.Editor editor) { - mHelper.apply(editor); - } - } - - private SharedPreferencesCompat() {} - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/WakefulBroadcastReceiver.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/WakefulBroadcastReceiver.java deleted file mode 100644 index 33b0f6f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/WakefulBroadcastReceiver.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content; - -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.os.PowerManager; -import android.util.Log; -import android.util.SparseArray; - -/** - * Helper for the common pattern of implementing a {@link BroadcastReceiver} - * that receives a device wakeup event and then passes the work off - * to a {@link android.app.Service}, while ensuring that the - * device does not go back to sleep during the transition. - * - *

This class takes care of creating and managing a partial wake lock - * for you; you must request the {@link android.Manifest.permission#WAKE_LOCK} - * permission to use it.

- * - *

Example

- * - *

A {@link WakefulBroadcastReceiver} uses the method - * {@link WakefulBroadcastReceiver#startWakefulService startWakefulService()} - * to start the service that does the work. This method is comparable to - * {@link Context#startService startService()}, except that - * the {@link WakefulBroadcastReceiver} is holding a wake lock when the service - * starts. The intent that is passed with - * {@link WakefulBroadcastReceiver#startWakefulService startWakefulService()} - * holds an extra identifying the wake lock.

- * - * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/content/SimpleWakefulReceiver.java complete} - * - *

The service (in this example, an {@link android.app.IntentService}) does - * some work. When it is finished, it releases the wake lock by calling - * {@link WakefulBroadcastReceiver#completeWakefulIntent - * completeWakefulIntent(intent)}. The intent it passes as a parameter - * is the same intent that the {@link WakefulBroadcastReceiver} originally - * passed in.

- * - * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/content/SimpleWakefulService.java complete} - */ -public abstract class WakefulBroadcastReceiver extends BroadcastReceiver { - private static final String EXTRA_WAKE_LOCK_ID = "android.support.content.wakelockid"; - - private static final SparseArray mActiveWakeLocks - = new SparseArray(); - private static int mNextId = 1; - - /** - * Do a {@link Context#startService(Intent) - * Context.startService}, but holding a wake lock while the service starts. - * This will modify the Intent to hold an extra identifying the wake lock; - * when the service receives it in {@link android.app.Service#onStartCommand - * Service.onStartCommand}, it should pass back the Intent it receives there to - * {@link #completeWakefulIntent(Intent)} in order to release - * the wake lock. - * - * @param context The Context in which it operate. - * @param intent The Intent with which to start the service, as per - * {@link Context#startService(Intent) - * Context.startService}. - */ - public static ComponentName startWakefulService(Context context, Intent intent) { - synchronized (mActiveWakeLocks) { - int id = mNextId; - mNextId++; - if (mNextId <= 0) { - mNextId = 1; - } - - intent.putExtra(EXTRA_WAKE_LOCK_ID, id); - ComponentName comp = context.startService(intent); - if (comp == null) { - return null; - } - - PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - "wake:" + comp.flattenToShortString()); - wl.setReferenceCounted(false); - wl.acquire(60*1000); - mActiveWakeLocks.put(id, wl); - return comp; - } - } - - /** - * Finish the execution from a previous {@link #startWakefulService}. Any wake lock - * that was being held will now be released. - * - * @param intent The Intent as originally generated by {@link #startWakefulService}. - * @return Returns true if the intent is associated with a wake lock that is - * now released; returns false if there was no wake lock specified for it. - */ - public static boolean completeWakefulIntent(Intent intent) { - final int id = intent.getIntExtra(EXTRA_WAKE_LOCK_ID, 0); - if (id == 0) { - return false; - } - synchronized (mActiveWakeLocks) { - PowerManager.WakeLock wl = mActiveWakeLocks.get(id); - if (wl != null) { - wl.release(); - mActiveWakeLocks.remove(id); - return true; - } - // We return true whether or not we actually found the wake lock - // the return code is defined to indicate whether the Intent contained - // an identifier for a wake lock that it was supposed to match. - // We just log a warning here if there is no wake lock found, which could - // happen for example if this function is called twice on the same - // intent or the process is killed and restarted before processing the intent. - Log.w("WakefulBroadcastReceiver", "No active wake lock id #" + id); - return true; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/package.html b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/package.html deleted file mode 100755 index 33bf4b5..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/package.html +++ /dev/null @@ -1,10 +0,0 @@ - - -Support android.content classes to assist with development of applications for -android API level 4 or later. The main features here are -{@link android.support.v4.content.Loader} and related classes and -{@link android.support.v4.content.LocalBroadcastManager} to -provide a cleaner implementation of broadcasts that don't need to go outside -of an app. - - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/pm/ActivityInfoCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/pm/ActivityInfoCompat.java deleted file mode 100644 index 6d91455..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/pm/ActivityInfoCompat.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.content.pm; - -/** - * Helper for accessing features in {@link android.content.pm.ActivityInfo} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class ActivityInfoCompat { - - private ActivityInfoCompat() { - /* Hide constructor */ - } - - /** - * Bit in ActivityInfo#configChanges that indicates that the - * activity can itself handle the ui mode. Set from the - * {@link android.R.attr#configChanges} attribute. - */ - public static final int CONFIG_UI_MODE = 0x0200; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/pm/package.html b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/pm/package.html deleted file mode 100755 index da850bd..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/pm/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - -Support android.content.pm classes to assist with development of applications for -android API level 4 or later. - - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompat.java deleted file mode 100644 index 3c92f29..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompat.java +++ /dev/null @@ -1,160 +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 p.android.support.v4.content.res; - -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.ColorInt; -import p.android.support.annotation.ColorRes; -import p.android.support.annotation.DrawableRes; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; - -import static android.os.Build.VERSION.SDK_INT; - -/** - * Helper for accessing features in {@link Resources} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class ResourcesCompat { - /** - * Return a drawable object associated with a particular resource ID and - * styled for the specified theme. Various types of objects will be - * returned depending on the underlying resource -- for example, a solid - * color, PNG image, scalable image, etc. - *

- * Prior to API level 21, the theme will not be applied and this method - * simply calls through to {@link Resources#getDrawable(int)}. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @param theme The theme used to style the drawable attributes, may be - * {@code null}. - * @return Drawable An object that can be used to draw this resource. - * @throws NotFoundException Throws NotFoundException if the given ID does - * not exist. - */ - @Nullable - @SuppressWarnings("deprecation") - public static Drawable getDrawable(@NonNull Resources res, @DrawableRes int id, - @Nullable Theme theme) throws NotFoundException { - if (SDK_INT >= 21) { - return ResourcesCompatApi21.getDrawable(res, id, theme); - } else { - return res.getDrawable(id); - } - } - - - /** - * Return a drawable object associated with a particular resource ID for - * the given screen density in DPI and styled for the specified theme. - *

- * Prior to API level 15, the theme and density will not be applied and - * this method simply calls through to {@link Resources#getDrawable(int)}. - *

- * Prior to API level 21, the theme will not be applied and this method - * calls through to Resources#getDrawableForDensity(int, int). - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @param density The desired screen density indicated by the resource as - * found in {@link android.util.DisplayMetrics}. - * @param theme The theme used to style the drawable attributes, may be - * {@code null}. - * @return Drawable An object that can be used to draw this resource. - * @throws NotFoundException Throws NotFoundException if the given ID does - * not exist. - */ - @Nullable - @SuppressWarnings("deprecation") - public static Drawable getDrawableForDensity(@NonNull Resources res, @DrawableRes int id, - int density, @Nullable Theme theme) throws NotFoundException { - if (SDK_INT >= 21) { - return ResourcesCompatApi21.getDrawableForDensity(res, id, density, theme); - } else if (SDK_INT >= 15) { - return ResourcesCompatIcsMr1.getDrawableForDensity(res, id, density); - } else { - return res.getDrawable(id); - } - } - - /** - * Returns a themed color integer associated with a particular resource ID. - * If the resource holds a complex {@link ColorStateList}, then the default - * color from the set is returned. - *

- * Prior to API level 23, the theme will not be applied and this method - * calls through to {@link Resources#getColor(int)}. - * - * @param id The desired resource identifier, as generated by the aapt - * tool. This integer encodes the package, type, and resource - * entry. The value 0 is an invalid identifier. - * @param theme The theme used to style the color attributes, may be - * {@code null}. - * @return A single color value in the form {@code 0xAARRGGBB}. - * @throws NotFoundException Throws NotFoundException if the given ID does - * not exist. - */ - @ColorInt - @SuppressWarnings("deprecation") - public static int getColor(@NonNull Resources res, @ColorRes int id, @Nullable Theme theme) - throws NotFoundException { - if (SDK_INT >= 23) { - return ResourcesCompatApi23.getColor(res, id, theme); - } else { - return res.getColor(id); - } - } - - /** - * Returns a themed color state list associated with a particular resource - * ID. The resource may contain either a single raw color value or a - * complex {@link ColorStateList} holding multiple possible colors. - *

- * Prior to API level 23, the theme will not be applied and this method - * calls through to {@link Resources#getColorStateList(int)}. - * - * @param id The desired resource identifier of a {@link ColorStateList}, - * as generated by the aapt tool. This integer encodes the - * package, type, and resource entry. The value 0 is an invalid - * identifier. - * @param theme The theme used to style the color attributes, may be - * {@code null}. - * @return A themed ColorStateList object containing either a single solid - * color or multiple colors that can be selected based on a state. - * @throws NotFoundException Throws NotFoundException if the given ID does - * not exist. - */ - @Nullable - @SuppressWarnings("deprecation") - public static ColorStateList getColorStateList(@NonNull Resources res, @ColorRes int id, - @Nullable Theme theme) throws NotFoundException { - if (SDK_INT >= 23) { - return ResourcesCompatApi23.getColorStateList(res, id, theme); - } else { - return res.getColorStateList(id); - } - } - - private ResourcesCompat() {} -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatApi21.java deleted file mode 100644 index 28b4f81..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatApi21.java +++ /dev/null @@ -1,34 +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 p.android.support.v4.content.res; - -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; -import android.graphics.drawable.Drawable; - -class ResourcesCompatApi21 { - public static Drawable getDrawable(Resources res, int id, Theme theme) - throws NotFoundException { - return res.getDrawable(id, theme); - } - - public static Drawable getDrawableForDensity(Resources res, int id, int density, Theme theme) - throws NotFoundException { - return res.getDrawableForDensity(id, density, theme); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatApi23.java deleted file mode 100644 index f4ab590..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatApi23.java +++ /dev/null @@ -1,33 +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 p.android.support.v4.content.res; - -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; - -class ResourcesCompatApi23 { - public static int getColor(Resources res, int id, Theme theme) throws NotFoundException { - return res.getColor(id, theme); - } - - public static ColorStateList getColorStateList(Resources res, int id, Theme theme) - throws NotFoundException { - return res.getColorStateList(id, theme); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatIcsMr1.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatIcsMr1.java deleted file mode 100644 index 5f4b2ef..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/ResourcesCompatIcsMr1.java +++ /dev/null @@ -1,28 +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 p.android.support.v4.content.res; - -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.graphics.drawable.Drawable; - -class ResourcesCompatIcsMr1 { - public static Drawable getDrawableForDensity(Resources res, int id, int density) - throws NotFoundException { - return res.getDrawableForDensity(id, density); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/TypedArrayUtils.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/TypedArrayUtils.java deleted file mode 100644 index b53b7c3..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/content/res/TypedArrayUtils.java +++ /dev/null @@ -1,73 +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 p.android.support.v4.content.res; - -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.AnyRes; -import p.android.support.annotation.StyleableRes; - -/** - * Compat methods for accessing TypedArray values. - * - * @hide - */ -public class TypedArrayUtils { - public static boolean getBoolean(TypedArray a, @StyleableRes int index, - @StyleableRes int fallbackIndex, boolean defaultValue) { - boolean val = a.getBoolean(fallbackIndex, defaultValue); - return a.getBoolean(index, val); - } - - public static Drawable getDrawable(TypedArray a, @StyleableRes int index, - @StyleableRes int fallbackIndex) { - Drawable val = a.getDrawable(index); - if (val == null) { - val = a.getDrawable(fallbackIndex); - } - return val; - } - - public static int getInt(TypedArray a, @StyleableRes int index, - @StyleableRes int fallbackIndex, int defaultValue) { - int val = a.getInt(fallbackIndex, defaultValue); - return a.getInt(index, val); - } - - public static @AnyRes int getResourceId(TypedArray a, @StyleableRes int index, - @StyleableRes int fallbackIndex, @AnyRes int defaultValue) { - int val = a.getResourceId(fallbackIndex, defaultValue); - return a.getResourceId(index, val); - } - - public static String getString(TypedArray a, @StyleableRes int index, - @StyleableRes int fallbackIndex) { - String val = a.getString(index); - if (val == null) { - val = a.getString(fallbackIndex); - } - return val; - } - - public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index, - @StyleableRes int fallbackIndex) { - CharSequence[] val = a.getTextArray(index); - if (val == null) { - val = a.getTextArray(fallbackIndex); - } - return val; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/database/DatabaseUtilsCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/database/DatabaseUtilsCompat.java deleted file mode 100644 index d8c0fb1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/database/DatabaseUtilsCompat.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.database; - -import android.text.TextUtils; - -/** - * Helper for accessing features in {@link android.database.DatabaseUtils} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class DatabaseUtilsCompat { - - private DatabaseUtilsCompat() { - /* Hide constructor */ - } - - /** - * Concatenates two SQL WHERE clauses, handling empty or null values. - */ - public static String concatenateWhere(String a, String b) { - if (TextUtils.isEmpty(a)) { - return b; - } - if (TextUtils.isEmpty(b)) { - return a; - } - - return "(" + a + ") AND (" + b + ")"; - } - - /** - * Appends one set of selection args to another. This is useful when adding a selection - * argument to a user provided set. - */ - public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) { - if (originalValues == null || originalValues.length == 0) { - return newValues; - } - String[] result = new String[originalValues.length + newValues.length ]; - System.arraycopy(originalValues, 0, result, 0, originalValues.length); - System.arraycopy(newValues, 0, result, originalValues.length, newValues.length); - return result; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/database/package.html b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/database/package.html deleted file mode 100755 index 25ac59a..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/database/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - -Support android.database classes to assist with development of applications for -android API level 4 or later. - - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompat.java deleted file mode 100644 index 85aa45f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompat.java +++ /dev/null @@ -1,113 +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 p.android.support.v4.graphics; - -import android.graphics.Bitmap; - -/** - * Helper for accessing features in {@link Bitmap} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class BitmapCompat { - /** - * Interface for the full API. - */ - interface BitmapImpl { - public boolean hasMipMap(Bitmap bitmap); - public void setHasMipMap(Bitmap bitmap, boolean hasMipMap); - public int getAllocationByteCount(Bitmap bitmap); - } - - static class BaseBitmapImpl implements BitmapImpl { - @Override - public boolean hasMipMap(Bitmap bitmap) { - return false; - } - - @Override - public void setHasMipMap(Bitmap bitmap, boolean hasMipMap) { - } - - @Override - public int getAllocationByteCount(Bitmap bitmap) { - return bitmap.getRowBytes() * bitmap.getHeight(); - } - } - - static class HcMr1BitmapCompatImpl extends BaseBitmapImpl { - @Override - public int getAllocationByteCount(Bitmap bitmap) { - return BitmapCompatHoneycombMr1.getAllocationByteCount(bitmap); - } - } - - static class JbMr2BitmapCompatImpl extends HcMr1BitmapCompatImpl { - @Override - public boolean hasMipMap(Bitmap bitmap){ - return BitmapCompatJellybeanMR2.hasMipMap(bitmap); - } - - @Override - public void setHasMipMap(Bitmap bitmap, boolean hasMipMap) { - BitmapCompatJellybeanMR2.setHasMipMap(bitmap, hasMipMap); - } - } - - static class KitKatBitmapCompatImpl extends JbMr2BitmapCompatImpl { - @Override - public int getAllocationByteCount(Bitmap bitmap) { - return BitmapCompatKitKat.getAllocationByteCount(bitmap); - } - } - - /** - * Select the correct implementation to use for the current platform. - */ - static final BitmapImpl IMPL; - static { - final int version = android.os.Build.VERSION.SDK_INT; - if (version >= 19) { - IMPL = new KitKatBitmapCompatImpl(); - } else if (version >= 18) { - IMPL = new JbMr2BitmapCompatImpl(); - } else if (version >= 12) { - IMPL = new HcMr1BitmapCompatImpl(); - } else { - IMPL = new BaseBitmapImpl(); - } - } - - public static boolean hasMipMap(Bitmap bitmap) { - return IMPL.hasMipMap(bitmap); - } - - public static void setHasMipMap(Bitmap bitmap, boolean hasMipMap) { - IMPL.setHasMipMap(bitmap, hasMipMap); - } - - /** - * Returns the size of the allocated memory used to store this bitmap's pixels in a backwards - * compatible way. - * - * @param bitmap the bitmap in which to return it's allocation size - * @return the allocation size in bytes - */ - public static int getAllocationByteCount(Bitmap bitmap) { - return IMPL.getAllocationByteCount(bitmap); - } - - private BitmapCompat() {} -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatHoneycombMr1.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatHoneycombMr1.java deleted file mode 100644 index 4688642..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatHoneycombMr1.java +++ /dev/null @@ -1,29 +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 p.android.support.v4.graphics; - -import android.graphics.Bitmap; - -/** - * Implementation of BitmapCompat that can use Honeycomb MR1 APIs. - */ -class BitmapCompatHoneycombMr1 { - - static int getAllocationByteCount(Bitmap bitmap) { - return bitmap.getByteCount(); - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatJellybeanMR2.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatJellybeanMR2.java deleted file mode 100644 index d4e21a1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatJellybeanMR2.java +++ /dev/null @@ -1,28 +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 p.android.support.v4.graphics; - -import android.graphics.Bitmap; - -class BitmapCompatJellybeanMR2 { - public static boolean hasMipMap(Bitmap bitmap) { - return bitmap.hasMipMap(); - } - - public static void setHasMipMap(Bitmap bitmap, boolean hasMipMap) { - bitmap.setHasMipMap(hasMipMap); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatKitKat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatKitKat.java deleted file mode 100644 index 5efffc6..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/BitmapCompatKitKat.java +++ /dev/null @@ -1,29 +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 p.android.support.v4.graphics; - -import android.graphics.Bitmap; - -/** - * Implementation of BitmapCompat that can use KitKat APIs. - */ -class BitmapCompatKitKat { - - static int getAllocationByteCount(Bitmap bitmap) { - return bitmap.getAllocationByteCount(); - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/ColorUtils.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/ColorUtils.java deleted file mode 100644 index 5953355..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/ColorUtils.java +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.graphics; - -import android.graphics.Color; -import p.android.support.annotation.ColorInt; -import p.android.support.annotation.FloatRange; -import p.android.support.annotation.IntRange; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.VisibleForTesting; - -/** - * A set of color-related utility methods, building upon those available in {@code Color}. - */ -public final class ColorUtils { - - private static final double XYZ_WHITE_REFERENCE_X = 95.047; - private static final double XYZ_WHITE_REFERENCE_Y = 100; - private static final double XYZ_WHITE_REFERENCE_Z = 108.883; - private static final double XYZ_EPSILON = 0.008856; - private static final double XYZ_KAPPA = 903.3; - - private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10; - private static final int MIN_ALPHA_SEARCH_PRECISION = 1; - - private static final ThreadLocal TEMP_ARRAY = new ThreadLocal<>(); - - private ColorUtils() {} - - /** - * Composite two potentially translucent colors over each other and returns the result. - */ - public static int compositeColors(@ColorInt int foreground, @ColorInt int background) { - int bgAlpha = Color.alpha(background); - int fgAlpha = Color.alpha(foreground); - int a = compositeAlpha(fgAlpha, bgAlpha); - - int r = compositeComponent(Color.red(foreground), fgAlpha, - Color.red(background), bgAlpha, a); - int g = compositeComponent(Color.green(foreground), fgAlpha, - Color.green(background), bgAlpha, a); - int b = compositeComponent(Color.blue(foreground), fgAlpha, - Color.blue(background), bgAlpha, a); - - return Color.argb(a, r, g, b); - } - - private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) { - return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF); - } - - private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) { - if (a == 0) return 0; - return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF); - } - - /** - * Returns the luminance of a color as a float between {@code 0.0} and {@code 1.0}. - *

Defined as the Y component in the XYZ representation of {@code color}.

- */ - @FloatRange(from = 0.0, to = 1.0) - public static double calculateLuminance(@ColorInt int color) { - final double[] result = getTempDouble3Array(); - colorToXYZ(color, result); - // Luminance is the Y component - return result[1] / 100; - } - - /** - * Returns the contrast ratio between {@code foreground} and {@code background}. - * {@code background} must be opaque. - *

- * Formula defined - * here. - */ - public static double calculateContrast(@ColorInt int foreground, @ColorInt int background) { - if (Color.alpha(background) != 255) { - throw new IllegalArgumentException("background can not be translucent: #" - + Integer.toHexString(background)); - } - if (Color.alpha(foreground) < 255) { - // If the foreground is translucent, composite the foreground over the background - foreground = compositeColors(foreground, background); - } - - final double luminance1 = calculateLuminance(foreground) + 0.05; - final double luminance2 = calculateLuminance(background) + 0.05; - - // Now return the lighter luminance divided by the darker luminance - return Math.max(luminance1, luminance2) / Math.min(luminance1, luminance2); - } - - /** - * Calculates the minimum alpha value which can be applied to {@code foreground} so that would - * have a contrast value of at least {@code minContrastRatio} when compared to - * {@code background}. - * - * @param foreground the foreground color - * @param background the opaque background color - * @param minContrastRatio the minimum contrast ratio - * @return the alpha value in the range 0-255, or -1 if no value could be calculated - */ - public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background, - float minContrastRatio) { - if (Color.alpha(background) != 255) { - throw new IllegalArgumentException("background can not be translucent: #" - + Integer.toHexString(background)); - } - - // First lets check that a fully opaque foreground has sufficient contrast - int testForeground = setAlphaComponent(foreground, 255); - double testRatio = calculateContrast(testForeground, background); - if (testRatio < minContrastRatio) { - // Fully opaque foreground does not have sufficient contrast, return error - return -1; - } - - // Binary search to find a value with the minimum value which provides sufficient contrast - int numIterations = 0; - int minAlpha = 0; - int maxAlpha = 255; - - while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS && - (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) { - final int testAlpha = (minAlpha + maxAlpha) / 2; - - testForeground = setAlphaComponent(foreground, testAlpha); - testRatio = calculateContrast(testForeground, background); - - if (testRatio < minContrastRatio) { - minAlpha = testAlpha; - } else { - maxAlpha = testAlpha; - } - - numIterations++; - } - - // Conservatively return the max of the range of possible alphas, which is known to pass. - return maxAlpha; - } - - /** - * Convert RGB components to HSL (hue-saturation-lightness). - *

    - *
  • outHsl[0] is Hue [0 .. 360)
  • - *
  • outHsl[1] is Saturation [0...1]
  • - *
  • outHsl[2] is Lightness [0...1]
  • - *
- * - * @param r red component value [0..255] - * @param g green component value [0..255] - * @param b blue component value [0..255] - * @param outHsl 3-element array which holds the resulting HSL components - */ - public static void RGBToHSL(@IntRange(from = 0x0, to = 0xFF) int r, - @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b, - @NonNull float[] outHsl) { - final float rf = r / 255f; - final float gf = g / 255f; - final float bf = b / 255f; - - final float max = Math.max(rf, Math.max(gf, bf)); - final float min = Math.min(rf, Math.min(gf, bf)); - final float deltaMaxMin = max - min; - - float h, s; - float l = (max + min) / 2f; - - if (max == min) { - // Monochromatic - h = s = 0f; - } else { - if (max == rf) { - h = ((gf - bf) / deltaMaxMin) % 6f; - } else if (max == gf) { - h = ((bf - rf) / deltaMaxMin) + 2f; - } else { - h = ((rf - gf) / deltaMaxMin) + 4f; - } - - s = deltaMaxMin / (1f - Math.abs(2f * l - 1f)); - } - - h = (h * 60f) % 360f; - if (h < 0) { - h += 360f; - } - - outHsl[0] = constrain(h, 0f, 360f); - outHsl[1] = constrain(s, 0f, 1f); - outHsl[2] = constrain(l, 0f, 1f); - } - - /** - * Convert the ARGB color to its HSL (hue-saturation-lightness) components. - *
    - *
  • outHsl[0] is Hue [0 .. 360)
  • - *
  • outHsl[1] is Saturation [0...1]
  • - *
  • outHsl[2] is Lightness [0...1]
  • - *
- * - * @param color the ARGB color to convert. The alpha component is ignored - * @param outHsl 3-element array which holds the resulting HSL components - */ - public static void colorToHSL(@ColorInt int color, @NonNull float[] outHsl) { - RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), outHsl); - } - - /** - * Convert HSL (hue-saturation-lightness) components to a RGB color. - *
    - *
  • hsl[0] is Hue [0 .. 360)
  • - *
  • hsl[1] is Saturation [0...1]
  • - *
  • hsl[2] is Lightness [0...1]
  • - *
- * If hsv values are out of range, they are pinned. - * - * @param hsl 3-element array which holds the input HSL components - * @return the resulting RGB color - */ - @ColorInt - public static int HSLToColor(@NonNull float[] hsl) { - final float h = hsl[0]; - final float s = hsl[1]; - final float l = hsl[2]; - - final float c = (1f - Math.abs(2 * l - 1f)) * s; - final float m = l - 0.5f * c; - final float x = c * (1f - Math.abs((h / 60f % 2f) - 1f)); - - final int hueSegment = (int) h / 60; - - int r = 0, g = 0, b = 0; - - switch (hueSegment) { - case 0: - r = Math.round(255 * (c + m)); - g = Math.round(255 * (x + m)); - b = Math.round(255 * m); - break; - case 1: - r = Math.round(255 * (x + m)); - g = Math.round(255 * (c + m)); - b = Math.round(255 * m); - break; - case 2: - r = Math.round(255 * m); - g = Math.round(255 * (c + m)); - b = Math.round(255 * (x + m)); - break; - case 3: - r = Math.round(255 * m); - g = Math.round(255 * (x + m)); - b = Math.round(255 * (c + m)); - break; - case 4: - r = Math.round(255 * (x + m)); - g = Math.round(255 * m); - b = Math.round(255 * (c + m)); - break; - case 5: - case 6: - r = Math.round(255 * (c + m)); - g = Math.round(255 * m); - b = Math.round(255 * (x + m)); - break; - } - - r = constrain(r, 0, 255); - g = constrain(g, 0, 255); - b = constrain(b, 0, 255); - - return Color.rgb(r, g, b); - } - - /** - * Set the alpha component of {@code color} to be {@code alpha}. - */ - @ColorInt - public static int setAlphaComponent(@ColorInt int color, - @IntRange(from = 0x0, to = 0xFF) int alpha) { - if (alpha < 0 || alpha > 255) { - throw new IllegalArgumentException("alpha must be between 0 and 255."); - } - return (color & 0x00ffffff) | (alpha << 24); - } - - /** - * Convert the ARGB color to its CIE Lab representative components. - * - * @param color the ARGB color to convert. The alpha component is ignored - * @param outLab 3-element array which holds the resulting LAB components - */ - public static void colorToLAB(@ColorInt int color, @NonNull double[] outLab) { - RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), outLab); - } - - /** - * Convert RGB components to its CIE Lab representative components. - * - *
    - *
  • outLab[0] is L [0 ...1)
  • - *
  • outLab[1] is a [-128...127)
  • - *
  • outLab[2] is b [-128...127)
  • - *
- * - * @param r red component value [0..255] - * @param g green component value [0..255] - * @param b blue component value [0..255] - * @param outLab 3-element array which holds the resulting LAB components - */ - public static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r, - @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b, - @NonNull double[] outLab) { - // First we convert RGB to XYZ - RGBToXYZ(r, g, b, outLab); - // outLab now contains XYZ - XYZToLAB(outLab[0], outLab[1], outLab[2], outLab); - // outLab now contains LAB representation - } - - /** - * Convert the ARGB color to it's CIE XYZ representative components. - * - *

The resulting XYZ representation will use the D65 illuminant and the CIE - * 2° Standard Observer (1931).

- * - *
    - *
  • outXyz[0] is X [0 ...95.047)
  • - *
  • outXyz[1] is Y [0...100)
  • - *
  • outXyz[2] is Z [0...108.883)
  • - *
- * - * @param color the ARGB color to convert. The alpha component is ignored - * @param outXyz 3-element array which holds the resulting LAB components - */ - public static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz) { - RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), outXyz); - } - - /** - * Convert RGB components to it's CIE XYZ representative components. - * - *

The resulting XYZ representation will use the D65 illuminant and the CIE - * 2° Standard Observer (1931).

- * - *
    - *
  • outXyz[0] is X [0 ...95.047)
  • - *
  • outXyz[1] is Y [0...100)
  • - *
  • outXyz[2] is Z [0...108.883)
  • - *
- * - * @param r red component value [0..255] - * @param g green component value [0..255] - * @param b blue component value [0..255] - * @param outXyz 3-element array which holds the resulting XYZ components - */ - public static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r, - @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b, - @NonNull double[] outXyz) { - if (outXyz.length != 3) { - throw new IllegalArgumentException("outXyz must have a length of 3."); - } - - double sr = r / 255.0; - sr = sr < 0.04045 ? sr / 12.92 : Math.pow((sr + 0.055) / 1.055, 2.4); - double sg = g / 255.0; - sg = sg < 0.04045 ? sg / 12.92 : Math.pow((sg + 0.055) / 1.055, 2.4); - double sb = b / 255.0; - sb = sb < 0.04045 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4); - - outXyz[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805); - outXyz[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722); - outXyz[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505); - } - - /** - * Converts a color from CIE XYZ to CIE Lab representation. - * - *

This method expects the XYZ representation to use the D65 illuminant and the CIE - * 2° Standard Observer (1931).

- * - *
    - *
  • outLab[0] is L [0 ...1)
  • - *
  • outLab[1] is a [-128...127)
  • - *
  • outLab[2] is b [-128...127)
  • - *
- * - * @param x X component value [0...95.047) - * @param y Y component value [0...100) - * @param z Z component value [0...108.883) - * @param outLab 3-element array which holds the resulting Lab components - */ - public static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x, - @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y, - @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z, - @NonNull double[] outLab) { - if (outLab.length != 3) { - throw new IllegalArgumentException("outLab must have a length of 3."); - } - x = pivotXyzComponent(x / XYZ_WHITE_REFERENCE_X); - y = pivotXyzComponent(y / XYZ_WHITE_REFERENCE_Y); - z = pivotXyzComponent(z / XYZ_WHITE_REFERENCE_Z); - outLab[0] = Math.max(0, 116 * y - 16); - outLab[1] = 500 * (x - y); - outLab[2] = 200 * (y - z); - } - - /** - * Converts a color from CIE Lab to CIE XYZ representation. - * - *

The resulting XYZ representation will use the D65 illuminant and the CIE - * 2° Standard Observer (1931).

- * - *
    - *
  • outXyz[0] is X [0 ...95.047)
  • - *
  • outXyz[1] is Y [0...100)
  • - *
  • outXyz[2] is Z [0...108.883)
  • - *
- * - * @param l L component value [0...100) - * @param a A component value [-128...127) - * @param b B component value [-128...127) - * @param outXyz 3-element array which holds the resulting XYZ components - */ - public static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l, - @FloatRange(from = -128, to = 127) final double a, - @FloatRange(from = -128, to = 127) final double b, - @NonNull double[] outXyz) { - final double fy = (l + 16) / 116; - final double fx = a / 500 + fy; - final double fz = fy - b / 200; - - double tmp = Math.pow(fx, 3); - final double xr = tmp > XYZ_EPSILON ? tmp : (116 * fx - 16) / XYZ_KAPPA; - final double yr = l > XYZ_KAPPA * XYZ_EPSILON ? Math.pow(fy, 3) : l / XYZ_KAPPA; - - tmp = Math.pow(fz, 3); - final double zr = tmp > XYZ_EPSILON ? tmp : (116 * fz - 16) / XYZ_KAPPA; - - outXyz[0] = xr * XYZ_WHITE_REFERENCE_X; - outXyz[1] = yr * XYZ_WHITE_REFERENCE_Y; - outXyz[2] = zr * XYZ_WHITE_REFERENCE_Z; - } - - /** - * Converts a color from CIE XYZ to its RGB representation. - * - *

This method expects the XYZ representation to use the D65 illuminant and the CIE - * 2° Standard Observer (1931).

- * - * @param x X component value [0...95.047) - * @param y Y component value [0...100) - * @param z Z component value [0...108.883) - * @return int containing the RGB representation - */ - @ColorInt - public static int XYZToColor(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x, - @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y, - @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z) { - double r = (x * 3.2406 + y * -1.5372 + z * -0.4986) / 100; - double g = (x * -0.9689 + y * 1.8758 + z * 0.0415) / 100; - double b = (x * 0.0557 + y * -0.2040 + z * 1.0570) / 100; - - r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r; - g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g; - b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b; - - return Color.rgb( - constrain((int) Math.round(r * 255), 0, 255), - constrain((int) Math.round(g * 255), 0, 255), - constrain((int) Math.round(b * 255), 0, 255)); - } - - /** - * Converts a color from CIE Lab to its RGB representation. - * - * @param l L component value [0...100] - * @param a A component value [-128...127] - * @param b B component value [-128...127] - * @return int containing the RGB representation - */ - @ColorInt - public static int LABToColor(@FloatRange(from = 0f, to = 100) final double l, - @FloatRange(from = -128, to = 127) final double a, - @FloatRange(from = -128, to = 127) final double b) { - final double[] result = getTempDouble3Array(); - LABToXYZ(l, a, b, result); - return XYZToColor(result[0], result[1], result[2]); - } - - /** - * Returns the euclidean distance between two LAB colors. - */ - public static double distanceEuclidean(@NonNull double[] labX, @NonNull double[] labY) { - return Math.sqrt(Math.pow(labX[0] - labY[0], 2) - + Math.pow(labX[1] - labY[1], 2) - + Math.pow(labX[2] - labY[2], 2)); - } - - private static float constrain(float amount, float low, float high) { - return amount < low ? low : (amount > high ? high : amount); - } - - private static int constrain(int amount, int low, int high) { - return amount < low ? low : (amount > high ? high : amount); - } - - private static double pivotXyzComponent(double component) { - return component > XYZ_EPSILON - ? Math.pow(component, 1 / 3.0) - : (XYZ_KAPPA * component + 16) / 116; - } - - /** - * Blend between two ARGB colors using the given ratio. - * - *

A blend ratio of 0.0 will result in {@code color1}, 0.5 will give an even blend, - * 1.0 will result in {@code color2}.

- * - * @param color1 the first ARGB color - * @param color2 the second ARGB color - * @param ratio the blend ratio of {@code color1} to {@code color2} - */ - @ColorInt - public static int blendARGB(@ColorInt int color1, @ColorInt int color2, - @FloatRange(from = 0.0, to = 1.0) float ratio) { - final float inverseRatio = 1 - ratio; - float a = Color.alpha(color1) * inverseRatio + Color.alpha(color2) * ratio; - float r = Color.red(color1) * inverseRatio + Color.red(color2) * ratio; - float g = Color.green(color1) * inverseRatio + Color.green(color2) * ratio; - float b = Color.blue(color1) * inverseRatio + Color.blue(color2) * ratio; - return Color.argb((int) a, (int) r, (int) g, (int) b); - } - - /** - * Blend between {@code hsl1} and {@code hsl2} using the given ratio. This will interpolate - * the hue using the shortest angle. - * - *

A blend ratio of 0.0 will result in {@code hsl1}, 0.5 will give an even blend, - * 1.0 will result in {@code hsl2}.

- * - * @param hsl1 3-element array which holds the first HSL color - * @param hsl2 3-element array which holds the second HSL color - * @param ratio the blend ratio of {@code hsl1} to {@code hsl2} - * @param outResult 3-element array which holds the resulting HSL components - */ - public static void blendHSL(@NonNull float[] hsl1, @NonNull float[] hsl2, - @FloatRange(from = 0.0, to = 1.0) float ratio, @NonNull float[] outResult) { - if (outResult.length != 3) { - throw new IllegalArgumentException("result must have a length of 3."); - } - final float inverseRatio = 1 - ratio; - // Since hue is circular we will need to interpolate carefully - outResult[0] = circularInterpolate(hsl1[0], hsl2[0], ratio); - outResult[1] = hsl1[1] * inverseRatio + hsl2[1] * ratio; - outResult[2] = hsl1[2] * inverseRatio + hsl2[2] * ratio; - } - - /** - * Blend between two CIE-LAB colors using the given ratio. - * - *

A blend ratio of 0.0 will result in {@code lab1}, 0.5 will give an even blend, - * 1.0 will result in {@code lab2}.

- * - * @param lab1 3-element array which holds the first LAB color - * @param lab2 3-element array which holds the second LAB color - * @param ratio the blend ratio of {@code lab1} to {@code lab2} - * @param outResult 3-element array which holds the resulting LAB components - */ - public static void blendLAB(@NonNull double[] lab1, @NonNull double[] lab2, - @FloatRange(from = 0.0, to = 1.0) double ratio, @NonNull double[] outResult) { - if (outResult.length != 3) { - throw new IllegalArgumentException("outResult must have a length of 3."); - } - final double inverseRatio = 1 - ratio; - outResult[0] = lab1[0] * inverseRatio + lab2[0] * ratio; - outResult[1] = lab1[1] * inverseRatio + lab2[1] * ratio; - outResult[2] = lab1[2] * inverseRatio + lab2[2] * ratio; - } - - @VisibleForTesting - static float circularInterpolate(float a, float b, float f) { - if (Math.abs(b - a) > 180) { - if (b > a) { - a += 360; - } else { - b += 360; - } - } - return (a + ((b - a) * f)) % 360; - } - - private static double[] getTempDouble3Array() { - double[] result = TEMP_ARRAY.get(); - if (result == null) { - result = new double[3]; - TEMP_ARRAY.set(result); - } - return result; - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompat.java deleted file mode 100644 index e542af0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompat.java +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.graphics.drawable; - -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.ColorFilter; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.ColorInt; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.v4.view.ViewCompat; -import android.util.AttributeSet; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -/** - * Helper for accessing features in {@link Drawable} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class DrawableCompat { - /** - * Interface for the full API. - */ - interface DrawableImpl { - void jumpToCurrentState(Drawable drawable); - void setAutoMirrored(Drawable drawable, boolean mirrored); - boolean isAutoMirrored(Drawable drawable); - void setHotspot(Drawable drawable, float x, float y); - void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom); - void setTint(Drawable drawable, int tint); - void setTintList(Drawable drawable, ColorStateList tint); - void setTintMode(Drawable drawable, PorterDuff.Mode tintMode); - Drawable wrap(Drawable drawable); - void setLayoutDirection(Drawable drawable, int layoutDirection); - int getLayoutDirection(Drawable drawable); - int getAlpha(Drawable drawable); - void applyTheme(Drawable drawable, Resources.Theme t); - boolean canApplyTheme(Drawable drawable); - ColorFilter getColorFilter(Drawable drawable); - void inflate(Drawable drawable, Resources res, XmlPullParser parser, AttributeSet attrs, - Resources.Theme t) throws IOException, XmlPullParserException; - } - - /** - * Interface implementation that doesn't use anything about v4 APIs. - */ - static class BaseDrawableImpl implements DrawableImpl { - @Override - public void jumpToCurrentState(Drawable drawable) { - } - - @Override - public void setAutoMirrored(Drawable drawable, boolean mirrored) { - } - - @Override - public boolean isAutoMirrored(Drawable drawable) { - return false; - } - - @Override - public void setHotspot(Drawable drawable, float x, float y) { - } - - @Override - public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) { - } - - @Override - public void setTint(Drawable drawable, int tint) { - DrawableCompatBase.setTint(drawable, tint); - } - - @Override - public void setTintList(Drawable drawable, ColorStateList tint) { - DrawableCompatBase.setTintList(drawable, tint); - } - - @Override - public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) { - DrawableCompatBase.setTintMode(drawable, tintMode); - } - - @Override - public Drawable wrap(Drawable drawable) { - return DrawableCompatBase.wrapForTinting(drawable); - } - - @Override - public void setLayoutDirection(Drawable drawable, int layoutDirection) { - // No op for API < 23 - } - - @Override - public int getLayoutDirection(Drawable drawable) { - return ViewCompat.LAYOUT_DIRECTION_LTR; - } - - @Override - public int getAlpha(Drawable drawable) { - return 0; - } - - @Override - public void applyTheme(Drawable drawable, Resources.Theme t) { - } - - @Override - public boolean canApplyTheme(Drawable drawable) { - return false; - } - - @Override - public ColorFilter getColorFilter(Drawable drawable) { - return null; - } - - @Override - public void inflate(Drawable drawable, Resources res, XmlPullParser parser, - AttributeSet attrs, Resources.Theme t) - throws IOException, XmlPullParserException { - DrawableCompatBase.inflate(drawable, res, parser, attrs, t); - } - } - - /** - * Interface implementation for devices with at least v5 APIs. - */ - static class EclairDrawableImpl extends BaseDrawableImpl { - @Override - public Drawable wrap(Drawable drawable) { - return DrawableCompatEclair.wrapForTinting(drawable); - } - } - - /** - * Interface implementation for devices with at least v11 APIs. - */ - static class HoneycombDrawableImpl extends EclairDrawableImpl { - @Override - public void jumpToCurrentState(Drawable drawable) { - DrawableCompatHoneycomb.jumpToCurrentState(drawable); - } - - @Override - public Drawable wrap(Drawable drawable) { - return DrawableCompatHoneycomb.wrapForTinting(drawable); - } - } - - static class JellybeanMr1DrawableImpl extends HoneycombDrawableImpl { - @Override - public void setLayoutDirection(Drawable drawable, int layoutDirection) { - DrawableCompatJellybeanMr1.setLayoutDirection(drawable, layoutDirection); - } - - @Override - public int getLayoutDirection(Drawable drawable) { - final int dir = DrawableCompatJellybeanMr1.getLayoutDirection(drawable); - return dir >= 0 ? dir : ViewCompat.LAYOUT_DIRECTION_LTR; - } - } - - /** - * Interface implementation for devices with at least KitKat APIs. - */ - static class KitKatDrawableImpl extends JellybeanMr1DrawableImpl { - @Override - public void setAutoMirrored(Drawable drawable, boolean mirrored) { - DrawableCompatKitKat.setAutoMirrored(drawable, mirrored); - } - - @Override - public boolean isAutoMirrored(Drawable drawable) { - return DrawableCompatKitKat.isAutoMirrored(drawable); - } - - @Override - public Drawable wrap(Drawable drawable) { - return DrawableCompatKitKat.wrapForTinting(drawable); - } - - @Override - public int getAlpha(Drawable drawable) { - return DrawableCompatKitKat.getAlpha(drawable); - } - } - - /** - * Interface implementation for devices with at least L APIs. - */ - static class LollipopDrawableImpl extends KitKatDrawableImpl { - @Override - public void setHotspot(Drawable drawable, float x, float y) { - DrawableCompatLollipop.setHotspot(drawable, x, y); - } - - @Override - public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) { - DrawableCompatLollipop.setHotspotBounds(drawable, left, top, right, bottom); - } - - @Override - public void setTint(Drawable drawable, int tint) { - DrawableCompatLollipop.setTint(drawable, tint); - } - - @Override - public void setTintList(Drawable drawable, ColorStateList tint) { - DrawableCompatLollipop.setTintList(drawable, tint); - } - - @Override - public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) { - DrawableCompatLollipop.setTintMode(drawable, tintMode); - } - - @Override - public Drawable wrap(Drawable drawable) { - return DrawableCompatLollipop.wrapForTinting(drawable); - } - - @Override - public void applyTheme(Drawable drawable, Resources.Theme t) { - DrawableCompatLollipop.applyTheme(drawable, t); - } - - @Override - public boolean canApplyTheme(Drawable drawable) { - return DrawableCompatLollipop.canApplyTheme(drawable); - } - - @Override - public ColorFilter getColorFilter(Drawable drawable) { - return DrawableCompatLollipop.getColorFilter(drawable); - } - - @Override - public void inflate(Drawable drawable, Resources res, XmlPullParser parser, - AttributeSet attrs, Resources.Theme t) - throws IOException, XmlPullParserException { - DrawableCompatLollipop.inflate(drawable, res, parser, attrs, t); - } - } - - /** - * Interface implementation for devices with at least M APIs. - */ - static class MDrawableImpl extends LollipopDrawableImpl { - @Override - public void setLayoutDirection(Drawable drawable, int layoutDirection) { - DrawableCompatApi23.setLayoutDirection(drawable, layoutDirection); - } - - @Override - public int getLayoutDirection(Drawable drawable) { - return DrawableCompatApi23.getLayoutDirection(drawable); - } - - @Override - public Drawable wrap(Drawable drawable) { - // No need to wrap on M+ - return drawable; - } - } - - /** - * Select the correct implementation to use for the current platform. - */ - static final DrawableImpl IMPL; - static { - final int version = android.os.Build.VERSION.SDK_INT; - if (version >= 23) { - IMPL = new MDrawableImpl(); - } else if (version >= 21) { - IMPL = new LollipopDrawableImpl(); - } else if (version >= 19) { - IMPL = new KitKatDrawableImpl(); - } else if (version >= 17) { - IMPL = new JellybeanMr1DrawableImpl(); - } else if (version >= 11) { - IMPL = new HoneycombDrawableImpl(); - } else if (version >= 5) { - IMPL = new EclairDrawableImpl(); - } else { - IMPL = new BaseDrawableImpl(); - } - } - - /** - * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}. - *

- * If running on a pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB} - * device this method does nothing. - * - * @param drawable The Drawable against which to invoke the method. - */ - public static void jumpToCurrentState(@NonNull Drawable drawable) { - IMPL.jumpToCurrentState(drawable); - } - - /** - * Set whether this Drawable is automatically mirrored when its layout - * direction is RTL (right-to left). See - * {@link android.util.LayoutDirection}. - *

- * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device - * this method does nothing. - * - * @param drawable The Drawable against which to invoke the method. - * @param mirrored Set to true if the Drawable should be mirrored, false if - * not. - */ - public static void setAutoMirrored(@NonNull Drawable drawable, boolean mirrored) { - IMPL.setAutoMirrored(drawable, mirrored); - } - - /** - * Tells if this Drawable will be automatically mirrored when its layout - * direction is RTL right-to-left. See {@link android.util.LayoutDirection}. - *

- * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device - * this method returns false. - * - * @param drawable The Drawable against which to invoke the method. - * @return boolean Returns true if this Drawable will be automatically - * mirrored. - */ - public static boolean isAutoMirrored(@NonNull Drawable drawable) { - return IMPL.isAutoMirrored(drawable); - } - - /** - * Specifies the hotspot's location within the drawable. - * - * @param drawable The Drawable against which to invoke the method. - * @param x The X coordinate of the center of the hotspot - * @param y The Y coordinate of the center of the hotspot - */ - public static void setHotspot(@NonNull Drawable drawable, float x, float y) { - IMPL.setHotspot(drawable, x, y); - } - - /** - * Sets the bounds to which the hotspot is constrained, if they should be - * different from the drawable bounds. - * - * @param drawable The Drawable against which to invoke the method. - */ - public static void setHotspotBounds(@NonNull Drawable drawable, int left, int top, - int right, int bottom) { - IMPL.setHotspotBounds(drawable, left, top, right, bottom); - } - - /** - * Specifies a tint for {@code drawable}. - * - * @param drawable The Drawable against which to invoke the method. - * @param tint Color to use for tinting this drawable - */ - public static void setTint(@NonNull Drawable drawable, @ColorInt int tint) { - IMPL.setTint(drawable, tint); - } - - /** - * Specifies a tint for {@code drawable} as a color state list. - * - * @param drawable The Drawable against which to invoke the method. - * @param tint Color state list to use for tinting this drawable, or null to clear the tint - */ - public static void setTintList(@NonNull Drawable drawable, @Nullable ColorStateList tint) { - IMPL.setTintList(drawable, tint); - } - - /** - * Specifies a tint blending mode for {@code drawable}. - * - * @param drawable The Drawable against which to invoke the method. - * @param tintMode A Porter-Duff blending mode - */ - public static void setTintMode(@NonNull Drawable drawable, @Nullable PorterDuff.Mode tintMode) { - IMPL.setTintMode(drawable, tintMode); - } - - /** - * Get the alpha value of the {@code drawable}. - * 0 means fully transparent, 255 means fully opaque. - * - * @param drawable The Drawable against which to invoke the method. - */ - public static int getAlpha(@NonNull Drawable drawable) { - return IMPL.getAlpha(drawable); - } - - /** - * Applies the specified theme to this Drawable and its children. - */ - public static void applyTheme(Drawable drawable, Resources.Theme t) { - IMPL.applyTheme(drawable, t); - } - - /** - * Whether a theme can be applied to this Drawable and its children. - */ - public static boolean canApplyTheme(Drawable drawable) { - return IMPL.canApplyTheme(drawable); - } - - /** - * Returns the current color filter, or {@code null} if none set. - * - * @return the current color filter, or {@code null} if none set - */ - public static ColorFilter getColorFilter(Drawable drawable) { - return IMPL.getColorFilter(drawable); - } - - /** - * Inflate this Drawable from an XML resource optionally styled by a theme. - * - * @param res Resources used to resolve attribute values - * @param parser XML parser from which to inflate this Drawable - * @param attrs Base set of attribute values - * @param theme Theme to apply, may be null - * @throws XmlPullParserException - * @throws IOException - */ - public static void inflate(Drawable drawable, Resources res, XmlPullParser parser, - AttributeSet attrs, Resources.Theme theme) - throws XmlPullParserException, IOException { - IMPL.inflate(drawable, res, parser, attrs, theme); - } - - /** - * Potentially wrap {@code drawable} so that it may be used for tinting across the - * different API levels, via the tinting methods in this class. - * - *

You must use the result of this call. If the given drawable is being used by a view - * (as it's background for instance), you must replace the original drawable with - * the result of this call:

- * - *
-     * Drawable bg = DrawableCompat.wrap(view.getBackground());
-     * // Need to set the background with the wrapped drawable
-     * view.setBackground(bg);
-     *
-     * // You can now tint the drawable
-     * DrawableCompat.setTint(bg, ...);
-     * 
- * - *

If you need to get hold of the original {@link Drawable} again, - * you can use the value returned from {@link #unwrap(Drawable)}.

- * - * @param drawable The Drawable to process - * @return A drawable capable of being tinted across all API levels. - * - * @see #setTint(Drawable, int) - * @see #setTintList(Drawable, ColorStateList) - * @see #setTintMode(Drawable, PorterDuff.Mode) - * @see #unwrap(Drawable) - */ - public static Drawable wrap(@NonNull Drawable drawable) { - return IMPL.wrap(drawable); - } - - /** - * Unwrap {@code drawable} if it is the result of a call to {@link #wrap(Drawable)}. If - * the {@code drawable} is not the result of a call to {@link #wrap(Drawable)} then - * {@code drawable} is returned as-is. - * - * @param drawable The drawable to unwrap - * @return the unwrapped {@link Drawable} or {@code drawable} if it hasn't been wrapped. - * - * @see #wrap(Drawable) - */ - public static T unwrap(@NonNull Drawable drawable) { - if (drawable instanceof DrawableWrapper) { - return (T) ((DrawableWrapper) drawable).getWrappedDrawable(); - } - return (T) drawable; - } - - /** - * Set the layout direction for this drawable. Should be a resolved - * layout direction, as the Drawable has no capacity to do the resolution on - * its own. - * - * @param layoutDirection the resolved layout direction for the drawable, - * either {@link ViewCompat#LAYOUT_DIRECTION_LTR} - * or {@link ViewCompat#LAYOUT_DIRECTION_RTL} - * @see #getLayoutDirection(Drawable) - */ - public static void setLayoutDirection(@NonNull Drawable drawable, int layoutDirection) { - IMPL.setLayoutDirection(drawable, layoutDirection); - } - - /** - * Returns the resolved layout direction for this Drawable. - * - * @return One of {@link ViewCompat#LAYOUT_DIRECTION_LTR}, - * {@link ViewCompat#LAYOUT_DIRECTION_RTL} - * @see #setLayoutDirection(Drawable, int) - */ - public static int getLayoutDirection(@NonNull Drawable drawable) { - return IMPL.getLayoutDirection(drawable); - } - - private DrawableCompat() {} -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatApi23.java deleted file mode 100644 index 9cd4fe2..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatApi23.java +++ /dev/null @@ -1,32 +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 p.android.support.v4.graphics.drawable; - -import android.graphics.drawable.Drawable; - -/** - * Implementation of drawable compatibility that can call M APIs. - */ -class DrawableCompatApi23 { - public static void setLayoutDirection(Drawable drawable, int layoutDirection) { - drawable.setLayoutDirection(layoutDirection); - } - - public static int getLayoutDirection(Drawable drawable) { - return drawable.getLayoutDirection(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatBase.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatBase.java deleted file mode 100644 index a7eb6ff..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatBase.java +++ /dev/null @@ -1,64 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -/** - * Base implementation of drawable compatibility. - */ -class DrawableCompatBase { - - public static void setTint(Drawable drawable, int tint) { - if (drawable instanceof TintAwareDrawable) { - ((TintAwareDrawable) drawable).setTint(tint); - } - } - - public static void setTintList(Drawable drawable, ColorStateList tint) { - if (drawable instanceof TintAwareDrawable) { - ((TintAwareDrawable) drawable).setTintList(tint); - } - } - - public static void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) { - if (drawable instanceof TintAwareDrawable) { - ((TintAwareDrawable) drawable).setTintMode(tintMode); - } - } - - public static Drawable wrapForTinting(Drawable drawable) { - if (!(drawable instanceof TintAwareDrawable)) { - return new DrawableWrapperDonut(drawable); - } - return drawable; - } - - public static void inflate(Drawable drawable, Resources res, XmlPullParser parser, - AttributeSet attrs, Resources.Theme t) - throws IOException, XmlPullParserException { - drawable.inflate(res, parser, attrs); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatEclair.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatEclair.java deleted file mode 100644 index f34bd22..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatEclair.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.graphics.drawable; - -import android.graphics.drawable.Drawable; - -/** - * Implementation of drawable compatibility that can call Eclair APIs. - */ -class DrawableCompatEclair { - public static Drawable wrapForTinting(Drawable drawable) { - if (!(drawable instanceof TintAwareDrawable)) { - return new DrawableWrapperEclair(drawable); - } - return drawable; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatHoneycomb.java deleted file mode 100644 index a628946..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatHoneycomb.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.graphics.drawable; - -import android.graphics.drawable.Drawable; - -/** - * Implementation of drawable compatibility that can call Honeycomb APIs. - */ -class DrawableCompatHoneycomb { - - public static void jumpToCurrentState(Drawable drawable) { - drawable.jumpToCurrentState(); - } - - public static Drawable wrapForTinting(Drawable drawable) { - if (!(drawable instanceof TintAwareDrawable)) { - return new DrawableWrapperHoneycomb(drawable); - } - return drawable; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatJellybeanMr1.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatJellybeanMr1.java deleted file mode 100644 index cf25b6f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatJellybeanMr1.java +++ /dev/null @@ -1,81 +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 p.android.support.v4.graphics.drawable; - -import android.graphics.drawable.Drawable; -import android.util.Log; - -import java.lang.reflect.Method; - -/** - * Implementation of drawable compatibility that can call Jellybean MR1 APIs. - */ -class DrawableCompatJellybeanMr1 { - - private static final String TAG = "DrawableCompatJellybeanMr1"; - - private static Method sSetLayoutDirectionMethod; - private static boolean sSetLayoutDirectionMethodFetched; - - private static Method sGetLayoutDirectionMethod; - private static boolean sGetLayoutDirectionMethodFetched; - - public static void setLayoutDirection(Drawable drawable, int layoutDirection) { - if (!sSetLayoutDirectionMethodFetched) { - try { - sSetLayoutDirectionMethod = - Drawable.class.getDeclaredMethod("setLayoutDirection", int.class); - sSetLayoutDirectionMethod.setAccessible(true); - } catch (NoSuchMethodException e) { - Log.i(TAG, "Failed to retrieve setLayoutDirection(int) method", e); - } - sSetLayoutDirectionMethodFetched = true; - } - - if (sSetLayoutDirectionMethod != null) { - try { - sSetLayoutDirectionMethod.invoke(drawable, layoutDirection); - } catch (Exception e) { - Log.i(TAG, "Failed to invoke setLayoutDirection(int) via reflection", e); - sSetLayoutDirectionMethod = null; - } - } - } - - public static int getLayoutDirection(Drawable drawable) { - if (!sGetLayoutDirectionMethodFetched) { - try { - sGetLayoutDirectionMethod = Drawable.class.getDeclaredMethod("getLayoutDirection"); - sGetLayoutDirectionMethod.setAccessible(true); - } catch (NoSuchMethodException e) { - Log.i(TAG, "Failed to retrieve getLayoutDirection() method", e); - } - sGetLayoutDirectionMethodFetched = true; - } - - if (sGetLayoutDirectionMethod != null) { - try { - return (int) sGetLayoutDirectionMethod.invoke(drawable); - } catch (Exception e) { - Log.i(TAG, "Failed to invoke getLayoutDirection() via reflection", e); - sGetLayoutDirectionMethod = null; - } - } - return -1; - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatKitKat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatKitKat.java deleted file mode 100644 index 4051d75..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatKitKat.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.graphics.drawable; - -import android.graphics.drawable.Drawable; - -/** - * Implementation of drawable compatibility that can call KitKat APIs. - */ -class DrawableCompatKitKat { - public static void setAutoMirrored(Drawable drawable, boolean mirrored) { - drawable.setAutoMirrored(mirrored); - } - - public static boolean isAutoMirrored(Drawable drawable) { - return drawable.isAutoMirrored(); - } - - public static Drawable wrapForTinting(Drawable drawable) { - if (!(drawable instanceof TintAwareDrawable)) { - return new DrawableWrapperKitKat(drawable); - } - return drawable; - } - - public static int getAlpha(Drawable drawable) { - return drawable.getAlpha(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatLollipop.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatLollipop.java deleted file mode 100644 index fc6f8a8..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableCompatLollipop.java +++ /dev/null @@ -1,80 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.ColorFilter; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; - -/** - * Implementation of drawable compatibility that can call L APIs. - */ -class DrawableCompatLollipop { - - public static void setHotspot(Drawable drawable, float x, float y) { - drawable.setHotspot(x, y); - } - - public static void setHotspotBounds(Drawable drawable, int left, int top, - int right, int bottom) { - drawable.setHotspotBounds( left, top, right, bottom); - } - - public static void setTint(Drawable drawable, int tint) { - drawable.setTint(tint); - } - - public static void setTintList(Drawable drawable, ColorStateList tint) { - drawable.setTintList(tint); - } - - public static void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) { - drawable.setTintMode(tintMode); - } - - public static Drawable wrapForTinting(final Drawable drawable) { - if (!(drawable instanceof TintAwareDrawable)) { - return new DrawableWrapperLollipop(drawable); - } - return drawable; - } - - public static void applyTheme(Drawable drawable, Resources.Theme t) { - drawable.applyTheme(t); - } - - public static boolean canApplyTheme(Drawable drawable) { - return drawable.canApplyTheme(); - } - - public static ColorFilter getColorFilter(Drawable drawable) { - return drawable.getColorFilter(); - } - - public static void inflate(Drawable drawable, Resources res, XmlPullParser parser, - AttributeSet attrs, Resources.Theme t) - throws IOException, XmlPullParserException { - drawable.inflate(res, parser, attrs, t); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapper.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapper.java deleted file mode 100644 index 555de84..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapper.java +++ /dev/null @@ -1,30 +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 p.android.support.v4.graphics.drawable; - -import android.graphics.drawable.Drawable; - -/** - * Interface which allows a {@link Drawable} to get/set wrapped - * drawables from {@code DrawableCompat}. - * - * @hide - */ -public interface DrawableWrapper { - Drawable getWrappedDrawable(); - void setWrappedDrawable(Drawable drawable); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperDonut.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperDonut.java deleted file mode 100644 index f0e2955..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperDonut.java +++ /dev/null @@ -1,383 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.Region; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; - -/** - * Drawable which delegates all calls to it's wrapped {@link Drawable}. - *

- * Also allows backward compatible tinting via a color or {@link ColorStateList}. - * This functionality is accessed via static methods in {@code DrawableCompat}. - */ -class DrawableWrapperDonut extends Drawable - implements Drawable.Callback, DrawableWrapper, TintAwareDrawable { - - static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; - - private int mCurrentColor; - private PorterDuff.Mode mCurrentMode; - private boolean mColorFilterSet; - - DrawableWrapperState mState; - private boolean mMutated; - - Drawable mDrawable; - - DrawableWrapperDonut(@NonNull DrawableWrapperState state, @Nullable Resources res) { - mState = state; - updateLocalState(res); - } - - /** - * Creates a new wrapper around the specified drawable. - * - * @param dr the drawable to wrap - */ - DrawableWrapperDonut(@Nullable Drawable dr) { - mState = mutateConstantState(); - // Now set the drawable... - setWrappedDrawable(dr); - } - - /** - * Initializes local dynamic properties from state. This should be called - * after significant state changes, e.g. from the One True Constructor and - * after inflating or applying a theme. - */ - private void updateLocalState(@Nullable Resources res) { - if (mState != null && mState.mDrawableState != null) { - final Drawable dr = newDrawableFromState(mState.mDrawableState, res); - setWrappedDrawable(dr); - } - } - - /** - * Allows us to call ConstantState.newDrawable(*) is a API safe way - */ - protected Drawable newDrawableFromState(@NonNull ConstantState state, - @Nullable Resources res) { - return state.newDrawable(); - } - - @Override - public void draw(Canvas canvas) { - mDrawable.draw(canvas); - } - - @Override - protected void onBoundsChange(Rect bounds) { - if (mDrawable != null) { - mDrawable.setBounds(bounds); - } - } - - @Override - public void setChangingConfigurations(int configs) { - mDrawable.setChangingConfigurations(configs); - } - - @Override - public int getChangingConfigurations() { - return super.getChangingConfigurations() - | (mState != null ? mState.getChangingConfigurations() : 0) - | mDrawable.getChangingConfigurations(); - } - - @Override - public void setDither(boolean dither) { - mDrawable.setDither(dither); - } - - @Override - public void setFilterBitmap(boolean filter) { - mDrawable.setFilterBitmap(filter); - } - - @Override - public void setAlpha(int alpha) { - mDrawable.setAlpha(alpha); - } - - @Override - public void setColorFilter(ColorFilter cf) { - mDrawable.setColorFilter(cf); - } - - @Override - public boolean isStateful() { - final ColorStateList tintList = (isCompatTintEnabled() && mState != null) - ? mState.mTint - : null; - return (tintList != null && tintList.isStateful()) || mDrawable.isStateful(); - } - - @Override - public boolean setState(final int[] stateSet) { - boolean handled = mDrawable.setState(stateSet); - handled = updateTint(stateSet) || handled; - return handled; - } - - @Override - public int[] getState() { - return mDrawable.getState(); - } - - @Override - public Drawable getCurrent() { - return mDrawable.getCurrent(); - } - - @Override - public boolean setVisible(boolean visible, boolean restart) { - return super.setVisible(visible, restart) || mDrawable.setVisible(visible, restart); - } - - @Override - public int getOpacity() { - return mDrawable.getOpacity(); - } - - @Override - public Region getTransparentRegion() { - return mDrawable.getTransparentRegion(); - } - - @Override - public int getIntrinsicWidth() { - return mDrawable.getIntrinsicWidth(); - } - - @Override - public int getIntrinsicHeight() { - return mDrawable.getIntrinsicHeight(); - } - - @Override - public int getMinimumWidth() { - return mDrawable.getMinimumWidth(); - } - - @Override - public int getMinimumHeight() { - return mDrawable.getMinimumHeight(); - } - - @Override - public boolean getPadding(Rect padding) { - return mDrawable.getPadding(padding); - } - - @Override - @Nullable - public ConstantState getConstantState() { - if (mState != null && mState.canConstantState()) { - mState.mChangingConfigurations = getChangingConfigurations(); - return mState; - } - return null; - } - - @Override - public Drawable mutate() { - if (!mMutated && super.mutate() == this) { - mState = mutateConstantState(); - if (mDrawable != null) { - mDrawable.mutate(); - } - if (mState != null) { - mState.mDrawableState = mDrawable != null ? mDrawable.getConstantState() : null; - } - mMutated = true; - } - return this; - } - - /** - * Mutates the constant state and returns the new state. - *

- * This method should never call the super implementation; it should always - * mutate and return its own constant state. - * - * @return the new state - */ - @NonNull - DrawableWrapperState mutateConstantState() { - return new DrawableWrapperStateDonut(mState, null); - } - - /** - * {@inheritDoc} - */ - public void invalidateDrawable(Drawable who) { - invalidateSelf(); - } - - /** - * {@inheritDoc} - */ - public void scheduleDrawable(Drawable who, Runnable what, long when) { - scheduleSelf(what, when); - } - - /** - * {@inheritDoc} - */ - public void unscheduleDrawable(Drawable who, Runnable what) { - unscheduleSelf(what); - } - - @Override - protected boolean onLevelChange(int level) { - return mDrawable.setLevel(level); - } - - @Override - public void setTint(int tint) { - setTintList(ColorStateList.valueOf(tint)); - } - - @Override - public void setTintList(ColorStateList tint) { - mState.mTint = tint; - updateTint(getState()); - } - - @Override - public void setTintMode(PorterDuff.Mode tintMode) { - mState.mTintMode = tintMode; - updateTint(getState()); - } - - private boolean updateTint(int[] state) { - if (!isCompatTintEnabled()) { - // If compat tinting is not enabled, fail fast - return false; - } - - final ColorStateList tintList = mState.mTint; - final PorterDuff.Mode tintMode = mState.mTintMode; - - if (tintList != null && tintMode != null) { - final int color = tintList.getColorForState(state, tintList.getDefaultColor()); - if (!mColorFilterSet || color != mCurrentColor || tintMode != mCurrentMode) { - setColorFilter(color, tintMode); - mCurrentColor = color; - mCurrentMode = tintMode; - mColorFilterSet = true; - return true; - } - } else { - mColorFilterSet = false; - clearColorFilter(); - } - return false; - } - - /** - * Returns the wrapped {@link Drawable} - */ - public final Drawable getWrappedDrawable() { - return mDrawable; - } - - /** - * Sets the current wrapped {@link Drawable} - */ - public final void setWrappedDrawable(Drawable dr) { - if (mDrawable != null) { - mDrawable.setCallback(null); - } - - mDrawable = dr; - - if (dr != null) { - dr.setCallback(this); - // Only call setters for data that's stored in the base Drawable. - dr.setVisible(isVisible(), true); - dr.setState(getState()); - dr.setLevel(getLevel()); - dr.setBounds(getBounds()); - if (mState != null) { - mState.mDrawableState = dr.getConstantState(); - } - } - - invalidateSelf(); - } - - protected boolean isCompatTintEnabled() { - // It's enabled by default on Donut - return true; - } - - protected static abstract class DrawableWrapperState extends ConstantState { - int mChangingConfigurations; - ConstantState mDrawableState; - - ColorStateList mTint = null; - PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; - - DrawableWrapperState(@Nullable DrawableWrapperState orig, @Nullable Resources res) { - if (orig != null) { - mChangingConfigurations = orig.mChangingConfigurations; - mDrawableState = orig.mDrawableState; - mTint = orig.mTint; - mTintMode = orig.mTintMode; - } - } - - @Override - public Drawable newDrawable() { - return newDrawable(null); - } - - public abstract Drawable newDrawable(@Nullable Resources res); - - @Override - public int getChangingConfigurations() { - return mChangingConfigurations - | (mDrawableState != null ? mDrawableState.getChangingConfigurations() : 0); - } - - boolean canConstantState() { - return mDrawableState != null; - } - } - - private static class DrawableWrapperStateDonut extends DrawableWrapperState { - DrawableWrapperStateDonut( - @Nullable DrawableWrapperState orig, @Nullable Resources res) { - super(orig, res); - } - - @Override - public Drawable newDrawable(@Nullable Resources res) { - return new DrawableWrapperDonut(this, res); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperEclair.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperEclair.java deleted file mode 100644 index afcbe37..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperEclair.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.graphics.drawable; - -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.Nullable; - -class DrawableWrapperEclair extends DrawableWrapperDonut { - - DrawableWrapperEclair(Drawable drawable) { - super(drawable); - } - - DrawableWrapperEclair(DrawableWrapperState state, Resources resources) { - super(state, resources); - } - - @Override - DrawableWrapperState mutateConstantState() { - return new DrawableWrapperStateEclair(mState, null); - } - - @Override - protected Drawable newDrawableFromState(ConstantState state, Resources res) { - return state.newDrawable(res); - } - - private static class DrawableWrapperStateEclair extends DrawableWrapperState { - DrawableWrapperStateEclair(@Nullable DrawableWrapperState orig, - @Nullable Resources res) { - super(orig, res); - } - - @Override - public Drawable newDrawable(@Nullable Resources res) { - return new DrawableWrapperEclair(this, res); - } - } -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperHoneycomb.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperHoneycomb.java deleted file mode 100644 index 7be8a1e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperHoneycomb.java +++ /dev/null @@ -1,56 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; - -class DrawableWrapperHoneycomb extends DrawableWrapperDonut { - - DrawableWrapperHoneycomb(Drawable drawable) { - super(drawable); - } - - DrawableWrapperHoneycomb(DrawableWrapperState state, Resources resources) { - super(state, resources); - } - - @Override - public void jumpToCurrentState() { - mDrawable.jumpToCurrentState(); - } - - @NonNull - @Override - DrawableWrapperState mutateConstantState() { - return new DrawableWrapperStateHoneycomb(mState, null); - } - - private static class DrawableWrapperStateHoneycomb extends DrawableWrapperState { - DrawableWrapperStateHoneycomb(@Nullable DrawableWrapperState orig, - @Nullable Resources res) { - super(orig, res); - } - - @Override - public Drawable newDrawable(@Nullable Resources res) { - return new DrawableWrapperHoneycomb(this, res); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperKitKat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperKitKat.java deleted file mode 100644 index 4c25295..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperKitKat.java +++ /dev/null @@ -1,61 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; - -class DrawableWrapperKitKat extends DrawableWrapperHoneycomb { - - DrawableWrapperKitKat(Drawable drawable) { - super(drawable); - } - - DrawableWrapperKitKat(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); - } - - @Override - public Drawable newDrawable(@Nullable Resources res) { - return new DrawableWrapperKitKat(this, res); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperLollipop.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperLollipop.java deleted file mode 100644 index 5334788..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/DrawableWrapperLollipop.java +++ /dev/null @@ -1,127 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.Outline; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.DrawableContainer; -import android.graphics.drawable.GradientDrawable; -import android.graphics.drawable.InsetDrawable; -import android.os.Build; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; - -class DrawableWrapperLollipop extends DrawableWrapperKitKat { - - DrawableWrapperLollipop(Drawable drawable) { - super(drawable); - } - - DrawableWrapperLollipop(DrawableWrapperState state, Resources resources) { - super(state, resources); - } - - @Override - public void setHotspot(float x, float y) { - mDrawable.setHotspot(x, y); - } - - @Override - public void setHotspotBounds(int left, int top, int right, int bottom) { - mDrawable.setHotspotBounds(left, top, right, bottom); - } - - @Override - public void getOutline(Outline outline) { - mDrawable.getOutline(outline); - } - - @Override - public Rect getDirtyBounds() { - return mDrawable.getDirtyBounds(); - } - - @Override - public void setTintList(ColorStateList tint) { - if (isCompatTintEnabled()) { - super.setTintList(tint); - } else { - mDrawable.setTintList(tint); - } - } - - @Override - public void setTint(int tintColor) { - if (isCompatTintEnabled()) { - super.setTint(tintColor); - } else { - mDrawable.setTint(tintColor); - } - } - - @Override - public void setTintMode(PorterDuff.Mode tintMode) { - if (isCompatTintEnabled()) { - super.setTintMode(tintMode); - } else { - mDrawable.setTintMode(tintMode); - } - } - - @Override - public boolean setState(int[] stateSet) { - if (super.setState(stateSet)) { - // Manually invalidate because the framework doesn't currently force an invalidation - // on a state change - invalidateSelf(); - return true; - } - return false; - } - - @Override - protected boolean isCompatTintEnabled() { - if (Build.VERSION.SDK_INT == 21) { - final Drawable drawable = mDrawable; - return drawable instanceof GradientDrawable || drawable instanceof DrawableContainer - || drawable instanceof InsetDrawable; - } - return false; - } - - @NonNull - @Override - DrawableWrapperState mutateConstantState() { - return new DrawableWrapperStateLollipop(mState, null); - } - - private static class DrawableWrapperStateLollipop extends DrawableWrapperState { - DrawableWrapperStateLollipop(@Nullable DrawableWrapperState orig, - @Nullable Resources res) { - super(orig, res); - } - - @Override - public Drawable newDrawable(@Nullable Resources res) { - return new DrawableWrapperLollipop(this, res); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java deleted file mode 100644 index 38775c9..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java +++ /dev/null @@ -1,393 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapShader; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Shader; -import android.graphics.drawable.Drawable; -import android.util.DisplayMetrics; -import android.view.Gravity; - -/** - * A Drawable that wraps a bitmap and can be drawn with rounded corners. You can create a - * RoundedBitmapDrawable from a file path, an input stream, or from a - * {@link Bitmap} object. - *

- * Also see the {@link Bitmap} class, which handles the management and - * transformation of raw bitmap graphics, and should be used when drawing to a - * {@link Canvas}. - *

- */ -public abstract class RoundedBitmapDrawable extends Drawable { - private static final int DEFAULT_PAINT_FLAGS = - Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG; - final Bitmap mBitmap; - private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; - private int mGravity = Gravity.FILL; - private final Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS); - private final BitmapShader mBitmapShader; - private final Matrix mShaderMatrix = new Matrix(); - private float mCornerRadius; - - final Rect mDstRect = new Rect(); // Gravity.apply() sets this - private final RectF mDstRectF = new RectF(); - - private boolean mApplyGravity = true; - private boolean mIsCircular; - - // These are scaled to match the target density. - private int mBitmapWidth; - private int mBitmapHeight; - - /** - * Returns the paint used to render this drawable. - */ - public final Paint getPaint() { - return mPaint; - } - - /** - * Returns the bitmap used by this drawable to render. May be null. - */ - public final Bitmap getBitmap() { - return mBitmap; - } - - private void computeBitmapSize() { - mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity); - mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity); - } - - /** - * Set the density scale at which this drawable will be rendered. This - * method assumes the drawable will be rendered at the same density as the - * specified canvas. - * - * @param canvas The Canvas from which the density scale must be obtained. - * - * @see Bitmap#setDensity(int) - * @see Bitmap#getDensity() - */ - public void setTargetDensity(Canvas canvas) { - setTargetDensity(canvas.getDensity()); - } - - /** - * Set the density scale at which this drawable will be rendered. - * - * @param metrics The DisplayMetrics indicating the density scale for this drawable. - * - * @see Bitmap#setDensity(int) - * @see Bitmap#getDensity() - */ - public void setTargetDensity(DisplayMetrics metrics) { - setTargetDensity(metrics.densityDpi); - } - - /** - * Set the density at which this drawable will be rendered. - * - * @param density The density scale for this drawable. - * - * @see Bitmap#setDensity(int) - * @see Bitmap#getDensity() - */ - public void setTargetDensity(int density) { - if (mTargetDensity != density) { - mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density; - if (mBitmap != null) { - computeBitmapSize(); - } - invalidateSelf(); - } - } - - /** - * Get the gravity used to position/stretch the bitmap within its bounds. - * - * @return the gravity applied to the bitmap - * - * @see Gravity - */ - public int getGravity() { - return mGravity; - } - - /** - * Set the gravity used to position/stretch the bitmap within its bounds. - * - * @param gravity the gravity - * - * @see Gravity - */ - public void setGravity(int gravity) { - if (mGravity != gravity) { - mGravity = gravity; - mApplyGravity = true; - invalidateSelf(); - } - } - - /** - * Enables or disables the mipmap hint for this drawable's bitmap. - * See {@link Bitmap#setHasMipMap(boolean)} for more information. - * - * If the bitmap is null, or the current API version does not support setting a mipmap hint, - * calling this method has no effect. - * - * @param mipMap True if the bitmap should use mipmaps, false otherwise. - * - * @see #hasMipMap() - */ - public void setMipMap(boolean mipMap) { - throw new UnsupportedOperationException(); // must be overridden in subclasses - } - - /** - * Indicates whether the mipmap hint is enabled on this drawable's bitmap. - * - * @return True if the mipmap hint is set, false otherwise. If the bitmap - * is null, this method always returns false. - * - * @see #setMipMap(boolean) - */ - public boolean hasMipMap() { - throw new UnsupportedOperationException(); // must be overridden in subclasses - } - - /** - * Enables or disables anti-aliasing for this drawable. Anti-aliasing affects - * the edges of the bitmap only so it applies only when the drawable is rotated. - * - * @param aa True if the bitmap should be anti-aliased, false otherwise. - * - * @see #hasAntiAlias() - */ - public void setAntiAlias(boolean aa) { - mPaint.setAntiAlias(aa); - invalidateSelf(); - } - - /** - * Indicates whether anti-aliasing is enabled for this drawable. - * - * @return True if anti-aliasing is enabled, false otherwise. - * - * @see #setAntiAlias(boolean) - */ - public boolean hasAntiAlias() { - return mPaint.isAntiAlias(); - } - - @Override - public void setFilterBitmap(boolean filter) { - mPaint.setFilterBitmap(filter); - invalidateSelf(); - } - - @Override - public void setDither(boolean dither) { - mPaint.setDither(dither); - invalidateSelf(); - } - - void gravityCompatApply(int gravity, int bitmapWidth, int bitmapHeight, - Rect bounds, Rect outRect) { - throw new UnsupportedOperationException(); - } - - void updateDstRect() { - if (mApplyGravity) { - if (mIsCircular) { - final int minDimen = Math.min(mBitmapWidth, mBitmapHeight); - gravityCompatApply(mGravity, minDimen, minDimen, getBounds(), mDstRect); - - // inset the drawing rectangle to the largest contained square, - // so that a circle will be drawn - final int minDrawDimen = Math.min(mDstRect.width(), mDstRect.height()); - final int insetX = Math.max(0, (mDstRect.width() - minDrawDimen) / 2); - final int insetY = Math.max(0, (mDstRect.height() - minDrawDimen) / 2); - mDstRect.inset(insetX, insetY); - mCornerRadius = 0.5f * minDrawDimen; - } else { - gravityCompatApply(mGravity, mBitmapWidth, mBitmapHeight, getBounds(), mDstRect); - } - mDstRectF.set(mDstRect); - - if (mBitmapShader != null) { - // setup shader matrix - mShaderMatrix.setTranslate(mDstRectF.left,mDstRectF.top); - mShaderMatrix.preScale( - mDstRectF.width() / mBitmap.getWidth(), - mDstRectF.height() / mBitmap.getHeight()); - mBitmapShader.setLocalMatrix(mShaderMatrix); - mPaint.setShader(mBitmapShader); - } - - mApplyGravity = false; - } - } - - @Override - public void draw(Canvas canvas) { - final Bitmap bitmap = mBitmap; - if (bitmap == null) { - return; - } - - updateDstRect(); - if (mPaint.getShader() == null) { - canvas.drawBitmap(bitmap, null, mDstRect, mPaint); - } else { - canvas.drawRoundRect(mDstRectF, mCornerRadius, mCornerRadius, mPaint); - } - } - - @Override - public void setAlpha(int alpha) { - final int oldAlpha = mPaint.getAlpha(); - if (alpha != oldAlpha) { - mPaint.setAlpha(alpha); - invalidateSelf(); - } - } - - public int getAlpha() { - return mPaint.getAlpha(); - } - - @Override - public void setColorFilter(ColorFilter cf) { - mPaint.setColorFilter(cf); - invalidateSelf(); - } - - public ColorFilter getColorFilter() { - return mPaint.getColorFilter(); - } - - /** - * Sets the image shape to circular. - *

This overwrites any calls made to {@link #setCornerRadius(float)} so far.

- */ - public void setCircular(boolean circular) { - mIsCircular = circular; - mApplyGravity = true; - if (circular) { - updateCircularCornerRadius(); - mPaint.setShader(mBitmapShader); - invalidateSelf(); - } else { - setCornerRadius(0); - } - } - - private void updateCircularCornerRadius() { - final int minCircularSize = Math.min(mBitmapHeight, mBitmapWidth); - mCornerRadius = minCircularSize / 2; - } - - /** - * @return true if the image is circular, else false. - */ - public boolean isCircular() { - return mIsCircular; - } - - /** - * Sets the corner radius to be applied when drawing the bitmap. - */ - public void setCornerRadius(float cornerRadius) { - if (mCornerRadius == cornerRadius) return; - - mIsCircular = false; - if (isGreaterThanZero(cornerRadius)) { - mPaint.setShader(mBitmapShader); - } else { - mPaint.setShader(null); - } - - mCornerRadius = cornerRadius; - invalidateSelf(); - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - if (mIsCircular) { - updateCircularCornerRadius(); - } - mApplyGravity = true; - } - - /** - * @return The corner radius applied when drawing the bitmap. - */ - public float getCornerRadius() { - return mCornerRadius; - } - - @Override - public int getIntrinsicWidth() { - return mBitmapWidth; - } - - @Override - public int getIntrinsicHeight() { - return mBitmapHeight; - } - - @Override - public int getOpacity() { - if (mGravity != Gravity.FILL || mIsCircular) { - return PixelFormat.TRANSLUCENT; - } - Bitmap bm = mBitmap; - return (bm == null - || bm.hasAlpha() - || mPaint.getAlpha() < 255 - || isGreaterThanZero(mCornerRadius)) - ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; - } - - RoundedBitmapDrawable(Resources res, Bitmap bitmap) { - if (res != null) { - mTargetDensity = res.getDisplayMetrics().densityDpi; - } - - mBitmap = bitmap; - if (mBitmap != null) { - computeBitmapSize(); - mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - } else { - mBitmapWidth = mBitmapHeight = -1; - mBitmapShader = null; - } - } - - private static boolean isGreaterThanZero(float toCompare) { - return toCompare > 0.05f; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java deleted file mode 100644 index c4ebec8..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java +++ /dev/null @@ -1,56 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Outline; -import android.graphics.Rect; -import android.view.Gravity; -import android.view.View; - -class RoundedBitmapDrawable21 extends RoundedBitmapDrawable { - protected RoundedBitmapDrawable21(Resources res, Bitmap bitmap) { - super(res, bitmap); - } - - @Override - public void getOutline(Outline outline) { - updateDstRect(); - outline.setRoundRect(mDstRect, getCornerRadius()); - } - - @Override - public void setMipMap(boolean mipMap) { - if (mBitmap != null) { - mBitmap.setHasMipMap(mipMap); - invalidateSelf(); - } - } - - @Override - public boolean hasMipMap() { - return mBitmap != null && mBitmap.hasMipMap(); - } - - @Override - void gravityCompatApply(int gravity, int bitmapWidth, int bitmapHeight, - Rect bounds, Rect outRect) { - Gravity.apply(gravity, bitmapWidth, bitmapHeight, - bounds, outRect, View.LAYOUT_DIRECTION_LTR); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java deleted file mode 100644 index cf2e445..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java +++ /dev/null @@ -1,100 +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 p.android.support.v4.graphics.drawable; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Rect; -import android.os.Build; -import p.android.support.v4.graphics.BitmapCompat; -import p.android.support.v4.view.GravityCompat; -import p.android.support.v4.view.ViewCompat; -import android.util.Log; - -/** - * Constructs {@link RoundedBitmapDrawable RoundedBitmapDrawable} objects, - * either from Bitmaps directly, or from streams and files. - */ -public final class RoundedBitmapDrawableFactory { - private static final String TAG = "RoundedBitmapDrawableFactory"; - - private static class DefaultRoundedBitmapDrawable extends RoundedBitmapDrawable { - DefaultRoundedBitmapDrawable(Resources res, Bitmap bitmap) { - super(res, bitmap); - } - - @Override - public void setMipMap(boolean mipMap) { - if (mBitmap != null) { - BitmapCompat.setHasMipMap(mBitmap, mipMap); - invalidateSelf(); - } - } - - @Override - public boolean hasMipMap() { - return mBitmap != null && BitmapCompat.hasMipMap(mBitmap); - } - - @Override - void gravityCompatApply(int gravity, int bitmapWidth, int bitmapHeight, - Rect bounds, Rect outRect) { - GravityCompat.apply(gravity, bitmapWidth, bitmapHeight, - bounds, outRect, ViewCompat.LAYOUT_DIRECTION_LTR); - } - } - - /** - * Returns a new drawable by creating it from a bitmap, setting initial target density based on - * the display metrics of the resources. - */ - public static RoundedBitmapDrawable create(Resources res, Bitmap bitmap) { - if (Build.VERSION.SDK_INT >= 21) { - return new RoundedBitmapDrawable21(res, bitmap); - } - return new DefaultRoundedBitmapDrawable(res, bitmap); - } - - /** - * Returns a new drawable, creating it by opening a given file path and decoding the bitmap. - */ - public static RoundedBitmapDrawable create(Resources res, - String filepath) { - final RoundedBitmapDrawable drawable = create(res, BitmapFactory.decodeFile(filepath)); - if (drawable.getBitmap() == null) { - Log.w(TAG, "RoundedBitmapDrawable cannot decode " + filepath); - } - return drawable; - } - - - /** - * Returns a new drawable, creating it by decoding a bitmap from the given input stream. - */ - public static RoundedBitmapDrawable create(Resources res, - java.io.InputStream is) { - final RoundedBitmapDrawable drawable = create(res, BitmapFactory.decodeStream(is)); - if (drawable.getBitmap() == null) { - Log.w(TAG, "RoundedBitmapDrawable cannot decode " + is); - } - return drawable; - } - - private RoundedBitmapDrawableFactory() {} - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/TintAwareDrawable.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/TintAwareDrawable.java deleted file mode 100644 index ff2f593..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/graphics/drawable/TintAwareDrawable.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.graphics.drawable; - -import android.content.res.ColorStateList; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import p.android.support.annotation.ColorInt; - -/** - * Interface which allows a {@link Drawable} to receive tinting calls - * from {@code DrawableCompat}. - * - * @hide - */ -public interface TintAwareDrawable { - void setTint(@ColorInt int tint); - void setTintList(ColorStateList tint); - void setTintMode(PorterDuff.Mode tintMode); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/display/DisplayManagerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/display/DisplayManagerCompat.java deleted file mode 100644 index d96dff1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/display/DisplayManagerCompat.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.hardware.display; - -import android.content.Context; -import android.view.Display; -import android.view.WindowManager; - -import java.util.WeakHashMap; - -/** - * Helper for accessing features in {@link android.hardware.display.DisplayManager} - * introduced after API level 4 in a backwards compatible fashion. - */ -public abstract class DisplayManagerCompat { - private static final WeakHashMap sInstances = - new WeakHashMap(); - - /** - * Display category: Presentation displays. - *

- * This category can be used to identify secondary displays that are suitable for - * use as presentation displays. - *

- * - * @see android.app.Presentation for information about presenting content - * on secondary displays. - * @see #getDisplays(String) - */ - public static final String DISPLAY_CATEGORY_PRESENTATION = - "android.hardware.display.category.PRESENTATION"; - - DisplayManagerCompat() { - } - - /** - * Gets an instance of the display manager given the context. - */ - public static DisplayManagerCompat getInstance(Context context) { - synchronized (sInstances) { - DisplayManagerCompat instance = sInstances.get(context); - if (instance == null) { - final int version = android.os.Build.VERSION.SDK_INT; - if (version >= 17) { - instance = new JellybeanMr1Impl(context); - } else { - instance = new LegacyImpl(context); - } - sInstances.put(context, instance); - } - return instance; - } - } - - /** - * Gets information about a logical display. - * - * The display metrics may be adjusted to provide compatibility - * for legacy applications. - * - * @param displayId The logical display id. - * @return The display object, or null if there is no valid display with the given id. - */ - public abstract Display getDisplay(int displayId); - - /** - * Gets all currently valid logical displays. - * - * @return An array containing all displays. - */ - public abstract Display[] getDisplays(); - - /** - * Gets all currently valid logical displays of the specified category. - *

- * When there are multiple displays in a category the returned displays are sorted - * of preference. For example, if the requested category is - * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays - * then the displays are sorted so that the first display in the returned array - * is the most preferred presentation display. The application may simply - * use the first display or allow the user to choose. - *

- * - * @param category The requested display category or null to return all displays. - * @return An array containing all displays sorted by order of preference. - * - * @see #DISPLAY_CATEGORY_PRESENTATION - */ - public abstract Display[] getDisplays(String category); - - private static class LegacyImpl extends DisplayManagerCompat { - private final WindowManager mWindowManager; - - public LegacyImpl(Context context) { - mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - } - - @Override - public Display getDisplay(int displayId) { - Display display = mWindowManager.getDefaultDisplay(); - if (display.getDisplayId() == displayId) { - return display; - } - return null; - } - - @Override - public Display[] getDisplays() { - return new Display[] { mWindowManager.getDefaultDisplay() }; - } - - @Override - public Display[] getDisplays(String category) { - return category == null ? getDisplays() : new Display[0]; - } - } - - private static class JellybeanMr1Impl extends DisplayManagerCompat { - private final Object mDisplayManagerObj; - - public JellybeanMr1Impl(Context context) { - mDisplayManagerObj = DisplayManagerJellybeanMr1.getDisplayManager(context); - } - - @Override - public Display getDisplay(int displayId) { - return DisplayManagerJellybeanMr1.getDisplay(mDisplayManagerObj, displayId); - } - - @Override - public Display[] getDisplays() { - return DisplayManagerJellybeanMr1.getDisplays(mDisplayManagerObj); - } - - @Override - public Display[] getDisplays(String category) { - return DisplayManagerJellybeanMr1.getDisplays(mDisplayManagerObj, category); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/display/DisplayManagerJellybeanMr1.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/display/DisplayManagerJellybeanMr1.java deleted file mode 100644 index 48694ee..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/display/DisplayManagerJellybeanMr1.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.hardware.display; - -import android.content.Context; -import android.view.Display; - -final class DisplayManagerJellybeanMr1 { - public static Object getDisplayManager(Context context) { - return context.getSystemService(Context.DISPLAY_SERVICE); - } - - public static Display getDisplay(Object displayManagerObj, int displayId) { - return ((android.hardware.display.DisplayManager)displayManagerObj).getDisplay(displayId); - } - - public static Display[] getDisplays(Object displayManagerObj) { - return ((android.hardware.display.DisplayManager)displayManagerObj).getDisplays(); - } - - public static Display[] getDisplays(Object displayManagerObj, String category) { - return ((android.hardware.display.DisplayManager)displayManagerObj).getDisplays(category); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java deleted file mode 100644 index 11d1723..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java +++ /dev/null @@ -1,312 +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 p.android.support.v4.hardware.fingerprint; - -import android.content.Context; -import android.os.Build; -import android.os.Handler; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.v4.os.CancellationSignal; - -import java.security.Signature; - -import javax.crypto.Cipher; -import javax.crypto.Mac; - -/** - * A class that coordinates access to the fingerprint hardware. - *

- * On platforms before {@link Build.VERSION_CODES#M}, this class behaves as there would - * be no fingerprint hardware available. - */ -public final class FingerprintManagerCompat { - - private Context mContext; - - /** Get a {@link FingerprintManagerCompat} instance for a provided context. */ - public static FingerprintManagerCompat from(Context context) { - return new FingerprintManagerCompat(context); - } - - private FingerprintManagerCompat(Context context) { - mContext = context; - } - - static final FingerprintManagerCompatImpl IMPL; - static { - final int version = Build.VERSION.SDK_INT; - if (version >= 23) { - IMPL = new Api23FingerprintManagerCompatImpl(); - } else { - IMPL = new LegacyFingerprintManagerCompatImpl(); - } - } - - /** - * Determine if there is at least one fingerprint enrolled. - * - * @return true if at least one fingerprint is enrolled, false otherwise - */ - public boolean hasEnrolledFingerprints() { - return IMPL.hasEnrolledFingerprints(mContext); - } - - /** - * Determine if fingerprint hardware is present and functional. - * - * @return true if hardware is present and functional, false otherwise. - */ - public boolean isHardwareDetected() { - return IMPL.isHardwareDetected(mContext); - } - - /** - * Request authentication of a crypto object. This call warms up the fingerprint hardware - * and starts scanning for a fingerprint. It terminates when - * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or - * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at - * which point the object is no longer valid. The operation can be canceled by using the - * provided cancel object. - * - * @param crypto object associated with the call or null if none required. - * @param flags optional flags; should be 0 - * @param cancel an object that can be used to cancel authentication - * @param callback an object to receive authentication events - * @param handler an optional handler for events - */ - public void authenticate(@Nullable CryptoObject crypto, int flags, - @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, - @Nullable Handler handler) { - IMPL.authenticate(mContext, crypto, flags, cancel, callback, handler); - } - - /** - * A wrapper class for the crypto objects supported by FingerprintManager. Currently the - * framework supports {@link Signature} and {@link Cipher} objects. - */ - public static class CryptoObject { - - private final Signature mSignature; - private final Cipher mCipher; - private final Mac mMac; - - public CryptoObject(Signature signature) { - mSignature = signature; - mCipher = null; - mMac = null; - - } - - public CryptoObject(Cipher cipher) { - mCipher = cipher; - mSignature = null; - mMac = null; - } - - public CryptoObject(Mac mac) { - mMac = mac; - mCipher = null; - mSignature = null; - } - - /** - * Get {@link Signature} object. - * @return {@link Signature} object or null if this doesn't contain one. - */ - public Signature getSignature() { return mSignature; } - - /** - * Get {@link Cipher} object. - * @return {@link Cipher} object or null if this doesn't contain one. - */ - public Cipher getCipher() { return mCipher; } - - /** - * Get {@link Mac} object. - * @return {@link Mac} object or null if this doesn't contain one. - */ - public Mac getMac() { return mMac; } - } - - /** - * Container for callback data from {@link FingerprintManagerCompat#authenticate(CryptoObject, - * int, CancellationSignal, AuthenticationCallback, Handler)}. - */ - public static final class AuthenticationResult { - private CryptoObject mCryptoObject; - - public AuthenticationResult(CryptoObject crypto) { - mCryptoObject = crypto; - } - - /** - * Obtain the crypto object associated with this transaction - * @return crypto object provided to {@link FingerprintManagerCompat#authenticate( - * CryptoObject, int, CancellationSignal, AuthenticationCallback, Handler)}. - */ - public CryptoObject getCryptoObject() { return mCryptoObject; } - } - - /** - * Callback structure provided to {@link FingerprintManagerCompat#authenticate(CryptoObject, - * int, CancellationSignal, AuthenticationCallback, Handler)}. Users of {@link - * FingerprintManagerCompat#authenticate(CryptoObject, int, CancellationSignal, - * AuthenticationCallback, Handler) } must provide an implementation of this for listening to - * fingerprint events. - */ - public static abstract class AuthenticationCallback { - /** - * Called when an unrecoverable error has been encountered and the operation is complete. - * No further callbacks will be made on this object. - * @param errMsgId An integer identifying the error message - * @param errString A human-readable error string that can be shown in UI - */ - public void onAuthenticationError(int errMsgId, CharSequence errString) { } - - /** - * Called when a recoverable error has been encountered during authentication. The help - * string is provided to give the user guidance for what went wrong, such as - * "Sensor dirty, please clean it." - * @param helpMsgId An integer identifying the error message - * @param helpString A human-readable string that can be shown in UI - */ - public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { } - - /** - * Called when a fingerprint is recognized. - * @param result An object containing authentication-related data - */ - public void onAuthenticationSucceeded(AuthenticationResult result) { } - - /** - * Called when a fingerprint is valid but not recognized. - */ - public void onAuthenticationFailed() { } - } - - private interface FingerprintManagerCompatImpl { - boolean hasEnrolledFingerprints(Context context); - boolean isHardwareDetected(Context context); - void authenticate(Context context, CryptoObject crypto, int flags, - CancellationSignal cancel, AuthenticationCallback callback, Handler handler); - } - - private static class LegacyFingerprintManagerCompatImpl - implements FingerprintManagerCompatImpl { - - public LegacyFingerprintManagerCompatImpl() { - } - - @Override - public boolean hasEnrolledFingerprints(Context context) { - return false; - } - - @Override - public boolean isHardwareDetected(Context context) { - return false; - } - - @Override - public void authenticate(Context context, CryptoObject crypto, int flags, - CancellationSignal cancel, AuthenticationCallback callback, Handler handler) { - // TODO: Figure out behavior when there is no fingerprint hardware available - } - } - - private static class Api23FingerprintManagerCompatImpl implements FingerprintManagerCompatImpl { - - public Api23FingerprintManagerCompatImpl() { - } - - @Override - public boolean hasEnrolledFingerprints(Context context) { - return FingerprintManagerCompatApi23.hasEnrolledFingerprints(context); - } - - @Override - public boolean isHardwareDetected(Context context) { - return FingerprintManagerCompatApi23.isHardwareDetected(context); - } - - @Override - public void authenticate(Context context, CryptoObject crypto, int flags, - CancellationSignal cancel, AuthenticationCallback callback, Handler handler) { - FingerprintManagerCompatApi23.authenticate(context, wrapCryptoObject(crypto), flags, - cancel != null ? cancel.getCancellationSignalObject() : null, - wrapCallback(callback), handler); - } - - private static FingerprintManagerCompatApi23.CryptoObject wrapCryptoObject( - CryptoObject cryptoObject) { - if (cryptoObject == null) { - return null; - } else if (cryptoObject.getCipher() != null) { - return new FingerprintManagerCompatApi23.CryptoObject(cryptoObject.getCipher()); - } else if (cryptoObject.getSignature() != null) { - return new FingerprintManagerCompatApi23.CryptoObject(cryptoObject.getSignature()); - } else if (cryptoObject.getMac() != null) { - return new FingerprintManagerCompatApi23.CryptoObject(cryptoObject.getMac()); - } else { - return null; - } - } - - private static CryptoObject unwrapCryptoObject( - FingerprintManagerCompatApi23.CryptoObject cryptoObject) { - if (cryptoObject == null) { - return null; - } else if (cryptoObject.getCipher() != null) { - return new CryptoObject(cryptoObject.getCipher()); - } else if (cryptoObject.getSignature() != null) { - return new CryptoObject(cryptoObject.getSignature()); - } else if (cryptoObject.getMac() != null) { - return new CryptoObject(cryptoObject.getMac()); - } else { - return null; - } - } - - private static FingerprintManagerCompatApi23.AuthenticationCallback wrapCallback( - final AuthenticationCallback callback) { - return new FingerprintManagerCompatApi23.AuthenticationCallback() { - @Override - public void onAuthenticationError(int errMsgId, CharSequence errString) { - callback.onAuthenticationError(errMsgId, errString); - } - - @Override - public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { - callback.onAuthenticationHelp(helpMsgId, helpString); - } - - @Override - public void onAuthenticationSucceeded( - FingerprintManagerCompatApi23.AuthenticationResultInternal result) { - callback.onAuthenticationSucceeded(new AuthenticationResult( - unwrapCryptoObject(result.getCryptoObject()))); - } - - @Override - public void onAuthenticationFailed() { - callback.onAuthenticationFailed(); - } - }; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java deleted file mode 100644 index cc73aa6..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java +++ /dev/null @@ -1,153 +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 p.android.support.v4.hardware.fingerprint; - -import android.content.Context; -import android.hardware.fingerprint.FingerprintManager; -import android.os.Handler; - -import java.security.Signature; - -import javax.crypto.Cipher; -import javax.crypto.Mac; - -/** - * Actual FingerprintManagerCompat implementation for API level 23 and later. - * @hide - */ -public final class FingerprintManagerCompatApi23 { - - private static FingerprintManager getFingerprintManager(Context ctx) { - return ctx.getSystemService(FingerprintManager.class); - } - - public static boolean hasEnrolledFingerprints(Context context) { - return getFingerprintManager(context).hasEnrolledFingerprints(); - } - - public static boolean isHardwareDetected(Context context) { - return getFingerprintManager(context).isHardwareDetected(); - } - - public static void authenticate(Context context, CryptoObject crypto, int flags, Object cancel, - AuthenticationCallback callback, Handler handler) { - getFingerprintManager(context).authenticate(wrapCryptoObject(crypto), - (android.os.CancellationSignal) cancel, flags, - wrapCallback(callback), handler); - } - - private static FingerprintManager.CryptoObject wrapCryptoObject(CryptoObject cryptoObject) { - if (cryptoObject == null) { - return null; - } else if (cryptoObject.getCipher() != null) { - return new FingerprintManager.CryptoObject(cryptoObject.getCipher()); - } else if (cryptoObject.getSignature() != null) { - return new FingerprintManager.CryptoObject(cryptoObject.getSignature()); - } else if (cryptoObject.getMac() != null) { - return new FingerprintManager.CryptoObject(cryptoObject.getMac()); - } else { - return null; - } - } - - private static CryptoObject unwrapCryptoObject(FingerprintManager.CryptoObject cryptoObject) { - if (cryptoObject == null) { - return null; - } else if (cryptoObject.getCipher() != null) { - return new CryptoObject(cryptoObject.getCipher()); - } else if (cryptoObject.getSignature() != null) { - return new CryptoObject(cryptoObject.getSignature()); - } else if (cryptoObject.getMac() != null) { - return new CryptoObject(cryptoObject.getMac()); - } else { - return null; - } - } - - private static FingerprintManager.AuthenticationCallback wrapCallback( - final AuthenticationCallback callback) { - return new FingerprintManager.AuthenticationCallback() { - @Override - public void onAuthenticationError(int errMsgId, CharSequence errString) { - callback.onAuthenticationError(errMsgId, errString); - } - - @Override - public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { - callback.onAuthenticationHelp(helpMsgId, helpString); - } - - @Override - public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { - callback.onAuthenticationSucceeded(new AuthenticationResultInternal( - unwrapCryptoObject(result.getCryptoObject()))); - } - - @Override - public void onAuthenticationFailed() { - callback.onAuthenticationFailed(); - } - }; - } - - public static class CryptoObject { - - private final Signature mSignature; - private final Cipher mCipher; - private final Mac mMac; - - public CryptoObject(Signature signature) { - mSignature = signature; - mCipher = null; - mMac = null; - } - - public CryptoObject(Cipher cipher) { - mCipher = cipher; - mSignature = null; - mMac = null; - } - - public CryptoObject(Mac mac) { - mMac = mac; - mCipher = null; - mSignature = null; - } - - public Signature getSignature() { return mSignature; } - public Cipher getCipher() { return mCipher; } - public Mac getMac() { return mMac; } - } - - public static final class AuthenticationResultInternal { - private CryptoObject mCryptoObject; - - public AuthenticationResultInternal(CryptoObject crypto) { - mCryptoObject = crypto; - } - - public CryptoObject getCryptoObject() { return mCryptoObject; } - } - - public static abstract class AuthenticationCallback { - - public void onAuthenticationError(int errMsgId, CharSequence errString) { } - public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { } - public void onAuthenticationSucceeded(AuthenticationResultInternal result) { } - public void onAuthenticationFailed() { } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportMenu.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportMenu.java deleted file mode 100644 index 6f4c86d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportMenu.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.internal.view; - -/** - * Interface for managing the items in a menu. - * - * This version extends the one available in the framework to ensures that any necessary - * elements added in later versions of the framework, are available for all platforms. - * - * @see android.view.Menu - * @hide - */ -public interface SupportMenu extends android.view.Menu { - - /** - * This is the part of an order integer that the user can provide. - * - * @hide - */ - static final int USER_MASK = 0x0000ffff; - /** - * Bit shift of the user portion of the order integer. - * - * @hide - */ - static final int USER_SHIFT = 0; - - /** - * This is the part of an order integer that supplies the category of the item. - * - * @hide - */ - static final int CATEGORY_MASK = 0xffff0000; - /** - * Bit shift of the category portion of the order integer. - * - * @hide - */ - static final int CATEGORY_SHIFT = 16; -} - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportMenuItem.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportMenuItem.java deleted file mode 100644 index 28ee43c..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportMenuItem.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.internal.view; - -import p.android.support.v4.view.ActionProvider; -import p.android.support.v4.view.MenuItemCompat; -import android.view.MenuItem; -import android.view.View; - -/** - * Interface for direct access to a previously created menu item. - * - * This version extends the one available in the framework to ensures that any necessary - * elements added in later versions of the framework, are available for all platforms. - * - * @see MenuItem - * @hide - */ -public interface SupportMenuItem extends MenuItem { - /* - * These should be kept in sync with attrs.xml enum constants for showAsAction - */ - /** - * Never show this item as a button in an Action Bar. - */ - public static final int SHOW_AS_ACTION_NEVER = 0; - /** - * Show this item as a button in an Action Bar if the system decides there is room for it. - */ - public static final int SHOW_AS_ACTION_IF_ROOM = 1; - /** - * Always show this item as a button in an Action Bar. - * Use sparingly! If too many items are set to always show in the Action Bar it can - * crowd the Action Bar and degrade the user experience on devices with smaller screens. - * A good rule of thumb is to have no more than 2 items set to always show at a time. - */ - public static final int SHOW_AS_ACTION_ALWAYS = 2; - - /** - * When this item is in the action bar, always show it with a text label even if it also has an - * icon specified. - */ - public static final int SHOW_AS_ACTION_WITH_TEXT = 4; - - /** - * This item's action view collapses to a normal menu item. When expanded, the action view - * temporarily takes over a larger segment of its container. - */ - public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; - - /** - * Sets how this item should display in the presence of an Action Bar. The parameter actionEnum - * is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS}, {@link #SHOW_AS_ACTION_IF_ROOM}, or - * {@link #SHOW_AS_ACTION_NEVER} should be used, and you may optionally OR the value with {@link - * #SHOW_AS_ACTION_WITH_TEXT}. SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as - * an action, it should be shown with a text label. - * - * @param actionEnum How the item should display. One of {@link #SHOW_AS_ACTION_ALWAYS}, {@link - * #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER}. - * SHOW_AS_ACTION_NEVER is the default. - * @see android.app.ActionBar - * @see #setActionView(View) - */ - public void setShowAsAction(int actionEnum); - - /** - * Sets how this item should display in the presence of an Action Bar. - * The parameter actionEnum is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS}, - * {@link #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER} should - * be used, and you may optionally OR the value with {@link #SHOW_AS_ACTION_WITH_TEXT}. - * SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as an action, - * it should be shown with a text label. - * - *

Note: This method differs from {@link #setShowAsAction(int)} only in that it - * returns the current MenuItem instance for call chaining. - * - * @param actionEnum How the item should display. One of {@link #SHOW_AS_ACTION_ALWAYS}, {@link - * #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER}. - * SHOW_AS_ACTION_NEVER is the default. - * @return This MenuItem instance for call chaining. - * @see android.app.ActionBar - * @see #setActionView(View) - */ - public MenuItem setShowAsActionFlags(int actionEnum); - - /** - * Set an action view for this menu item. An action view will be displayed in place - * of an automatically generated menu item element in the UI when this item is shown - * as an action within a parent. - * - *

Note: Setting an action view overrides the action provider - * provider set via {@link #setSupportActionProvider(ActionProvider)}.

- * - * @param view View to use for presenting this item to the user. - * @return This Item so additional setters can be called. - * @see #setShowAsAction(int) - */ - public MenuItem setActionView(View view); - - /** - * Set an action view for this menu item. An action view will be displayed in place - * of an automatically generated menu item element in the UI when this item is shown - * as an action within a parent. - * - *

Note: Setting an action view overrides the action provider - * provider set via {@link #setSupportActionProvider(ActionProvider)}.

- * - * @param resId Layout resource to use for presenting this item to the user. - * @return This Item so additional setters can be called. - * @see #setShowAsAction(int) - */ - public MenuItem setActionView(int resId); - - /** - * Returns the currently set action view for this menu item. - * - * @return This item's action view - * @see #setActionView(View) - * @see #setShowAsAction(int) - */ - public View getActionView(); - - /** - * Sets the {@link ActionProvider} responsible for creating an action view if - * the item is placed on the action bar. The provider also provides a default - * action invoked if the item is placed in the overflow menu. - * - *

Note: Setting an action provider overrides the action view - * set via {@link #setActionView(int)} or {@link #setActionView(View)}. - *

- * - * @param actionProvider The action provider. - * @return This Item so additional setters can be called. - * @see ActionProvider - */ - public SupportMenuItem setSupportActionProvider(ActionProvider actionProvider); - - /** - * Gets the {@link ActionProvider}. - * - * @return The action provider. - * @see ActionProvider - * @see #setSupportActionProvider(ActionProvider) - */ - public ActionProvider getSupportActionProvider(); - - /** - * Expand the action view associated with this menu item. The menu item must have an action view - * set, as well as the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. If a - * listener has been set using {@link #setSupportOnActionExpandListener(MenuItemCompat.OnActionExpandListener)} - * it will have its {@link MenuItemCompat.OnActionExpandListener#onMenuItemActionExpand(MenuItem)} method - * invoked. The listener may return false from this method to prevent expanding the action view. - * - * @return true if the action view was expanded, false otherwise. - */ - public boolean expandActionView(); - - /** - * Collapse the action view associated with this menu item. The menu item must have an action - * view set, as well as the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. If a - * listener has been set using {@link #setSupportOnActionExpandListener(MenuItemCompat.OnActionExpandListener)} - * it will have its {@link MenuItemCompat.OnActionExpandListener#onMenuItemActionCollapse(MenuItem)} method - * invoked. The listener may return false from this method to prevent collapsing the action - * view. - * - * @return true if the action view was collapsed, false otherwise. - */ - public boolean collapseActionView(); - - /** - * Returns true if this menu item's action view has been expanded. - * - * @return true if the item's action view is expanded, false otherwise. - * @see #expandActionView() - * @see #collapseActionView() - * @see #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW - * @see MenuItemCompat.OnActionExpandListener - */ - public boolean isActionViewExpanded(); - - /** - * Set an {@link MenuItemCompat.OnActionExpandListener} on this menu item to be notified when the associated - * action view is expanded or collapsed. The menu item must be configured to expand or collapse - * its action view using the flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. - * - * @param listener Listener that will respond to expand/collapse events - * @return This menu item instance for call chaining - */ - public SupportMenuItem setSupportOnActionExpandListener(MenuItemCompat.OnActionExpandListener listener); -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportSubMenu.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportSubMenu.java deleted file mode 100644 index 1e61a54..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/internal/view/SupportSubMenu.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.internal.view; - -/** - * Subclass of {@link SupportMenu} for sub menus. - * - * This version extends the one available in the framework to ensures that any necessary - * elements added in later versions of the framework, are available for all platforms. - * - * @see android.view.SubMenu - * @hide - */ -public interface SupportSubMenu extends SupportMenu, android.view.SubMenu { -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/IMediaBrowserServiceAdapterApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/IMediaBrowserServiceAdapterApi21.java deleted file mode 100644 index b1ecc37..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/IMediaBrowserServiceAdapterApi21.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.os.Binder; -import android.os.Bundle; -import android.os.IBinder; -import android.os.IInterface; -import android.os.Parcel; -import android.os.RemoteException; -import android.os.ResultReceiver; - -/** - * An adapter class for replacing the auto generated hidden class, IMediaBrowserService.Stub - */ -class IMediaBrowserServiceAdapterApi21 { - static abstract class Stub extends Binder implements IInterface { - private static final String DESCRIPTOR = "android.service.media.IMediaBrowserService"; - // Following TRANSACTION_XXX values are synchronized with the auto generated java file - // from IMediaBrowserService.aidl - private static final int TRANSACTION_connect = IBinder.FIRST_CALL_TRANSACTION + 0; - private static final int TRANSACTION_disconnect = IBinder.FIRST_CALL_TRANSACTION + 1; - private static final int TRANSACTION_addSubscription = IBinder.FIRST_CALL_TRANSACTION + 2; - private static final int TRANSACTION_removeSubscription = - IBinder.FIRST_CALL_TRANSACTION + 3; - private static final int TRANSACTION_getMediaItem = IBinder.FIRST_CALL_TRANSACTION + 4; - - public Stub() { - attachInterface(this, DESCRIPTOR); - } - - @Override - public IBinder asBinder() { - return this; - } - - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - switch (code) { - case IBinder.INTERFACE_TRANSACTION: { - reply.writeString(DESCRIPTOR); - return true; - } - case TRANSACTION_connect: { - data.enforceInterface(DESCRIPTOR); - String arg0 = data.readString(); - Bundle arg1; - if (data.readInt() != 0) { - arg1 = Bundle.CREATOR.createFromParcel(data); - } else { - arg1 = null; - } - Object arg2 = IMediaBrowserServiceCallbacksAdapterApi21.Stub.asInterface( - data.readStrongBinder()); - connect(arg0, arg1, arg2); - return true; - } - case TRANSACTION_disconnect: { - data.enforceInterface(DESCRIPTOR); - Object arg0 = IMediaBrowserServiceCallbacksAdapterApi21.Stub.asInterface( - data.readStrongBinder()); - disconnect(arg0); - return true; - } - case TRANSACTION_addSubscription: { - data.enforceInterface(DESCRIPTOR); - String arg0 = data.readString(); - Object arg1 = IMediaBrowserServiceCallbacksAdapterApi21.Stub.asInterface( - data.readStrongBinder()); - addSubscription(arg0, arg1); - return true; - } - case TRANSACTION_removeSubscription: { - data.enforceInterface(DESCRIPTOR); - String arg0 = data.readString(); - Object arg1 = IMediaBrowserServiceCallbacksAdapterApi21.Stub.asInterface( - data.readStrongBinder()); - removeSubscription(arg0, arg1); - return true; - } - case TRANSACTION_getMediaItem: { - data.enforceInterface(DESCRIPTOR); - String arg0 = data.readString(); - ResultReceiver arg1; - if (data.readInt() != 0) { - arg1 = ResultReceiver.CREATOR.createFromParcel(data); - } else { - arg1 = null; - } - getMediaItem(arg0, arg1); - return true; - } - } - return super.onTransact(code, data, reply, flags); - } - - public abstract void connect(final String pkg, final Bundle rootHints, - final Object callbacks); - public abstract void disconnect(final Object callbacks); - public abstract void addSubscription(final String id, final Object callbacks); - public abstract void removeSubscription(final String id, final Object callbacks); - public abstract void getMediaItem(final String mediaId, final ResultReceiver receiver); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/IMediaBrowserServiceCallbacksAdapterApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/IMediaBrowserServiceCallbacksAdapterApi21.java deleted file mode 100644 index 976949f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/IMediaBrowserServiceCallbacksAdapterApi21.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.media.session.MediaSession; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * An adapter class for accessing the hidden framework classes, IMediaBrowserServiceCallbacks and - * IMediaBrowserServiceCallbacks.Stub using reflection. - */ -class IMediaBrowserServiceCallbacksAdapterApi21 { - - Object mCallbackObject; - private Method mAsBinderMethod; - private Method mOnConnectMethod; - private Method mOnConnectFailedMethod; - private Method mOnLoadChildrenMethod; - - IMediaBrowserServiceCallbacksAdapterApi21(Object callbackObject) { - mCallbackObject = callbackObject; - try { - Class theClass = Class.forName("android.service.media.IMediaBrowserServiceCallbacks"); - Class parceledListSliceClass = Class.forName("android.content.pm.ParceledListSlice"); - mAsBinderMethod = theClass.getMethod("asBinder"); - mOnConnectMethod = theClass.getMethod("onConnect", - new Class[] { String.class, MediaSession.Token.class, Bundle.class }); - mOnConnectFailedMethod = theClass.getMethod("onConnectFailed"); - mOnLoadChildrenMethod = theClass.getMethod("onLoadChildren", - new Class[] { String.class, parceledListSliceClass }); - } catch (ClassNotFoundException | NoSuchMethodException e) { - e.printStackTrace(); - } - } - - IBinder asBinder() { - IBinder result = null; - try { - result = (IBinder) mAsBinderMethod.invoke(mCallbackObject); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - return result; - } - - void onConnect(String root, Object session, Bundle extras) throws RemoteException { - try { - mOnConnectMethod.invoke(mCallbackObject, root, session, extras); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - } - - void onConnectFailed() throws RemoteException { - try { - mOnConnectFailedMethod.invoke(mCallbackObject); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - } - - void onLoadChildren(String mediaId, Object parceledListSliceObj) throws RemoteException { - try { - mOnLoadChildrenMethod.invoke(mCallbackObject, mediaId, parceledListSliceObj); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - } - - static class Stub { - static Method sAsInterfaceMethod; - static { - try { - Class theClass = Class.forName( - "android.service.media.IMediaBrowserServiceCallbacks$Stub"); - sAsInterfaceMethod = theClass.getMethod( - "asInterface", new Class[] { IBinder.class }); - } catch (ClassNotFoundException | NoSuchMethodException e) { - e.printStackTrace(); - } - } - - static Object asInterface(IBinder binder) { - Object result = null; - try { - result = sAsInterfaceMethod.invoke(null, binder); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - return result; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompat.java deleted file mode 100644 index fa0d275..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompat.java +++ /dev/null @@ -1,1676 +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 p.android.support.v4.media; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.RemoteException; -import p.android.support.annotation.IntDef; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.v4.app.BundleCompat; -import p.android.support.v4.media.session.MediaControllerCompat; -import p.android.support.v4.media.session.MediaSessionCompat; -import p.android.support.v4.os.ResultReceiver; -import p.android.support.v4.util.ArrayMap; -import android.text.TextUtils; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static p.android.support.v4.media.MediaBrowserProtocol.*; - -/** - * Browses media content offered by a {@link MediaBrowserServiceCompat}. - *

- * This object is not thread-safe. All calls should happen on the thread on which the browser - * was constructed. - *

- */ -public final class MediaBrowserCompat { - private static final String TAG = "MediaBrowserCompat"; - - /** - * Used as an int extra field to denote the page number to subscribe. - * The value of {@code EXTRA_PAGE} should be greater than or equal to 1. - * - * @see android.service.media.MediaBrowserService.BrowserRoot - * @see #EXTRA_PAGE_SIZE - * {@hide} - */ - public static final String EXTRA_PAGE = "android.media.browse.extra.PAGE"; - - /** - * Used as an int extra field to denote the number of media items in a page. - * The value of {@code EXTRA_PAGE_SIZE} should be greater than or equal to 1. - * - * @see android.service.media.MediaBrowserService.BrowserRoot - * @see #EXTRA_PAGE - * {@hide} - */ - public static final String EXTRA_PAGE_SIZE = "android.media.browse.extra.PAGE_SIZE"; - - private final MediaBrowserImpl mImpl; - - /** - * Creates a media browser for the specified media browse service. - * - * @param context The context. - * @param serviceComponent The component name of the media browse service. - * @param callback The connection callback. - * @param rootHints An optional bundle of service-specific arguments to send - * to the media browse service when connecting and retrieving the root id - * for browsing, or null if none. The contents of this bundle may affect - * the information returned when browsing. - */ - public MediaBrowserCompat(Context context, ComponentName serviceComponent, - ConnectionCallback callback, Bundle rootHints) { - if (android.os.Build.VERSION.SDK_INT >= 23) { - mImpl = new MediaBrowserImplApi23(context, serviceComponent, callback, rootHints); - } else if (android.os.Build.VERSION.SDK_INT >= 21) { - mImpl = new MediaBrowserImplApi21(context, serviceComponent, callback, rootHints); - } else { - mImpl = new MediaBrowserImplBase(context, serviceComponent, callback, rootHints); - } - } - - /** - * Connects to the media browse service. - *

- * The connection callback specified in the constructor will be invoked - * when the connection completes or fails. - *

- */ - public void connect() { - mImpl.connect(); - } - - /** - * Disconnects from the media browse service. - * After this, no more callbacks will be received. - */ - public void disconnect() { - mImpl.disconnect(); - } - - /** - * Returns whether the browser is connected to the service. - */ - public boolean isConnected() { - return mImpl.isConnected(); - } - - /** - * Gets the service component that the media browser is connected to. - */ - public @NonNull - ComponentName getServiceComponent() { - return mImpl.getServiceComponent(); - } - - /** - * Gets the root id. - *

- * Note that the root id may become invalid or change when when the - * browser is disconnected. - *

- * - * @throws IllegalStateException if not connected. - */ - public @NonNull String getRoot() { - return mImpl.getRoot(); - } - - /** - * Gets any extras for the media service. - * - * @throws IllegalStateException if not connected. - */ - public @Nullable - Bundle getExtras() { - return mImpl.getExtras(); - } - - /** - * Gets the media session token associated with the media browser. - *

- * Note that the session token may become invalid or change when when the - * browser is disconnected. - *

- * - * @return The session token for the browser, never null. - * - * @throws IllegalStateException if not connected. - */ - public @NonNull MediaSessionCompat.Token getSessionToken() { - return mImpl.getSessionToken(); - } - - /** - * Queries for information about the media items that are contained within - * the specified id and subscribes to receive updates when they change. - *

- * The list of subscriptions is maintained even when not connected and is - * restored after the reconnection. It is ok to subscribe while not connected - * but the results will not be returned until the connection completes. - *

- *

- * If the id is already subscribed with a different callback then the new - * callback will replace the previous one and the child data will be - * reloaded. - *

- * - * @param parentId The id of the parent media item whose list of children - * will be subscribed. - * @param callback The callback to receive the list of children. - */ - public void subscribe(@NonNull String parentId, @NonNull SubscriptionCallback callback) { - mImpl.subscribe(parentId, null, callback); - } - - /** - * Queries with service-specific arguments for information about the media items - * that are contained within the specified id and subscribes to receive updates - * when they change. - *

- * The list of subscriptions is maintained even when not connected and is - * restored after the reconnection. It is ok to subscribe while not connected - * but the results will not be returned until the connection completes. - *

- *

- * If the id is already subscribed with a different callback then the new - * callback will replace the previous one and the child data will be - * reloaded. - *

- * - * @param parentId The id of the parent media item whose list of children - * will be subscribed. - * @param options A bundle of service-specific arguments to send to the media - * browse service. The contents of this bundle may affect the - * information returned when browsing. - * @param callback The callback to receive the list of children. - * {@hide} - */ - public void subscribe(@NonNull String parentId, @NonNull Bundle options, - @NonNull SubscriptionCallback callback) { - if (options == null) { - throw new IllegalArgumentException("options are null"); - } - mImpl.subscribe(parentId, options, callback); - } - - /** - * Unsubscribes for changes to the children of the specified media id. - *

- * The query callback will no longer be invoked for results associated with - * this id once this method returns. - *

- * - * @param parentId The id of the parent media item whose list of children - * will be unsubscribed. - */ - public void unsubscribe(@NonNull String parentId) { - mImpl.unsubscribe(parentId, null); - } - - /** - * Unsubscribes for changes to the children of the specified media id. - *

- * The query callback will no longer be invoked for results associated with - * this id once this method returns. - *

- * - * @param parentId The id of the parent media item whose list of children - * will be unsubscribed. - * @param options A bundle sent to the media browse service to subscribe. - * {@hide} - */ - public void unsubscribe(@NonNull String parentId, @NonNull Bundle options) { - if (options == null) { - throw new IllegalArgumentException("options are null"); - } - mImpl.unsubscribe(parentId, options); - } - - /** - * Retrieves a specific {@link MediaItem} from the connected service. Not - * all services may support this, so falling back to subscribing to the - * parent's id should be used when unavailable. - * - * @param mediaId The id of the item to retrieve. - * @param cb The callback to receive the result on. - */ - public void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb) { - mImpl.getItem(mediaId, cb); - } - - /** - * A class with information on a single media item for use in browsing media. - */ - public static class MediaItem implements Parcelable { - private final int mFlags; - private final MediaDescriptionCompat mDescription; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE }) - public @interface Flags { } - - /** - * Flag: Indicates that the item has children of its own. - */ - public static final int FLAG_BROWSABLE = 1 << 0; - - /** - * Flag: Indicates that the item is playable. - *

- * The id of this item may be passed to - * {@link MediaControllerCompat.TransportControls#playFromMediaId(String, Bundle)} - * to start playing it. - *

- */ - public static final int FLAG_PLAYABLE = 1 << 1; - - /** - * Create a new MediaItem for use in browsing media. - * @param description The description of the media, which must include a - * media id. - * @param flags The flags for this item. - */ - public MediaItem(@NonNull MediaDescriptionCompat description, @Flags int flags) { - if (description == null) { - throw new IllegalArgumentException("description cannot be null"); - } - if (TextUtils.isEmpty(description.getMediaId())) { - throw new IllegalArgumentException("description must have a non-empty media id"); - } - mFlags = flags; - mDescription = description; - } - - /** - * Private constructor. - */ - private MediaItem(Parcel in) { - mFlags = in.readInt(); - mDescription = MediaDescriptionCompat.CREATOR.createFromParcel(in); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeInt(mFlags); - mDescription.writeToParcel(out, flags); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("MediaItem{"); - sb.append("mFlags=").append(mFlags); - sb.append(", mDescription=").append(mDescription); - sb.append('}'); - return sb.toString(); - } - - public static final Creator CREATOR = - new Creator() { - @Override - public MediaItem createFromParcel(Parcel in) { - return new MediaItem(in); - } - - @Override - public MediaItem[] newArray(int size) { - return new MediaItem[size]; - } - }; - - /** - * Gets the flags of the item. - */ - public @Flags int getFlags() { - return mFlags; - } - - /** - * Returns whether this item is browsable. - * @see #FLAG_BROWSABLE - */ - public boolean isBrowsable() { - return (mFlags & FLAG_BROWSABLE) != 0; - } - - /** - * Returns whether this item is playable. - * @see #FLAG_PLAYABLE - */ - public boolean isPlayable() { - return (mFlags & FLAG_PLAYABLE) != 0; - } - - /** - * Returns the description of the media. - */ - public @NonNull MediaDescriptionCompat getDescription() { - return mDescription; - } - - /** - * Returns the media id for this item. - */ - public @NonNull String getMediaId() { - return mDescription.getMediaId(); - } - } - - /** - * Callbacks for connection related events. - */ - public static class ConnectionCallback { - final Object mConnectionCallbackObj; - private ConnectionCallbackInternal mConnectionCallbackInternal; - - public ConnectionCallback() { - if (android.os.Build.VERSION.SDK_INT >= 21) { - mConnectionCallbackObj = - MediaBrowserCompatApi21.createConnectionCallback(new StubApi21()); - } else { - mConnectionCallbackObj = null; - } - } - - /** - * Invoked after {@link MediaBrowserCompat#connect()} when the request has successfully - * completed. - */ - public void onConnected() { - } - - /** - * Invoked when the client is disconnected from the media browser. - */ - public void onConnectionSuspended() { - } - - /** - * Invoked when the connection to the media browser failed. - */ - public void onConnectionFailed() { - } - - void setInternalConnectionCallback(ConnectionCallbackInternal connectionCallbackInternal) { - mConnectionCallbackInternal = connectionCallbackInternal; - } - - interface ConnectionCallbackInternal { - void onConnected(); - void onConnectionSuspended(); - void onConnectionFailed(); - } - - private class StubApi21 implements MediaBrowserCompatApi21.ConnectionCallback { - @Override - public void onConnected() { - if (mConnectionCallbackInternal != null) { - mConnectionCallbackInternal.onConnected(); - } - ConnectionCallback.this.onConnected(); - } - - @Override - public void onConnectionSuspended() { - if (mConnectionCallbackInternal != null) { - mConnectionCallbackInternal.onConnectionSuspended(); - } - ConnectionCallback.this.onConnectionSuspended(); - } - - @Override - public void onConnectionFailed() { - if (mConnectionCallbackInternal != null) { - mConnectionCallbackInternal.onConnectionFailed(); - } - ConnectionCallback.this.onConnectionFailed(); - } - } - } - - /** - * Callbacks for subscription related events. - */ - public static abstract class SubscriptionCallback { - /** - * Called when the list of children is loaded or updated. - * - * @param parentId The media id of the parent media item. - * @param children The children which were loaded, or null if the id is invalid. - */ - public void onChildrenLoaded(@NonNull String parentId, List children) { - } - - /** - * Called when the list of children is loaded or updated. - * - * @param parentId The media id of the parent media item. - * @param children The children which were loaded, or null if the id is invalid. - * @param options A bundle of service-specific arguments to send to the media - * browse service. The contents of this bundle may affect the - * information returned when browsing. - * {@hide} - */ - public void onChildrenLoaded(@NonNull String parentId, List children, - @NonNull Bundle options) { - } - - /** - * Called when the id doesn't exist or other errors in subscribing. - *

- * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} - * called, because some errors may heal themselves. - *

- * - * @param parentId The media id of the parent media item whose children could not be loaded. - */ - public void onError(@NonNull String parentId) { - } - - /** - * Called when the id doesn't exist or other errors in subscribing. - *

- * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} - * called, because some errors may heal themselves. - *

- * - * @param parentId The media id of the parent media item whose children could - * not be loaded. - * @param options A bundle of service-specific arguments sent to the media - * browse service. - * {@hide} - */ - public void onError(@NonNull String parentId, @NonNull Bundle options) { - } - } - - /** - * Callbacks for subscription related events. - */ - static class SubscriptionCallbackApi21 extends SubscriptionCallback { - SubscriptionCallback mSubscriptionCallback; - private final Object mSubscriptionCallbackObj; - private Bundle mOptions; - - public SubscriptionCallbackApi21(SubscriptionCallback callback, Bundle options) { - mSubscriptionCallback = callback; - mOptions = options; - mSubscriptionCallbackObj = - MediaBrowserCompatApi21.createSubscriptionCallback(new StubApi21()); - } - - /** - * Called when the list of children is loaded or updated. - * - * @param parentId The media id of the parent media item. - * @param children The children which were loaded, or null if the id is invalid. - */ - public void onChildrenLoaded(@NonNull String parentId, List children) { - mSubscriptionCallback.onChildrenLoaded(parentId, children); - } - - /** - * Called when the list of children is loaded or updated. - * - * @param parentId The media id of the parent media item. - * @param children The children which were loaded, or null if the id is invalid. - * @param options A bundle of service-specific arguments to send to the media - * browse service. The contents of this bundle may affect the - * information returned when browsing. - * {@hide} - */ - public void onChildrenLoaded(@NonNull String parentId, List children, - @NonNull Bundle options) { - mSubscriptionCallback.onChildrenLoaded(parentId, children, options); - } - - /** - * Called when the id doesn't exist or other errors in subscribing. - *

- * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} - * called, because some errors may heal themselves. - *

- * - * @param parentId The media id of the parent media item whose children could not be loaded. - */ - public void onError(@NonNull String parentId) { - mSubscriptionCallback.onError(parentId); - } - - /** - * Called when the id doesn't exist or other errors in subscribing. - *

- * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} - * called, because some errors may heal themselves. - *

- * - * @param parentId The media id of the parent media item whose children could - * not be loaded. - * @param options A bundle of service-specific arguments sent to the media - * browse service. - * {@hide} - */ - public void onError(@NonNull String parentId, @NonNull Bundle options) { - mSubscriptionCallback.onError(parentId, options); - } - - private class StubApi21 implements MediaBrowserCompatApi21.SubscriptionCallback { - @Override - public void onChildrenLoaded(@NonNull String parentId, List children) { - List mediaItems = null; - if (children != null) { - mediaItems = new ArrayList<>(); - for (Parcel parcel : children) { - parcel.setDataPosition(0); - mediaItems.add( - MediaItem.CREATOR.createFromParcel(parcel)); - parcel.recycle(); - } - } - if (mOptions != null) { - SubscriptionCallbackApi21.this.onChildrenLoaded(parentId, - MediaBrowserCompatUtils.applyOptions(mediaItems, mOptions), - mOptions); - } else { - SubscriptionCallbackApi21.this.onChildrenLoaded(parentId, mediaItems); - } - } - - @Override - public void onError(@NonNull String parentId) { - if (mOptions != null) { - SubscriptionCallbackApi21.this.onError(parentId, mOptions); - } else { - SubscriptionCallbackApi21.this.onError(parentId); - } - } - } - } - - /** - * Callback for receiving the result of {@link #getItem}. - */ - public static abstract class ItemCallback { - final Object mItemCallbackObj; - - public ItemCallback() { - if (android.os.Build.VERSION.SDK_INT >= 23) { - mItemCallbackObj = MediaBrowserCompatApi23.createItemCallback(new StubApi23()); - } else { - mItemCallbackObj = null; - } - } - - /** - * Called when the item has been returned by the browser service. - * - * @param item The item that was returned or null if it doesn't exist. - */ - public void onItemLoaded(MediaItem item) { - } - - /** - * Called when the item doesn't exist or there was an error retrieving it. - * - * @param itemId The media id of the media item which could not be loaded. - */ - public void onError(@NonNull String itemId) { - } - - private class StubApi23 implements MediaBrowserCompatApi23.ItemCallback { - @Override - public void onItemLoaded(Parcel itemParcel) { - itemParcel.setDataPosition(0); - MediaItem item = MediaItem.CREATOR.createFromParcel(itemParcel); - itemParcel.recycle(); - ItemCallback.this.onItemLoaded(item); - } - - @Override - public void onError(@NonNull String itemId) { - ItemCallback.this.onError(itemId); - } - } - } - - interface MediaBrowserImpl { - void connect(); - void disconnect(); - boolean isConnected(); - ComponentName getServiceComponent(); - @NonNull String getRoot(); - @Nullable Bundle getExtras(); - @NonNull MediaSessionCompat.Token getSessionToken(); - void subscribe(@NonNull String parentId, Bundle options, - @NonNull SubscriptionCallback callback); - void unsubscribe(@NonNull String parentId, Bundle options); - void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb); - } - - interface MediaBrowserServiceCallbackImpl { - void onServiceConnected(Messenger callback, String root, MediaSessionCompat.Token session, - Bundle extra); - void onConnectionFailed(Messenger callback); - void onLoadChildren(Messenger callback, String parentId, List list, Bundle options); - } - - static class MediaBrowserImplBase - implements MediaBrowserImpl, MediaBrowserServiceCallbackImpl { - private static final boolean DBG = false; - - private static final int CONNECT_STATE_DISCONNECTED = 0; - private static final int CONNECT_STATE_CONNECTING = 1; - private static final int CONNECT_STATE_CONNECTED = 2; - private static final int CONNECT_STATE_SUSPENDED = 3; - - private final Context mContext; - private final ComponentName mServiceComponent; - private final ConnectionCallback mCallback; - private final Bundle mRootHints; - private final CallbackHandler mHandler = new CallbackHandler(this); - private final ArrayMap mSubscriptions = new ArrayMap<>(); - - private int mState = CONNECT_STATE_DISCONNECTED; - private MediaServiceConnection mServiceConnection; - private ServiceBinderWrapper mServiceBinderWrapper; - private Messenger mCallbacksMessenger; - private String mRootId; - private MediaSessionCompat.Token mMediaSessionToken; - private Bundle mExtras; - - public MediaBrowserImplBase(Context context, ComponentName serviceComponent, - ConnectionCallback callback, Bundle rootHints) { - if (context == null) { - throw new IllegalArgumentException("context must not be null"); - } - if (serviceComponent == null) { - throw new IllegalArgumentException("service component must not be null"); - } - if (callback == null) { - throw new IllegalArgumentException("connection callback must not be null"); - } - mContext = context; - mServiceComponent = serviceComponent; - mCallback = callback; - mRootHints = rootHints; - } - - public void connect() { - if (mState != CONNECT_STATE_DISCONNECTED) { - throw new IllegalStateException("connect() called while not disconnected (state=" - + getStateLabel(mState) + ")"); - } - // TODO: remove this extra check. - if (DBG) { - if (mServiceConnection != null) { - throw new RuntimeException("mServiceConnection should be null. Instead it is " - + mServiceConnection); - } - } - if (mServiceBinderWrapper != null) { - throw new RuntimeException("mServiceBinderWrapper should be null. Instead it is " - + mServiceBinderWrapper); - } - if (mCallbacksMessenger != null) { - throw new RuntimeException("mCallbacksMessenger should be null. Instead it is " - + mCallbacksMessenger); - } - - mState = CONNECT_STATE_CONNECTING; - - final Intent intent = new Intent(MediaBrowserServiceCompat.SERVICE_INTERFACE); - intent.setComponent(mServiceComponent); - - final ServiceConnection thisConnection = mServiceConnection = - new MediaServiceConnection(); - - boolean bound = false; - try { - bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); - } catch (Exception ex) { - Log.e(TAG, "Failed binding to service " + mServiceComponent); - } - - if (!bound) { - // Tell them that it didn't work. We are already on the main thread, - // but we don't want to do callbacks inside of connect(). So post it, - // and then check that we are on the same ServiceConnection. We know - // we won't also get an onServiceConnected or onServiceDisconnected, - // so we won't be doing double callbacks. - mHandler.post(new Runnable() { - @Override - public void run() { - // Ensure that nobody else came in or tried to connect again. - if (thisConnection == mServiceConnection) { - forceCloseConnection(); - mCallback.onConnectionFailed(); - } - } - }); - } - - if (DBG) { - Log.d(TAG, "connect..."); - dump(); - } - } - - public void disconnect() { - // It's ok to call this any state, because allowing this lets apps not have - // to check isConnected() unnecessarily. They won't appreciate the extra - // assertions for this. We do everything we can here to go back to a sane state. - if (mCallbacksMessenger != null) { - try { - mServiceBinderWrapper.disconnect(mCallbacksMessenger); - } catch (RemoteException ex) { - // We are disconnecting anyway. Log, just for posterity but it's not - // a big problem. - Log.w(TAG, "RemoteException during connect for " + mServiceComponent); - } - } - forceCloseConnection(); - - if (DBG) { - Log.d(TAG, "disconnect..."); - dump(); - } - } - - /** - * Null out the variables and unbind from the service. This doesn't include - * calling disconnect on the service, because we only try to do that in the - * clean shutdown cases. - *

- * Everywhere that calls this EXCEPT for disconnect() should follow it with - * a call to mCallback.onConnectionFailed(). Disconnect doesn't do that callback - * for a clean shutdown, but everywhere else is a dirty shutdown and should - * notify the app. - */ - private void forceCloseConnection() { - if (mServiceConnection != null) { - mContext.unbindService(mServiceConnection); - } - mState = CONNECT_STATE_DISCONNECTED; - mServiceConnection = null; - mServiceBinderWrapper = null; - mCallbacksMessenger = null; - mHandler.setCallbacksMessenger(null); - mRootId = null; - mMediaSessionToken = null; - } - - public boolean isConnected() { - return mState == CONNECT_STATE_CONNECTED; - } - - public @NonNull - ComponentName getServiceComponent() { - if (!isConnected()) { - throw new IllegalStateException("getServiceComponent() called while not connected" + - " (state=" + mState + ")"); - } - return mServiceComponent; - } - - public @NonNull String getRoot() { - if (!isConnected()) { - throw new IllegalStateException("getRoot() called while not connected" - + "(state=" + getStateLabel(mState) + ")"); - } - return mRootId; - } - - public @Nullable - Bundle getExtras() { - if (!isConnected()) { - throw new IllegalStateException("getExtras() called while not connected (state=" - + getStateLabel(mState) + ")"); - } - return mExtras; - } - - public @NonNull MediaSessionCompat.Token getSessionToken() { - if (!isConnected()) { - throw new IllegalStateException("getSessionToken() called while not connected" - + "(state=" + mState + ")"); - } - return mMediaSessionToken; - } - - public void subscribe(@NonNull String parentId, Bundle options, - @NonNull SubscriptionCallback callback) { - // Check arguments. - if (TextUtils.isEmpty(parentId)) { - throw new IllegalArgumentException("parentId is empty."); - } - if (callback == null) { - throw new IllegalArgumentException("callback is null"); - } - // Update or create the subscription. - Subscription sub = mSubscriptions.get(parentId); - if (sub == null) { - sub = new Subscription(); - mSubscriptions.put(parentId, sub); - } - sub.setCallbackForOptions(callback, options); - - // If we are connected, tell the service that we are watching. If we aren't - // connected, the service will be told when we connect. - if (mState == CONNECT_STATE_CONNECTED) { - try { - mServiceBinderWrapper.addSubscription(parentId, options, mCallbacksMessenger); - } catch (RemoteException e) { - // Process is crashing. We will disconnect, and upon reconnect we will - // automatically reregister. So nothing to do here. - Log.d(TAG, "addSubscription failed with RemoteException parentId=" + parentId); - } - } - } - - public void unsubscribe(@NonNull String parentId, Bundle options) { - // Check arguments. - if (TextUtils.isEmpty(parentId)) { - throw new IllegalArgumentException("parentId is empty."); - } - - // Remove from our list. - Subscription sub = mSubscriptions.get(parentId); - - // Tell the service if necessary. - if (sub != null && sub.remove(options) && mState == CONNECT_STATE_CONNECTED) { - try { - mServiceBinderWrapper.removeSubscription( - parentId, options, mCallbacksMessenger); - } catch (RemoteException e) { - // Process is crashing. We will disconnect, and upon reconnect we will - // automatically reregister. So nothing to do here. - Log.d(TAG, "removeSubscription failed with RemoteException parentId=" - + parentId); - } - } - if (sub != null && sub.isEmpty()) { - mSubscriptions.remove(parentId); - } - } - - public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { - if (TextUtils.isEmpty(mediaId)) { - throw new IllegalArgumentException("mediaId is empty."); - } - if (cb == null) { - throw new IllegalArgumentException("cb is null."); - } - if (mState != CONNECT_STATE_CONNECTED) { - Log.i(TAG, "Not connected, unable to retrieve the MediaItem."); - mHandler.post(new Runnable() { - @Override - public void run() { - cb.onError(mediaId); - } - }); - return; - } - ResultReceiver receiver = new ItemReceiver(mediaId, cb, mHandler); - try { - mServiceBinderWrapper.getMediaItem(mediaId, receiver); - } catch (RemoteException e) { - Log.i(TAG, "Remote error getting media item."); - mHandler.post(new Runnable() { - @Override - public void run() { - cb.onError(mediaId); - } - }); - } - } - - public void onServiceConnected(final Messenger callback, final String root, - final MediaSessionCompat.Token session, final Bundle extra) { - // Check to make sure there hasn't been a disconnect or a different ServiceConnection. - if (!isCurrent(callback, "onConnect")) { - return; - } - // Don't allow them to call us twice. - if (mState != CONNECT_STATE_CONNECTING) { - Log.w(TAG, "onConnect from service while mState=" + getStateLabel(mState) - + "... ignoring"); - return; - } - mRootId = root; - mMediaSessionToken = session; - mExtras = extra; - mState = CONNECT_STATE_CONNECTED; - - if (DBG) { - Log.d(TAG, "ServiceCallbacks.onConnect..."); - dump(); - } - mCallback.onConnected(); - - // we may receive some subscriptions before we are connected, so re-subscribe - // everything now - try { - for (Map.Entry subscriptionEntry - : mSubscriptions.entrySet()) { - String id = subscriptionEntry.getKey(); - Subscription sub = subscriptionEntry.getValue(); - for (Bundle options : sub.getOptionsList()) { - mServiceBinderWrapper.addSubscription(id, options, mCallbacksMessenger); - } - } - } catch (RemoteException ex) { - // Process is crashing. We will disconnect, and upon reconnect we will - // automatically reregister. So nothing to do here. - Log.d(TAG, "addSubscription failed with RemoteException."); - } - } - - public void onConnectionFailed(final Messenger callback) { - Log.e(TAG, "onConnectFailed for " + mServiceComponent); - - // Check to make sure there hasn't been a disconnect or a different ServiceConnection. - if (!isCurrent(callback, "onConnectFailed")) { - return; - } - // Don't allow them to call us twice. - if (mState != CONNECT_STATE_CONNECTING) { - Log.w(TAG, "onConnect from service while mState=" + getStateLabel(mState) - + "... ignoring"); - return; - } - - // Clean up - forceCloseConnection(); - - // Tell the app. - mCallback.onConnectionFailed(); - } - - public void onLoadChildren(final Messenger callback, final String parentId, - final List list, final Bundle options) { - // Check that there hasn't been a disconnect or a different ServiceConnection. - if (!isCurrent(callback, "onLoadChildren")) { - return; - } - - List data = list; - if (DBG) { - Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId); - } - - // Check that the subscription is still subscribed. - final Subscription subscription = mSubscriptions.get(parentId); - if (subscription == null) { - if (DBG) { - Log.d(TAG, "onLoadChildren for id that isn't subscribed id=" + parentId); - } - return; - } - - // Tell the app. - SubscriptionCallback subscriptionCallback = subscription.getCallback(options); - if (subscriptionCallback != null) { - if (options == null) { - subscriptionCallback.onChildrenLoaded(parentId, data); - } else { - subscriptionCallback.onChildrenLoaded(parentId, data, options); - } - } - } - - /** - * For debugging. - */ - private static String getStateLabel(int state) { - switch (state) { - case CONNECT_STATE_DISCONNECTED: - return "CONNECT_STATE_DISCONNECTED"; - case CONNECT_STATE_CONNECTING: - return "CONNECT_STATE_CONNECTING"; - case CONNECT_STATE_CONNECTED: - return "CONNECT_STATE_CONNECTED"; - case CONNECT_STATE_SUSPENDED: - return "CONNECT_STATE_SUSPENDED"; - default: - return "UNKNOWN/" + state; - } - } - - /** - * Return true if {@code callback} is the current ServiceCallbacks. Also logs if it's not. - */ - private boolean isCurrent(Messenger callback, String funcName) { - if (mCallbacksMessenger != callback) { - if (mState != CONNECT_STATE_DISCONNECTED) { - Log.i(TAG, funcName + " for " + mServiceComponent + " with mCallbacksMessenger=" - + mCallbacksMessenger + " this=" + this); - } - return false; - } - return true; - } - - /** - * Log internal state. - * @hide - */ - void dump() { - Log.d(TAG, "MediaBrowserCompat..."); - Log.d(TAG, " mServiceComponent=" + mServiceComponent); - Log.d(TAG, " mCallback=" + mCallback); - Log.d(TAG, " mRootHints=" + mRootHints); - Log.d(TAG, " mState=" + getStateLabel(mState)); - Log.d(TAG, " mServiceConnection=" + mServiceConnection); - Log.d(TAG, " mServiceBinderWrapper=" + mServiceBinderWrapper); - Log.d(TAG, " mCallbacksMessenger=" + mCallbacksMessenger); - Log.d(TAG, " mRootId=" + mRootId); - Log.d(TAG, " mMediaSessionToken=" + mMediaSessionToken); - } - - /** - * ServiceConnection to the other app. - */ - private class MediaServiceConnection implements ServiceConnection { - @Override - public void onServiceConnected(final ComponentName name, final IBinder binder) { - postOrRun(new Runnable() { - @Override - public void run() { - if (DBG) { - Log.d(TAG, "MediaServiceConnection.onServiceConnected name=" + name - + " binder=" + binder); - dump(); - } - - // Make sure we are still the current connection, and that they haven't - // called disconnect(). - if (!isCurrent("onServiceConnected")) { - return; - } - - // Save their binder - mServiceBinderWrapper = new ServiceBinderWrapper(binder); - - // We make a new mServiceCallbacks each time we connect so that we can drop - // responses from previous connections. - mCallbacksMessenger = new Messenger(mHandler); - mHandler.setCallbacksMessenger(mCallbacksMessenger); - - mState = CONNECT_STATE_CONNECTING; - - // Call connect, which is async. When we get a response from that we will - // say that we're connected. - try { - if (DBG) { - Log.d(TAG, "ServiceCallbacks.onConnect..."); - dump(); - } - mServiceBinderWrapper.connect( - mContext, mRootHints, mCallbacksMessenger); - } catch (RemoteException ex) { - // Connect failed, which isn't good. But the auto-reconnect on the - // service will take over and we will come back. We will also get the - // onServiceDisconnected, which has all the cleanup code. So let that - // do it. - Log.w(TAG, "RemoteException during connect for " + mServiceComponent); - if (DBG) { - Log.d(TAG, "ServiceCallbacks.onConnect..."); - dump(); - } - } - } - }); - } - - @Override - public void onServiceDisconnected(final ComponentName name) { - postOrRun(new Runnable() { - @Override - public void run() { - if (DBG) { - Log.d(TAG, "MediaServiceConnection.onServiceDisconnected name=" + name - + " this=" + this + " mServiceConnection=" + - mServiceConnection); - dump(); - } - - // Make sure we are still the current connection, and that they haven't - // called disconnect(). - if (!isCurrent("onServiceDisconnected")) { - return; - } - - // Clear out what we set in onServiceConnected - mServiceBinderWrapper = null; - mCallbacksMessenger = null; - mHandler.setCallbacksMessenger(null); - - // And tell the app that it's suspended. - mState = CONNECT_STATE_SUSPENDED; - mCallback.onConnectionSuspended(); - } - }); - } - - private void postOrRun(Runnable r) { - if (Thread.currentThread() == mHandler.getLooper().getThread()) { - r.run(); - } else { - mHandler.post(r); - } - } - - /** - * Return true if this is the current ServiceConnection. Also logs if it's not. - */ - private boolean isCurrent(String funcName) { - if (mServiceConnection != this) { - if (mState != CONNECT_STATE_DISCONNECTED) { - // Check mState, because otherwise this log is noisy. - Log.i(TAG, funcName + " for " + mServiceComponent + - " with mServiceConnection=" + mServiceConnection + " this=" + this); - } - return false; - } - return true; - } - } - } - - static class MediaBrowserImplApi21 implements MediaBrowserImpl, MediaBrowserServiceCallbackImpl, - ConnectionCallback.ConnectionCallbackInternal { - private static final boolean DBG = false; - - protected Object mBrowserObj; - - private final ComponentName mServiceComponent; - private final CallbackHandler mHandler = new CallbackHandler(this); - private final ArrayMap mSubscriptions = new ArrayMap<>(); - - private ServiceBinderWrapper mServiceBinderWrapper; - private Messenger mCallbacksMessenger; - - public MediaBrowserImplApi21(Context context, ComponentName serviceComponent, - ConnectionCallback callback, Bundle rootHints) { - mServiceComponent = serviceComponent; - callback.setInternalConnectionCallback(this); - mBrowserObj = MediaBrowserCompatApi21.createBrowser(context, serviceComponent, - callback.mConnectionCallbackObj, rootHints); - } - - @Override - public void connect() { - MediaBrowserCompatApi21.connect(mBrowserObj); - } - - @Override - public void disconnect() { - if (mServiceBinderWrapper != null && mCallbacksMessenger != null) { - try { - mServiceBinderWrapper.unregisterCallbackMessenger(mCallbacksMessenger); - } catch (RemoteException e) { - Log.i(TAG, "Remote error unregistering client messenger." ); - } - } - MediaBrowserCompatApi21.disconnect(mBrowserObj); - } - - @Override - public boolean isConnected() { - return MediaBrowserCompatApi21.isConnected(mBrowserObj); - } - - @Override - public ComponentName getServiceComponent() { - return MediaBrowserCompatApi21.getServiceComponent(mBrowserObj); - } - - @NonNull - @Override - public String getRoot() { - return MediaBrowserCompatApi21.getRoot(mBrowserObj); - } - - @Nullable - @Override - public Bundle getExtras() { - return MediaBrowserCompatApi21.getExtras(mBrowserObj); - } - - @NonNull - @Override - public MediaSessionCompat.Token getSessionToken() { - return MediaSessionCompat.Token.fromToken( - MediaBrowserCompatApi21.getSessionToken(mBrowserObj)); - } - - @Override - public void subscribe(@NonNull final String parentId, final Bundle options, - @NonNull final SubscriptionCallback callback) { - // Update or create the subscription. - SubscriptionCallbackApi21 cb21 = new SubscriptionCallbackApi21(callback, options); - Subscription sub = mSubscriptions.get(parentId); - if (sub == null) { - sub = new Subscription(); - mSubscriptions.put(parentId, sub); - } - sub.setCallbackForOptions(cb21, options); - if (MediaBrowserCompatApi21.isConnected(mBrowserObj)) { - if (options == null || mServiceBinderWrapper == null) { - MediaBrowserCompatApi21.subscribe( - mBrowserObj, parentId, cb21.mSubscriptionCallbackObj); - } else { - try { - mServiceBinderWrapper.addSubscription( - parentId, options, mCallbacksMessenger); - } catch (RemoteException e) { - // Process is crashing. We will disconnect, and upon reconnect we will - // automatically reregister. So nothing to do here. - Log.i(TAG, "Remote error subscribing media item: " + parentId); - } - } - } - } - - @Override - public void unsubscribe(@NonNull String parentId, Bundle options) { - // Check arguments. - if (TextUtils.isEmpty(parentId)) { - throw new IllegalArgumentException("parentId is empty."); - } - - // Remove from our list. - Subscription sub = mSubscriptions.get(parentId); - if (sub != null && sub.remove(options)) { - // Tell the service if necessary. - if (options == null || mServiceBinderWrapper == null) { - if (mServiceBinderWrapper != null || sub.isEmpty()) { - MediaBrowserCompatApi21.unsubscribe(mBrowserObj, parentId); - } - } else if (mServiceBinderWrapper == null) { - try { - mServiceBinderWrapper.removeSubscription( - parentId, options, mCallbacksMessenger); - } catch (RemoteException e) { - // Process is crashing. We will disconnect, and upon reconnect we will - // automatically reregister. So nothing to do here. - Log.d(TAG, "removeSubscription failed with RemoteException parentId=" - + parentId); - } - } - } - if (sub != null && sub.isEmpty()) { - mSubscriptions.remove(parentId); - } - } - - @Override - public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { - if (TextUtils.isEmpty(mediaId)) { - throw new IllegalArgumentException("mediaId is empty."); - } - if (cb == null) { - throw new IllegalArgumentException("cb is null."); - } - if (!MediaBrowserCompatApi21.isConnected(mBrowserObj)) { - Log.i(TAG, "Not connected, unable to retrieve the MediaItem."); - mHandler.post(new Runnable() { - @Override - public void run() { - cb.onError(mediaId); - } - }); - return; - } - if (mServiceBinderWrapper == null) { - mHandler.post(new Runnable() { - @Override - public void run() { - // Default framework implementation. - cb.onItemLoaded(null); - } - }); - return; - } - ResultReceiver receiver = new ItemReceiver(mediaId, cb, mHandler); - try { - mServiceBinderWrapper.getMediaItem(mediaId, receiver); - } catch (RemoteException e) { - Log.i(TAG, "Remote error getting media item: " + mediaId); - mHandler.post(new Runnable() { - @Override - public void run() { - cb.onError(mediaId); - } - }); - } - } - - @Override - public void onConnected() { - Bundle extras = MediaBrowserCompatApi21.getExtras(mBrowserObj); - if (extras == null) { - return; - } - IBinder serviceBinder = BundleCompat.getBinder(extras, EXTRA_MESSENGER_BINDER); - if (serviceBinder != null) { - mServiceBinderWrapper = new ServiceBinderWrapper(serviceBinder); - mCallbacksMessenger = new Messenger(mHandler); - mHandler.setCallbacksMessenger(mCallbacksMessenger); - try { - mServiceBinderWrapper.registerCallbackMessenger(mCallbacksMessenger); - } catch (RemoteException e) { - Log.i(TAG, "Remote error registering client messenger." ); - } - onServiceConnected(mCallbacksMessenger, null, null, null); - } - } - - @Override - public void onConnectionSuspended() { - mServiceBinderWrapper = null; - mCallbacksMessenger = null; - mHandler.setCallbacksMessenger(null); - } - - @Override - public void onConnectionFailed() { - // Do noting - } - - // FYI, this method is not called by CallbackHandler. - @Override - public void onServiceConnected(final Messenger callback, final String root, - final MediaSessionCompat.Token session, final Bundle extra) { - // we may receive some subscriptions before we are connected, so re-subscribe - // everything now - for (Map.Entry subscriptionEntry : mSubscriptions.entrySet()) { - String id = subscriptionEntry.getKey(); - Subscription sub = subscriptionEntry.getValue(); - List optionsList = sub.getOptionsList(); - List callbackList = sub.getCallbacks(); - for (int i = 0; i < optionsList.size(); ++i) { - if (optionsList.get(i) == null) { - MediaBrowserCompatApi21.subscribe(mBrowserObj, id, - ((SubscriptionCallbackApi21)callbackList.get(i)) - .mSubscriptionCallbackObj); - } else { - try { - mServiceBinderWrapper.addSubscription( - id, optionsList.get(i), mCallbacksMessenger); - } catch (RemoteException e) { - // Process is crashing. We will disconnect, and upon reconnect we will - // automatically reregister. So nothing to do here. - Log.d(TAG, "addSubscription failed with RemoteException parentId=" + id); - } - } - } - } - } - - @Override - public void onConnectionFailed(Messenger callback) { - // This method will not be called. - } - - @Override - public void onLoadChildren(Messenger callback, String parentId, List list, - @NonNull Bundle options) { - if (mCallbacksMessenger != callback) { - return; - } - - List data = list; - if (DBG) { - Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId); - } - - // Check that the subscription is still subscribed. - Subscription subscription = mSubscriptions.get(parentId); - if (subscription == null) { - if (DBG) { - Log.d(TAG, "onLoadChildren for id that isn't subscribed id=" + parentId); - } - return; - } - - // Tell the app. - subscription.getCallback(options).onChildrenLoaded(parentId, data, options); - } - } - - static class MediaBrowserImplApi23 extends MediaBrowserImplApi21 { - public MediaBrowserImplApi23(Context context, ComponentName serviceComponent, - ConnectionCallback callback, Bundle rootHints) { - super(context, serviceComponent, callback, rootHints); - } - - @Override - public void getItem(@NonNull String mediaId, @NonNull ItemCallback cb) { - MediaBrowserCompatApi23.getItem(mBrowserObj, mediaId, cb.mItemCallbackObj); - } - } - - private static class Subscription { - private final List mCallbacks; - private final List mOptionsList; - - public Subscription() { - mCallbacks = new ArrayList(); - mOptionsList = new ArrayList(); - } - - public boolean isEmpty() { - return mCallbacks.isEmpty(); - } - - public List getOptionsList() { - return mOptionsList; - } - - public List getCallbacks() { - return mCallbacks; - } - - public void setCallbackForOptions(SubscriptionCallback callback, Bundle options) { - for (int i = 0; i < mOptionsList.size(); ++i) { - if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { - mCallbacks.set(i, callback); - return; - } - } - mCallbacks.add(callback); - mOptionsList.add(options); - } - - public boolean remove(Bundle options) { - for (int i = 0; i < mOptionsList.size(); ++i) { - if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { - mCallbacks.remove(i); - mOptionsList.remove(i); - return true; - } - } - return false; - } - - public SubscriptionCallback getCallback(Bundle options) { - for (int i = 0; i < mOptionsList.size(); ++i) { - if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { - return mCallbacks.get(i); - } - } - return null; - } - } - - private static class CallbackHandler extends Handler { - private final MediaBrowserServiceCallbackImpl mCallbackImpl; - private WeakReference mCallbacksMessengerRef; - - CallbackHandler(MediaBrowserServiceCallbackImpl callbackImpl) { - super(); - mCallbackImpl = callbackImpl; - } - - @Override - public void handleMessage(Message msg) { - if (mCallbacksMessengerRef == null) { - return; - } - Bundle data = msg.getData(); - data.setClassLoader(MediaSessionCompat.class.getClassLoader()); - switch (msg.what) { - case SERVICE_MSG_ON_CONNECT: - mCallbackImpl.onServiceConnected(mCallbacksMessengerRef.get(), - data.getString(DATA_MEDIA_ITEM_ID), - (MediaSessionCompat.Token) data.getParcelable(DATA_MEDIA_SESSION_TOKEN), - data.getBundle(DATA_ROOT_HINTS)); - break; - case SERVICE_MSG_ON_CONNECT_FAILED: - mCallbackImpl.onConnectionFailed(mCallbacksMessengerRef.get()); - break; - case SERVICE_MSG_ON_LOAD_CHILDREN: - mCallbackImpl.onLoadChildren(mCallbacksMessengerRef.get(), - data.getString(DATA_MEDIA_ITEM_ID), - data.getParcelableArrayList(DATA_MEDIA_ITEM_LIST), - data.getBundle(DATA_OPTIONS)); - break; - default: - Log.w(TAG, "Unhandled message: " + msg - + "\n Client version: " + CLIENT_VERSION_CURRENT - + "\n Service version: " + msg.arg1); - } - } - - void setCallbacksMessenger(Messenger callbacksMessenger) { - mCallbacksMessengerRef = new WeakReference<>(callbacksMessenger); - } - } - - private static class ServiceBinderWrapper { - private Messenger mMessenger; - - public ServiceBinderWrapper(IBinder target) { - mMessenger = new Messenger(target); - } - - void connect(Context context, Bundle rootHint, Messenger callbacksMessenger) - throws RemoteException { - Bundle data = new Bundle(); - data.putString(DATA_PACKAGE_NAME, context.getPackageName()); - data.putBundle(DATA_ROOT_HINTS, rootHint); - sendRequest(CLIENT_MSG_CONNECT, data, callbacksMessenger); - } - - void disconnect(Messenger callbacksMessenger) throws RemoteException { - sendRequest(CLIENT_MSG_DISCONNECT, null, callbacksMessenger); - } - - void addSubscription(String parentId, Bundle options, Messenger callbacksMessenger) - throws RemoteException { - Bundle data = new Bundle(); - data.putString(DATA_MEDIA_ITEM_ID, parentId); - data.putBundle(DATA_OPTIONS, options); - sendRequest(CLIENT_MSG_ADD_SUBSCRIPTION, data, callbacksMessenger); - } - - void removeSubscription(String parentId, Bundle options, Messenger callbacksMessenger) - throws RemoteException { - Bundle data = new Bundle(); - data.putString(DATA_MEDIA_ITEM_ID, parentId); - data.putBundle(DATA_OPTIONS, options); - sendRequest(CLIENT_MSG_REMOVE_SUBSCRIPTION, data, callbacksMessenger); - } - - void getMediaItem(String mediaId, ResultReceiver receiver) throws RemoteException { - Bundle data = new Bundle(); - data.putString(DATA_MEDIA_ITEM_ID, mediaId); - data.putParcelable(DATA_RESULT_RECEIVER, receiver); - sendRequest(CLIENT_MSG_GET_MEDIA_ITEM, data, null); - } - - void registerCallbackMessenger(Messenger callbackMessenger) throws RemoteException { - sendRequest(CLIENT_MSG_REGISTER_CALLBACK_MESSENGER, null, callbackMessenger); - } - - void unregisterCallbackMessenger(Messenger callbackMessenger) throws RemoteException { - sendRequest(CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER, null, callbackMessenger); - } - - private void sendRequest(int what, Bundle data, Messenger cbMessenger) - throws RemoteException { - Message msg = Message.obtain(); - msg.what = what; - msg.arg1 = CLIENT_VERSION_CURRENT; - msg.setData(data); - msg.replyTo = cbMessenger; - mMessenger.send(msg); - } - } - - private static class ItemReceiver extends ResultReceiver { - private final String mMediaId; - private final ItemCallback mCallback; - - ItemReceiver(String mediaId, ItemCallback callback, Handler handler) { - super(handler); - mMediaId = mediaId; - mCallback = callback; - } - - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - resultData.setClassLoader(MediaBrowserCompat.class.getClassLoader()); - if (resultCode != 0 || resultData == null - || !resultData.containsKey(MediaBrowserServiceCompat.KEY_MEDIA_ITEM)) { - mCallback.onError(mMediaId); - return; - } - Parcelable item = resultData.getParcelable(MediaBrowserServiceCompat.KEY_MEDIA_ITEM); - if (item instanceof MediaItem) { - mCallback.onItemLoaded((MediaItem) item); - } else { - mCallback.onError(mMediaId); - } - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatApi21.java deleted file mode 100644 index 79220dc..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatApi21.java +++ /dev/null @@ -1,153 +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 p.android.support.v4.media; - -import android.content.ComponentName; -import android.content.Context; -import android.media.browse.MediaBrowser; -import android.os.Bundle; -import android.os.Parcel; -import p.android.support.annotation.NonNull; - -import java.util.ArrayList; -import java.util.List; - -class MediaBrowserCompatApi21 { - static final String NULL_MEDIA_ITEM_ID = - "MediaBrowserCompat.NULL_MEDIA_ITEM"; - - public static Object createConnectionCallback(ConnectionCallback callback) { - return new ConnectionCallbackProxy<>(callback); - } - - public static Object createBrowser(Context context, ComponentName serviceComponent, - Object callback, Bundle rootHints) { - return new MediaBrowser(context, serviceComponent, - (MediaBrowser.ConnectionCallback) callback, rootHints); - } - - public static void connect(Object browserObj) { - ((MediaBrowser)browserObj).connect(); - } - - public static void disconnect(Object browserObj) { - ((MediaBrowser)browserObj).disconnect(); - - } - - public static boolean isConnected(Object browserObj) { - return ((MediaBrowser)browserObj).isConnected(); - } - - public static ComponentName getServiceComponent(Object browserObj) { - return ((MediaBrowser)browserObj).getServiceComponent(); - } - - public static String getRoot(Object browserObj) { - return ((MediaBrowser)browserObj).getRoot(); - } - - public static Bundle getExtras(Object browserObj) { - return ((MediaBrowser)browserObj).getExtras(); - } - - public static Object getSessionToken(Object browserObj) { - return ((MediaBrowser)browserObj).getSessionToken(); - } - - public static Object createSubscriptionCallback(SubscriptionCallback callback) { - return new SubscriptionCallbackProxy<>(callback); - } - - public static void subscribe( - Object browserObj, String parentId, Object subscriptionCallbackObj) { - ((MediaBrowser)browserObj).subscribe(parentId, - (MediaBrowser.SubscriptionCallback) subscriptionCallbackObj); - } - - public static void unsubscribe(Object browserObj, String parentId) { - ((MediaBrowser)browserObj).unsubscribe(parentId); - } - - interface ConnectionCallback { - void onConnected(); - void onConnectionSuspended(); - void onConnectionFailed(); - } - - static class ConnectionCallbackProxy - extends MediaBrowser.ConnectionCallback { - protected final T mConnectionCallback; - - public ConnectionCallbackProxy(T connectionCallback) { - mConnectionCallback = connectionCallback; - } - - @Override - public void onConnected() { - mConnectionCallback.onConnected(); - } - - @Override - public void onConnectionSuspended() { - mConnectionCallback.onConnectionSuspended(); - } - - @Override - public void onConnectionFailed() { - mConnectionCallback.onConnectionFailed(); - } - } - - interface SubscriptionCallback { - void onChildrenLoaded(@NonNull String parentId, List children); - void onError(@NonNull String parentId); - } - - static class SubscriptionCallbackProxy - extends MediaBrowser.SubscriptionCallback { - protected final T mSubscriptionCallback; - - public SubscriptionCallbackProxy(T callback) { - mSubscriptionCallback = callback; - } - - @Override - public void onChildrenLoaded(@NonNull String parentId, - List children) { - List parcelList = null; - if (children != null && children.size() == 1 - && children.get(0).getMediaId().equals(NULL_MEDIA_ITEM_ID)) { - children = null; - } - if (children != null) { - parcelList = new ArrayList<>(); - for (MediaBrowser.MediaItem item : children) { - Parcel parcel = Parcel.obtain(); - item.writeToParcel(parcel, 0); - parcelList.add(parcel); - } - } - mSubscriptionCallback.onChildrenLoaded(parentId, parcelList); - } - - @Override - public void onError(@NonNull String parentId) { - mSubscriptionCallback.onError(parentId); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatApi23.java deleted file mode 100644 index 230be86..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatApi23.java +++ /dev/null @@ -1,57 +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 p.android.support.v4.media; - -import android.media.browse.MediaBrowser; -import android.os.Parcel; -import p.android.support.annotation.NonNull; - -class MediaBrowserCompatApi23 { - - public static Object createItemCallback(ItemCallback callback) { - return new ItemCallbackProxy<>(callback); - } - - public static void getItem(Object browserObj, String mediaId, Object itemCallbackObj) { - ((MediaBrowser) browserObj).getItem(mediaId, ((MediaBrowser.ItemCallback) itemCallbackObj)); - } - - interface ItemCallback { - void onItemLoaded(Parcel itemParcel); - void onError(@NonNull String itemId); - } - - static class ItemCallbackProxy extends MediaBrowser.ItemCallback { - protected final T mItemCallback; - - public ItemCallbackProxy(T callback) { - mItemCallback = callback; - } - - @Override - public void onItemLoaded(MediaBrowser.MediaItem item) { - Parcel parcel = Parcel.obtain(); - item.writeToParcel(parcel, 0); - mItemCallback.onItemLoaded(parcel); - } - - @Override - public void onError(@NonNull String itemId) { - mItemCallback.onError(itemId); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatUtils.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatUtils.java deleted file mode 100644 index 3a839d0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserCompatUtils.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.os.Bundle; - -import java.util.List; - -/** - * @hide - */ -public class MediaBrowserCompatUtils { - public static boolean areSameOptions(Bundle options1, Bundle options2) { - if (options1 == options2) { - return true; - } else if (options1 == null) { - return options2.getInt(MediaBrowserCompat.EXTRA_PAGE, -1) == -1 - && options2.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1) == -1; - } else if (options2 == null) { - return options1.getInt(MediaBrowserCompat.EXTRA_PAGE, -1) == -1 - && options1.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1) == -1; - } else { - return options1.getInt(MediaBrowserCompat.EXTRA_PAGE, -1) - == options2.getInt(MediaBrowserCompat.EXTRA_PAGE, -1) - && options1.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1) - == options2.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1); - } - } - - public static boolean hasDuplicatedItems(Bundle options1, Bundle options2) { - int page1 = options1 == null ? -1 : options1.getInt(MediaBrowserCompat.EXTRA_PAGE, -1); - int page2 = options2 == null ? -1 :options2.getInt(MediaBrowserCompat.EXTRA_PAGE, -1); - int pageSize1 = options1 == null - ? -1 :options1.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1); - int pageSize2 = options2 == null - ? -1 :options2.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1); - - int startIndex1, startIndex2, endIndex1, endIndex2; - if (page1 == -1 || pageSize1 == -1) { - startIndex1 = 0; - endIndex1 = Integer.MAX_VALUE; - } else { - startIndex1 = pageSize1 * (page1 - 1); - endIndex1 = startIndex1 + pageSize1 - 1; - } - - if (page2 == -1 || pageSize2 == -1) { - startIndex2 = 0; - endIndex2 = Integer.MAX_VALUE; - } else { - startIndex2 = pageSize2 * (page2 - 1); - endIndex2 = startIndex2 + pageSize2 - 1; - } - - if (startIndex1 <= startIndex2 && startIndex2 <= endIndex1) { - return true; - } else if (startIndex1 <= endIndex2 && endIndex2 <= endIndex1) { - return true; - } - return false; - } - - public static List applyOptions( - List list, final Bundle options) { - int page = options.getInt(MediaBrowserCompat.EXTRA_PAGE, -1); - int pageSize = options.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1); - if (page == -1 && pageSize == -1) { - return list; - } - int fromIndex = pageSize * (page - 1); - int toIndex = fromIndex + pageSize; - if (page < 1 || pageSize < 1 || fromIndex >= list.size()) { - return null; - } - if (toIndex > list.size()) { - toIndex = list.size(); - } - return list.subList(fromIndex, toIndex); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserProtocol.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserProtocol.java deleted file mode 100644 index 10371f6..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserProtocol.java +++ /dev/null @@ -1,153 +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 p.android.support.v4.media; - -/*** - * Defines the communication protocol for media browsers and media browser services. - * @hide - */ -class MediaBrowserProtocol { - - public static final String DATA_CALLING_UID = "data_calling_uid"; - public static final String DATA_MEDIA_ITEM_ID = "data_media_item_id"; - public static final String DATA_MEDIA_ITEM_LIST = "data_media_item_list"; - public static final String DATA_MEDIA_SESSION_TOKEN = "data_media_session_token"; - public static final String DATA_OPTIONS = "data_options"; - public static final String DATA_PACKAGE_NAME = "data_package_name"; - public static final String DATA_RESULT_RECEIVER = "data_result_receiver"; - public static final String DATA_ROOT_HINTS = "data_root_hints"; - - public static final String EXTRA_SERVICE_VERSION = "extra_service_version"; - public static final String EXTRA_MESSENGER_BINDER = "extra_messenger"; - - /** - * MediaBrowserCompat will check the version of the connected MediaBrowserServiceCompat, - * and it will not send messages if they are introduced in the higher version of the - * MediaBrowserServiceCompat. - */ - public static final int SERVICE_VERSION_1 = 1; - public static final int SERVICE_VERSION_CURRENT = SERVICE_VERSION_1; - - /* - * Messages sent from the media browser service compat to the media browser compat. - * (Compat implementation for IMediaBrowserServiceCallbacks) - * DO NOT RENUMBER THESE! - */ - - /** (service v1) - * Sent after {@link MediaBrowserCompat#connect()} when the request has successfully - * completed. - * - arg1 : The service version - * - data - * DATA_MEDIA_ITEM_ID : A string for the root media item id - * DATA_MEDIA_SESSION_TOKEN : Media session token - * DATA_ROOT_HINTS : An extras bundle which contains EXTRA_SERVICE_VERSION - */ - public static final int SERVICE_MSG_ON_CONNECT = 1; - - /** (service v1) - * Sent after {@link MediaBrowserCompat#connect()} when the connection to the media browser - * failed. - * - arg1 : service version - */ - public static final int SERVICE_MSG_ON_CONNECT_FAILED = 2; - - /** (service v1) - * Sent when the list of children is loaded or updated. - * - arg1 : The service version - * - data - * DATA_MEDIA_ITEM_ID : A string for the parent media item id - * DATA_MEDIA_ITEM_LIST : An array list for the media item children - * DATA_OPTIONS : A bundle of service-specific arguments sent from the media browse to - * the media browser service - */ - public static final int SERVICE_MSG_ON_LOAD_CHILDREN = 3; - - /** - * MediaBrowserServiceCompat will check the version of the MediaBrowserCompat, and it will not - * send messages if they are introduced in the higher version of the MediaBrowserCompat. - */ - public static final int CLIENT_VERSION_1 = 1; - public static final int CLIENT_VERSION_CURRENT = CLIENT_VERSION_1; - - /* - * Messages sent from the media browser compat to the media browser service compat. - * (Compat implementation for IMediaBrowserService) - * DO NOT RENUMBER THESE! - */ - - /** (client v1) - * Sent to connect to the media browse service compat. - * - arg1 : The client version - * - data - * DATA_PACKAGE_NAME : A string for the package name of MediaBrowserCompat - * DATA_ROOT_HINTS : An optional root hints bundle of service-specific arguments - * - replyTo : Callback messenger - */ - public static final int CLIENT_MSG_CONNECT = 1; - - /** (client v1) - * Sent to disconnect from the media browse service compat. - * - arg1 : The client version - * - replyTo : Callback messenger - */ - public static final int CLIENT_MSG_DISCONNECT = 2; - - /** (client v1) - * Sent to subscribe for changes to the children of the specified media id. - * - arg1 : The client version - * - data - * DATA_MEDIA_ITEM_ID : A string for a media item id - * DATA_OPTIONS : A bundle of service-specific arguments sent from the media browse to - * the media browser service - * - replyTo : Callback messenger - */ - public static final int CLIENT_MSG_ADD_SUBSCRIPTION = 3; - - /** (client v1) - * Sent to unsubscribe for changes to the children of the specified media id. - * - arg1 : The client version - * - data - * DATA_MEDIA_ITEM_ID : A string for a media item id - * DATA_OPTIONS : A bundle of service-specific arguments sent from the media browse to - * the media browser service - * - replyTo : Callback messenger - */ - public static final int CLIENT_MSG_REMOVE_SUBSCRIPTION = 4; - - /** (client v1) - * Sent to retrieve a specific media item from the connected service. - * - arg1 : The client version - * - data - * DATA_MEDIA_ITEM_ID : A string for a media item id - * DATA_RESULT_RECEIVER : Result receiver to get the result - */ - public static final int CLIENT_MSG_GET_MEDIA_ITEM = 5; - - /** (client v1) - * Sent to register the client messenger - * - arg1 : The client version - * - replyTo : Callback messenger - */ - public static final int CLIENT_MSG_REGISTER_CALLBACK_MESSENGER = 6; - - /** (client v1) - * Sent to unregister the client messenger - * - arg1 : The client version - * - replyTo : Callback messenger - */ - public static final int CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER = 7; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompat.java deleted file mode 100644 index c74cee1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompat.java +++ /dev/null @@ -1,1031 +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 p.android.support.v4.media; - -import android.app.Service; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Binder; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.Parcel; -import android.os.RemoteException; -import p.android.support.annotation.IntDef; -import p.android.support.annotation.NonNull; -import p.android.support.annotation.Nullable; -import p.android.support.v4.app.BundleCompat; -import p.android.support.v4.media.session.MediaSessionCompat; -import p.android.support.v4.os.ResultReceiver; -import p.android.support.v4.util.ArrayMap; -import android.text.TextUtils; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -/** - * Base class for media browse services. - *

- * Media browse services enable applications to browse media content provided by an application - * and ask the application to start playing it. They may also be used to control content that - * is already playing by way of a {@link MediaSessionCompat}. - *

- * - * To extend this class, you must declare the service in your manifest file with - * an intent filter with the {@link #SERVICE_INTERFACE} action. - * - * For example: - *

- * <service android:name=".MyMediaBrowserServiceCompat"
- *          android:label="@string/service_name" >
- *     <intent-filter>
- *         <action android:name="android.media.browse.MediaBrowserService" />
- *     </intent-filter>
- * </service>
- * 
- */ -public abstract class MediaBrowserServiceCompat extends Service { - private static final String TAG = "MediaBrowserServiceCompat"; - private static final boolean DBG = false; - - private MediaBrowserServiceImpl mImpl; - - /** - * The {@link Intent} that must be declared as handled by the service. - */ - public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService"; - - /** - * A key for passing the MediaItem to the ResultReceiver in getItem. - * - * @hide - */ - public static final String KEY_MEDIA_ITEM = "media_item"; - - private static final int RESULT_FLAG_OPTION_NOT_HANDLED = 0x00000001; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED }) - private @interface ResultFlags { } - - private final ArrayMap mConnections = new ArrayMap<>(); - private final ServiceHandler mHandler = new ServiceHandler(); - MediaSessionCompat.Token mSession; - - interface MediaBrowserServiceImpl { - void onCreate(); - IBinder onBind(Intent intent); - } - - class MediaBrowserServiceImplBase implements MediaBrowserServiceImpl { - private Messenger mMessenger; - - @Override - public void onCreate() { - mMessenger = new Messenger(mHandler); - } - - @Override - public IBinder onBind(Intent intent) { - if (SERVICE_INTERFACE.equals(intent.getAction())) { - return mMessenger.getBinder(); - } - return null; - } - } - - class MediaBrowserServiceImplApi21 implements MediaBrowserServiceImpl { - private Object mServiceObj; - - @Override - public void onCreate() { - mServiceObj = MediaBrowserServiceCompatApi21.createService(); - MediaBrowserServiceCompatApi21.onCreate(mServiceObj, new ServiceImplApi21()); - } - - @Override - public IBinder onBind(Intent intent) { - return MediaBrowserServiceCompatApi21.onBind(mServiceObj, intent); - } - } - - class MediaBrowserServiceImplApi23 implements MediaBrowserServiceImpl { - private Object mServiceObj; - - @Override - public void onCreate() { - mServiceObj = MediaBrowserServiceCompatApi23.createService(); - MediaBrowserServiceCompatApi23.onCreate(mServiceObj, new ServiceImplApi23()); - } - - @Override - public IBinder onBind(Intent intent) { - return MediaBrowserServiceCompatApi23.onBind(mServiceObj, intent); - } - } - - private final class ServiceHandler extends Handler { - private final ServiceImpl mServiceImpl = new ServiceImpl(); - - @Override - public void handleMessage(Message msg) { - Bundle data = msg.getData(); - switch (msg.what) { - case MediaBrowserProtocol.CLIENT_MSG_CONNECT: - mServiceImpl.connect(data.getString(MediaBrowserProtocol.DATA_PACKAGE_NAME), - data.getInt(MediaBrowserProtocol.DATA_CALLING_UID), data.getBundle(MediaBrowserProtocol.DATA_ROOT_HINTS), - new ServiceCallbacksCompat(msg.replyTo)); - break; - case MediaBrowserProtocol.CLIENT_MSG_DISCONNECT: - mServiceImpl.disconnect(new ServiceCallbacksCompat(msg.replyTo)); - break; - case MediaBrowserProtocol.CLIENT_MSG_ADD_SUBSCRIPTION: - mServiceImpl.addSubscription(data.getString(MediaBrowserProtocol.DATA_MEDIA_ITEM_ID), - data.getBundle(MediaBrowserProtocol.DATA_OPTIONS), new ServiceCallbacksCompat(msg.replyTo)); - break; - case MediaBrowserProtocol.CLIENT_MSG_REMOVE_SUBSCRIPTION: - mServiceImpl.removeSubscription(data.getString(MediaBrowserProtocol.DATA_MEDIA_ITEM_ID), - data.getBundle(MediaBrowserProtocol.DATA_OPTIONS), new ServiceCallbacksCompat(msg.replyTo)); - break; - case MediaBrowserProtocol.CLIENT_MSG_GET_MEDIA_ITEM: - mServiceImpl.getMediaItem(data.getString(MediaBrowserProtocol.DATA_MEDIA_ITEM_ID), - (ResultReceiver) data.getParcelable(MediaBrowserProtocol.DATA_RESULT_RECEIVER)); - break; - case MediaBrowserProtocol.CLIENT_MSG_REGISTER_CALLBACK_MESSENGER: - mServiceImpl.registerCallbacks(new ServiceCallbacksCompat(msg.replyTo)); - break; - case MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER: - mServiceImpl.unregisterCallbacks(new ServiceCallbacksCompat(msg.replyTo)); - break; - default: - Log.w(TAG, "Unhandled message: " + msg - + "\n Service version: " + MediaBrowserProtocol.SERVICE_VERSION_CURRENT - + "\n Client version: " + msg.arg1); - } - } - - @Override - public boolean sendMessageAtTime(Message msg, long uptimeMillis) { - // Binder.getCallingUid() in handleMessage will return the uid of this process. - // In order to get the right calling uid, Binder.getCallingUid() should be called here. - Bundle data = msg.getData(); - data.setClassLoader(MediaBrowserCompat.class.getClassLoader()); - data.putInt(MediaBrowserProtocol.DATA_CALLING_UID, Binder.getCallingUid()); - return super.sendMessageAtTime(msg, uptimeMillis); - } - - public void postOrRun(Runnable r) { - if (Thread.currentThread() == getLooper().getThread()) { - r.run(); - } else { - post(r); - } - } - - public ServiceImpl getServiceImpl() { - return mServiceImpl; - } - } - - /** - * All the info about a connection. - */ - private class ConnectionRecord { - String pkg; - Bundle rootHints; - ServiceCallbacks callbacks; - BrowserRoot root; - HashMap> subscriptions = new HashMap(); - } - - /** - * Completion handler for asynchronous callback methods in {@link MediaBrowserServiceCompat}. - *

- * Each of the methods that takes one of these to send the result must call - * {@link #sendResult} to respond to the caller with the given results. If those - * functions return without calling {@link #sendResult}, they must instead call - * {@link #detach} before returning, and then may call {@link #sendResult} when - * they are done. If more than one of those methods is called, an exception will - * be thrown. - * - * @see MediaBrowserServiceCompat#onLoadChildren - * @see MediaBrowserServiceCompat#onLoadItem - */ - public static class Result { - private Object mDebug; - private boolean mDetachCalled; - private boolean mSendResultCalled; - private int mFlags; - - Result(Object debug) { - mDebug = debug; - } - - /** - * Send the result back to the caller. - */ - public void sendResult(T result) { - if (mSendResultCalled) { - throw new IllegalStateException("sendResult() called twice for: " + mDebug); - } - mSendResultCalled = true; - onResultSent(result, mFlags); - } - - /** - * Detach this message from the current thread and allow the {@link #sendResult} - * call to happen later. - */ - public void detach() { - if (mDetachCalled) { - throw new IllegalStateException("detach() called when detach() had already" - + " been called for: " + mDebug); - } - if (mSendResultCalled) { - throw new IllegalStateException("detach() called when sendResult() had already" - + " been called for: " + mDebug); - } - mDetachCalled = true; - } - - boolean isDone() { - return mDetachCalled || mSendResultCalled; - } - - void setFlags(@ResultFlags int flags) { - mFlags = flags; - } - - /** - * Called when the result is sent, after assertions about not being called twice - * have happened. - */ - void onResultSent(T result, @ResultFlags int flags) { - } - } - - private class ServiceImpl { - public void connect(final String pkg, final int uid, final Bundle rootHints, - final ServiceCallbacks callbacks) { - - if (!isValidPackage(pkg, uid)) { - throw new IllegalArgumentException("Package/uid mismatch: uid=" + uid - + " package=" + pkg); - } - - mHandler.postOrRun(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - - // Clear out the old subscriptions. We are getting new ones. - mConnections.remove(b); - - final ConnectionRecord connection = new ConnectionRecord(); - connection.pkg = pkg; - connection.rootHints = rootHints; - connection.callbacks = callbacks; - - connection.root = - MediaBrowserServiceCompat.this.onGetRoot(pkg, uid, rootHints); - - // If they didn't return something, don't allow this client. - if (connection.root == null) { - Log.i(TAG, "No root for client " + pkg + " from service " - + getClass().getName()); - try { - callbacks.onConnectFailed(); - } catch (RemoteException ex) { - Log.w(TAG, "Calling onConnectFailed() failed. Ignoring. " - + "pkg=" + pkg); - } - } else { - try { - mConnections.put(b, connection); - if (mSession != null) { - callbacks.onConnect(connection.root.getRootId(), - mSession, connection.root.getExtras()); - } - } catch (RemoteException ex) { - Log.w(TAG, "Calling onConnect() failed. Dropping client. " - + "pkg=" + pkg); - mConnections.remove(b); - } - } - } - }); - } - - public void disconnect(final ServiceCallbacks callbacks) { - mHandler.postOrRun(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - - // Clear out the old subscriptions. We are getting new ones. - final ConnectionRecord old = mConnections.remove(b); - if (old != null) { - // TODO - } - } - }); - } - - public void addSubscription(final String id, final Bundle options, - final ServiceCallbacks callbacks) { - mHandler.postOrRun(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - - // Get the record for the connection - final ConnectionRecord connection = mConnections.get(b); - if (connection == null) { - Log.w(TAG, "addSubscription for callback that isn't registered id=" - + id); - return; - } - - MediaBrowserServiceCompat.this.addSubscription(id, connection, options); - } - }); - } - - public void removeSubscription(final String id, final Bundle options, - final ServiceCallbacks callbacks) { - mHandler.postOrRun(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - - ConnectionRecord connection = mConnections.get(b); - if (connection == null) { - Log.w(TAG, "removeSubscription for callback that isn't registered id=" - + id); - return; - } - if (!MediaBrowserServiceCompat.this.removeSubscription( - id, connection, options)) { - Log.w(TAG, "removeSubscription called for " + id - + " which is not subscribed"); - } - } - }); - } - - public void getMediaItem(final String mediaId, final ResultReceiver receiver) { - if (TextUtils.isEmpty(mediaId) || receiver == null) { - return; - } - - mHandler.postOrRun(new Runnable() { - @Override - public void run() { - performLoadItem(mediaId, receiver); - } - }); - } - - // Used when {@link MediaBrowserProtocol#EXTRA_MESSENGER_BINDER} is used. - public void registerCallbacks(final ServiceCallbacks callbacks) { - mHandler.postOrRun(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - // Clear out the old subscriptions. We are getting new ones. - mConnections.remove(b); - - final ConnectionRecord connection = new ConnectionRecord(); - connection.callbacks = callbacks; - mConnections.put(b, connection); - } - }); - } - - // Used when {@link MediaBrowserProtocol#EXTRA_MESSENGER_BINDER} is used. - public void unregisterCallbacks(final ServiceCallbacks callbacks) { - mHandler.postOrRun(new Runnable() { - @Override - public void run() { - final IBinder b = callbacks.asBinder(); - mConnections.remove(b); - } - }); - } - } - - private class ServiceImplApi21 implements MediaBrowserServiceCompatApi21.ServiceImplApi21 { - final ServiceImpl mServiceImpl; - - ServiceImplApi21() { - mServiceImpl = mHandler.getServiceImpl(); - } - - @Override - public void connect(final String pkg, final Bundle rootHints, - final MediaBrowserServiceCompatApi21.ServiceCallbacks callbacks) { - mServiceImpl.connect(pkg, Binder.getCallingUid(), rootHints, - new ServiceCallbacksApi21(callbacks)); - } - - @Override - public void disconnect(final MediaBrowserServiceCompatApi21.ServiceCallbacks callbacks) { - mServiceImpl.disconnect(new ServiceCallbacksApi21(callbacks)); - } - - - @Override - public void addSubscription( - final String id, final MediaBrowserServiceCompatApi21.ServiceCallbacks callbacks) { - mServiceImpl.addSubscription(id, null, new ServiceCallbacksApi21(callbacks)); - } - - @Override - public void removeSubscription(final String id, - final MediaBrowserServiceCompatApi21.ServiceCallbacks callbacks) { - mServiceImpl.removeSubscription(id, null, new ServiceCallbacksApi21(callbacks)); - } - } - - private class ServiceImplApi23 extends ServiceImplApi21 - implements MediaBrowserServiceCompatApi23.ServiceImplApi23 { - @Override - public void getMediaItem(final String mediaId, - final MediaBrowserServiceCompatApi23.ItemCallback cb) { - ResultReceiver receiverCompat = new ResultReceiver(mHandler) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - MediaBrowserCompat.MediaItem item = resultData.getParcelable(KEY_MEDIA_ITEM); - Parcel itemParcel = null; - if (item != null) { - itemParcel = Parcel.obtain(); - item.writeToParcel(itemParcel, 0); - } - cb.onItemLoaded(resultCode, resultData, itemParcel); - } - }; - mServiceImpl.getMediaItem(mediaId, receiverCompat); - } - } - - private interface ServiceCallbacks { - IBinder asBinder(); - void onConnect(String root, MediaSessionCompat.Token session, Bundle extras) - throws RemoteException; - void onConnectFailed() throws RemoteException; - void onLoadChildren(String mediaId, List list, Bundle options) - throws RemoteException; - } - - private class ServiceCallbacksCompat implements ServiceCallbacks { - final Messenger mCallbacks; - - ServiceCallbacksCompat(Messenger callbacks) { - mCallbacks = callbacks; - } - - public IBinder asBinder() { - return mCallbacks.getBinder(); - } - - public void onConnect(String root, MediaSessionCompat.Token session, Bundle extras) - throws RemoteException { - if (extras == null) { - extras = new Bundle(); - } - extras.putInt(MediaBrowserProtocol.EXTRA_SERVICE_VERSION, MediaBrowserProtocol.SERVICE_VERSION_CURRENT); - Bundle data = new Bundle(); - data.putString(MediaBrowserProtocol.DATA_MEDIA_ITEM_ID, root); - data.putParcelable(MediaBrowserProtocol.DATA_MEDIA_SESSION_TOKEN, session); - data.putBundle(MediaBrowserProtocol.DATA_ROOT_HINTS, extras); - sendRequest(MediaBrowserProtocol.SERVICE_MSG_ON_CONNECT, data); - } - - public void onConnectFailed() throws RemoteException { - sendRequest(MediaBrowserProtocol.SERVICE_MSG_ON_CONNECT_FAILED, null); - } - - public void onLoadChildren(String mediaId, List list, - Bundle options) throws RemoteException { - Bundle data = new Bundle(); - data.putString(MediaBrowserProtocol.DATA_MEDIA_ITEM_ID, mediaId); - data.putBundle(MediaBrowserProtocol.DATA_OPTIONS, options); - if (list != null) { - data.putParcelableArrayList(MediaBrowserProtocol.DATA_MEDIA_ITEM_LIST, - list instanceof ArrayList ? (ArrayList) list : new ArrayList<>(list)); - } - sendRequest(MediaBrowserProtocol.SERVICE_MSG_ON_LOAD_CHILDREN, data); - } - - private void sendRequest(int what, Bundle data) throws RemoteException { - Message msg = Message.obtain(); - msg.what = what; - msg.arg1 = MediaBrowserProtocol.SERVICE_VERSION_CURRENT; - msg.setData(data); - mCallbacks.send(msg); - } - } - - private class ServiceCallbacksApi21 implements ServiceCallbacks { - final MediaBrowserServiceCompatApi21.ServiceCallbacks mCallbacks; - Messenger mMessenger; - - ServiceCallbacksApi21(MediaBrowserServiceCompatApi21.ServiceCallbacks callbacks) { - mCallbacks = callbacks; - } - - public IBinder asBinder() { - return mCallbacks.asBinder(); - } - - public void onConnect(String root, MediaSessionCompat.Token session, Bundle extras) - throws RemoteException { - if (extras == null) { - extras = new Bundle(); - } - mMessenger = new Messenger(mHandler); - BundleCompat.putBinder(extras, MediaBrowserProtocol.EXTRA_MESSENGER_BINDER, mMessenger.getBinder()); - extras.putInt(MediaBrowserProtocol.EXTRA_SERVICE_VERSION, MediaBrowserProtocol.SERVICE_VERSION_CURRENT); - mCallbacks.onConnect(root, session.getToken(), extras); - } - - public void onConnectFailed() throws RemoteException { - mCallbacks.onConnectFailed(); - } - - public void onLoadChildren(String mediaId, List list, - Bundle options) throws RemoteException { - List parcelList = null; - if (list != null) { - parcelList = new ArrayList<>(); - for (MediaBrowserCompat.MediaItem item : list) { - Parcel parcel = Parcel.obtain(); - item.writeToParcel(parcel, 0); - parcelList.add(parcel); - } - } - mCallbacks.onLoadChildren(mediaId, parcelList); - } - } - - @Override - public void onCreate() { - super.onCreate(); - if (Build.VERSION.SDK_INT >= 23) { - mImpl = new MediaBrowserServiceImplApi23(); - } else if (Build.VERSION.SDK_INT >= 21) { - mImpl = new MediaBrowserServiceImplApi21(); - } else { - mImpl = new MediaBrowserServiceImplBase(); - } - mImpl.onCreate(); - } - - @Override - public IBinder onBind(Intent intent) { - return mImpl.onBind(intent); - } - - @Override - public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - } - - /** - * Called to get the root information for browsing by a particular client. - *

- * The implementation should verify that the client package has permission - * to access browse media information before returning the root id; it - * should return null if the client is not allowed to access this - * information. - *

- * - * @param clientPackageName The package name of the application which is - * requesting access to browse media. - * @param clientUid The uid of the application which is requesting access to - * browse media. - * @param rootHints An optional bundle of service-specific arguments to send - * to the media browse service when connecting and retrieving the - * root id for browsing, or null if none. The contents of this - * bundle may affect the information returned when browsing. - * @return The {@link BrowserRoot} for accessing this app's content or null. - */ - public abstract @Nullable - BrowserRoot onGetRoot(@NonNull String clientPackageName, - int clientUid, @Nullable Bundle rootHints); - - /** - * Called to get information about the children of a media item. - *

- * Implementations must call {@link Result#sendResult result.sendResult} - * with the list of children. If loading the children will be an expensive - * operation that should be performed on another thread, - * {@link Result#detach result.detach} may be called before returning from - * this function, and then {@link Result#sendResult result.sendResult} - * called when the loading is complete. - * - * @param parentId The id of the parent media item whose children are to be - * queried. - * @param result The Result to send the list of children to, or null if the - * id is invalid. - */ - public abstract void onLoadChildren(@NonNull String parentId, - @NonNull Result> result); - - /** - * Called to get information about the children of a media item. - *

- * Implementations must call {@link Result#sendResult result.sendResult} - * with the list of children. If loading the children will be an expensive - * operation that should be performed on another thread, - * {@link Result#detach result.detach} may be called before returning from - * this function, and then {@link Result#sendResult result.sendResult} - * called when the loading is complete. - * - * @param parentId The id of the parent media item whose children are to be - * queried. - * @param result The Result to send the list of children to, or null if the - * id is invalid. - * @param options A bundle of service-specific arguments sent from the media - * browse. The information returned through the result should be - * affected by the contents of this bundle. - * {@hide} - */ - public void onLoadChildren(@NonNull String parentId, - @NonNull Result> result, @NonNull Bundle options) { - // To support backward compatibility, when the implementation of MediaBrowserService doesn't - // override onLoadChildren() with options, onLoadChildren() without options will be used - // instead, and the options will be applied in the implementation of result.onResultSent(). - result.setFlags(RESULT_FLAG_OPTION_NOT_HANDLED); - onLoadChildren(parentId, result); - } - - /** - * Called to get information about a specific media item. - *

- * Implementations must call {@link Result#sendResult result.sendResult}. If - * loading the item will be an expensive operation {@link Result#detach - * result.detach} may be called before returning from this function, and - * then {@link Result#sendResult result.sendResult} called when the item has - * been loaded. - *

- * The default implementation sends a null result. - * - * @param itemId The id for the specific - * {@link MediaBrowserCompat.MediaItem}. - * @param result The Result to send the item to, or null if the id is - * invalid. - */ - public void onLoadItem(String itemId, Result result) { - result.sendResult(null); - } - - /** - * Call to set the media session. - *

- * This should be called as soon as possible during the service's startup. - * It may only be called once. - * - * @param token The token for the service's {@link MediaSessionCompat}. - */ - public void setSessionToken(final MediaSessionCompat.Token token) { - if (token == null) { - throw new IllegalArgumentException("Session token may not be null."); - } - if (mSession != null) { - throw new IllegalStateException("The session token has already been set."); - } - mSession = token; - mHandler.post(new Runnable() { - @Override - public void run() { - for (IBinder key : mConnections.keySet()) { - ConnectionRecord connection = mConnections.get(key); - try { - connection.callbacks.onConnect(connection.root.getRootId(), token, - connection.root.getExtras()); - } catch (RemoteException e) { - Log.w(TAG, "Connection for " + connection.pkg + " is no longer valid."); - mConnections.remove(key); - } - } - } - }); - } - - /** - * Gets the session token, or null if it has not yet been created - * or if it has been destroyed. - */ - public @Nullable MediaSessionCompat.Token getSessionToken() { - return mSession; - } - - /** - * Notifies all connected media browsers that the children of - * the specified parent id have changed in some way. - * This will cause browsers to fetch subscribed content again. - * - * @param parentId The id of the parent media item whose - * children changed. - */ - public void notifyChildrenChanged(@NonNull String parentId) { - notifyChildrenChangedInternal(parentId, null); - } - - /** - * Notifies all connected media browsers that the children of - * the specified parent id have changed in some way. - * This will cause browsers to fetch subscribed content again. - * - * @param parentId The id of the parent media item whose - * children changed. - * @param options A bundle of service-specific arguments to send - * to the media browse. The contents of this bundle may - * contain the information about the change. - * {@hide} - */ - public void notifyChildrenChanged(@NonNull String parentId, @NonNull Bundle options) { - if (options == null) { - throw new IllegalArgumentException("options cannot be null in notifyChildrenChanged"); - } - notifyChildrenChangedInternal(parentId, options); - } - - private void notifyChildrenChangedInternal(final String parentId, final Bundle options) { - if (parentId == null) { - throw new IllegalArgumentException("parentId cannot be null in notifyChildrenChanged"); - } - mHandler.post(new Runnable() { - @Override - public void run() { - for (IBinder binder : mConnections.keySet()) { - ConnectionRecord connection = mConnections.get(binder); - List optionsList = connection.subscriptions.get(parentId); - if (optionsList != null) { - for (Bundle bundle : optionsList) { - if (MediaBrowserCompatUtils.hasDuplicatedItems(options, bundle)) { - performLoadChildren(parentId, connection, bundle); - break; - } - } - } - } - } - }); - } - - /** - * Return whether the given package is one of the ones that is owned by the uid. - */ - private boolean isValidPackage(String pkg, int uid) { - if (pkg == null) { - return false; - } - final PackageManager pm = getPackageManager(); - final String[] packages = pm.getPackagesForUid(uid); - final int N = packages.length; - for (int i=0; i optionsList = connection.subscriptions.get(id); - if (optionsList == null) { - optionsList = new ArrayList(); - } - for (Bundle bundle : optionsList) { - if (MediaBrowserCompatUtils.areSameOptions(options, bundle)) { - return; - } - } - optionsList.add(options); - connection.subscriptions.put(id, optionsList); - // send the results - performLoadChildren(id, connection, options); - } - - /** - * Remove the subscription. - */ - private boolean removeSubscription(String id, ConnectionRecord connection, Bundle options) { - boolean removed = false; - List optionsList = connection.subscriptions.get(id); - if (optionsList != null) { - for (Bundle bundle : optionsList) { - if (MediaBrowserCompatUtils.areSameOptions(options, bundle)) { - removed = true; - optionsList.remove(bundle); - break; - } - } - if (optionsList.size() == 0) { - connection.subscriptions.remove(id); - } - } - return removed; - } - - /** - * Call onLoadChildren and then send the results back to the connection. - *

- * Callers must make sure that this connection is still connected. - */ - private void performLoadChildren(final String parentId, final ConnectionRecord connection, - final Bundle options) { - final Result> result - = new Result>(parentId) { - @Override - void onResultSent(List list, @ResultFlags int flag) { - if (mConnections.get(connection.callbacks.asBinder()) != connection) { - if (DBG) { - Log.d(TAG, "Not sending onLoadChildren result for connection that has" - + " been disconnected. pkg=" + connection.pkg + " id=" + parentId); - } - return; - } - - List filteredList = - (flag & RESULT_FLAG_OPTION_NOT_HANDLED) != 0 - ? MediaBrowserCompatUtils.applyOptions(list, options) : list; - try { - connection.callbacks.onLoadChildren(parentId, filteredList, options); - } catch (RemoteException ex) { - // The other side is in the process of crashing. - Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId - + " package=" + connection.pkg); - } - } - }; - - if (options == null) { - onLoadChildren(parentId, result); - } else { - onLoadChildren(parentId, result, options); - } - - if (!result.isDone()) { - throw new IllegalStateException("onLoadChildren must call detach() or sendResult()" - + " before returning for package=" + connection.pkg + " id=" + parentId); - } - } - - private List applyOptions(List list, - final Bundle options) { - int page = options.getInt(MediaBrowserCompat.EXTRA_PAGE, -1); - int pageSize = options.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1); - if (page == -1 && pageSize == -1) { - return list; - } - int fromIndex = pageSize * (page - 1); - int toIndex = fromIndex + pageSize; - if (page < 1 || pageSize < 1 || fromIndex >= list.size()) { - return Collections.emptyList(); - } - if (toIndex > list.size()) { - toIndex = list.size(); - } - return list.subList(fromIndex, toIndex); - } - - private void performLoadItem(String itemId, final ResultReceiver receiver) { - final Result result = - new Result(itemId) { - @Override - void onResultSent(MediaBrowserCompat.MediaItem item, @ResultFlags int flag) { - Bundle bundle = new Bundle(); - bundle.putParcelable(KEY_MEDIA_ITEM, item); - receiver.send(0, bundle); - } - }; - - MediaBrowserServiceCompat.this.onLoadItem(itemId, result); - - if (!result.isDone()) { - throw new IllegalStateException("onLoadItem must call detach() or sendResult()" - + " before returning for id=" + itemId); - } - } - - /** - * Contains information that the browser service needs to send to the client - * when first connected. - */ - public static final class BrowserRoot { - /** - * The lookup key for a boolean that indicates whether the browser service should return a - * browser root for recently played media items. - * - *

When creating a media browser for a given media browser service, this key can be - * supplied as a root hint for retrieving media items that are recently played. - * If the media browser service can provide such media items, the implementation must return - * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back. - * - *

The root hint may contain multiple keys. - * - * @see #EXTRA_OFFLINE - * @see #EXTRA_SUGGESTED - * @hide - */ - public static final String EXTRA_RECENT = "android.service.media.extra.RECENT"; - - /** - * The lookup key for a boolean that indicates whether the browser service should return a - * browser root for offline media items. - * - *

When creating a media browser for a given media browser service, this key can be - * supplied as a root hint for retrieving media items that are can be played without an - * internet connection. - * If the media browser service can provide such media items, the implementation must return - * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back. - * - *

The root hint may contain multiple keys. - * - * @see #EXTRA_RECENT - * @see #EXTRA_SUGGESTED - * @hide - */ - public static final String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE"; - - /** - * The lookup key for a boolean that indicates whether the browser service should return a - * browser root for suggested media items. - * - *

When creating a media browser for a given media browser service, this key can be - * supplied as a root hint for retrieving the media items suggested by the media browser - * service. - * If the media browser service can provide such media items, the implementation must return - * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back. - * - *

The root hint may contain multiple keys. - * - * @see #EXTRA_RECENT - * @see #EXTRA_OFFLINE - * @hide - */ - public static final String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED"; - - final private String mRootId; - final private Bundle mExtras; - - /** - * Constructs a browser root. - * @param rootId The root id for browsing. - * @param extras Any extras about the browser service. - */ - public BrowserRoot(@NonNull String rootId, @Nullable Bundle extras) { - if (rootId == null) { - throw new IllegalArgumentException("The root id in BrowserRoot cannot be null. " + - "Use null for BrowserRoot instead."); - } - mRootId = rootId; - mExtras = extras; - } - - /** - * Gets the root id for browsing. - */ - public String getRootId() { - return mRootId; - } - - /** - * Gets any extras about the browser service. - */ - public Bundle getExtras() { - return mExtras; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompatApi21.java deleted file mode 100644 index bd9b57b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompatApi21.java +++ /dev/null @@ -1,160 +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 p.android.support.v4.media; - -import android.content.Intent; -import android.media.MediaDescription; -import android.media.browse.MediaBrowser; -import android.os.Build; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Parcel; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.service.media.MediaBrowserService; - -import java.util.ArrayList; -import java.util.List; - -class MediaBrowserServiceCompatApi21 { - - public static Object createService() { - return new MediaBrowserServiceAdaptorApi21(); - } - - public static void onCreate(Object serviceObj, ServiceImplApi21 serviceImpl) { - ((MediaBrowserServiceAdaptorApi21) serviceObj).onCreate(serviceImpl); - } - - public static IBinder onBind(Object serviceObj, Intent intent) { - return ((MediaBrowserServiceAdaptorApi21) serviceObj).onBind(intent); - } - - public interface ServiceImplApi21 { - void connect(final String pkg, final Bundle rootHints, final ServiceCallbacks callbacks); - void disconnect(final ServiceCallbacks callbacks); - void addSubscription(final String id, final ServiceCallbacks callbacks); - void removeSubscription(final String id, final ServiceCallbacks callbacks); - } - - public interface ServiceCallbacks { - IBinder asBinder(); - void onConnect(String root, Object session, Bundle extras) throws RemoteException; - void onConnectFailed() throws RemoteException; - void onLoadChildren(String mediaId, List list) throws RemoteException; - } - - public static class ServiceCallbacksApi21 implements ServiceCallbacks { - private static Object sNullParceledListSliceObj; - static { - MediaDescription nullDescription = new MediaDescription.Builder().setMediaId( - MediaBrowserCompatApi21.NULL_MEDIA_ITEM_ID).build(); - MediaBrowser.MediaItem nullMediaItem = new MediaBrowser.MediaItem(nullDescription, 0); - List nullMediaItemList = new ArrayList<>(); - nullMediaItemList.add(nullMediaItem); - sNullParceledListSliceObj = ParceledListSliceAdapterApi21.newInstance(nullMediaItemList); - } - - private final IMediaBrowserServiceCallbacksAdapterApi21 mCallbacks; - - ServiceCallbacksApi21(Object callbacksObj) { - mCallbacks = new IMediaBrowserServiceCallbacksAdapterApi21(callbacksObj); - } - - public IBinder asBinder() { - return mCallbacks.asBinder(); - } - - public void onConnect(String root, Object session, Bundle extras) throws RemoteException { - mCallbacks.onConnect(root, session, extras); - } - - public void onConnectFailed() throws RemoteException { - mCallbacks.onConnectFailed(); - } - - public void onLoadChildren(String mediaId, List list) throws RemoteException { - List itemList = null; - if (list != null) { - itemList = new ArrayList<>(); - for (Parcel parcel : list) { - parcel.setDataPosition(0); - itemList.add(MediaBrowser.MediaItem.CREATOR.createFromParcel(parcel)); - parcel.recycle(); - } - } - Object pls; - if (Build.VERSION.SDK_INT > 23) { - pls = itemList == null ? null : ParceledListSliceAdapterApi21.newInstance(itemList); - } else { - pls = itemList == null ? sNullParceledListSliceObj - : ParceledListSliceAdapterApi21.newInstance(itemList); - } - mCallbacks.onLoadChildren(mediaId, pls); - } - } - - static class MediaBrowserServiceAdaptorApi21 { - ServiceBinderProxyApi21 mBinder; - - public void onCreate(ServiceImplApi21 serviceImpl) { - mBinder = new ServiceBinderProxyApi21(serviceImpl); - } - - public IBinder onBind(Intent intent) { - if (MediaBrowserService.SERVICE_INTERFACE.equals(intent.getAction())) { - return mBinder; - } - return null; - } - - static class ServiceBinderProxyApi21 extends IMediaBrowserServiceAdapterApi21.Stub { - final ServiceImplApi21 mServiceImpl; - - ServiceBinderProxyApi21(ServiceImplApi21 serviceImpl) { - super(); - mServiceImpl = serviceImpl; - } - - @Override - public void connect(final String pkg, final Bundle rootHints, final Object callbacks) { - mServiceImpl.connect(pkg, rootHints, new ServiceCallbacksApi21(callbacks)); - } - - @Override - public void disconnect(final Object callbacks) { - mServiceImpl.disconnect(new ServiceCallbacksApi21(callbacks)); - } - - @Override - public void addSubscription(final String id, final Object callbacks) { - mServiceImpl.addSubscription(id, new ServiceCallbacksApi21(callbacks)); - } - - @Override - public void removeSubscription(final String id, - final Object callbacks) { - mServiceImpl.removeSubscription(id, new ServiceCallbacksApi21(callbacks)); - } - - @Override - public void getMediaItem(final String mediaId, final ResultReceiver receiver) { - // No operation since this method is added in API 23. - } - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompatApi23.java deleted file mode 100644 index 7ab5f8b..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaBrowserServiceCompatApi23.java +++ /dev/null @@ -1,86 +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 p.android.support.v4.media; - -import android.media.browse.MediaBrowser; -import android.os.Bundle; -import android.os.Parcel; -import android.os.ResultReceiver; -import android.service.media.MediaBrowserService; -import android.util.Log; - -class MediaBrowserServiceCompatApi23 extends MediaBrowserServiceCompatApi21 { - private static final String TAG = "MediaBrowserServiceCompatApi21"; - - public static Object createService() { - return new MediaBrowserServiceAdaptorApi23(); - } - - public static void onCreate(Object serviceObj, ServiceImplApi23 serviceImpl) { - ((MediaBrowserServiceAdaptorApi23) serviceObj).onCreate(serviceImpl); - } - - public interface ServiceImplApi23 extends ServiceImplApi21 { - void getMediaItem(final String mediaId, final ItemCallback cb); - } - - public interface ItemCallback { - void onItemLoaded(int resultCode, Bundle resultData, Parcel itemParcel); - } - - static class MediaBrowserServiceAdaptorApi23 extends MediaBrowserServiceAdaptorApi21 { - - public void onCreate(ServiceImplApi23 serviceImpl) { - mBinder = new ServiceBinderProxyApi23(serviceImpl); - } - - private static class ServiceBinderProxyApi23 extends ServiceBinderProxyApi21 { - ServiceImplApi23 mServiceImpl; - - ServiceBinderProxyApi23(ServiceImplApi23 serviceImpl) { - super(serviceImpl); - mServiceImpl = serviceImpl; - } - - @Override - public void getMediaItem(final String mediaId, final ResultReceiver receiver) { - final String KEY_MEDIA_ITEM; - try { - KEY_MEDIA_ITEM = (String) MediaBrowserService.class.getDeclaredField( - "KEY_MEDIA_ITEM").get(null); - } catch (IllegalAccessException | NoSuchFieldException e) { - Log.i(TAG, "Failed to get KEY_MEDIA_ITEM via reflection", e); - return; - } - - mServiceImpl.getMediaItem(mediaId, new ItemCallback() { - @Override - public void onItemLoaded(int resultCode, Bundle resultData, Parcel itemParcel) { - if (itemParcel != null) { - itemParcel.setDataPosition(0); - MediaBrowser.MediaItem item = - MediaBrowser.MediaItem.CREATOR.createFromParcel(itemParcel); - resultData.putParcelable(KEY_MEDIA_ITEM, item); - itemParcel.recycle(); - } - receiver.send(resultCode, resultData); - } - }); - } - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompat.java deleted file mode 100644 index 95ac6b4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompat.java +++ /dev/null @@ -1,448 +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 p.android.support.v4.media; - -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import p.android.support.annotation.Nullable; -import android.text.TextUtils; - -/** - * A simple set of metadata for a media item suitable for display. This can be - * created using the Builder or retrieved from existing metadata using - * {@link MediaMetadataCompat#getDescription()}. - */ -public final class MediaDescriptionCompat implements Parcelable { - /** - * Custom key to store a media URI on API 21-22 devices (before it became part of the - * framework class) when parceling/converting to and from framework objects. - * - * @hide - */ - public static final String DESCRIPTION_KEY_MEDIA_URI = - "android.support.v4.media.description.MEDIA_URI"; - /** - * Custom key to store whether the original Bundle provided by the developer was null - * - * @hide - */ - public static final String DESCRIPTION_KEY_NULL_BUNDLE_FLAG = - "android.support.v4.media.description.NULL_BUNDLE_FLAG"; - /** - * A unique persistent id for the content or null. - */ - private final String mMediaId; - /** - * A primary title suitable for display or null. - */ - private final CharSequence mTitle; - /** - * A subtitle suitable for display or null. - */ - private final CharSequence mSubtitle; - /** - * A description suitable for display or null. - */ - private final CharSequence mDescription; - /** - * A bitmap icon suitable for display or null. - */ - private final Bitmap mIcon; - /** - * A Uri for an icon suitable for display or null. - */ - private final Uri mIconUri; - /** - * Extras for opaque use by apps/system. - */ - private final Bundle mExtras; - /** - * A Uri to identify this content. - */ - private final Uri mMediaUri; - - /** - * A cached copy of the equivalent framework object. - */ - private Object mDescriptionObj; - - private MediaDescriptionCompat(String mediaId, CharSequence title, CharSequence subtitle, - CharSequence description, Bitmap icon, Uri iconUri, Bundle extras, Uri mediaUri) { - mMediaId = mediaId; - mTitle = title; - mSubtitle = subtitle; - mDescription = description; - mIcon = icon; - mIconUri = iconUri; - mExtras = extras; - mMediaUri = mediaUri; - } - - private MediaDescriptionCompat(Parcel in) { - mMediaId = in.readString(); - mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mIcon = in.readParcelable(null); - mIconUri = in.readParcelable(null); - mExtras = in.readBundle(); - mMediaUri = in.readParcelable(null); - } - - /** - * Returns the media id or null. See - * {@link MediaMetadataCompat#METADATA_KEY_MEDIA_ID}. - */ - @Nullable - public String getMediaId() { - return mMediaId; - } - - /** - * Returns a title suitable for display or null. - * - * @return A title or null. - */ - @Nullable - public CharSequence getTitle() { - return mTitle; - } - - /** - * Returns a subtitle suitable for display or null. - * - * @return A subtitle or null. - */ - @Nullable - public CharSequence getSubtitle() { - return mSubtitle; - } - - /** - * Returns a description suitable for display or null. - * - * @return A description or null. - */ - @Nullable - public CharSequence getDescription() { - return mDescription; - } - - /** - * Returns a bitmap icon suitable for display or null. - * - * @return An icon or null. - */ - @Nullable - public Bitmap getIconBitmap() { - return mIcon; - } - - /** - * Returns a Uri for an icon suitable for display or null. - * - * @return An icon uri or null. - */ - @Nullable - public Uri getIconUri() { - return mIconUri; - } - - /** - * Returns any extras that were added to the description. - * - * @return A bundle of extras or null. - */ - @Nullable - public Bundle getExtras() { - return mExtras; - } - - /** - * Returns a Uri representing this content or null. - * - * @return A media Uri or null. - */ - @Nullable - public Uri getMediaUri() { - return mMediaUri; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - if (Build.VERSION.SDK_INT < 21) { - dest.writeString(mMediaId); - TextUtils.writeToParcel(mTitle, dest, flags); - TextUtils.writeToParcel(mSubtitle, dest, flags); - TextUtils.writeToParcel(mDescription, dest, flags); - dest.writeParcelable(mIcon, flags); - dest.writeParcelable(mIconUri, flags); - dest.writeBundle(mExtras); - dest.writeParcelable(mMediaUri, flags); - } else { - MediaDescriptionCompatApi21.writeToParcel(getMediaDescription(), dest, flags); - } - } - - @Override - public String toString() { - return mTitle + ", " + mSubtitle + ", " + mDescription; - } - - /** - * Gets the underlying framework {@link android.media.MediaDescription} - * object. - *

- * This method is only supported on - * {@link Build.VERSION_CODES#LOLLIPOP} and later. - *

- * - * @return An equivalent {@link android.media.MediaDescription} object, or - * null if none. - */ - public Object getMediaDescription() { - if (mDescriptionObj != null || Build.VERSION.SDK_INT < 21) { - return mDescriptionObj; - } - Object bob = MediaDescriptionCompatApi21.Builder.newInstance(); - MediaDescriptionCompatApi21.Builder.setMediaId(bob, mMediaId); - MediaDescriptionCompatApi21.Builder.setTitle(bob, mTitle); - MediaDescriptionCompatApi21.Builder.setSubtitle(bob, mSubtitle); - MediaDescriptionCompatApi21.Builder.setDescription(bob, mDescription); - MediaDescriptionCompatApi21.Builder.setIconBitmap(bob, mIcon); - MediaDescriptionCompatApi21.Builder.setIconUri(bob, mIconUri); - // Media URI was not added until API 23, so add it to the Bundle of extras to - // ensure the data is not lost - this ensures that - // fromMediaDescription(getMediaDescription(mediaDescriptionCompat)) returns - // an equivalent MediaDescriptionCompat on all API levels - Bundle extras = mExtras; - if (Build.VERSION.SDK_INT < 23 && mMediaUri != null) { - if (extras == null) { - extras = new Bundle(); - extras.putBoolean(DESCRIPTION_KEY_NULL_BUNDLE_FLAG, true); - } - extras.putParcelable(DESCRIPTION_KEY_MEDIA_URI, mMediaUri); - } - MediaDescriptionCompatApi21.Builder.setExtras(bob, extras); - if (Build.VERSION.SDK_INT >= 23) { - MediaDescriptionCompatApi23.Builder.setMediaUri(bob, mMediaUri); - } - mDescriptionObj = MediaDescriptionCompatApi21.Builder.build(bob); - - return mDescriptionObj; - } - - /** - * Creates an instance from a framework - * {@link android.media.MediaDescription} object. - *

- * This method is only supported on API 21+. - *

- * - * @param descriptionObj A {@link android.media.MediaDescription} object, or - * null if none. - * @return An equivalent {@link MediaMetadataCompat} object, or null if - * none. - */ - public static MediaDescriptionCompat fromMediaDescription(Object descriptionObj) { - if (descriptionObj == null || Build.VERSION.SDK_INT < 21) { - return null; - } - - Builder bob = new Builder(); - bob.setMediaId(MediaDescriptionCompatApi21.getMediaId(descriptionObj)); - bob.setTitle(MediaDescriptionCompatApi21.getTitle(descriptionObj)); - bob.setSubtitle(MediaDescriptionCompatApi21.getSubtitle(descriptionObj)); - bob.setDescription(MediaDescriptionCompatApi21.getDescription(descriptionObj)); - bob.setIconBitmap(MediaDescriptionCompatApi21.getIconBitmap(descriptionObj)); - bob.setIconUri(MediaDescriptionCompatApi21.getIconUri(descriptionObj)); - Bundle extras = MediaDescriptionCompatApi21.getExtras(descriptionObj); - Uri mediaUri = extras == null ? null : - (Uri) extras.getParcelable(DESCRIPTION_KEY_MEDIA_URI); - if (mediaUri != null) { - if (extras.containsKey(DESCRIPTION_KEY_NULL_BUNDLE_FLAG) && extras.size() == 2) { - // The extras were only created for the media URI, so we set it back to null to - // ensure mediaDescriptionCompat.getExtras() equals - // fromMediaDescription(getMediaDescription(mediaDescriptionCompat)).getExtras() - extras = null; - } else { - // Remove media URI keys to ensure mediaDescriptionCompat.getExtras().keySet() - // equals fromMediaDescription(getMediaDescription(mediaDescriptionCompat)) - // .getExtras().keySet() - extras.remove(DESCRIPTION_KEY_MEDIA_URI); - extras.remove(DESCRIPTION_KEY_NULL_BUNDLE_FLAG); - } - } - bob.setExtras(extras); - if (mediaUri != null) { - bob.setMediaUri(mediaUri); - } else if (Build.VERSION.SDK_INT >= 23) { - bob.setMediaUri(MediaDescriptionCompatApi23.getMediaUri(descriptionObj)); - } - MediaDescriptionCompat descriptionCompat = bob.build(); - descriptionCompat.mDescriptionObj = descriptionObj; - - return descriptionCompat; - } - - public static final Creator CREATOR = - new Creator() { - @Override - public MediaDescriptionCompat createFromParcel(Parcel in) { - if (Build.VERSION.SDK_INT < 21) { - return new MediaDescriptionCompat(in); - } else { - return fromMediaDescription(MediaDescriptionCompatApi21.fromParcel(in)); - } - } - - @Override - public MediaDescriptionCompat[] newArray(int size) { - return new MediaDescriptionCompat[size]; - } - }; - - /** - * Builder for {@link MediaDescriptionCompat} objects. - */ - public static final class Builder { - private String mMediaId; - private CharSequence mTitle; - private CharSequence mSubtitle; - private CharSequence mDescription; - private Bitmap mIcon; - private Uri mIconUri; - private Bundle mExtras; - private Uri mMediaUri; - - /** - * Creates an initially empty builder. - */ - public Builder() { - } - - /** - * Sets the media id. - * - * @param mediaId The unique id for the item or null. - * @return this - */ - public Builder setMediaId(@Nullable String mediaId) { - mMediaId = mediaId; - return this; - } - - /** - * Sets the title. - * - * @param title A title suitable for display to the user or null. - * @return this - */ - public Builder setTitle(@Nullable CharSequence title) { - mTitle = title; - return this; - } - - /** - * Sets the subtitle. - * - * @param subtitle A subtitle suitable for display to the user or null. - * @return this - */ - public Builder setSubtitle(@Nullable CharSequence subtitle) { - mSubtitle = subtitle; - return this; - } - - /** - * Sets the description. - * - * @param description A description suitable for display to the user or - * null. - * @return this - */ - public Builder setDescription(@Nullable CharSequence description) { - mDescription = description; - return this; - } - - /** - * Sets the icon. - * - * @param icon A {@link Bitmap} icon suitable for display to the user or - * null. - * @return this - */ - public Builder setIconBitmap(@Nullable Bitmap icon) { - mIcon = icon; - return this; - } - - /** - * Sets the icon uri. - * - * @param iconUri A {@link Uri} for an icon suitable for display to the - * user or null. - * @return this - */ - public Builder setIconUri(@Nullable Uri iconUri) { - mIconUri = iconUri; - return this; - } - - /** - * Sets a bundle of extras. - * - * @param extras The extras to include with this description or null. - * @return this - */ - public Builder setExtras(@Nullable Bundle extras) { - mExtras = extras; - return this; - } - - /** - * Sets the media uri. - * - * @param mediaUri The content's {@link Uri} for the item or null. - * @return this - */ - public Builder setMediaUri(@Nullable Uri mediaUri) { - mMediaUri = mediaUri; - return this; - } - - /** - * Creates a {@link MediaDescriptionCompat} instance with the specified - * fields. - * - * @return A MediaDescriptionCompat instance. - */ - public MediaDescriptionCompat build() { - return new MediaDescriptionCompat(mMediaId, mTitle, mSubtitle, mDescription, mIcon, - mIconUri, mExtras, mMediaUri); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompatApi21.java deleted file mode 100644 index 02aa7ca..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompatApi21.java +++ /dev/null @@ -1,100 +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 p.android.support.v4.media; - -import android.graphics.Bitmap; -import android.media.MediaDescription; -import android.net.Uri; -import android.os.Bundle; -import android.os.Parcel; - -class MediaDescriptionCompatApi21 { - - public static String getMediaId(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getMediaId(); - } - - public static CharSequence getTitle(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getTitle(); - } - - public static CharSequence getSubtitle(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getSubtitle(); - } - - public static CharSequence getDescription(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getDescription(); - } - - public static Bitmap getIconBitmap(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getIconBitmap(); - } - - public static Uri getIconUri(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getIconUri(); - } - - public static Bundle getExtras(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getExtras(); - } - - public static void writeToParcel(Object descriptionObj, Parcel dest, int flags) { - ((MediaDescription) descriptionObj).writeToParcel(dest, flags); - } - - public static Object fromParcel(Parcel in) { - return MediaDescription.CREATOR.createFromParcel(in); - } - - static class Builder { - public static Object newInstance() { - return new MediaDescription.Builder(); - } - - - public static void setMediaId(Object builderObj, String mediaId) { - ((MediaDescription.Builder)builderObj).setMediaId(mediaId); - } - - public static void setTitle(Object builderObj, CharSequence title) { - ((MediaDescription.Builder)builderObj).setTitle(title); - } - - public static void setSubtitle(Object builderObj, CharSequence subtitle) { - ((MediaDescription.Builder)builderObj).setSubtitle(subtitle); - } - - public static void setDescription(Object builderObj, CharSequence description) { - ((MediaDescription.Builder)builderObj).setDescription(description); - } - - public static void setIconBitmap(Object builderObj, Bitmap iconBitmap) { - ((MediaDescription.Builder)builderObj).setIconBitmap(iconBitmap); - } - - public static void setIconUri(Object builderObj, Uri iconUri) { - ((MediaDescription.Builder)builderObj).setIconUri(iconUri); - } - - public static void setExtras(Object builderObj, Bundle extras) { - ((MediaDescription.Builder)builderObj).setExtras(extras); - } - - public static Object build(Object builderObj) { - return ((MediaDescription.Builder) builderObj).build(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompatApi23.java deleted file mode 100644 index f8775b9..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaDescriptionCompatApi23.java +++ /dev/null @@ -1,31 +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 p.android.support.v4.media; - -import android.media.MediaDescription; -import android.net.Uri; - -class MediaDescriptionCompatApi23 extends MediaDescriptionCompatApi21 { - public static Uri getMediaUri(Object descriptionObj) { - return ((MediaDescription) descriptionObj).getMediaUri(); - } - - static class Builder extends MediaDescriptionCompatApi21.Builder { - public static void setMediaUri(Object builderObj, Uri mediaUri) { - ((MediaDescription.Builder)builderObj).setMediaUri(mediaUri); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompat.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompat.aidl deleted file mode 100644 index 037a3f2..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompat.aidl +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2014, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.plug.v4.media; - -parcelable MediaMetadataCompat; diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompat.java deleted file mode 100644 index a62ae19..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompat.java +++ /dev/null @@ -1,756 +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 p.android.support.v4.media; - -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import p.android.support.annotation.StringDef; -import p.android.support.v4.util.ArrayMap; -import android.text.TextUtils; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Set; - -/** - * Contains metadata about an item, such as the title, artist, etc. - */ -public final class MediaMetadataCompat implements Parcelable { - private static final String TAG = "MediaMetadata"; - - /** - * The title of the media. - */ - public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE"; - - /** - * The artist of the media. - */ - public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST"; - - /** - * The duration of the media in ms. A negative duration indicates that the - * duration is unknown (or infinite). - */ - public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION"; - - /** - * The album title for the media. - */ - public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM"; - - /** - * The author of the media. - */ - public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR"; - - /** - * The writer of the media. - */ - public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER"; - - /** - * The composer of the media. - */ - public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER"; - - /** - * The compilation status of the media. - */ - public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION"; - - /** - * The date the media was created or published. The format is unspecified - * but RFC 3339 is recommended. - */ - public static final String METADATA_KEY_DATE = "android.media.metadata.DATE"; - - /** - * The year the media was created or published as a long. - */ - public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR"; - - /** - * The genre of the media. - */ - public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE"; - - /** - * The track number for the media. - */ - public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER"; - - /** - * The number of tracks in the media's original source. - */ - public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS"; - - /** - * The disc number for the media's original source. - */ - public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER"; - - /** - * The artist for the album of the media's original source. - */ - public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST"; - - /** - * The artwork for the media as a {@link Bitmap}. - */ - public static final String METADATA_KEY_ART = "android.media.metadata.ART"; - - /** - * The artwork for the media as a Uri style String. - */ - public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI"; - - /** - * The artwork for the album of the media's original source as a - * {@link Bitmap}. - */ - public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART"; - - /** - * The artwork for the album of the media's original source as a Uri style - * String. - */ - public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI"; - - /** - * The user's rating for the media. - * - * @see RatingCompat - */ - public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING"; - - /** - * The overall rating for the media. - * - * @see RatingCompat - */ - public static final String METADATA_KEY_RATING = "android.media.metadata.RATING"; - - /** - * A title that is suitable for display to the user. This will generally be - * the same as {@link #METADATA_KEY_TITLE} but may differ for some formats. - * When displaying media described by this metadata this should be preferred - * if present. - */ - public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE"; - - /** - * A subtitle that is suitable for display to the user. When displaying a - * second line for media described by this metadata this should be preferred - * to other fields if present. - */ - public static final String METADATA_KEY_DISPLAY_SUBTITLE - = "android.media.metadata.DISPLAY_SUBTITLE"; - - /** - * A description that is suitable for display to the user. When displaying - * more information for media described by this metadata this should be - * preferred to other fields if present. - */ - public static final String METADATA_KEY_DISPLAY_DESCRIPTION - = "android.media.metadata.DISPLAY_DESCRIPTION"; - - /** - * An icon or thumbnail that is suitable for display to the user. When - * displaying an icon for media described by this metadata this should be - * preferred to other fields if present. This must be a {@link Bitmap}. - */ - public static final String METADATA_KEY_DISPLAY_ICON - = "android.media.metadata.DISPLAY_ICON"; - - /** - * An icon or thumbnail that is suitable for display to the user. When - * displaying more information for media described by this metadata the - * display description should be preferred to other fields when present. - * This must be a Uri style String. - */ - public static final String METADATA_KEY_DISPLAY_ICON_URI - = "android.media.metadata.DISPLAY_ICON_URI"; - - /** - * A String key for identifying the content. This value is specific to the - * service providing the content. If used, this should be a persistent - * unique key for the underlying content. - */ - public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID"; - - /** - * @hide - */ - @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR, - METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION, - METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI, - METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE, - METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI, - METADATA_KEY_MEDIA_ID}) - @Retention(RetentionPolicy.SOURCE) - public @interface TextKey {} - - /** - * @hide - */ - @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER, - METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER}) - @Retention(RetentionPolicy.SOURCE) - public @interface LongKey {} - - /** - * @hide - */ - @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON}) - @Retention(RetentionPolicy.SOURCE) - public @interface BitmapKey {} - - /** - * @hide - */ - @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING}) - @Retention(RetentionPolicy.SOURCE) - public @interface RatingKey {} - - private static final int METADATA_TYPE_LONG = 0; - private static final int METADATA_TYPE_TEXT = 1; - private static final int METADATA_TYPE_BITMAP = 2; - private static final int METADATA_TYPE_RATING = 3; - private static final ArrayMap METADATA_KEYS_TYPE; - - static { - METADATA_KEYS_TYPE = new ArrayMap(); - METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP); - METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP); - METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING); - METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP); - METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT); - METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_ID, METADATA_TYPE_TEXT); - } - - private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = { - METADATA_KEY_TITLE, - METADATA_KEY_ARTIST, - METADATA_KEY_ALBUM, - METADATA_KEY_ALBUM_ARTIST, - METADATA_KEY_WRITER, - METADATA_KEY_AUTHOR, - METADATA_KEY_COMPOSER - }; - - private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = { - METADATA_KEY_DISPLAY_ICON, - METADATA_KEY_ART, - METADATA_KEY_ALBUM_ART - }; - - private static final @TextKey String[] PREFERRED_URI_ORDER = { - METADATA_KEY_DISPLAY_ICON_URI, - METADATA_KEY_ART_URI, - METADATA_KEY_ALBUM_ART_URI - }; - - private final Bundle mBundle; - private Object mMetadataObj; - private MediaDescriptionCompat mDescription; - - private MediaMetadataCompat(Bundle bundle) { - mBundle = new Bundle(bundle); - } - - private MediaMetadataCompat(Parcel in) { - mBundle = in.readBundle(); - } - - /** - * Returns true if the given key is contained in the metadata - * - * @param key a String key - * @return true if the key exists in this metadata, false otherwise - */ - public boolean containsKey(String key) { - return mBundle.containsKey(key); - } - - /** - * Returns the value associated with the given key, or null if no mapping of - * the desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key The key the value is stored under - * @return a CharSequence value, or null - */ - public CharSequence getText(@TextKey String key) { - return mBundle.getCharSequence(key); - } - - /** - * Returns the value associated with the given key, or null if no mapping of - * the desired type exists for the given key or a null value is explicitly - * associated with the key. - * - * @param key The key the value is stored under - * @return a String value, or null - */ - public String getString(@TextKey String key) { - CharSequence text = mBundle.getCharSequence(key); - if (text != null) { - return text.toString(); - } - return null; - } - - /** - * Returns the value associated with the given key, or 0L if no long exists - * for the given key. - * - * @param key The key the value is stored under - * @return a long value - */ - public long getLong(@LongKey String key) { - return mBundle.getLong(key, 0); - } - - /** - * Return a {@link RatingCompat} for the given key or null if no rating exists for - * the given key. - * - * @param key The key the value is stored under - * @return A {@link RatingCompat} or null - */ - public RatingCompat getRating(@RatingKey String key) { - RatingCompat rating = null; - try { - if (Build.VERSION.SDK_INT >= 21) { - // On platform version 21 or higher, mBundle stores a Rating object. Convert it to - // RatingCompat. - rating = RatingCompat.fromRating(mBundle.getParcelable(key)); - } else { - rating = mBundle.getParcelable(key); - } - } catch (Exception e) { - // ignore, value was not a bitmap - Log.w(TAG, "Failed to retrieve a key as Rating.", e); - } - return rating; - } - - /** - * Return a {@link Bitmap} for the given key or null if no bitmap exists for - * the given key. - * - * @param key The key the value is stored under - * @return A {@link Bitmap} or null - */ - public Bitmap getBitmap(@BitmapKey String key) { - Bitmap bmp = null; - try { - bmp = mBundle.getParcelable(key); - } catch (Exception e) { - // ignore, value was not a bitmap - Log.w(TAG, "Failed to retrieve a key as Bitmap.", e); - } - return bmp; - } - - /** - * Returns a simple description of this metadata for display purposes. - * - * @return A simple description of this metadata. - */ - public MediaDescriptionCompat getDescription() { - if (mDescription != null) { - return mDescription; - } - - String mediaId = getString(METADATA_KEY_MEDIA_ID); - - CharSequence[] text = new CharSequence[3]; - Bitmap icon = null; - Uri iconUri = null; - - // First handle the case where display data is set already - CharSequence displayText = getText(METADATA_KEY_DISPLAY_TITLE); - if (!TextUtils.isEmpty(displayText)) { - // If they have a display title use only display data, otherwise use - // our best bets - text[0] = displayText; - text[1] = getText(METADATA_KEY_DISPLAY_SUBTITLE); - text[2] = getText(METADATA_KEY_DISPLAY_DESCRIPTION); - } else { - // Use whatever fields we can - int textIndex = 0; - int keyIndex = 0; - while (textIndex < text.length && keyIndex < PREFERRED_DESCRIPTION_ORDER.length) { - CharSequence next = getText(PREFERRED_DESCRIPTION_ORDER[keyIndex++]); - if (!TextUtils.isEmpty(next)) { - // Fill in the next empty bit of text - text[textIndex++] = next; - } - } - } - - // Get the best art bitmap we can find - for (int i = 0; i < PREFERRED_BITMAP_ORDER.length; i++) { - Bitmap next = getBitmap(PREFERRED_BITMAP_ORDER[i]); - if (next != null) { - icon = next; - break; - } - } - - // Get the best Uri we can find - for (int i = 0; i < PREFERRED_URI_ORDER.length; i++) { - String next = getString(PREFERRED_URI_ORDER[i]); - if (!TextUtils.isEmpty(next)) { - iconUri = Uri.parse(next); - break; - } - } - - MediaDescriptionCompat.Builder bob = new MediaDescriptionCompat.Builder(); - bob.setMediaId(mediaId); - bob.setTitle(text[0]); - bob.setSubtitle(text[1]); - bob.setDescription(text[2]); - bob.setIconBitmap(icon); - bob.setIconUri(iconUri); - mDescription = bob.build(); - - return mDescription; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeBundle(mBundle); - } - - /** - * Get the number of fields in this metadata. - * - * @return The number of fields in the metadata. - */ - public int size() { - return mBundle.size(); - } - - /** - * Returns a Set containing the Strings used as keys in this metadata. - * - * @return a Set of String keys - */ - public Set keySet() { - return mBundle.keySet(); - } - - /** - * Gets the bundle backing the metadata object. This is available to support - * backwards compatibility. Apps should not modify the bundle directly. - * - * @return The Bundle backing this metadata. - */ - public Bundle getBundle() { - return mBundle; - } - - /** - * Creates an instance from a framework {@link android.media.MediaMetadata} - * object. - *

- * This method is only supported on - * {@link Build.VERSION_CODES#LOLLIPOP} and later. - *

- * - * @param metadataObj A {@link android.media.MediaMetadata} object, or null - * if none. - * @return An equivalent {@link MediaMetadataCompat} object, or null if - * none. - */ - public static MediaMetadataCompat fromMediaMetadata(Object metadataObj) { - if (metadataObj == null || Build.VERSION.SDK_INT < 21) { - return null; - } - - Parcel p = Parcel.obtain(); - MediaMetadataCompatApi21.writeToParcel(metadataObj, p, 0); - p.setDataPosition(0); - MediaMetadataCompat metadata = MediaMetadataCompat.CREATOR.createFromParcel(p); - p.recycle(); - metadata.mMetadataObj = metadataObj; - return metadata; - } - - /** - * Gets the underlying framework {@link android.media.MediaMetadata} object. - *

- * This method is only supported on - * {@link Build.VERSION_CODES#LOLLIPOP} and later. - *

- * - * @return An equivalent {@link android.media.MediaMetadata} object, or null - * if none. - */ - public Object getMediaMetadata() { - if (mMetadataObj != null || Build.VERSION.SDK_INT < 21) { - return mMetadataObj; - } - - Parcel p = Parcel.obtain(); - writeToParcel(p, 0); - p.setDataPosition(0); - mMetadataObj = MediaMetadataCompatApi21.createFromParcel(p); - p.recycle(); - return mMetadataObj; - } - - public static final Creator CREATOR = - new Creator() { - @Override - public MediaMetadataCompat createFromParcel(Parcel in) { - return new MediaMetadataCompat(in); - } - - @Override - public MediaMetadataCompat[] newArray(int size) { - return new MediaMetadataCompat[size]; - } - }; - - /** - * Use to build MediaMetadata objects. The system defined metadata keys must - * use the appropriate data type. - */ - public static final class Builder { - private final Bundle mBundle; - - /** - * Create an empty Builder. Any field that should be included in the - * {@link MediaMetadataCompat} must be added. - */ - public Builder() { - mBundle = new Bundle(); - } - - /** - * Create a Builder using a {@link MediaMetadataCompat} instance to set the - * initial values. All fields in the source metadata will be included in - * the new metadata. Fields can be overwritten by adding the same key. - * - * @param source - */ - public Builder(MediaMetadataCompat source) { - mBundle = new Bundle(source.mBundle); - } - - /** - * Put a CharSequence value into the metadata. Custom keys may be used, - * but if the METADATA_KEYs defined in this class are used they may only - * be one of the following: - *
    - *
  • {@link #METADATA_KEY_TITLE}
  • - *
  • {@link #METADATA_KEY_ARTIST}
  • - *
  • {@link #METADATA_KEY_ALBUM}
  • - *
  • {@link #METADATA_KEY_AUTHOR}
  • - *
  • {@link #METADATA_KEY_WRITER}
  • - *
  • {@link #METADATA_KEY_COMPOSER}
  • - *
  • {@link #METADATA_KEY_DATE}
  • - *
  • {@link #METADATA_KEY_GENRE}
  • - *
  • {@link #METADATA_KEY_ALBUM_ARTIST}
  • - *
  • {@link #METADATA_KEY_ART_URI}
  • - *
  • {@link #METADATA_KEY_ALBUM_ART_URI}
  • - *
  • {@link #METADATA_KEY_DISPLAY_TITLE}
  • - *
  • {@link #METADATA_KEY_DISPLAY_SUBTITLE}
  • - *
  • {@link #METADATA_KEY_DISPLAY_DESCRIPTION}
  • - *
  • {@link #METADATA_KEY_DISPLAY_ICON_URI}
  • - *
- * - * @param key The key for referencing this value - * @param value The CharSequence value to store - * @return The Builder to allow chaining - */ - public Builder putText(@TextKey String key, CharSequence value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a CharSequence"); - } - } - mBundle.putCharSequence(key, value); - return this; - } - - /** - * Put a String value into the metadata. Custom keys may be used, but if - * the METADATA_KEYs defined in this class are used they may only be one - * of the following: - *
    - *
  • {@link #METADATA_KEY_TITLE}
  • - *
  • {@link #METADATA_KEY_ARTIST}
  • - *
  • {@link #METADATA_KEY_ALBUM}
  • - *
  • {@link #METADATA_KEY_AUTHOR}
  • - *
  • {@link #METADATA_KEY_WRITER}
  • - *
  • {@link #METADATA_KEY_COMPOSER}
  • - *
  • {@link #METADATA_KEY_DATE}
  • - *
  • {@link #METADATA_KEY_GENRE}
  • - *
  • {@link #METADATA_KEY_ALBUM_ARTIST}
  • - *
  • {@link #METADATA_KEY_ART_URI}
  • - *
  • {@link #METADATA_KEY_ALBUM_ART_URI}
  • - *
  • {@link #METADATA_KEY_DISPLAY_TITLE}
  • - *
  • {@link #METADATA_KEY_DISPLAY_SUBTITLE}
  • - *
  • {@link #METADATA_KEY_DISPLAY_DESCRIPTION}
  • - *
  • {@link #METADATA_KEY_DISPLAY_ICON_URI}
  • - *
- * - * @param key The key for referencing this value - * @param value The String value to store - * @return The Builder to allow chaining - */ - public Builder putString(@TextKey String key, String value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a String"); - } - } - mBundle.putCharSequence(key, value); - return this; - } - - /** - * Put a long value into the metadata. Custom keys may be used, but if - * the METADATA_KEYs defined in this class are used they may only be one - * of the following: - *
    - *
  • {@link #METADATA_KEY_DURATION}
  • - *
  • {@link #METADATA_KEY_TRACK_NUMBER}
  • - *
  • {@link #METADATA_KEY_NUM_TRACKS}
  • - *
  • {@link #METADATA_KEY_DISC_NUMBER}
  • - *
  • {@link #METADATA_KEY_YEAR}
  • - *
- * - * @param key The key for referencing this value - * @param value The String value to store - * @return The Builder to allow chaining - */ - public Builder putLong(@LongKey String key, long value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a long"); - } - } - mBundle.putLong(key, value); - return this; - } - - /** - * Put a {@link RatingCompat} into the metadata. Custom keys may be used, but - * if the METADATA_KEYs defined in this class are used they may only be - * one of the following: - *
    - *
  • {@link #METADATA_KEY_RATING}
  • - *
  • {@link #METADATA_KEY_USER_RATING}
  • - *
- * - * @param key The key for referencing this value - * @param value The String value to store - * @return The Builder to allow chaining - */ - public Builder putRating(@RatingKey String key, RatingCompat value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a Rating"); - } - } - if (Build.VERSION.SDK_INT >= 21) { - // On platform version 21 or higher, use Rating instead of RatingCompat so mBundle - // can be unmarshalled. - mBundle.putParcelable(key, (Parcelable) value.getRating()); - } else { - mBundle.putParcelable(key, value); - } - return this; - } - - /** - * Put a {@link Bitmap} into the metadata. Custom keys may be used, but - * if the METADATA_KEYs defined in this class are used they may only be - * one of the following: - *
    - *
  • {@link #METADATA_KEY_ART}
  • - *
  • {@link #METADATA_KEY_ALBUM_ART}
  • - *
  • {@link #METADATA_KEY_DISPLAY_ICON}
  • - *
- * - * @param key The key for referencing this value - * @param value The Bitmap to store - * @return The Builder to allow chaining - */ - public Builder putBitmap(@BitmapKey String key, Bitmap value) { - if (METADATA_KEYS_TYPE.containsKey(key)) { - if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) { - throw new IllegalArgumentException("The " + key - + " key cannot be used to put a Bitmap"); - } - } - mBundle.putParcelable(key, value); - return this; - } - - /** - * Creates a {@link MediaMetadataCompat} instance with the specified fields. - * - * @return The new MediaMetadata instance - */ - public MediaMetadataCompat build() { - return new MediaMetadataCompat(mBundle); - } - } - -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompatApi21.java deleted file mode 100644 index 959cb6c..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/MediaMetadataCompatApi21.java +++ /dev/null @@ -1,84 +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 p.android.support.v4.media; - -import android.graphics.Bitmap; -import android.media.MediaMetadata; -import android.media.Rating; -import android.os.Parcel; - -import java.util.Set; - -class MediaMetadataCompatApi21 { - public static Set keySet(Object metadataObj) { - return ((MediaMetadata)metadataObj).keySet(); - } - - public static Bitmap getBitmap(Object metadataObj, String key) { - return ((MediaMetadata)metadataObj).getBitmap(key); - } - - public static long getLong(Object metadataObj, String key) { - return ((MediaMetadata)metadataObj).getLong(key); - } - - public static Object getRating(Object metadataObj, String key) { - return ((MediaMetadata)metadataObj).getRating(key); - } - - public static CharSequence getText(Object metadataObj, String key) { - return ((MediaMetadata) metadataObj).getText(key); - } - - public static void writeToParcel(Object metadataObj, Parcel dest, int flags) { - ((MediaMetadata) metadataObj).writeToParcel(dest, flags); - } - - public static Object createFromParcel(Parcel in) { - return MediaMetadata.CREATOR.createFromParcel(in); - } - - public static class Builder { - public static Object newInstance() { - return new MediaMetadata.Builder(); - } - - public static void putBitmap(Object builderObj, String key, Bitmap value) { - ((MediaMetadata.Builder)builderObj).putBitmap(key, value); - } - - public static void putLong(Object builderObj, String key, long value) { - ((MediaMetadata.Builder)builderObj).putLong(key, value); - } - - public static void putRating(Object builderObj, String key, Object ratingObj) { - ((MediaMetadata.Builder)builderObj).putRating(key, (Rating)ratingObj); - } - - public static void putText(Object builderObj, String key, CharSequence value) { - ((MediaMetadata.Builder) builderObj).putText(key, value); - } - - public static void putString(Object builderObj, String key, String value) { - ((MediaMetadata.Builder) builderObj).putString(key, value); - } - - public static Object build(Object builderObj) { - return ((MediaMetadata.Builder)builderObj).build(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/ParceledListSliceAdapterApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/ParceledListSliceAdapterApi21.java deleted file mode 100644 index 771ca12..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/ParceledListSliceAdapterApi21.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.media.browse.MediaBrowser; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.List; - -/** - * An adapter class for accessing the hidden framework classes, ParceledListSlice using reflection. - */ -class ParceledListSliceAdapterApi21 { - private static Constructor sConstructor; - static { - try { - Class theClass = Class.forName("android.content.pm.ParceledListSlice"); - sConstructor = theClass.getConstructor(new Class[] { List.class }); - } catch (ClassNotFoundException | NoSuchMethodException e) { - e.printStackTrace(); - } - } - - static Object newInstance(List itemList) { - Object result = null; - try { - result = sConstructor.newInstance(itemList); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - return result; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompat.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompat.aidl deleted file mode 100644 index b8849ed..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompat.aidl +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2014, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.plug.v4.media; - -parcelable RatingCompat; diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompat.java deleted file mode 100644 index 426f99f..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompat.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import p.android.support.annotation.IntDef; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * A class to encapsulate rating information used as content metadata. - * A rating is defined by its rating style (see {@link #RATING_HEART}, - * {@link #RATING_THUMB_UP_DOWN}, {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, - * {@link #RATING_5_STARS} or {@link #RATING_PERCENTAGE}) and the actual rating value (which may - * be defined as "unrated"), both of which are defined when the rating instance is constructed - * through one of the factory methods. - */ -public final class RatingCompat implements Parcelable { - private final static String TAG = "Rating"; - - /** - * @hide - */ - @IntDef({RATING_NONE, RATING_HEART, RATING_THUMB_UP_DOWN, RATING_3_STARS, RATING_4_STARS, - RATING_5_STARS, RATING_PERCENTAGE}) - @Retention(RetentionPolicy.SOURCE) - public @interface Style {} - - /** - * @hide - */ - @IntDef({RATING_3_STARS, RATING_4_STARS, RATING_5_STARS}) - @Retention(RetentionPolicy.SOURCE) - public @interface StarStyle {} - - /** - * Indicates a rating style is not supported. A Rating will never have this - * type, but can be used by other classes to indicate they do not support - * Rating. - */ - public final static int RATING_NONE = 0; - - /** - * A rating style with a single degree of rating, "heart" vs "no heart". Can be used to - * indicate the content referred to is a favorite (or not). - */ - public final static int RATING_HEART = 1; - - /** - * A rating style for "thumb up" vs "thumb down". - */ - public final static int RATING_THUMB_UP_DOWN = 2; - - /** - * A rating style with 0 to 3 stars. - */ - public final static int RATING_3_STARS = 3; - - /** - * A rating style with 0 to 4 stars. - */ - public final static int RATING_4_STARS = 4; - - /** - * A rating style with 0 to 5 stars. - */ - public final static int RATING_5_STARS = 5; - - /** - * A rating style expressed as a percentage. - */ - public final static int RATING_PERCENTAGE = 6; - - private final static float RATING_NOT_RATED = -1.0f; - - private final int mRatingStyle; - private final float mRatingValue; - - private Object mRatingObj; // framework Rating object - - private RatingCompat(@Style int ratingStyle, float rating) { - mRatingStyle = ratingStyle; - mRatingValue = rating; - } - - @Override - public String toString() { - return "Rating:style=" + mRatingStyle + " rating=" - + (mRatingValue < 0.0f ? "unrated" : String.valueOf(mRatingValue)); - } - - @Override - public int describeContents() { - return mRatingStyle; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mRatingStyle); - dest.writeFloat(mRatingValue); - } - - public static final Creator CREATOR - = new Creator() { - /** - * Rebuilds a Rating previously stored with writeToParcel(). - * @param p Parcel object to read the Rating from - * @return a new Rating created from the data in the parcel - */ - @Override - public RatingCompat createFromParcel(Parcel p) { - return new RatingCompat(p.readInt(), p.readFloat()); - } - - @Override - public RatingCompat[] newArray(int size) { - return new RatingCompat[size]; - } - }; - - /** - * Return a Rating instance with no rating. - * Create and return a new Rating instance with no rating known for the given - * rating style. - * @param ratingStyle one of {@link #RATING_HEART}, {@link #RATING_THUMB_UP_DOWN}, - * {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS}, - * or {@link #RATING_PERCENTAGE}. - * @return null if an invalid rating style is passed, a new Rating instance otherwise. - */ - public static RatingCompat newUnratedRating(@Style int ratingStyle) { - switch(ratingStyle) { - case RATING_HEART: - case RATING_THUMB_UP_DOWN: - case RATING_3_STARS: - case RATING_4_STARS: - case RATING_5_STARS: - case RATING_PERCENTAGE: - return new RatingCompat(ratingStyle, RATING_NOT_RATED); - default: - return null; - } - } - - /** - * Return a Rating instance with a heart-based rating. - * Create and return a new Rating instance with a rating style of {@link #RATING_HEART}, - * and a heart-based rating. - * @param hasHeart true for a "heart selected" rating, false for "heart unselected". - * @return a new Rating instance. - */ - public static RatingCompat newHeartRating(boolean hasHeart) { - return new RatingCompat(RATING_HEART, hasHeart ? 1.0f : 0.0f); - } - - /** - * Return a Rating instance with a thumb-based rating. - * Create and return a new Rating instance with a {@link #RATING_THUMB_UP_DOWN} - * rating style, and a "thumb up" or "thumb down" rating. - * @param thumbIsUp true for a "thumb up" rating, false for "thumb down". - * @return a new Rating instance. - */ - public static RatingCompat newThumbRating(boolean thumbIsUp) { - return new RatingCompat(RATING_THUMB_UP_DOWN, thumbIsUp ? 1.0f : 0.0f); - } - - /** - * Return a Rating instance with a star-based rating. - * Create and return a new Rating instance with one of the star-base rating styles - * and the given integer or fractional number of stars. Non integer values can for instance - * be used to represent an average rating value, which might not be an integer number of stars. - * @param starRatingStyle one of {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, - * {@link #RATING_5_STARS}. - * @param starRating a number ranging from 0.0f to 3.0f, 4.0f or 5.0f according to - * the rating style. - * @return null if the rating style is invalid, or the rating is out of range, - * a new Rating instance otherwise. - */ - public static RatingCompat newStarRating(@StarStyle int starRatingStyle, - float starRating) { - float maxRating = -1.0f; - switch(starRatingStyle) { - case RATING_3_STARS: - maxRating = 3.0f; - break; - case RATING_4_STARS: - maxRating = 4.0f; - break; - case RATING_5_STARS: - maxRating = 5.0f; - break; - default: - Log.e(TAG, "Invalid rating style (" + starRatingStyle + ") for a star rating"); - return null; - } - if ((starRating < 0.0f) || (starRating > maxRating)) { - Log.e(TAG, "Trying to set out of range star-based rating"); - return null; - } - return new RatingCompat(starRatingStyle, starRating); - } - - /** - * Return a Rating instance with a percentage-based rating. - * Create and return a new Rating instance with a {@link #RATING_PERCENTAGE} - * rating style, and a rating of the given percentage. - * @param percent the value of the rating - * @return null if the rating is out of range, a new Rating instance otherwise. - */ - public static RatingCompat newPercentageRating(float percent) { - if ((percent < 0.0f) || (percent > 100.0f)) { - Log.e(TAG, "Invalid percentage-based rating value"); - return null; - } else { - return new RatingCompat(RATING_PERCENTAGE, percent); - } - } - - /** - * Return whether there is a rating value available. - * @return true if the instance was not created with {@link #newUnratedRating(int)}. - */ - public boolean isRated() { - return mRatingValue >= 0.0f; - } - - /** - * Return the rating style. - * @return one of {@link #RATING_HEART}, {@link #RATING_THUMB_UP_DOWN}, - * {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS}, - * or {@link #RATING_PERCENTAGE}. - */ - @Style - public int getRatingStyle() { - return mRatingStyle; - } - - /** - * Return whether the rating is "heart selected". - * @return true if the rating is "heart selected", false if the rating is "heart unselected", - * if the rating style is not {@link #RATING_HEART} or if it is unrated. - */ - public boolean hasHeart() { - if (mRatingStyle != RATING_HEART) { - return false; - } else { - return (mRatingValue == 1.0f); - } - } - - /** - * Return whether the rating is "thumb up". - * @return true if the rating is "thumb up", false if the rating is "thumb down", - * if the rating style is not {@link #RATING_THUMB_UP_DOWN} or if it is unrated. - */ - public boolean isThumbUp() { - if (mRatingStyle != RATING_THUMB_UP_DOWN) { - return false; - } else { - return (mRatingValue == 1.0f); - } - } - - /** - * Return the star-based rating value. - * @return a rating value greater or equal to 0.0f, or a negative value if the rating style is - * not star-based, or if it is unrated. - */ - public float getStarRating() { - switch (mRatingStyle) { - case RATING_3_STARS: - case RATING_4_STARS: - case RATING_5_STARS: - if (isRated()) { - return mRatingValue; - } - default: - return -1.0f; - } - } - - /** - * Return the percentage-based rating value. - * @return a rating value greater or equal to 0.0f, or a negative value if the rating style is - * not percentage-based, or if it is unrated. - */ - public float getPercentRating() { - if ((mRatingStyle != RATING_PERCENTAGE) || !isRated()) { - return -1.0f; - } else { - return mRatingValue; - } - } - - /** - * Creates an instance from a framework {@link android.media.Rating} object. - *

- * This method is only supported on API 21+. - *

- * - * @param ratingObj A {@link android.media.Rating} object, or null if none. - * @return An equivalent {@link RatingCompat} object, or null if none. - */ - public static RatingCompat fromRating(Object ratingObj) { - if (ratingObj == null || Build.VERSION.SDK_INT < 21) { - return null; - } - - final int ratingStyle = RatingCompatApi21.getRatingStyle(ratingObj); - final RatingCompat rating; - if (RatingCompatApi21.isRated(ratingObj)) { - switch (ratingStyle) { - case RATING_HEART: - rating = newHeartRating(RatingCompatApi21.hasHeart(ratingObj)); - break; - case RATING_THUMB_UP_DOWN: - rating = newThumbRating(RatingCompatApi21.isThumbUp(ratingObj)); - break; - case RATING_3_STARS: - case RATING_4_STARS: - case RATING_5_STARS: - rating = newStarRating(ratingStyle, - RatingCompatApi21.getStarRating(ratingObj)); - break; - case RATING_PERCENTAGE: - rating = newPercentageRating(RatingCompatApi21.getPercentRating(ratingObj)); - break; - default: - return null; - } - } else { - rating = newUnratedRating(ratingStyle); - } - rating.mRatingObj = ratingObj; - return rating; - } - - /** - * Gets the underlying framework {@link android.media.Rating} object. - *

- * This method is only supported on API 21+. - *

- * - * @return An equivalent {@link android.media.Rating} object, or null if none. - */ - public Object getRating() { - if (mRatingObj != null || Build.VERSION.SDK_INT < 21) { - return mRatingObj; - } - - if (isRated()) { - switch (mRatingStyle) { - case RATING_HEART: - mRatingObj = RatingCompatApi21.newHeartRating(hasHeart()); - break; - case RATING_THUMB_UP_DOWN: - mRatingObj = RatingCompatApi21.newThumbRating(isThumbUp()); - break; - case RATING_3_STARS: - case RATING_4_STARS: - case RATING_5_STARS: - mRatingObj = RatingCompatApi21.newStarRating(mRatingStyle, getStarRating()); - break; - case RATING_PERCENTAGE: - mRatingObj = RatingCompatApi21.newPercentageRating(getPercentRating()); - default: - return null; - } - } else { - mRatingObj = RatingCompatApi21.newUnratedRating(mRatingStyle); - } - return mRatingObj; - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompatApi21.java deleted file mode 100644 index 84c2185..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/RatingCompatApi21.java +++ /dev/null @@ -1,65 +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 p.android.support.v4.media; - -import android.media.Rating; - -class RatingCompatApi21 { - public static Object newUnratedRating(int ratingStyle) { - return Rating.newUnratedRating(ratingStyle); - } - - public static Object newHeartRating(boolean hasHeart) { - return Rating.newHeartRating(hasHeart); - } - - public static Object newThumbRating(boolean thumbIsUp) { - return Rating.newThumbRating(thumbIsUp); - } - - public static Object newStarRating(int starRatingStyle, float starRating) { - return Rating.newStarRating(starRatingStyle, starRating); - } - - public static Object newPercentageRating(float percent) { - return Rating.newPercentageRating(percent); - } - - public static boolean isRated(Object ratingObj) { - return ((Rating)ratingObj).isRated(); - } - - public static int getRatingStyle(Object ratingObj) { - return ((Rating)ratingObj).getRatingStyle(); - } - - public static boolean hasHeart(Object ratingObj) { - return ((Rating)ratingObj).hasHeart(); - } - - public static boolean isThumbUp(Object ratingObj) { - return ((Rating)ratingObj).isThumbUp(); - } - - public static float getStarRating(Object ratingObj) { - return ((Rating)ratingObj).getStarRating(); - } - - public static float getPercentRating(Object ratingObj) { - return ((Rating)ratingObj).getPercentRating(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportController.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportController.java deleted file mode 100644 index 875d4ba..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportController.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -/** - * Base interface to controlling a media transport. This is the - * interface for implementing things like on-screen controls: it - * allows them to request changes in playback, retrieve the current - * playback state, and monitor for changes to the playback state. - */ -public abstract class TransportController { - /** - * Start listening to changes in playback state. - */ - public abstract void registerStateListener(TransportStateListener listener); - - /** - * Stop listening to changes in playback state. - */ - public abstract void unregisterStateListener(TransportStateListener listener); - - /** - * Request that the player start its playback at its current position. - */ - public abstract void startPlaying(); - - /** - * Request that the player pause its playback and stay at its current position. - */ - public abstract void pausePlaying(); - - /** - * Request that the player stop its playback; it may clear its state in whatever - * way is appropriate. - */ - public abstract void stopPlaying(); - - /** - * Retrieve the total duration of the media stream, in milliseconds. - */ - public abstract long getDuration(); - - /** - * Retrieve the current playback location in the media stream, in milliseconds. - */ - public abstract long getCurrentPosition(); - - /** - * Move to a new location in the media stream. - * @param pos Position to move to, in milliseconds. - */ - public abstract void seekTo(long pos); - - /** - * Return whether the player is currently playing its stream. - */ - public abstract boolean isPlaying(); - - /** - * Retrieve amount, in percentage (0-100), that the media stream has been buffered - * on to the local device. Return 100 if the stream is always local. - */ - public abstract int getBufferPercentage(); - - /** - * Retrieve the flags for the media transport control buttons that this transport supports. - * Result is a combination of the following flags: - * {@link TransportMediator#FLAG_KEY_MEDIA_PREVIOUS}, - * {@link TransportMediator#FLAG_KEY_MEDIA_REWIND}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, - * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}, - * {@link TransportMediator#FLAG_KEY_MEDIA_FAST_FORWARD}, - * {@link TransportMediator#FLAG_KEY_MEDIA_NEXT} - */ - public abstract int getTransportControlFlags(); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediator.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediator.java deleted file mode 100644 index 056ad2d..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediator.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.app.Activity; -import android.content.Context; -import android.media.AudioManager; -import android.os.Build; -import p.android.support.v4.view.KeyEventCompat; -import android.view.KeyEvent; -import android.view.View; - -import java.util.ArrayList; - -/** - * Helper for implementing a media transport control (with play, pause, skip, and - * other media actions). Takes care of both key events and advanced features - * like {@link android.media.RemoteControlClient}. This class is intended to - * serve as an intermediary between transport controls (whether they be on-screen - * controls, hardware buttons, remote controls) and the actual player. The player - * is represented by a single {@link TransportPerformer} that must be supplied to - * this class. On-screen controls that want to control and show the state of the - * player should do this through calls to the {@link TransportController} interface. - * - *

Here is a simple but fairly complete sample of a video player that is built - * around this class. Note that the MediaController class used here is not the one - * included in the standard Android framework, but a custom implementation. Real - * applications often implement their own transport controls, or you can copy the - * implementation here out of Support4Demos.

- * - * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java - * complete} - */ -public class TransportMediator extends TransportController { - final Context mContext; - final TransportPerformer mCallbacks; - final AudioManager mAudioManager; - final View mView; - final Object mDispatcherState; - final TransportMediatorJellybeanMR2 mController; - final ArrayList mListeners - = new ArrayList(); - final TransportMediatorCallback mTransportKeyCallback - = new TransportMediatorCallback() { - @Override - public void handleKey(KeyEvent key) { - key.dispatch(mKeyEventCallback); - } - @Override - public void handleAudioFocusChange(int focusChange) { - mCallbacks.onAudioFocusChange(focusChange); - } - - @Override - public long getPlaybackPosition() { - return mCallbacks.onGetCurrentPosition(); - } - - @Override - public void playbackPositionUpdate(long newPositionMs) { - mCallbacks.onSeekTo(newPositionMs); - } - }; - - /** Synonym for {@link KeyEvent#KEYCODE_MEDIA_PLAY KeyEvent.KEYCODE_MEDIA_PLAY} */ - public static final int KEYCODE_MEDIA_PLAY = 126; - /** Synonym for {@link KeyEvent#KEYCODE_MEDIA_PAUSE KeyEvent.KEYCODE_MEDIA_PAUSE} */ - public static final int KEYCODE_MEDIA_PAUSE = 127; - /** Synonym for {@link KeyEvent#KEYCODE_MEDIA_RECORD KeyEvent.KEYCODE_MEDIA_RECORD} */ - public static final int KEYCODE_MEDIA_RECORD = 130; - - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PREVIOUS - * RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS */ - public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0; - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_REWIND - * RemoteControlClient.FLAG_KEY_MEDIA_REWIND */ - public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1; - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY - * RemoteControlClient.FLAG_KEY_MEDIA_PLAY */ - public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2; - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY_PAUSE - * RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE */ - public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3; - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PAUSE - * RemoteControlClient.FLAG_KEY_MEDIA_PAUSE */ - public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4; - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_STOP - * RemoteControlClient.FLAG_KEY_MEDIA_STOP */ - public final static int FLAG_KEY_MEDIA_STOP = 1 << 5; - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_FAST_FORWARD - * RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD */ - public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6; - /** Synonym for {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_NEXT - * RemoteControlClient.FLAG_KEY_MEDIA_NEXT */ - public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7; - - static boolean isMediaKey(int keyCode) { - switch (keyCode) { - case KEYCODE_MEDIA_PLAY: - case KEYCODE_MEDIA_PAUSE: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - case KeyEvent.KEYCODE_MUTE: - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_STOP: - case KeyEvent.KEYCODE_MEDIA_NEXT: - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_REWIND: - case KEYCODE_MEDIA_RECORD: - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { - return true; - } - } - return false; - } - - final KeyEvent.Callback mKeyEventCallback = new KeyEvent.Callback() { - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return isMediaKey(keyCode) ? mCallbacks.onMediaButtonDown(keyCode, event) : false; - } - - public boolean onKeyLongPress(int keyCode, KeyEvent event) { - return false; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - return isMediaKey(keyCode) ? mCallbacks.onMediaButtonUp(keyCode, event) : false; - } - - @Override - public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) { - return false; - } - }; - - public TransportMediator(Activity activity, TransportPerformer callbacks) { - this(activity, null, callbacks); - } - - public TransportMediator(View view, TransportPerformer callbacks) { - this(null, view, callbacks); - } - - private TransportMediator(Activity activity, View view, TransportPerformer callbacks) { - mContext = activity != null ? activity : view.getContext(); - mCallbacks = callbacks; - mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); - mView = activity != null ? activity.getWindow().getDecorView() : view; - mDispatcherState = KeyEventCompat.getKeyDispatcherState(mView); - if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2 - mController = new TransportMediatorJellybeanMR2(mContext, mAudioManager, - mView, mTransportKeyCallback); - } else { - mController = null; - } - } - - /** - * Return the {@link android.media.RemoteControlClient} associated with this transport. - * This returns a generic Object since the RemoteControlClient is not availble before - * {@link Build.VERSION_CODES#ICE_CREAM_SANDWICH}. Further, this class - * will not use RemoteControlClient in its implementation until - * {@link Build.VERSION_CODES#JELLY_BEAN_MR2}. You should always check for - * null here and not do anything with the RemoteControlClient if none is given; this - * way you don't need to worry about the current platform API version. - * - *

Note that this class takes possession of the - * {@link android.media.RemoteControlClient.OnGetPlaybackPositionListener} and - * {@link android.media.RemoteControlClient.OnPlaybackPositionUpdateListener} callbacks; - * you will interact with these through - * {@link TransportPerformer#onGetCurrentPosition() TransportPerformer.onGetCurrentPosition} and - * {@link TransportPerformer#onSeekTo TransportPerformer.onSeekTo}, respectively.

- */ - public Object getRemoteControlClient() { - return mController != null ? mController.getRemoteControlClient() : null; - } - - /** - * Must call from {@link Activity#dispatchKeyEvent Activity.dispatchKeyEvent} to give - * the transport an opportunity to intercept media keys. Any such keys will show up - * in {@link TransportPerformer}. - * @param event - */ - public boolean dispatchKeyEvent(KeyEvent event) { - return KeyEventCompat.dispatch(event, mKeyEventCallback, mDispatcherState, this); - } - - public void registerStateListener(TransportStateListener listener) { - mListeners.add(listener); - } - - public void unregisterStateListener(TransportStateListener listener) { - mListeners.remove(listener); - } - - private TransportStateListener[] getListeners() { - if (mListeners.size() <= 0) { - return null; - } - TransportStateListener listeners[] = new TransportStateListener[mListeners.size()]; - mListeners.toArray(listeners); - return listeners; - } - - private void reportPlayingChanged() { - TransportStateListener[] listeners = getListeners(); - if (listeners != null) { - for (TransportStateListener listener : listeners) { - listener.onPlayingChanged(this); - } - } - } - - private void reportTransportControlsChanged() { - TransportStateListener[] listeners = getListeners(); - if (listeners != null) { - for (TransportStateListener listener : listeners) { - listener.onTransportControlsChanged(this); - } - } - } - - private void pushControllerState() { - if (mController != null) { - mController.refreshState(mCallbacks.onIsPlaying(), - mCallbacks.onGetCurrentPosition(), - mCallbacks.onGetTransportControlFlags()); - } - } - - public void refreshState() { - pushControllerState(); - reportPlayingChanged(); - reportTransportControlsChanged(); - } - - /** - * Move the controller into the playing state. This updates the remote control - * client to indicate it is playing, and takes audio focus for the app. - */ - @Override - public void startPlaying() { - if (mController != null) { - mController.startPlaying(); - } - mCallbacks.onStart(); - pushControllerState(); - reportPlayingChanged(); - } - - /** - * Move the controller into the paused state. This updates the remote control - * client to indicate it is paused, but keeps audio focus. - */ - @Override - public void pausePlaying() { - if (mController != null) { - mController.pausePlaying(); - } - mCallbacks.onPause(); - pushControllerState(); - reportPlayingChanged(); - } - - /** - * Move the controller into the stopped state. This updates the remote control - * client to indicate it is stopped, and removes audio focus from the app. - */ - @Override - public void stopPlaying() { - if (mController != null) { - mController.stopPlaying(); - } - mCallbacks.onStop(); - pushControllerState(); - reportPlayingChanged(); - } - - @Override - public long getDuration() { - return mCallbacks.onGetDuration(); - } - - @Override - public long getCurrentPosition() { - return mCallbacks.onGetCurrentPosition(); - } - - @Override - public void seekTo(long pos) { - mCallbacks.onSeekTo(pos); - } - - @Override - public boolean isPlaying() { - return mCallbacks.onIsPlaying(); - } - - @Override - public int getBufferPercentage() { - return mCallbacks.onGetBufferPercentage(); - } - - /** - * Retrieves the flags for the media transport control buttons that this transport supports. - * Result is a combination of the following flags: - * {@link #FLAG_KEY_MEDIA_PREVIOUS}, - * {@link #FLAG_KEY_MEDIA_REWIND}, - * {@link #FLAG_KEY_MEDIA_PLAY}, - * {@link #FLAG_KEY_MEDIA_PLAY_PAUSE}, - * {@link #FLAG_KEY_MEDIA_PAUSE}, - * {@link #FLAG_KEY_MEDIA_STOP}, - * {@link #FLAG_KEY_MEDIA_FAST_FORWARD}, - * {@link #FLAG_KEY_MEDIA_NEXT} - */ - public int getTransportControlFlags() { - return mCallbacks.onGetTransportControlFlags(); - } - - /** - * Optionally call when no longer using the TransportController. Its resources - * will also be automatically cleaned up when your activity/view is detached from - * its window, so you don't normally need to call this explicitly. - */ - public void destroy() { - mController.destroy(); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediatorCallback.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediatorCallback.java deleted file mode 100644 index 92be763..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediatorCallback.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.view.KeyEvent; - -interface TransportMediatorCallback { - public void handleKey(KeyEvent key); - public void handleAudioFocusChange(int focusChange); - public long getPlaybackPosition(); - public void playbackPositionUpdate(long newPositionMs); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediatorJellybeanMR2.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediatorJellybeanMR2.java deleted file mode 100644 index 0cd0f11..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportMediatorJellybeanMR2.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.media.AudioManager; -import android.media.RemoteControlClient; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewTreeObserver; - -class TransportMediatorJellybeanMR2 { - final Context mContext; - final AudioManager mAudioManager; - final View mTargetView; - final TransportMediatorCallback mTransportCallback; - final String mReceiverAction; - final IntentFilter mReceiverFilter; - final Intent mIntent; - final ViewTreeObserver.OnWindowAttachListener mWindowAttachListener = - new ViewTreeObserver.OnWindowAttachListener() { - @Override - public void onWindowAttached() { - windowAttached(); - } - @Override - public void onWindowDetached() { - windowDetached(); - } - }; - final ViewTreeObserver.OnWindowFocusChangeListener mWindowFocusListener = - new ViewTreeObserver.OnWindowFocusChangeListener() { - @Override - public void onWindowFocusChanged(boolean hasFocus) { - if (hasFocus) gainFocus(); - else loseFocus(); - } - }; - final BroadcastReceiver mMediaButtonReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - try { - KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); - mTransportCallback.handleKey(event); - } catch (ClassCastException e) { - Log.w("TransportController", e); - } - } - }; - AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener - = new AudioManager.OnAudioFocusChangeListener() { - @Override - public void onAudioFocusChange(int focusChange) { - mTransportCallback.handleAudioFocusChange(focusChange); - } - }; - final RemoteControlClient.OnGetPlaybackPositionListener mGetPlaybackPositionListener - = new RemoteControlClient.OnGetPlaybackPositionListener() { - @Override - public long onGetPlaybackPosition() { - return mTransportCallback.getPlaybackPosition(); - } - }; - final RemoteControlClient.OnPlaybackPositionUpdateListener mPlaybackPositionUpdateListener - = new RemoteControlClient.OnPlaybackPositionUpdateListener() { - public void onPlaybackPositionUpdate(long newPositionMs) { - mTransportCallback.playbackPositionUpdate(newPositionMs); - } - }; - - PendingIntent mPendingIntent; - RemoteControlClient mRemoteControl; - boolean mFocused; - int mPlayState = 0; - boolean mAudioFocused; - - public TransportMediatorJellybeanMR2(Context context, AudioManager audioManager, - View view, TransportMediatorCallback transportCallback) { - mContext = context; - mAudioManager = audioManager; - mTargetView = view; - mTransportCallback = transportCallback; - mReceiverAction = context.getPackageName() + ":transport:" + System.identityHashCode(this); - mIntent = new Intent(mReceiverAction); - mIntent.setPackage(context.getPackageName()); - mReceiverFilter = new IntentFilter(); - mReceiverFilter.addAction(mReceiverAction); - mTargetView.getViewTreeObserver().addOnWindowAttachListener(mWindowAttachListener); - mTargetView.getViewTreeObserver().addOnWindowFocusChangeListener(mWindowFocusListener); - } - - public Object getRemoteControlClient() { - return mRemoteControl; - } - - public void destroy() { - windowDetached(); - mTargetView.getViewTreeObserver().removeOnWindowAttachListener(mWindowAttachListener); - mTargetView.getViewTreeObserver().removeOnWindowFocusChangeListener(mWindowFocusListener); - } - - void windowAttached() { - mContext.registerReceiver(mMediaButtonReceiver, mReceiverFilter); - mPendingIntent = PendingIntent.getBroadcast(mContext, 0, mIntent, - PendingIntent.FLAG_CANCEL_CURRENT); - mRemoteControl = new RemoteControlClient(mPendingIntent); - mRemoteControl.setOnGetPlaybackPositionListener(mGetPlaybackPositionListener); - mRemoteControl.setPlaybackPositionUpdateListener(mPlaybackPositionUpdateListener); - } - - void gainFocus() { - if (!mFocused) { - mFocused = true; - mAudioManager.registerMediaButtonEventReceiver(mPendingIntent); - mAudioManager.registerRemoteControlClient(mRemoteControl); - if (mPlayState == RemoteControlClient.PLAYSTATE_PLAYING) { - takeAudioFocus(); - } - } - } - - void takeAudioFocus() { - if (!mAudioFocused) { - mAudioFocused = true; - mAudioManager.requestAudioFocus(mAudioFocusChangeListener, - AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); - } - } - - public void startPlaying() { - if (mPlayState != RemoteControlClient.PLAYSTATE_PLAYING) { - mPlayState = RemoteControlClient.PLAYSTATE_PLAYING; - mRemoteControl.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING); - } - if (mFocused) { - takeAudioFocus(); - } - } - - public void refreshState(boolean playing, long position, int transportControls) { - if (mRemoteControl != null) { - mRemoteControl.setPlaybackState(playing ? RemoteControlClient.PLAYSTATE_PLAYING - : RemoteControlClient.PLAYSTATE_STOPPED, position, playing ? 1 : 0); - mRemoteControl.setTransportControlFlags(transportControls); - } - } - - public void pausePlaying() { - if (mPlayState == RemoteControlClient.PLAYSTATE_PLAYING) { - mPlayState = RemoteControlClient.PLAYSTATE_PAUSED; - mRemoteControl.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED); - } - dropAudioFocus(); - } - - public void stopPlaying() { - if (mPlayState != RemoteControlClient.PLAYSTATE_STOPPED) { - mPlayState = RemoteControlClient.PLAYSTATE_STOPPED; - mRemoteControl.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED); - } - dropAudioFocus(); - } - - void dropAudioFocus() { - if (mAudioFocused) { - mAudioFocused = false; - mAudioManager.abandonAudioFocus(mAudioFocusChangeListener); - } - } - - void loseFocus() { - dropAudioFocus(); - if (mFocused) { - mFocused = false; - mAudioManager.unregisterRemoteControlClient(mRemoteControl); - mAudioManager.unregisterMediaButtonEventReceiver(mPendingIntent); - } - } - - void windowDetached() { - loseFocus(); - if (mPendingIntent != null) { - mContext.unregisterReceiver(mMediaButtonReceiver); - mPendingIntent.cancel(); - mPendingIntent = null; - mRemoteControl = null; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportPerformer.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportPerformer.java deleted file mode 100644 index b13b061..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportPerformer.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -import android.os.SystemClock; -import android.view.KeyEvent; - -/** - * Implemented by the playback side of the media system, to respond to - * requests to perform actions and to retrieve its current state. These - * requests may either come from key events dispatched directly to your UI, or - * events sent over a media button event receiver that this class keeps active - * while your window is in focus. - */ -public abstract class TransportPerformer { - /** - * Request to start playback on the media, resuming from whatever current state - * (position etc) it is in. - */ - public abstract void onStart(); - - /** - * Request to pause playback of the media, staying at the current playback position - * and other state so a later call to {@link #onStart()} will resume at the same place. - */ - public abstract void onPause(); - - /** - * Request to completely stop playback of the media, clearing whatever state the - * player thinks is appropriate. - */ - public abstract void onStop(); - - /** - * Request to return the duration of the current media, in milliseconds. - */ - public abstract long onGetDuration(); - - /** - * Request to return the current playback position, in milliseconds. - */ - public abstract long onGetCurrentPosition(); - - /** - * Request to move the current playback position. - * @param pos New position to move to, in milliseconds. - */ - public abstract void onSeekTo(long pos); - - /** - * Request to find out whether the player is currently playing its media. - */ - public abstract boolean onIsPlaying(); - - /** - * Request to find out how much of the media has been buffered on the local device. - * @return Return a percentage (0-100) indicating how much of the total data - * has been buffered. The default implementation returns 100, meaning the content - * is always on the local device. - */ - public int onGetBufferPercentage() { - return 100; - } - - /** - * Retrieves the flags for the media transport control buttons that this transport supports. - * Result is a combination of the following flags: - * {@link TransportMediator#FLAG_KEY_MEDIA_PREVIOUS}, - * {@link TransportMediator#FLAG_KEY_MEDIA_REWIND}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, - * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}, - * {@link TransportMediator#FLAG_KEY_MEDIA_FAST_FORWARD}, - * {@link TransportMediator#FLAG_KEY_MEDIA_NEXT} - * - *

The default implementation returns: - * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, - * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, and - * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}

- */ - public int onGetTransportControlFlags() { - return TransportMediator.FLAG_KEY_MEDIA_PLAY - | TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE - | TransportMediator.FLAG_KEY_MEDIA_PAUSE - | TransportMediator.FLAG_KEY_MEDIA_STOP; - } - - /** - * Report that a media button has been pressed. This is like - * {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)} but - * will only deliver media keys. The default implementation handles these keys: - *
    - *
  • KEYCODE_MEDIA_PLAY: call {@link #onStart}
  • - *
  • KEYCODE_MEDIA_PAUSE: call {@link #onPause}
  • - *
  • KEYCODE_MEDIA_STOP: call {@link #onStop}
  • - *
  • KEYCODE_MEDIA_PLAY_PAUSE and KEYCODE_HEADSETHOOK: call {@link #onPause} - * if {@link #onIsPlaying()} returns true, otherwise call {@link #onStart}
  • - *
- * @param keyCode The code of the media key. - * @param event The full key event. - * @return Indicate whether the key has been consumed. The default - * implementation always returns true. This only matters for keys - * being dispatched here from - * {@link TransportMediator#dispatchKeyEvent(KeyEvent) - * TransportController.dispatchKeyEvent}, and determines whether the key - * continues on to its default key handling (which for media keys means - * being delivered to the current media remote control, which should - * be us). - */ - public boolean onMediaButtonDown(int keyCode, KeyEvent event) { - switch (keyCode) { - case TransportMediator.KEYCODE_MEDIA_PLAY: - onStart(); - return true; - case TransportMediator.KEYCODE_MEDIA_PAUSE: - onPause(); - return true; - case KeyEvent.KEYCODE_MEDIA_STOP: - onStop(); - return true; - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - case KeyEvent.KEYCODE_HEADSETHOOK: - if (onIsPlaying()) { - onPause(); - } else { - onStart(); - } - } - return true; - } - - /** - * Report that a media button has been released. This is like - * {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)} but - * will only deliver media keys. The default implementation does nothing. - * @param keyCode The code of the media key. - * @param event The full key event. - * @return Indicate whether the key has been consumed. The default - * implementation always returns true. This only matters for keys - * being dispatched here from - * {@link TransportMediator#dispatchKeyEvent(KeyEvent) - * TransportController.dispatchKeyEvent}, and determines whether the key - * continues on to its default key handling (which for media keys means - * being delivered to the current media remote control, which should - * be us). - */ - public boolean onMediaButtonUp(int keyCode, KeyEvent event) { - return true; - } - - // Copy constants from framework since we can't link to them. - static final int AUDIOFOCUS_GAIN = 1; - static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; - static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; - static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN; - static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT; - static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = - -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; - - /** - * Report that audio focus has changed on the app. This only happens if - * you have indicated you have started playing with - * {@link TransportMediator#startPlaying TransportController.startPlaying}, - * which takes audio focus for you. - * @param focusChange The type of focus change, as per - * {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange(int) - * OnAudioFocusChangeListener.onAudioFocusChange}. The default implementation will - * deliver a {@link KeyEvent#KEYCODE_MEDIA_STOP} - * when receiving {@link android.media.AudioManager#AUDIOFOCUS_LOSS}. - */ - public void onAudioFocusChange(int focusChange) { - int keyCode = 0; - switch (focusChange) { - case AUDIOFOCUS_LOSS: - // This will cause us to stop playback, which means we drop audio focus - // so we will not get any further audio focus gain. - keyCode = TransportMediator.KEYCODE_MEDIA_PAUSE; - break; - } - if (keyCode != 0) { - final long now = SystemClock.uptimeMillis(); - onMediaButtonDown(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0)); - onMediaButtonUp(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0)); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportStateListener.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportStateListener.java deleted file mode 100644 index 4c4a8be..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/TransportStateListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package p.android.support.v4.media; - -/** - * A listener for playback changes that can be registered with - * {@link TransportController}. - */ -public class TransportStateListener { - /** - * The play state of the transport changed. Use - * {@link TransportController#isPlaying() - * TransportController.isPlaying()} to determine the new state. - */ - public void onPlayingChanged(TransportController controller) { - } - - /** - * The available controls of the transport changed. Use - * {@link TransportController#getTransportControlFlags()} - * TransportController.getTransportControlFlags()} to determine the new state. - */ - public void onTransportControlsChanged(TransportController controller) { - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/VolumeProviderCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/VolumeProviderCompat.java deleted file mode 100644 index 7558e9a..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/VolumeProviderCompat.java +++ /dev/null @@ -1,189 +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 p.android.support.v4.media; - -import android.os.Build; -import p.android.support.annotation.IntDef; -import p.android.support.v4.media.session.MediaSessionCompat; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Handles requests to adjust or set the volume on a session. This is also used - * to push volume updates back to the session after a request has been handled. - * You can set a volume provider on a session by calling - * {@link MediaSessionCompat#setPlaybackToRemote}. - */ -public abstract class VolumeProviderCompat { - - /** - * @hide - */ - @IntDef({VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE, VOLUME_CONTROL_ABSOLUTE}) - @Retention(RetentionPolicy.SOURCE) - public @interface ControlType {} - - /** - * The volume is fixed and can not be modified. Requests to change volume - * should be ignored. - */ - public static final int VOLUME_CONTROL_FIXED = 0; - - /** - * The volume control uses relative adjustment via - * {@link #onAdjustVolume(int)}. Attempts to set the volume to a specific - * value should be ignored. - */ - public static final int VOLUME_CONTROL_RELATIVE = 1; - - /** - * The volume control uses an absolute value. It may be adjusted using - * {@link #onAdjustVolume(int)} or set directly using - * {@link #onSetVolumeTo(int)}. - */ - public static final int VOLUME_CONTROL_ABSOLUTE = 2; - - private final int mControlType; - private final int mMaxVolume; - private int mCurrentVolume; - private Callback mCallback; - - private Object mVolumeProviderObj; - - /** - * Create a new volume provider for handling volume events. You must specify - * the type of volume control and the maximum volume that can be used. - * - * @param volumeControl The method for controlling volume that is used by - * this provider. - * @param maxVolume The maximum allowed volume. - * @param currentVolume The current volume. - */ - public VolumeProviderCompat(@ControlType int volumeControl, int maxVolume, int currentVolume) { - mControlType = volumeControl; - mMaxVolume = maxVolume; - mCurrentVolume = currentVolume; - } - - /** - * Get the current volume of the provider. - * - * @return The current volume. - */ - public final int getCurrentVolume() { - return mCurrentVolume; - } - - /** - * Get the volume control type that this volume provider uses. - * - * @return The volume control type for this volume provider - */ - @ControlType - public final int getVolumeControl() { - return mControlType; - } - - /** - * Get the maximum volume this provider allows. - * - * @return The max allowed volume. - */ - public final int getMaxVolume() { - return mMaxVolume; - } - - /** - * Set the current volume and notify the system that the volume has been - * changed. - * - * @param currentVolume The current volume of the output. - */ - public final void setCurrentVolume(int currentVolume) { - mCurrentVolume = currentVolume; - Object volumeProviderObj = getVolumeProvider(); - if (volumeProviderObj != null) { - VolumeProviderCompatApi21.setCurrentVolume(volumeProviderObj, currentVolume); - } - if (mCallback != null) { - mCallback.onVolumeChanged(this); - } - } - - /** - * Override to handle requests to set the volume of the current output. - * - * @param volume The volume to set the output to. - */ - public void onSetVolumeTo(int volume) { - } - - /** - * Override to handle requests to adjust the volume of the current output. - * - * @param direction The direction to adjust the volume in. - */ - public void onAdjustVolume(int direction) { - } - - /** - * Sets a callback to receive volume changes. - *

- * Used internally by the support library. - *

- */ - public void setCallback(Callback callback) { - mCallback = callback; - } - - /** - * Gets the underlying framework {@link android.media.VolumeProvider} object. - *

- * This method is only supported on API 21+. - *

- * - * @return An equivalent {@link android.media.VolumeProvider} object, or null if none. - */ - public Object getVolumeProvider() { - if (mVolumeProviderObj != null || Build.VERSION.SDK_INT < 21) { - return mVolumeProviderObj; - } - - mVolumeProviderObj = VolumeProviderCompatApi21.createVolumeProvider( - mControlType, mMaxVolume, mCurrentVolume, new VolumeProviderCompatApi21.Delegate() { - - @Override - public void onSetVolumeTo(int volume) { - VolumeProviderCompat.this.onSetVolumeTo(volume); - } - - @Override - public void onAdjustVolume(int direction) { - VolumeProviderCompat.this.onAdjustVolume(direction); - } - }); - return mVolumeProviderObj; - } - - /** - * Listens for changes to the volume. - */ - public static abstract class Callback { - public abstract void onVolumeChanged(VolumeProviderCompat volumeProvider); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/VolumeProviderCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/VolumeProviderCompatApi21.java deleted file mode 100644 index 00185ae..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/VolumeProviderCompatApi21.java +++ /dev/null @@ -1,45 +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 p.android.support.v4.media; - -import android.media.VolumeProvider; - -class VolumeProviderCompatApi21 { - public static Object createVolumeProvider(int volumeControl, int maxVolume, int currentVolume, - final Delegate delegate) { - return new VolumeProvider(volumeControl, maxVolume, currentVolume) { - @Override - public void onSetVolumeTo(int volume) { - delegate.onSetVolumeTo(volume); - } - - @Override - public void onAdjustVolume(int direction) { - delegate.onAdjustVolume(direction); - } - }; - } - - public static void setCurrentVolume(Object volumeProviderObj, int currentVolume) { - ((VolumeProvider) volumeProviderObj).setCurrentVolume(currentVolume); - } - - public interface Delegate { - void onSetVolumeTo(int volume); - void onAdjustVolume(int delta); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaControllerCallback.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaControllerCallback.aidl deleted file mode 100644 index dc991f1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaControllerCallback.aidl +++ /dev/null @@ -1,40 +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 android.plug.v4.media.session; - -import android.os.Bundle; -import android.plug.v4.media.MediaMetadataCompat; -import android.plug.v4.media.session.ParcelableVolumeInfo; -import android.plug.v4.media.session.PlaybackStateCompat; -import android.plug.v4.media.session.MediaSessionCompat; - -/** - * Callback interface for a MediaSessionCompat to send updates to a - * MediaControllerCompat. This is only used on pre-Lollipop systems. - * @hide - */ -oneway interface IMediaControllerCallback { - void onEvent(String event, in Bundle extras); - void onSessionDestroyed(); - - // These callbacks are for the TransportController - void onPlaybackStateChanged(in PlaybackStateCompat state); - void onMetadataChanged(in MediaMetadataCompat metadata); - void onQueueChanged(in List queue); - void onQueueTitleChanged(CharSequence title); - void onExtrasChanged(in Bundle extras); - void onVolumeInfoChanged(in ParcelableVolumeInfo info); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaControllerCallback.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaControllerCallback.java deleted file mode 100644 index 64e0878..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaControllerCallback.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * This file is auto-generated. DO NOT MODIFY. - * Original file: /Users/user/Documents/dev/android/projects/oss/oss-android-sdk/libraries/src/main/aidl/android/plug/v4/media/session/IMediaControllerCallback.aidl - */ -package p.android.support.v4.media.session; - -import p.android.support.v4.media.MediaMetadataCompat; - -/** - * Callback interface for a MediaSessionCompat to send updates to a - * MediaControllerCompat. This is only used on pre-Lollipop systems. - * @hide - */ -public interface IMediaControllerCallback extends android.os.IInterface -{ -/** Local-side IPC implementation stub class. */ -public static abstract class Stub extends android.os.Binder implements IMediaControllerCallback -{ -private static final java.lang.String DESCRIPTOR = "android.plug.v4.media.session.IMediaControllerCallback"; -/** Construct the stub at attach it to the interface. */ -public Stub() -{ -this.attachInterface(this, DESCRIPTOR); -} -/** - * Cast an IBinder object into an android.plug.v4.media.session.IMediaControllerCallback interface, - * generating a proxy if needed. - */ -public static IMediaControllerCallback asInterface(android.os.IBinder obj) -{ -if ((obj==null)) { -return null; -} -android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); -if (((iin!=null)&&(iin instanceof IMediaControllerCallback))) { -return ((IMediaControllerCallback)iin); -} -return new IMediaControllerCallback.Stub.Proxy(obj); -} -@Override public android.os.IBinder asBinder() -{ -return this; -} -@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException -{ -java.lang.String descriptor = DESCRIPTOR; -switch (code) -{ -case INTERFACE_TRANSACTION: -{ -reply.writeString(descriptor); -return true; -} -case TRANSACTION_onEvent: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -android.os.Bundle _arg1; -if ((0!=data.readInt())) { -_arg1 = android.os.Bundle.CREATOR.createFromParcel(data); -} -else { -_arg1 = null; -} -this.onEvent(_arg0, _arg1); -return true; -} -case TRANSACTION_onSessionDestroyed: -{ -data.enforceInterface(descriptor); -this.onSessionDestroyed(); -return true; -} -case TRANSACTION_onPlaybackStateChanged: -{ -data.enforceInterface(descriptor); -PlaybackStateCompat _arg0; -if ((0!=data.readInt())) { -_arg0 = PlaybackStateCompat.CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -this.onPlaybackStateChanged(_arg0); -return true; -} -case TRANSACTION_onMetadataChanged: -{ -data.enforceInterface(descriptor); -MediaMetadataCompat _arg0; -if ((0!=data.readInt())) { -_arg0 = MediaMetadataCompat.CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -this.onMetadataChanged(_arg0); -return true; -} -case TRANSACTION_onQueueChanged: -{ -data.enforceInterface(descriptor); -java.util.List _arg0; -_arg0 = data.createTypedArrayList(MediaSessionCompat.QueueItem.CREATOR); -this.onQueueChanged(_arg0); -return true; -} -case TRANSACTION_onQueueTitleChanged: -{ -data.enforceInterface(descriptor); -java.lang.CharSequence _arg0; -if ((0!=data.readInt())) { -_arg0 = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -this.onQueueTitleChanged(_arg0); -return true; -} -case TRANSACTION_onExtrasChanged: -{ -data.enforceInterface(descriptor); -android.os.Bundle _arg0; -if ((0!=data.readInt())) { -_arg0 = android.os.Bundle.CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -this.onExtrasChanged(_arg0); -return true; -} -case TRANSACTION_onVolumeInfoChanged: -{ -data.enforceInterface(descriptor); -ParcelableVolumeInfo _arg0; -if ((0!=data.readInt())) { -_arg0 = ParcelableVolumeInfo.CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -this.onVolumeInfoChanged(_arg0); -return true; -} -default: -{ -return super.onTransact(code, data, reply, flags); -} -} -} -private static class Proxy implements IMediaControllerCallback -{ -private android.os.IBinder mRemote; -Proxy(android.os.IBinder remote) -{ -mRemote = remote; -} -@Override public android.os.IBinder asBinder() -{ -return mRemote; -} -public java.lang.String getInterfaceDescriptor() -{ -return DESCRIPTOR; -} -@Override public void onEvent(java.lang.String event, android.os.Bundle extras) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(event); -if ((extras!=null)) { -_data.writeInt(1); -extras.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_onEvent, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -@Override public void onSessionDestroyed() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_onSessionDestroyed, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -// These callbacks are for the TransportController - -@Override public void onPlaybackStateChanged(PlaybackStateCompat state) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((state!=null)) { -_data.writeInt(1); -state.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_onPlaybackStateChanged, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -@Override public void onMetadataChanged(MediaMetadataCompat metadata) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((metadata!=null)) { -_data.writeInt(1); -metadata.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_onMetadataChanged, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -@Override public void onQueueChanged(java.util.List queue) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeTypedList(queue); -mRemote.transact(Stub.TRANSACTION_onQueueChanged, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -@Override public void onQueueTitleChanged(java.lang.CharSequence title) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((title!=null)) { -_data.writeInt(1); -android.text.TextUtils.writeToParcel(title, _data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_onQueueTitleChanged, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -@Override public void onExtrasChanged(android.os.Bundle extras) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((extras!=null)) { -_data.writeInt(1); -extras.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_onExtrasChanged, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -@Override public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((info!=null)) { -_data.writeInt(1); -info.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_onVolumeInfoChanged, _data, null, android.os.IBinder.FLAG_ONEWAY); -} -finally { -_data.recycle(); -} -} -} -static final int TRANSACTION_onEvent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); -static final int TRANSACTION_onSessionDestroyed = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); -static final int TRANSACTION_onPlaybackStateChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); -static final int TRANSACTION_onMetadataChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3); -static final int TRANSACTION_onQueueChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4); -static final int TRANSACTION_onQueueTitleChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5); -static final int TRANSACTION_onExtrasChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6); -static final int TRANSACTION_onVolumeInfoChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7); -} -public void onEvent(java.lang.String event, android.os.Bundle extras) throws android.os.RemoteException; -public void onSessionDestroyed() throws android.os.RemoteException; -// These callbacks are for the TransportController - -public void onPlaybackStateChanged(PlaybackStateCompat state) throws android.os.RemoteException; -public void onMetadataChanged(MediaMetadataCompat metadata) throws android.os.RemoteException; -public void onQueueChanged(java.util.List queue) throws android.os.RemoteException; -public void onQueueTitleChanged(java.lang.CharSequence title) throws android.os.RemoteException; -public void onExtrasChanged(android.os.Bundle extras) throws android.os.RemoteException; -public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws android.os.RemoteException; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaSession.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaSession.aidl deleted file mode 100644 index 91ed931..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaSession.aidl +++ /dev/null @@ -1,70 +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 android.plug.v4.media.session; - -import android.app.PendingIntent; -import android.content.Intent; -import android.plug.v4.media.MediaMetadataCompat; -import android.plug.v4.media.RatingCompat; -import android.plug.v4.media.session.IMediaControllerCallback; -import android.plug.v4.media.session.ParcelableVolumeInfo; -import android.plug.v4.media.session.PlaybackStateCompat; -import android.plug.v4.media.session.MediaSessionCompat; -import android.os.Bundle; -import android.view.KeyEvent; - -import java.util.List; - -/** - * Interface to a MediaSessionCompat. This is only used on pre-Lollipop systems. - * @hide - */ -interface IMediaSession { - void sendCommand(String command, in Bundle args, in MediaSessionCompat.ResultReceiverWrapper cb); - boolean sendMediaButton(in KeyEvent mediaButton); - void registerCallbackListener(in IMediaControllerCallback cb); - void unregisterCallbackListener(in IMediaControllerCallback cb); - boolean isTransportControlEnabled(); - String getPackageName(); - String getTag(); - PendingIntent getLaunchPendingIntent(); - long getFlags(); - ParcelableVolumeInfo getVolumeAttributes(); - void adjustVolume(int direction, int flags, String packageName); - void setVolumeTo(int value, int flags, String packageName); - - // These commands are for the TransportControls - void play(); - void playFromMediaId(String uri, in Bundle extras); - void playFromSearch(String string, in Bundle extras); - void playFromUri(in Uri uri, in Bundle extras); - void skipToQueueItem(long id); - void pause(); - void stop(); - void next(); - void previous(); - void fastForward(); - void rewind(); - void seekTo(long pos); - void rate(in RatingCompat rating); - void sendCustomAction(String action, in Bundle args); - MediaMetadataCompat getMetadata(); - PlaybackStateCompat getPlaybackState(); - List getQueue(); - CharSequence getQueueTitle(); - Bundle getExtras(); - int getRatingType(); -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaSession.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaSession.java deleted file mode 100644 index df77bdb..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/IMediaSession.java +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * This file is auto-generated. DO NOT MODIFY. - * Original file: /Users/user/Documents/dev/android/projects/oss/oss-android-sdk/libraries/src/main/aidl/android/plug/v4/media/session/IMediaSession.aidl - */ -package p.android.support.v4.media.session; - -import p.android.support.v4.media.MediaMetadataCompat; -import p.android.support.v4.media.RatingCompat; - -/** - * Interface to a MediaSessionCompat. This is only used on pre-Lollipop systems. - * @hide - */ -public interface IMediaSession extends android.os.IInterface -{ -/** Local-side IPC implementation stub class. */ -public static abstract class Stub extends android.os.Binder implements IMediaSession -{ -private static final java.lang.String DESCRIPTOR = "android.plug.v4.media.session.IMediaSession"; -/** Construct the stub at attach it to the interface. */ -public Stub() -{ -this.attachInterface(this, DESCRIPTOR); -} -/** - * Cast an IBinder object into an android.plug.v4.media.session.IMediaSession interface, - * generating a proxy if needed. - */ -public static IMediaSession asInterface(android.os.IBinder obj) -{ -if ((obj==null)) { -return null; -} -android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); -if (((iin!=null)&&(iin instanceof IMediaSession))) { -return ((IMediaSession)iin); -} -return new IMediaSession.Stub.Proxy(obj); -} -@Override public android.os.IBinder asBinder() -{ -return this; -} -@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException -{ -java.lang.String descriptor = DESCRIPTOR; -switch (code) -{ -case INTERFACE_TRANSACTION: -{ -reply.writeString(descriptor); -return true; -} -case TRANSACTION_sendCommand: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -android.os.Bundle _arg1; -if ((0!=data.readInt())) { -_arg1 = android.os.Bundle.CREATOR.createFromParcel(data); -} -else { -_arg1 = null; -} -MediaSessionCompat.ResultReceiverWrapper _arg2; -if ((0!=data.readInt())) { -_arg2 = MediaSessionCompat.ResultReceiverWrapper.CREATOR.createFromParcel(data); -} -else { -_arg2 = null; -} -this.sendCommand(_arg0, _arg1, _arg2); -reply.writeNoException(); -return true; -} -case TRANSACTION_sendMediaButton: -{ -data.enforceInterface(descriptor); -android.view.KeyEvent _arg0; -if ((0!=data.readInt())) { -_arg0 = android.view.KeyEvent.CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -boolean _result = this.sendMediaButton(_arg0); -reply.writeNoException(); -reply.writeInt(((_result)?(1):(0))); -return true; -} -case TRANSACTION_registerCallbackListener: -{ -data.enforceInterface(descriptor); -IMediaControllerCallback _arg0; -_arg0 = IMediaControllerCallback.Stub.asInterface(data.readStrongBinder()); -this.registerCallbackListener(_arg0); -reply.writeNoException(); -return true; -} -case TRANSACTION_unregisterCallbackListener: -{ -data.enforceInterface(descriptor); -IMediaControllerCallback _arg0; -_arg0 = IMediaControllerCallback.Stub.asInterface(data.readStrongBinder()); -this.unregisterCallbackListener(_arg0); -reply.writeNoException(); -return true; -} -case TRANSACTION_isTransportControlEnabled: -{ -data.enforceInterface(descriptor); -boolean _result = this.isTransportControlEnabled(); -reply.writeNoException(); -reply.writeInt(((_result)?(1):(0))); -return true; -} -case TRANSACTION_getPackageName: -{ -data.enforceInterface(descriptor); -java.lang.String _result = this.getPackageName(); -reply.writeNoException(); -reply.writeString(_result); -return true; -} -case TRANSACTION_getTag: -{ -data.enforceInterface(descriptor); -java.lang.String _result = this.getTag(); -reply.writeNoException(); -reply.writeString(_result); -return true; -} -case TRANSACTION_getLaunchPendingIntent: -{ -data.enforceInterface(descriptor); -android.app.PendingIntent _result = this.getLaunchPendingIntent(); -reply.writeNoException(); -if ((_result!=null)) { -reply.writeInt(1); -_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); -} -else { -reply.writeInt(0); -} -return true; -} -case TRANSACTION_getFlags: -{ -data.enforceInterface(descriptor); -long _result = this.getFlags(); -reply.writeNoException(); -reply.writeLong(_result); -return true; -} -case TRANSACTION_getVolumeAttributes: -{ -data.enforceInterface(descriptor); -ParcelableVolumeInfo _result = this.getVolumeAttributes(); -reply.writeNoException(); -if ((_result!=null)) { -reply.writeInt(1); -_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); -} -else { -reply.writeInt(0); -} -return true; -} -case TRANSACTION_adjustVolume: -{ -data.enforceInterface(descriptor); -int _arg0; -_arg0 = data.readInt(); -int _arg1; -_arg1 = data.readInt(); -java.lang.String _arg2; -_arg2 = data.readString(); -this.adjustVolume(_arg0, _arg1, _arg2); -reply.writeNoException(); -return true; -} -case TRANSACTION_setVolumeTo: -{ -data.enforceInterface(descriptor); -int _arg0; -_arg0 = data.readInt(); -int _arg1; -_arg1 = data.readInt(); -java.lang.String _arg2; -_arg2 = data.readString(); -this.setVolumeTo(_arg0, _arg1, _arg2); -reply.writeNoException(); -return true; -} -case TRANSACTION_play: -{ -data.enforceInterface(descriptor); -this.play(); -reply.writeNoException(); -return true; -} -case TRANSACTION_playFromMediaId: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -android.os.Bundle _arg1; -if ((0!=data.readInt())) { -_arg1 = android.os.Bundle.CREATOR.createFromParcel(data); -} -else { -_arg1 = null; -} -this.playFromMediaId(_arg0, _arg1); -reply.writeNoException(); -return true; -} -case TRANSACTION_playFromSearch: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -android.os.Bundle _arg1; -if ((0!=data.readInt())) { -_arg1 = android.os.Bundle.CREATOR.createFromParcel(data); -} -else { -_arg1 = null; -} -this.playFromSearch(_arg0, _arg1); -reply.writeNoException(); -return true; -} -case TRANSACTION_playFromUri: -{ -data.enforceInterface(descriptor); -android.net.Uri _arg0; -if ((0!=data.readInt())) { -_arg0 = android.net.Uri.CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -android.os.Bundle _arg1; -if ((0!=data.readInt())) { -_arg1 = android.os.Bundle.CREATOR.createFromParcel(data); -} -else { -_arg1 = null; -} -this.playFromUri(_arg0, _arg1); -reply.writeNoException(); -return true; -} -case TRANSACTION_skipToQueueItem: -{ -data.enforceInterface(descriptor); -long _arg0; -_arg0 = data.readLong(); -this.skipToQueueItem(_arg0); -reply.writeNoException(); -return true; -} -case TRANSACTION_pause: -{ -data.enforceInterface(descriptor); -this.pause(); -reply.writeNoException(); -return true; -} -case TRANSACTION_stop: -{ -data.enforceInterface(descriptor); -this.stop(); -reply.writeNoException(); -return true; -} -case TRANSACTION_next: -{ -data.enforceInterface(descriptor); -this.next(); -reply.writeNoException(); -return true; -} -case TRANSACTION_previous: -{ -data.enforceInterface(descriptor); -this.previous(); -reply.writeNoException(); -return true; -} -case TRANSACTION_fastForward: -{ -data.enforceInterface(descriptor); -this.fastForward(); -reply.writeNoException(); -return true; -} -case TRANSACTION_rewind: -{ -data.enforceInterface(descriptor); -this.rewind(); -reply.writeNoException(); -return true; -} -case TRANSACTION_seekTo: -{ -data.enforceInterface(descriptor); -long _arg0; -_arg0 = data.readLong(); -this.seekTo(_arg0); -reply.writeNoException(); -return true; -} -case TRANSACTION_rate: -{ -data.enforceInterface(descriptor); -RatingCompat _arg0; -if ((0!=data.readInt())) { -_arg0 = RatingCompat.CREATOR.createFromParcel(data); -} -else { -_arg0 = null; -} -this.rate(_arg0); -reply.writeNoException(); -return true; -} -case TRANSACTION_sendCustomAction: -{ -data.enforceInterface(descriptor); -java.lang.String _arg0; -_arg0 = data.readString(); -android.os.Bundle _arg1; -if ((0!=data.readInt())) { -_arg1 = android.os.Bundle.CREATOR.createFromParcel(data); -} -else { -_arg1 = null; -} -this.sendCustomAction(_arg0, _arg1); -reply.writeNoException(); -return true; -} -case TRANSACTION_getMetadata: -{ -data.enforceInterface(descriptor); -MediaMetadataCompat _result = this.getMetadata(); -reply.writeNoException(); -if ((_result!=null)) { -reply.writeInt(1); -_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); -} -else { -reply.writeInt(0); -} -return true; -} -case TRANSACTION_getPlaybackState: -{ -data.enforceInterface(descriptor); -PlaybackStateCompat _result = this.getPlaybackState(); -reply.writeNoException(); -if ((_result!=null)) { -reply.writeInt(1); -_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); -} -else { -reply.writeInt(0); -} -return true; -} -case TRANSACTION_getQueue: -{ -data.enforceInterface(descriptor); -java.util.List _result = this.getQueue(); -reply.writeNoException(); -reply.writeTypedList(_result); -return true; -} -case TRANSACTION_getQueueTitle: -{ -data.enforceInterface(descriptor); -java.lang.CharSequence _result = this.getQueueTitle(); -reply.writeNoException(); -if ((_result!=null)) { -reply.writeInt(1); -android.text.TextUtils.writeToParcel(_result, reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); -} -else { -reply.writeInt(0); -} -return true; -} -case TRANSACTION_getExtras: -{ -data.enforceInterface(descriptor); -android.os.Bundle _result = this.getExtras(); -reply.writeNoException(); -if ((_result!=null)) { -reply.writeInt(1); -_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); -} -else { -reply.writeInt(0); -} -return true; -} -case TRANSACTION_getRatingType: -{ -data.enforceInterface(descriptor); -int _result = this.getRatingType(); -reply.writeNoException(); -reply.writeInt(_result); -return true; -} -default: -{ -return super.onTransact(code, data, reply, flags); -} -} -} -private static class Proxy implements IMediaSession -{ -private android.os.IBinder mRemote; -Proxy(android.os.IBinder remote) -{ -mRemote = remote; -} -@Override public android.os.IBinder asBinder() -{ -return mRemote; -} -public java.lang.String getInterfaceDescriptor() -{ -return DESCRIPTOR; -} -@Override public void sendCommand(java.lang.String command, android.os.Bundle args, MediaSessionCompat.ResultReceiverWrapper cb) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(command); -if ((args!=null)) { -_data.writeInt(1); -args.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -if ((cb!=null)) { -_data.writeInt(1); -cb.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_sendCommand, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public boolean sendMediaButton(android.view.KeyEvent mediaButton) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -boolean _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((mediaButton!=null)) { -_data.writeInt(1); -mediaButton.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_sendMediaButton, _data, _reply, 0); -_reply.readException(); -_result = (0!=_reply.readInt()); -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public void registerCallbackListener(IMediaControllerCallback cb) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null))); -mRemote.transact(Stub.TRANSACTION_registerCallbackListener, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void unregisterCallbackListener(IMediaControllerCallback cb) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null))); -mRemote.transact(Stub.TRANSACTION_unregisterCallbackListener, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public boolean isTransportControlEnabled() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -boolean _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_isTransportControlEnabled, _data, _reply, 0); -_reply.readException(); -_result = (0!=_reply.readInt()); -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public java.lang.String getPackageName() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -java.lang.String _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getPackageName, _data, _reply, 0); -_reply.readException(); -_result = _reply.readString(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public java.lang.String getTag() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -java.lang.String _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getTag, _data, _reply, 0); -_reply.readException(); -_result = _reply.readString(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public android.app.PendingIntent getLaunchPendingIntent() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -android.app.PendingIntent _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getLaunchPendingIntent, _data, _reply, 0); -_reply.readException(); -if ((0!=_reply.readInt())) { -_result = android.app.PendingIntent.CREATOR.createFromParcel(_reply); -} -else { -_result = null; -} -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public long getFlags() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -long _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getFlags, _data, _reply, 0); -_reply.readException(); -_result = _reply.readLong(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public ParcelableVolumeInfo getVolumeAttributes() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -ParcelableVolumeInfo _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getVolumeAttributes, _data, _reply, 0); -_reply.readException(); -if ((0!=_reply.readInt())) { -_result = ParcelableVolumeInfo.CREATOR.createFromParcel(_reply); -} -else { -_result = null; -} -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public void adjustVolume(int direction, int flags, java.lang.String packageName) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeInt(direction); -_data.writeInt(flags); -_data.writeString(packageName); -mRemote.transact(Stub.TRANSACTION_adjustVolume, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void setVolumeTo(int value, int flags, java.lang.String packageName) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeInt(value); -_data.writeInt(flags); -_data.writeString(packageName); -mRemote.transact(Stub.TRANSACTION_setVolumeTo, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -// These commands are for the TransportControls - -@Override public void play() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_play, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void playFromMediaId(java.lang.String uri, android.os.Bundle extras) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(uri); -if ((extras!=null)) { -_data.writeInt(1); -extras.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_playFromMediaId, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void playFromSearch(java.lang.String string, android.os.Bundle extras) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(string); -if ((extras!=null)) { -_data.writeInt(1); -extras.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_playFromSearch, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void playFromUri(android.net.Uri uri, android.os.Bundle extras) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((uri!=null)) { -_data.writeInt(1); -uri.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -if ((extras!=null)) { -_data.writeInt(1); -extras.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_playFromUri, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void skipToQueueItem(long id) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeLong(id); -mRemote.transact(Stub.TRANSACTION_skipToQueueItem, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void pause() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_pause, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void stop() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void next() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_next, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void previous() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_previous, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void fastForward() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_fastForward, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void rewind() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_rewind, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void seekTo(long pos) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeLong(pos); -mRemote.transact(Stub.TRANSACTION_seekTo, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void rate(RatingCompat rating) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -if ((rating!=null)) { -_data.writeInt(1); -rating.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_rate, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public void sendCustomAction(java.lang.String action, android.os.Bundle args) throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -try { -_data.writeInterfaceToken(DESCRIPTOR); -_data.writeString(action); -if ((args!=null)) { -_data.writeInt(1); -args.writeToParcel(_data, 0); -} -else { -_data.writeInt(0); -} -mRemote.transact(Stub.TRANSACTION_sendCustomAction, _data, _reply, 0); -_reply.readException(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -} -@Override public MediaMetadataCompat getMetadata() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -MediaMetadataCompat _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getMetadata, _data, _reply, 0); -_reply.readException(); -if ((0!=_reply.readInt())) { -_result = MediaMetadataCompat.CREATOR.createFromParcel(_reply); -} -else { -_result = null; -} -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public PlaybackStateCompat getPlaybackState() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -PlaybackStateCompat _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getPlaybackState, _data, _reply, 0); -_reply.readException(); -if ((0!=_reply.readInt())) { -_result = PlaybackStateCompat.CREATOR.createFromParcel(_reply); -} -else { -_result = null; -} -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public java.util.List getQueue() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -java.util.List _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getQueue, _data, _reply, 0); -_reply.readException(); -_result = _reply.createTypedArrayList(MediaSessionCompat.QueueItem.CREATOR); -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public java.lang.CharSequence getQueueTitle() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -java.lang.CharSequence _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getQueueTitle, _data, _reply, 0); -_reply.readException(); -if ((0!=_reply.readInt())) { -_result = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(_reply); -} -else { -_result = null; -} -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public android.os.Bundle getExtras() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -android.os.Bundle _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getExtras, _data, _reply, 0); -_reply.readException(); -if ((0!=_reply.readInt())) { -_result = android.os.Bundle.CREATOR.createFromParcel(_reply); -} -else { -_result = null; -} -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -@Override public int getRatingType() throws android.os.RemoteException -{ -android.os.Parcel _data = android.os.Parcel.obtain(); -android.os.Parcel _reply = android.os.Parcel.obtain(); -int _result; -try { -_data.writeInterfaceToken(DESCRIPTOR); -mRemote.transact(Stub.TRANSACTION_getRatingType, _data, _reply, 0); -_reply.readException(); -_result = _reply.readInt(); -} -finally { -_reply.recycle(); -_data.recycle(); -} -return _result; -} -} -static final int TRANSACTION_sendCommand = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); -static final int TRANSACTION_sendMediaButton = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); -static final int TRANSACTION_registerCallbackListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); -static final int TRANSACTION_unregisterCallbackListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3); -static final int TRANSACTION_isTransportControlEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4); -static final int TRANSACTION_getPackageName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5); -static final int TRANSACTION_getTag = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6); -static final int TRANSACTION_getLaunchPendingIntent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7); -static final int TRANSACTION_getFlags = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8); -static final int TRANSACTION_getVolumeAttributes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9); -static final int TRANSACTION_adjustVolume = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10); -static final int TRANSACTION_setVolumeTo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11); -static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12); -static final int TRANSACTION_playFromMediaId = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13); -static final int TRANSACTION_playFromSearch = (android.os.IBinder.FIRST_CALL_TRANSACTION + 14); -static final int TRANSACTION_playFromUri = (android.os.IBinder.FIRST_CALL_TRANSACTION + 15); -static final int TRANSACTION_skipToQueueItem = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16); -static final int TRANSACTION_pause = (android.os.IBinder.FIRST_CALL_TRANSACTION + 17); -static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 18); -static final int TRANSACTION_next = (android.os.IBinder.FIRST_CALL_TRANSACTION + 19); -static final int TRANSACTION_previous = (android.os.IBinder.FIRST_CALL_TRANSACTION + 20); -static final int TRANSACTION_fastForward = (android.os.IBinder.FIRST_CALL_TRANSACTION + 21); -static final int TRANSACTION_rewind = (android.os.IBinder.FIRST_CALL_TRANSACTION + 22); -static final int TRANSACTION_seekTo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 23); -static final int TRANSACTION_rate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 24); -static final int TRANSACTION_sendCustomAction = (android.os.IBinder.FIRST_CALL_TRANSACTION + 25); -static final int TRANSACTION_getMetadata = (android.os.IBinder.FIRST_CALL_TRANSACTION + 26); -static final int TRANSACTION_getPlaybackState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 27); -static final int TRANSACTION_getQueue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 28); -static final int TRANSACTION_getQueueTitle = (android.os.IBinder.FIRST_CALL_TRANSACTION + 29); -static final int TRANSACTION_getExtras = (android.os.IBinder.FIRST_CALL_TRANSACTION + 30); -static final int TRANSACTION_getRatingType = (android.os.IBinder.FIRST_CALL_TRANSACTION + 31); -} -public void sendCommand(java.lang.String command, android.os.Bundle args, MediaSessionCompat.ResultReceiverWrapper cb) throws android.os.RemoteException; -public boolean sendMediaButton(android.view.KeyEvent mediaButton) throws android.os.RemoteException; -public void registerCallbackListener(IMediaControllerCallback cb) throws android.os.RemoteException; -public void unregisterCallbackListener(IMediaControllerCallback cb) throws android.os.RemoteException; -public boolean isTransportControlEnabled() throws android.os.RemoteException; -public java.lang.String getPackageName() throws android.os.RemoteException; -public java.lang.String getTag() throws android.os.RemoteException; -public android.app.PendingIntent getLaunchPendingIntent() throws android.os.RemoteException; -public long getFlags() throws android.os.RemoteException; -public ParcelableVolumeInfo getVolumeAttributes() throws android.os.RemoteException; -public void adjustVolume(int direction, int flags, java.lang.String packageName) throws android.os.RemoteException; -public void setVolumeTo(int value, int flags, java.lang.String packageName) throws android.os.RemoteException; -// These commands are for the TransportControls - -public void play() throws android.os.RemoteException; -public void playFromMediaId(java.lang.String uri, android.os.Bundle extras) throws android.os.RemoteException; -public void playFromSearch(java.lang.String string, android.os.Bundle extras) throws android.os.RemoteException; -public void playFromUri(android.net.Uri uri, android.os.Bundle extras) throws android.os.RemoteException; -public void skipToQueueItem(long id) throws android.os.RemoteException; -public void pause() throws android.os.RemoteException; -public void stop() throws android.os.RemoteException; -public void next() throws android.os.RemoteException; -public void previous() throws android.os.RemoteException; -public void fastForward() throws android.os.RemoteException; -public void rewind() throws android.os.RemoteException; -public void seekTo(long pos) throws android.os.RemoteException; -public void rate(RatingCompat rating) throws android.os.RemoteException; -public void sendCustomAction(java.lang.String action, android.os.Bundle args) throws android.os.RemoteException; -public MediaMetadataCompat getMetadata() throws android.os.RemoteException; -public PlaybackStateCompat getPlaybackState() throws android.os.RemoteException; -public java.util.List getQueue() throws android.os.RemoteException; -public java.lang.CharSequence getQueueTitle() throws android.os.RemoteException; -public android.os.Bundle getExtras() throws android.os.RemoteException; -public int getRatingType() throws android.os.RemoteException; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaButtonReceiver.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaButtonReceiver.java deleted file mode 100644 index d14ea48..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaButtonReceiver.java +++ /dev/null @@ -1,142 +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 p.android.support.v4.media.session; - -import android.app.Service; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import p.android.support.v4.media.MediaBrowserServiceCompat; -import android.view.KeyEvent; - -import java.util.List; - -/** - * A media button receiver receives and helps translate hardware media playback buttons, - * such as those found on wired and wireless headsets, into the appropriate callbacks - * in your app. - *

- * You can add this MediaButtonReceiver to your app by adding it directly to your - * AndroidManifest.xml: - *

- * <receiver android:name="MediaButtonReceiver" >
- *   <intent-filter>
- *     <action android:name="android.intent.action.MEDIA_BUTTON" />
- *   </intent-filter>
- * </receiver>
- * 
- * This class assumes you have a {@link Service} in your app that controls - * media playback via a {@link MediaSessionCompat} - all {@link Intent}s received by - * the MediaButtonReceiver will be forwarded to that service. - *

- * First priority is given to a {@link Service} - * that includes an intent filter that handles {@link Intent#ACTION_MEDIA_BUTTON}: - *

- * <service android:name="com.example.android.MediaPlaybackService" >
- *   <intent-filter>
- *     <action android:name="android.intent.action.MEDIA_BUTTON" />
- *   </intent-filter>
- * </service>
- * 
- * - * If such a {@link Service} is not found, MediaButtonReceiver will attempt to - * find a media browser service implementation. - * If neither is available or more than one valid service/media browser service is found, an - * {@link IllegalStateException} will be thrown. - *

- * Events can then be handled in {@link Service#onStartCommand(Intent, int, int)} by calling - * {@link MediaButtonReceiver#handleIntent(MediaSessionCompat, Intent)}, passing in - * your current {@link MediaSessionCompat}: - *

- * private MediaSessionCompat mMediaSessionCompat = ...;
- *
- * public int onStartCommand(Intent intent, int flags, int startId) {
- *   MediaButtonReceiver.handleIntent(mMediaSessionCompat, intent);
- *   return super.onStartCommand(intent, flags, startId);
- * }
- * 
- * - * This ensures that the correct callbacks to {@link MediaSessionCompat.Callback} - * will be triggered based on the incoming {@link KeyEvent}. - */ -public class MediaButtonReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Intent queryIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); - queryIntent.setPackage(context.getPackageName()); - PackageManager pm = context.getPackageManager(); - List resolveInfos = pm.queryIntentServices(queryIntent, 0); - if (resolveInfos.isEmpty()) { - // Fall back to looking for any available media browser service - queryIntent.setAction(MediaBrowserServiceCompat.SERVICE_INTERFACE); - resolveInfos = pm.queryIntentServices(queryIntent, 0); - } - if (resolveInfos.isEmpty()) { - throw new IllegalStateException("Could not find any Service that handles " + - Intent.ACTION_MEDIA_BUTTON + " or a media browser service implementation"); - } else if (resolveInfos.size() != 1) { - throw new IllegalStateException("Expected 1 Service that handles " + - queryIntent.getAction() + ", found " + resolveInfos.size() ); - } - ResolveInfo resolveInfo = resolveInfos.get(0); - ComponentName componentName = new ComponentName(resolveInfo.serviceInfo.packageName, - resolveInfo.serviceInfo.name); - intent.setComponent(componentName); - context.startService(intent); - } - - /** - * Extracts any available {@link KeyEvent} from an {@link Intent#ACTION_MEDIA_BUTTON} - * intent, passing it onto the {@link MediaSessionCompat} using - * {@link MediaControllerCompat#dispatchMediaButtonEvent(KeyEvent)}, which in turn - * will trigger callbacks to the {@link MediaSessionCompat.Callback} registered via - * {@link MediaSessionCompat#setCallback(MediaSessionCompat.Callback)}. - *

- * The returned {@link KeyEvent} is non-null if any {@link KeyEvent} is found and can - * be used if any additional processing is needed beyond what is done in the - * {@link MediaSessionCompat.Callback}. An example of is to prevent redelivery of a - * {@link KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE} Intent in the case of the Service being - * restarted (which, by default, will redeliver the last received Intent). - *

-     * KeyEvent keyEvent = MediaButtonReceiver.handleIntent(mediaSession, intent);
-     * if (keyEvent != null && keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
-     *   Intent emptyIntent = new Intent(intent);
-     *   emptyIntent.setAction("");
-     *   startService(emptyIntent);
-     * }
-     * 
- * @param mediaSessionCompat A {@link MediaSessionCompat} that has a - * {@link MediaSessionCompat.Callback} set. - * @param intent The intent to parse. - * @return The extracted {@link KeyEvent} if found, or null. - */ - public static KeyEvent handleIntent(MediaSessionCompat mediaSessionCompat, Intent intent) { - if (mediaSessionCompat == null || intent == null - || !Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction()) - || !intent.hasExtra(Intent.EXTRA_KEY_EVENT)) { - return null; - } - KeyEvent ke = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); - MediaControllerCompat mediaController = mediaSessionCompat.getController(); - mediaController.dispatchMediaButtonEvent(ke); - return ke; - } -} - diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompat.java deleted file mode 100644 index ef8c4fe..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompat.java +++ /dev/null @@ -1,1389 +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 p.android.support.v4.media.session; - -import android.app.PendingIntent; -import android.content.Context; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.os.ResultReceiver; -import p.android.support.v4.media.RatingCompat; -import p.android.support.v4.media.MediaMetadataCompat; -import p.android.support.v4.media.VolumeProviderCompat; -import p.android.support.v4.media.session.PlaybackStateCompat.CustomAction; -import android.text.TextUtils; -import android.util.Log; -import android.view.KeyEvent; - -import java.util.ArrayList; -import java.util.List; - -/** - * Allows an app to interact with an ongoing media session. Media buttons and - * other commands can be sent to the session. A callback may be registered to - * receive updates from the session, such as metadata and play state changes. - *

- * A MediaController can be created if you have a {@link MediaSessionCompat.Token} - * from the session owner. - *

- * MediaController objects are thread-safe. - *

- * This is a helper for accessing features in {@link android.media.session.MediaSession} - * introduced after API level 4 in a backwards compatible fashion. - */ -public final class MediaControllerCompat { - private static final String TAG = "MediaControllerCompat"; - - private final MediaControllerImpl mImpl; - private final MediaSessionCompat.Token mToken; - - /** - * Creates a media controller from a session. - * - * @param session The session to be controlled. - */ - public MediaControllerCompat(Context context, MediaSessionCompat session) { - if (session == null) { - throw new IllegalArgumentException("session must not be null"); - } - mToken = session.getSessionToken(); - - if (android.os.Build.VERSION.SDK_INT >= 23) { - mImpl = new MediaControllerImplApi23(context, session); - } else if (android.os.Build.VERSION.SDK_INT >= 21) { - mImpl = new MediaControllerImplApi21(context, session); - } else { - mImpl = new MediaControllerImplBase(mToken); - } - } - - /** - * Creates a media controller from a session token which may have - * been obtained from another process. - * - * @param sessionToken The token of the session to be controlled. - * @throws RemoteException if the session is not accessible. - */ - public MediaControllerCompat(Context context, MediaSessionCompat.Token sessionToken) - throws RemoteException { - if (sessionToken == null) { - throw new IllegalArgumentException("sessionToken must not be null"); - } - mToken = sessionToken; - - if (android.os.Build.VERSION.SDK_INT >= 23) { - mImpl = new MediaControllerImplApi23(context, sessionToken); - } else if (android.os.Build.VERSION.SDK_INT >= 21) { - mImpl = new MediaControllerImplApi21(context, sessionToken); - } else { - mImpl = new MediaControllerImplBase(mToken); - } - } - - /** - * Get a {@link TransportControls} instance for this session. - * - * @return A controls instance - */ - public TransportControls getTransportControls() { - return mImpl.getTransportControls(); - } - - /** - * Send the specified media button event to the session. Only media keys can - * be sent by this method, other keys will be ignored. - * - * @param keyEvent The media button event to dispatch. - * @return true if the event was sent to the session, false otherwise. - */ - public boolean dispatchMediaButtonEvent(KeyEvent keyEvent) { - if (keyEvent == null) { - throw new IllegalArgumentException("KeyEvent may not be null"); - } - return mImpl.dispatchMediaButtonEvent(keyEvent); - } - - /** - * Get the current playback state for this session. - * - * @return The current PlaybackState or null - */ - public PlaybackStateCompat getPlaybackState() { - return mImpl.getPlaybackState(); - } - - /** - * Get the current metadata for this session. - * - * @return The current MediaMetadata or null. - */ - public MediaMetadataCompat getMetadata() { - return mImpl.getMetadata(); - } - - /** - * Get the current play queue for this session if one is set. If you only - * care about the current item {@link #getMetadata()} should be used. - * - * @return The current play queue or null. - */ - public List getQueue() { - return mImpl.getQueue(); - } - - /** - * Get the queue title for this session. - */ - public CharSequence getQueueTitle() { - return mImpl.getQueueTitle(); - } - - /** - * Get the extras for this session. - */ - public Bundle getExtras() { - return mImpl.getExtras(); - } - - /** - * Get the rating type supported by the session. One of: - *

    - *
  • {@link RatingCompat#RATING_NONE}
  • - *
  • {@link RatingCompat#RATING_HEART}
  • - *
  • {@link RatingCompat#RATING_THUMB_UP_DOWN}
  • - *
  • {@link RatingCompat#RATING_3_STARS}
  • - *
  • {@link RatingCompat#RATING_4_STARS}
  • - *
  • {@link RatingCompat#RATING_5_STARS}
  • - *
  • {@link RatingCompat#RATING_PERCENTAGE}
  • - *
- * - * @return The supported rating type - */ - public int getRatingType() { - return mImpl.getRatingType(); - } - - /** - * Get the flags for this session. Flags are defined in - * {@link MediaSessionCompat}. - * - * @return The current set of flags for the session. - */ - public long getFlags() { - return mImpl.getFlags(); - } - - /** - * Get the current playback info for this session. - * - * @return The current playback info or null. - */ - public PlaybackInfo getPlaybackInfo() { - return mImpl.getPlaybackInfo(); - } - - /** - * Get an intent for launching UI associated with this session if one - * exists. - * - * @return A {@link PendingIntent} to launch UI or null. - */ - public PendingIntent getSessionActivity() { - return mImpl.getSessionActivity(); - } - - /** - * Get the token for the session this controller is connected to. - * - * @return The session's token. - */ - public MediaSessionCompat.Token getSessionToken() { - return mToken; - } - - /** - * Set the volume of the output this session is playing on. The command will - * be ignored if it does not support - * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in - * {@link AudioManager} may be used to affect the handling. - * - * @see #getPlaybackInfo() - * @param value The value to set it to, between 0 and the reported max. - * @param flags Flags from {@link AudioManager} to include with the volume - * request. - */ - public void setVolumeTo(int value, int flags) { - mImpl.setVolumeTo(value, flags); - } - - /** - * Adjust the volume of the output this session is playing on. The direction - * must be one of {@link AudioManager#ADJUST_LOWER}, - * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}. - * The command will be ignored if the session does not support - * {@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE} or - * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in - * {@link AudioManager} may be used to affect the handling. - * - * @see #getPlaybackInfo() - * @param direction The direction to adjust the volume in. - * @param flags Any flags to pass with the command. - */ - public void adjustVolume(int direction, int flags) { - mImpl.adjustVolume(direction, flags); - } - - /** - * Adds a callback to receive updates from the Session. Updates will be - * posted on the caller's thread. - * - * @param callback The callback object, must not be null. - */ - public void registerCallback(Callback callback) { - registerCallback(callback, null); - } - - /** - * Adds a callback to receive updates from the session. Updates will be - * posted on the specified handler's thread. - * - * @param callback The callback object, must not be null. - * @param handler The handler to post updates on. If null the callers thread - * will be used. - */ - public void registerCallback(Callback callback, Handler handler) { - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } - if (handler == null) { - handler = new Handler(); - } - mImpl.registerCallback(callback, handler); - } - - /** - * Stop receiving updates on the specified callback. If an update has - * already been posted you may still receive it after calling this method. - * - * @param callback The callback to remove - */ - public void unregisterCallback(Callback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } - mImpl.unregisterCallback(callback); - } - - /** - * Sends a generic command to the session. It is up to the session creator - * to decide what commands and parameters they will support. As such, - * commands should only be sent to sessions that the controller owns. - * - * @param command The command to send - * @param params Any parameters to include with the command - * @param cb The callback to receive the result on - */ - public void sendCommand(String command, Bundle params, ResultReceiver cb) { - if (TextUtils.isEmpty(command)) { - throw new IllegalArgumentException("command cannot be null or empty"); - } - mImpl.sendCommand(command, params, cb); - } - - /** - * Get the session owner's package name. - * - * @return The package name of of the session owner. - */ - public String getPackageName() { - return mImpl.getPackageName(); - } - - /** - * Gets the underlying framework - * {@link android.media.session.MediaController} object. - *

- * This method is only supported on API 21+. - *

- * - * @return The underlying {@link android.media.session.MediaController} - * object, or null if none. - */ - public Object getMediaController() { - return mImpl.getMediaController(); - } - - /** - * Callback for receiving updates on from the session. A Callback can be - * registered using {@link #registerCallback} - */ - public static abstract class Callback implements IBinder.DeathRecipient { - private final Object mCallbackObj; - private MessageHandler mHandler; - - private boolean mRegistered = false; - - public Callback() { - if (android.os.Build.VERSION.SDK_INT >= 21) { - mCallbackObj = MediaControllerCompatApi21.createCallback(new StubApi21()); - } else { - mCallbackObj = new StubCompat(); - } - } - - /** - * Override to handle the session being destroyed. The session is no - * longer valid after this call and calls to it will be ignored. - */ - public void onSessionDestroyed() { - } - - /** - * Override to handle custom events sent by the session owner without a - * specified interface. Controllers should only handle these for - * sessions they own. - * - * @param event The event from the session. - * @param extras Optional parameters for the event. - */ - public void onSessionEvent(String event, Bundle extras) { - } - - /** - * Override to handle changes in playback state. - * - * @param state The new playback state of the session - */ - public void onPlaybackStateChanged(PlaybackStateCompat state) { - } - - /** - * Override to handle changes to the current metadata. - * - * @param metadata The current metadata for the session or null if none. - * @see MediaMetadata - */ - public void onMetadataChanged(MediaMetadataCompat metadata) { - } - - /** - * Override to handle changes to items in the queue. - * - * @see MediaSessionCompat.QueueItem - * @param queue A list of items in the current play queue. It should - * include the currently playing item as well as previous and - * upcoming items if applicable. - */ - public void onQueueChanged(List queue) { - } - - /** - * Override to handle changes to the queue title. - * - * @param title The title that should be displayed along with the play - * queue such as "Now Playing". May be null if there is no - * such title. - */ - public void onQueueTitleChanged(CharSequence title) { - } - - /** - * Override to handle chagnes to the {@link MediaSessionCompat} extras. - * - * @param extras The extras that can include other information - * associated with the {@link MediaSessionCompat}. - */ - public void onExtrasChanged(Bundle extras) { - } - - /** - * Override to handle changes to the audio info. - * - * @param info The current audio info for this session. - */ - public void onAudioInfoChanged(PlaybackInfo info) { - } - - @Override - public void binderDied() { - onSessionDestroyed(); - } - - /** - * Set the handler to use for pre 21 callbacks. - */ - private void setHandler(Handler handler) { - mHandler = new MessageHandler(handler.getLooper()); - } - - private class StubApi21 implements MediaControllerCompatApi21.Callback { - @Override - public void onSessionDestroyed() { - Callback.this.onSessionDestroyed(); - } - - @Override - public void onSessionEvent(String event, Bundle extras) { - Callback.this.onSessionEvent(event, extras); - } - - @Override - public void onPlaybackStateChanged(Object stateObj) { - Callback.this.onPlaybackStateChanged( - PlaybackStateCompat.fromPlaybackState(stateObj)); - } - - @Override - public void onMetadataChanged(Object metadataObj) { - Callback.this.onMetadataChanged( - MediaMetadataCompat.fromMediaMetadata(metadataObj)); - } - } - - private class StubCompat extends IMediaControllerCallback.Stub { - - @Override - public void onEvent(String event, Bundle extras) throws RemoteException { - mHandler.post(MessageHandler.MSG_EVENT, event, extras); - } - - @Override - public void onSessionDestroyed() throws RemoteException { - mHandler.post(MessageHandler.MSG_DESTROYED, null, null); - } - - @Override - public void onPlaybackStateChanged(PlaybackStateCompat state) throws RemoteException { - mHandler.post(MessageHandler.MSG_UPDATE_PLAYBACK_STATE, state, null); - } - - @Override - public void onMetadataChanged(MediaMetadataCompat metadata) throws RemoteException { - mHandler.post(MessageHandler.MSG_UPDATE_METADATA, metadata, null); - } - - @Override - public void onQueueChanged(List queue) throws RemoteException { - mHandler.post(MessageHandler.MSG_UPDATE_QUEUE, queue, null); - } - - @Override - public void onQueueTitleChanged(CharSequence title) throws RemoteException { - mHandler.post(MessageHandler.MSG_UPDATE_QUEUE_TITLE, title, null); - } - - @Override - public void onExtrasChanged(Bundle extras) throws RemoteException { - mHandler.post(MessageHandler.MSG_UPDATE_EXTRAS, extras, null); - } - - @Override - public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException { - PlaybackInfo pi = null; - if (info != null) { - pi = new PlaybackInfo(info.volumeType, info.audioStream, info.controlType, - info.maxVolume, info.currentVolume); - } - mHandler.post(MessageHandler.MSG_UPDATE_VOLUME, pi, null); - } - } - - private class MessageHandler extends Handler { - private static final int MSG_EVENT = 1; - private static final int MSG_UPDATE_PLAYBACK_STATE = 2; - private static final int MSG_UPDATE_METADATA = 3; - private static final int MSG_UPDATE_VOLUME = 4; - private static final int MSG_UPDATE_QUEUE = 5; - private static final int MSG_UPDATE_QUEUE_TITLE = 6; - private static final int MSG_UPDATE_EXTRAS = 7; - private static final int MSG_DESTROYED = 8; - - public MessageHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - if (!mRegistered) { - return; - } - switch (msg.what) { - case MSG_EVENT: - onSessionEvent((String) msg.obj, msg.getData()); - break; - case MSG_UPDATE_PLAYBACK_STATE: - onPlaybackStateChanged((PlaybackStateCompat) msg.obj); - break; - case MSG_UPDATE_METADATA: - onMetadataChanged((MediaMetadataCompat) msg.obj); - break; - case MSG_UPDATE_QUEUE: - onQueueChanged((List) msg.obj); - break; - case MSG_UPDATE_QUEUE_TITLE: - onQueueTitleChanged((CharSequence) msg.obj); - break; - case MSG_UPDATE_EXTRAS: - onExtrasChanged((Bundle) msg.obj); - break; - case MSG_UPDATE_VOLUME: - onAudioInfoChanged((PlaybackInfo) msg.obj); - break; - case MSG_DESTROYED: - onSessionDestroyed(); - break; - } - } - - public void post(int what, Object obj, Bundle data) { - Message msg = obtainMessage(what, obj); - msg.setData(data); - msg.sendToTarget(); - } - } - } - - /** - * Interface for controlling media playback on a session. This allows an app - * to send media transport commands to the session. - */ - public static abstract class TransportControls { - TransportControls() { - } - - /** - * Request that the player start its playback at its current position. - */ - public abstract void play(); - - /** - * Request that the player start playback for a specific {@link Uri}. - * - * @param mediaId The uri of the requested media. - * @param extras Optional extras that can include extra information - * about the media item to be played. - */ - public abstract void playFromMediaId(String mediaId, Bundle extras); - - /** - * Request that the player start playback for a specific search query. - * An empty or null query should be treated as a request to play any - * music. - * - * @param query The search query. - * @param extras Optional extras that can include extra information - * about the query. - */ - public abstract void playFromSearch(String query, Bundle extras); - - /** - * Request that the player start playback for a specific {@link Uri}. - * - * @param uri The URI of the requested media. - * @param extras Optional extras that can include extra information about the media item - * to be played. - */ - public abstract void playFromUri(Uri uri, Bundle extras); - - /** - * Play an item with a specific id in the play queue. If you specify an - * id that is not in the play queue, the behavior is undefined. - */ - public abstract void skipToQueueItem(long id); - - /** - * Request that the player pause its playback and stay at its current - * position. - */ - public abstract void pause(); - - /** - * Request that the player stop its playback; it may clear its state in - * whatever way is appropriate. - */ - public abstract void stop(); - - /** - * Move to a new location in the media stream. - * - * @param pos Position to move to, in milliseconds. - */ - public abstract void seekTo(long pos); - - /** - * Start fast forwarding. If playback is already fast forwarding this - * may increase the rate. - */ - public abstract void fastForward(); - - /** - * Skip to the next item. - */ - public abstract void skipToNext(); - - /** - * Start rewinding. If playback is already rewinding this may increase - * the rate. - */ - public abstract void rewind(); - - /** - * Skip to the previous item. - */ - public abstract void skipToPrevious(); - - /** - * Rate the current content. This will cause the rating to be set for - * the current user. The Rating type must match the type returned by - * {@link #getRatingType()}. - * - * @param rating The rating to set for the current content - */ - public abstract void setRating(RatingCompat rating); - - /** - * Send a custom action for the {@link MediaSessionCompat} to perform. - * - * @param customAction The action to perform. - * @param args Optional arguments to supply to the - * {@link MediaSessionCompat} for this custom action. - */ - public abstract void sendCustomAction(CustomAction customAction, - Bundle args); - - /** - * Send the id and args from a custom action for the - * {@link MediaSessionCompat} to perform. - * - * @see #sendCustomAction(CustomAction action, - * Bundle args) - * @param action The action identifier of the - * {@link CustomAction} as specified by - * the {@link MediaSessionCompat}. - * @param args Optional arguments to supply to the - * {@link MediaSessionCompat} for this custom action. - */ - public abstract void sendCustomAction(String action, Bundle args); - } - - /** - * Holds information about the way volume is handled for this session. - */ - public static final class PlaybackInfo { - /** - * The session uses local playback. - */ - public static final int PLAYBACK_TYPE_LOCAL = 1; - /** - * The session uses remote playback. - */ - public static final int PLAYBACK_TYPE_REMOTE = 2; - - private final int mPlaybackType; - // TODO update audio stream with AudioAttributes support version - private final int mAudioStream; - private final int mVolumeControl; - private final int mMaxVolume; - private final int mCurrentVolume; - - PlaybackInfo(int type, int stream, int control, int max, int current) { - mPlaybackType = type; - mAudioStream = stream; - mVolumeControl = control; - mMaxVolume = max; - mCurrentVolume = current; - } - - /** - * Get the type of volume handling, either local or remote. One of: - *
    - *
  • {@link PlaybackInfo#PLAYBACK_TYPE_LOCAL}
  • - *
  • {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE}
  • - *
- * - * @return The type of volume handling this session is using. - */ - public int getPlaybackType() { - return mPlaybackType; - } - - /** - * Get the stream this is currently controlling volume on. When the volume - * type is {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} this value does not - * have meaning and should be ignored. - * - * @return The stream this session is playing on. - */ - public int getAudioStream() { - // TODO switch to AudioAttributesCompat when it is added. - return mAudioStream; - } - - /** - * Get the type of volume control that can be used. One of: - *
    - *
  • {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}
  • - *
  • {@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE}
  • - *
  • {@link VolumeProviderCompat#VOLUME_CONTROL_FIXED}
  • - *
- * - * @return The type of volume control that may be used with this - * session. - */ - public int getVolumeControl() { - return mVolumeControl; - } - - /** - * Get the maximum volume that may be set for this session. - * - * @return The maximum allowed volume where this session is playing. - */ - public int getMaxVolume() { - return mMaxVolume; - } - - /** - * Get the current volume for this session. - * - * @return The current volume where this session is playing. - */ - public int getCurrentVolume() { - return mCurrentVolume; - } - } - - interface MediaControllerImpl { - void registerCallback(Callback callback, Handler handler); - - void unregisterCallback(Callback callback); - boolean dispatchMediaButtonEvent(KeyEvent keyEvent); - TransportControls getTransportControls(); - PlaybackStateCompat getPlaybackState(); - MediaMetadataCompat getMetadata(); - - List getQueue(); - CharSequence getQueueTitle(); - Bundle getExtras(); - int getRatingType(); - long getFlags(); - PlaybackInfo getPlaybackInfo(); - PendingIntent getSessionActivity(); - - void setVolumeTo(int value, int flags); - void adjustVolume(int direction, int flags); - void sendCommand(String command, Bundle params, ResultReceiver cb); - - String getPackageName(); - Object getMediaController(); - } - - static class MediaControllerImplBase implements MediaControllerImpl { - private MediaSessionCompat.Token mToken; - private IMediaSession mBinder; - private TransportControls mTransportControls; - - public MediaControllerImplBase(MediaSessionCompat.Token token) { - mToken = token; - mBinder = IMediaSession.Stub.asInterface((IBinder) token.getToken()); - } - - @Override - public void registerCallback(Callback callback, Handler handler) { - if (callback == null) { - throw new IllegalArgumentException("callback may not be null."); - } - try { - mBinder.asBinder().linkToDeath(callback, 0); - mBinder.registerCallbackListener((IMediaControllerCallback) callback.mCallbackObj); - callback.setHandler(handler); - callback.mRegistered = true; - } catch (RemoteException e) { - Log.e(TAG, "Dead object in registerCallback. " + e); - callback.onSessionDestroyed(); - } - } - - @Override - public void unregisterCallback(Callback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback may not be null."); - } - try { - mBinder.unregisterCallbackListener( - (IMediaControllerCallback) callback.mCallbackObj); - mBinder.asBinder().unlinkToDeath(callback, 0); - callback.mRegistered = false; - } catch (RemoteException e) { - Log.e(TAG, "Dead object in unregisterCallback. " + e); - } - } - - @Override - public boolean dispatchMediaButtonEvent(KeyEvent event) { - if (event == null) { - throw new IllegalArgumentException("event may not be null."); - } - try { - mBinder.sendMediaButton(event); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in dispatchMediaButtonEvent. " + e); - } - return false; - } - - @Override - public TransportControls getTransportControls() { - if (mTransportControls == null) { - mTransportControls = new TransportControlsBase(mBinder); - } - - return mTransportControls; - } - - @Override - public PlaybackStateCompat getPlaybackState() { - try { - return mBinder.getPlaybackState(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getPlaybackState. " + e); - } - return null; - } - - @Override - public MediaMetadataCompat getMetadata() { - try { - return mBinder.getMetadata(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getMetadata. " + e); - } - return null; - } - - @Override - public List getQueue() { - try { - return mBinder.getQueue(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getQueue. " + e); - } - return null; - } - - @Override - public CharSequence getQueueTitle() { - try { - return mBinder.getQueueTitle(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getQueueTitle. " + e); - } - return null; - } - - @Override - public Bundle getExtras() { - try { - return mBinder.getExtras(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getExtras. " + e); - } - return null; - } - - @Override - public int getRatingType() { - try { - return mBinder.getRatingType(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getRatingType. " + e); - } - return 0; - } - - @Override - public long getFlags() { - try { - return mBinder.getFlags(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getFlags. " + e); - } - return 0; - } - - @Override - public PlaybackInfo getPlaybackInfo() { - try { - ParcelableVolumeInfo info = mBinder.getVolumeAttributes(); - PlaybackInfo pi = new PlaybackInfo(info.volumeType, info.audioStream, - info.controlType, info.maxVolume, info.currentVolume); - return pi; - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getPlaybackInfo. " + e); - } - return null; - } - - @Override - public PendingIntent getSessionActivity() { - try { - return mBinder.getLaunchPendingIntent(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getSessionActivity. " + e); - } - return null; - } - - @Override - public void setVolumeTo(int value, int flags) { - try { - mBinder.setVolumeTo(value, flags, null); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in setVolumeTo. " + e); - } - } - - @Override - public void adjustVolume(int direction, int flags) { - try { - mBinder.adjustVolume(direction, flags, null); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in adjustVolume. " + e); - } - } - - @Override - public void sendCommand(String command, Bundle params, ResultReceiver cb) { - try { - mBinder.sendCommand(command, params, - new MediaSessionCompat.ResultReceiverWrapper(cb)); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in sendCommand. " + e); - } - } - - @Override - public String getPackageName() { - try { - return mBinder.getPackageName(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getPackageName. " + e); - } - return null; - } - - @Override - public Object getMediaController() { - return null; - } - } - - static class TransportControlsBase extends TransportControls { - private IMediaSession mBinder; - - public TransportControlsBase(IMediaSession binder) { - mBinder = binder; - } - - @Override - public void play() { - try { - mBinder.play(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in play. " + e); - } - } - - @Override - public void playFromMediaId(String mediaId, Bundle extras) { - try { - mBinder.playFromMediaId(mediaId, extras); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in playFromMediaId. " + e); - } - } - - @Override - public void playFromSearch(String query, Bundle extras) { - try { - mBinder.playFromSearch(query, extras); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in playFromSearch. " + e); - } - } - - @Override - public void playFromUri(Uri uri, Bundle extras) { - try { - mBinder.playFromUri(uri, extras); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in playFromUri. " + e); - } - } - - @Override - public void skipToQueueItem(long id) { - try { - mBinder.skipToQueueItem(id); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in skipToQueueItem. " + e); - } - } - - @Override - public void pause() { - try { - mBinder.pause(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in pause. " + e); - } - } - - @Override - public void stop() { - try { - mBinder.stop(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in stop. " + e); - } - } - - @Override - public void seekTo(long pos) { - try { - mBinder.seekTo(pos); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in seekTo. " + e); - } - } - - @Override - public void fastForward() { - try { - mBinder.fastForward(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in fastForward. " + e); - } - } - - @Override - public void skipToNext() { - try { - mBinder.next(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in skipToNext. " + e); - } - } - - @Override - public void rewind() { - try { - mBinder.rewind(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in rewind. " + e); - } - } - - @Override - public void skipToPrevious() { - try { - mBinder.previous(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in skipToPrevious. " + e); - } - } - - @Override - public void setRating(RatingCompat rating) { - try { - mBinder.rate(rating); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in setRating. " + e); - } - } - - @Override - public void sendCustomAction(CustomAction customAction, Bundle args) { - sendCustomAction(customAction.getAction(), args); - } - - @Override - public void sendCustomAction(String action, Bundle args) { - try { - mBinder.sendCustomAction(action, args); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in sendCustomAction. " + e); - } - } - } - - static class MediaControllerImplApi21 implements MediaControllerImpl { - protected final Object mControllerObj; - - public MediaControllerImplApi21(Context context, MediaSessionCompat session) { - mControllerObj = MediaControllerCompatApi21.fromToken(context, - session.getSessionToken().getToken()); - } - - public MediaControllerImplApi21(Context context, MediaSessionCompat.Token sessionToken) - throws RemoteException { - mControllerObj = MediaControllerCompatApi21.fromToken(context, - sessionToken.getToken()); - if (mControllerObj == null) throw new RemoteException(); - } - - @Override - public void registerCallback(Callback callback, Handler handler) { - MediaControllerCompatApi21.registerCallback(mControllerObj, callback.mCallbackObj, handler); - } - - @Override - public void unregisterCallback(Callback callback) { - MediaControllerCompatApi21.unregisterCallback(mControllerObj, callback.mCallbackObj); - } - - @Override - public boolean dispatchMediaButtonEvent(KeyEvent event) { - return MediaControllerCompatApi21.dispatchMediaButtonEvent(mControllerObj, event); - } - - @Override - public TransportControls getTransportControls() { - Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj); - return controlsObj != null ? new TransportControlsApi21(controlsObj) : null; - } - - @Override - public PlaybackStateCompat getPlaybackState() { - Object stateObj = MediaControllerCompatApi21.getPlaybackState(mControllerObj); - return stateObj != null ? PlaybackStateCompat.fromPlaybackState(stateObj) : null; - } - - @Override - public MediaMetadataCompat getMetadata() { - Object metadataObj = MediaControllerCompatApi21.getMetadata(mControllerObj); - return metadataObj != null ? MediaMetadataCompat.fromMediaMetadata(metadataObj) : null; - } - - @Override - public List getQueue() { - List queueObjs = MediaControllerCompatApi21.getQueue(mControllerObj); - if (queueObjs == null) { - return null; - } - List queue = - new ArrayList(); - for (Object item : queueObjs) { - queue.add(MediaSessionCompat.QueueItem.obtain(item)); - } - return queue; - } - - @Override - public CharSequence getQueueTitle() { - return MediaControllerCompatApi21.getQueueTitle(mControllerObj); - } - - @Override - public Bundle getExtras() { - return MediaControllerCompatApi21.getExtras(mControllerObj); - } - - @Override - public int getRatingType() { - return MediaControllerCompatApi21.getRatingType(mControllerObj); - } - - @Override - public long getFlags() { - return MediaControllerCompatApi21.getFlags(mControllerObj); - } - - @Override - public PlaybackInfo getPlaybackInfo() { - Object volumeInfoObj = MediaControllerCompatApi21.getPlaybackInfo(mControllerObj); - return volumeInfoObj != null ? new PlaybackInfo( - MediaControllerCompatApi21.PlaybackInfo.getPlaybackType(volumeInfoObj), - MediaControllerCompatApi21.PlaybackInfo.getLegacyAudioStream(volumeInfoObj), - MediaControllerCompatApi21.PlaybackInfo.getVolumeControl(volumeInfoObj), - MediaControllerCompatApi21.PlaybackInfo.getMaxVolume(volumeInfoObj), - MediaControllerCompatApi21.PlaybackInfo.getCurrentVolume(volumeInfoObj)) : null; - } - - @Override - public PendingIntent getSessionActivity() { - return MediaControllerCompatApi21.getSessionActivity(mControllerObj); - } - - @Override - public void setVolumeTo(int value, int flags) { - MediaControllerCompatApi21.setVolumeTo(mControllerObj, value, flags); - } - - @Override - public void adjustVolume(int direction, int flags) { - MediaControllerCompatApi21.adjustVolume(mControllerObj, direction, flags); - } - - @Override - public void sendCommand(String command, Bundle params, ResultReceiver cb) { - MediaControllerCompatApi21.sendCommand(mControllerObj, command, params, cb); - } - - @Override - public String getPackageName() { - return MediaControllerCompatApi21.getPackageName(mControllerObj); - } - - @Override - public Object getMediaController() { - return mControllerObj; - } - } - - static class TransportControlsApi21 extends TransportControls { - protected final Object mControlsObj; - - public TransportControlsApi21(Object controlsObj) { - mControlsObj = controlsObj; - } - - @Override - public void play() { - MediaControllerCompatApi21.TransportControls.play(mControlsObj); - } - - @Override - public void pause() { - MediaControllerCompatApi21.TransportControls.pause(mControlsObj); - } - - @Override - public void stop() { - MediaControllerCompatApi21.TransportControls.stop(mControlsObj); - } - - @Override - public void seekTo(long pos) { - MediaControllerCompatApi21.TransportControls.seekTo(mControlsObj, pos); - } - - @Override - public void fastForward() { - MediaControllerCompatApi21.TransportControls.fastForward(mControlsObj); - } - - @Override - public void rewind() { - MediaControllerCompatApi21.TransportControls.rewind(mControlsObj); - } - - @Override - public void skipToNext() { - MediaControllerCompatApi21.TransportControls.skipToNext(mControlsObj); - } - - @Override - public void skipToPrevious() { - MediaControllerCompatApi21.TransportControls.skipToPrevious(mControlsObj); - } - - @Override - public void setRating(RatingCompat rating) { - MediaControllerCompatApi21.TransportControls.setRating(mControlsObj, - rating != null ? rating.getRating() : null); - } - - @Override - public void playFromMediaId(String mediaId, Bundle extras) { - MediaControllerCompatApi21.TransportControls.playFromMediaId(mControlsObj, mediaId, - extras); - } - - @Override - public void playFromSearch(String query, Bundle extras) { - MediaControllerCompatApi21.TransportControls.playFromSearch(mControlsObj, query, - extras); - } - - @Override - public void playFromUri(Uri uri, Bundle extras) { - if (uri == null || Uri.EMPTY.equals(uri)) { - throw new IllegalArgumentException( - "You must specify a non-empty Uri for playFromUri."); - } - Bundle bundle = new Bundle(); - bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_URI, uri); - bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras); - sendCustomAction(MediaSessionCompat.ACTION_PLAY_FROM_URI, bundle); - } - - @Override - public void skipToQueueItem(long id) { - MediaControllerCompatApi21.TransportControls.skipToQueueItem(mControlsObj, id); - } - - @Override - public void sendCustomAction(CustomAction customAction, Bundle args) { - MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj, - customAction.getAction(), args); - } - - @Override - public void sendCustomAction(String action, Bundle args) { - MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj, action, - args); - } - } - - static class MediaControllerImplApi23 extends MediaControllerImplApi21 { - - public MediaControllerImplApi23(Context context, MediaSessionCompat session) { - super(context, session); - } - - public MediaControllerImplApi23(Context context, MediaSessionCompat.Token sessionToken) - throws RemoteException { - super(context, sessionToken); - } - - @Override - public TransportControls getTransportControls() { - Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj); - return controlsObj != null ? new TransportControlsApi23(controlsObj) : null; - } - } - - static class TransportControlsApi23 extends TransportControlsApi21 { - - public TransportControlsApi23(Object controlsObj) { - super(controlsObj); - } - - @Override - public void playFromUri(Uri uri, Bundle extras) { - MediaControllerCompatApi23.TransportControls.playFromUri(mControlsObj, uri, - extras); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompatApi21.java deleted file mode 100644 index adf5fa4..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompatApi21.java +++ /dev/null @@ -1,281 +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 p.android.support.v4.media.session; - -import android.app.PendingIntent; -import android.content.Context; -import android.media.AudioAttributes; -import android.media.AudioManager; -import android.media.MediaMetadata; -import android.media.Rating; -import android.media.session.MediaController; -import android.media.session.MediaSession; -import android.media.session.PlaybackState; -import android.os.Bundle; -import android.os.Handler; -import android.os.ResultReceiver; -import android.view.KeyEvent; - -import java.util.ArrayList; -import java.util.List; - -class MediaControllerCompatApi21 { - public static Object fromToken(Context context, Object sessionToken) { - return new MediaController(context, (MediaSession.Token) sessionToken); - } - - public static Object createCallback(Callback callback) { - return new CallbackProxy(callback); - } - - public static void registerCallback(Object controllerObj, Object callbackObj, Handler handler) { - ((MediaController) controllerObj).registerCallback( - (MediaController.Callback)callbackObj, handler); - } - - public static void unregisterCallback(Object controllerObj, Object callbackObj) { - ((MediaController) controllerObj) - .unregisterCallback((MediaController.Callback) callbackObj); - } - - public static Object getTransportControls(Object controllerObj) { - return ((MediaController)controllerObj).getTransportControls(); - } - - public static Object getPlaybackState(Object controllerObj) { - return ((MediaController)controllerObj).getPlaybackState(); - } - - public static Object getMetadata(Object controllerObj) { - return ((MediaController)controllerObj).getMetadata(); - } - - public static List getQueue(Object controllerObj) { - List queue = ((MediaController) controllerObj).getQueue(); - if (queue == null) { - return null; - } - List queueObjs = new ArrayList(queue); - return queueObjs; - } - - public static CharSequence getQueueTitle(Object controllerObj) { - return ((MediaController) controllerObj).getQueueTitle(); - } - - public static Bundle getExtras(Object controllerObj) { - return ((MediaController) controllerObj).getExtras(); - } - - public static int getRatingType(Object controllerObj) { - return ((MediaController) controllerObj).getRatingType(); - } - - public static long getFlags(Object controllerObj) { - return ((MediaController) controllerObj).getFlags(); - } - - public static Object getPlaybackInfo(Object controllerObj) { - return ((MediaController) controllerObj).getPlaybackInfo(); - } - - public static PendingIntent getSessionActivity(Object controllerObj) { - return ((MediaController) controllerObj).getSessionActivity(); - } - - public static boolean dispatchMediaButtonEvent(Object controllerObj, KeyEvent event) { - return ((MediaController) controllerObj).dispatchMediaButtonEvent(event); - } - - public static void setVolumeTo(Object controllerObj, int value, int flags) { - ((MediaController) controllerObj).setVolumeTo(value, flags); - } - - public static void adjustVolume(Object controllerObj, int direction, int flags) { - ((MediaController) controllerObj).adjustVolume(direction, flags); - } - - public static void sendCommand(Object controllerObj, - String command, Bundle params, ResultReceiver cb) { - ((MediaController) controllerObj).sendCommand(command, params, cb); - } - - public static String getPackageName(Object controllerObj) { - return ((MediaController) controllerObj).getPackageName(); - } - - public static class TransportControls { - public static void play(Object controlsObj) { - ((MediaController.TransportControls)controlsObj).play(); - } - - public static void pause(Object controlsObj) { - ((MediaController.TransportControls)controlsObj).pause(); - } - - public static void stop(Object controlsObj) { - ((MediaController.TransportControls)controlsObj).stop(); - } - - public static void seekTo(Object controlsObj, long pos) { - ((MediaController.TransportControls)controlsObj).seekTo(pos); - } - - public static void fastForward(Object controlsObj) { - ((MediaController.TransportControls)controlsObj).fastForward(); - } - - public static void rewind(Object controlsObj) { - ((MediaController.TransportControls)controlsObj).rewind(); - } - - public static void skipToNext(Object controlsObj) { - ((MediaController.TransportControls)controlsObj).skipToNext(); - } - - public static void skipToPrevious(Object controlsObj) { - ((MediaController.TransportControls)controlsObj).skipToPrevious(); - } - - public static void setRating(Object controlsObj, Object ratingObj) { - ((MediaController.TransportControls)controlsObj).setRating((Rating)ratingObj); - } - - public static void playFromMediaId(Object controlsObj, String mediaId, Bundle extras) { - ((MediaController.TransportControls) controlsObj).playFromMediaId(mediaId, extras); - } - - public static void playFromSearch(Object controlsObj, String query, Bundle extras) { - ((MediaController.TransportControls) controlsObj).playFromSearch(query, extras); - } - - public static void skipToQueueItem(Object controlsObj, long id) { - ((MediaController.TransportControls) controlsObj).skipToQueueItem(id); - } - - public static void sendCustomAction(Object controlsObj, String action, Bundle args) { - ((MediaController.TransportControls) controlsObj).sendCustomAction(action, args); - } - } - - public static class PlaybackInfo { - public static int getPlaybackType(Object volumeInfoObj) { - return ((MediaController.PlaybackInfo)volumeInfoObj).getPlaybackType(); - } - - public static AudioAttributes getAudioAttributes(Object volumeInfoObj) { - return ((MediaController.PlaybackInfo) volumeInfoObj).getAudioAttributes(); - } - - public static int getLegacyAudioStream(Object volumeInfoObj) { - AudioAttributes attrs = getAudioAttributes(volumeInfoObj); - return toLegacyStreamType(attrs); - } - - public static int getVolumeControl(Object volumeInfoObj) { - return ((MediaController.PlaybackInfo)volumeInfoObj).getVolumeControl(); - } - - public static int getMaxVolume(Object volumeInfoObj) { - return ((MediaController.PlaybackInfo)volumeInfoObj).getMaxVolume(); - } - - public static int getCurrentVolume(Object volumeInfoObj) { - return ((MediaController.PlaybackInfo)volumeInfoObj).getCurrentVolume(); - } - - // This is copied from AudioAttributes.toLegacyStreamType. TODO This - // either needs to be kept in sync with that one or toLegacyStreamType - // needs to be made public so it can be used by the support lib. - private static final int FLAG_SCO = 0x1 << 2; - private static final int STREAM_BLUETOOTH_SCO = 6; - private static final int STREAM_SYSTEM_ENFORCED = 7; - private static int toLegacyStreamType(AudioAttributes aa) { - // flags to stream type mapping - if ((aa.getFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) - == AudioAttributes.FLAG_AUDIBILITY_ENFORCED) { - return STREAM_SYSTEM_ENFORCED; - } - if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) { - return STREAM_BLUETOOTH_SCO; - } - - // usage to stream type mapping - switch (aa.getUsage()) { - case AudioAttributes.USAGE_MEDIA: - case AudioAttributes.USAGE_GAME: - case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY: - case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: - return AudioManager.STREAM_MUSIC; - case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION: - return AudioManager.STREAM_SYSTEM; - case AudioAttributes.USAGE_VOICE_COMMUNICATION: - return AudioManager.STREAM_VOICE_CALL; - case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING: - return AudioManager.STREAM_DTMF; - case AudioAttributes.USAGE_ALARM: - return AudioManager.STREAM_ALARM; - case AudioAttributes.USAGE_NOTIFICATION_RINGTONE: - return AudioManager.STREAM_RING; - case AudioAttributes.USAGE_NOTIFICATION: - case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST: - case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT: - case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED: - case AudioAttributes.USAGE_NOTIFICATION_EVENT: - return AudioManager.STREAM_NOTIFICATION; - case AudioAttributes.USAGE_UNKNOWN: - default: - return AudioManager.STREAM_MUSIC; - } - } - } - - public static interface Callback { - public void onSessionDestroyed(); - public void onSessionEvent(String event, Bundle extras); - public void onPlaybackStateChanged(Object stateObj); - public void onMetadataChanged(Object metadataObj); - } - - static class CallbackProxy extends MediaController.Callback { - protected final T mCallback; - - public CallbackProxy(T callback) { - mCallback = callback; - } - - @Override - public void onSessionDestroyed() { - mCallback.onSessionDestroyed(); - } - - @Override - public void onSessionEvent(String event, Bundle extras) { - mCallback.onSessionEvent(event, extras); - } - - @Override - public void onPlaybackStateChanged(PlaybackState state) { - mCallback.onPlaybackStateChanged(state); - } - - @Override - public void onMetadataChanged(MediaMetadata metadata) { - mCallback.onMetadataChanged(metadata); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompatApi23.java deleted file mode 100644 index f2bf6d3..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaControllerCompatApi23.java +++ /dev/null @@ -1,30 +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 p.android.support.v4.media.session; - -import android.media.session.MediaController; -import android.net.Uri; -import android.os.Bundle; - -class MediaControllerCompatApi23 { - - public static class TransportControls extends MediaControllerCompatApi21.TransportControls { - public static void playFromUri(Object controlsObj, Uri uri, Bundle extras) { - ((MediaController.TransportControls) controlsObj).playFromUri(uri, extras); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompat.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompat.aidl deleted file mode 100644 index 328c7aa..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompat.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright 2014, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.plug.v4.media.session; - -parcelable MediaSessionCompat.Token; -parcelable MediaSessionCompat.QueueItem; -parcelable MediaSessionCompat.ResultReceiverWrapper; diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompat.java deleted file mode 100644 index 6ea96e9..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompat.java +++ /dev/null @@ -1,2114 +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 p.android.support.v4.media.session; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.Bitmap; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.os.SystemClock; -import p.android.support.v4.media.RatingCompat; -import p.android.support.annotation.IntDef; -import p.android.support.v4.media.MediaDescriptionCompat; -import p.android.support.v4.media.MediaMetadataCompat; -import p.android.support.v4.media.VolumeProviderCompat; -import android.text.TextUtils; -import android.util.Log; -import android.view.KeyEvent; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; - -/** - * Allows interaction with media controllers, volume keys, media buttons, and - * transport controls. - *

- * A MediaSession should be created when an app wants to publish media playback - * information or handle media keys. In general an app only needs one session - * for all playback, though multiple sessions can be created to provide finer - * grain controls of media. - *

- * Once a session is created the owner of the session may pass its - * {@link #getSessionToken() session token} to other processes to allow them to - * create a {@link MediaControllerCompat} to interact with the session. - *

- * To receive commands, media keys, and other events a {@link Callback} must be - * set with {@link #setCallback(Callback)}. - *

- * When an app is finished performing playback it must call {@link #release()} - * to clean up the session and notify any controllers. - *

- * MediaSessionCompat objects are not thread safe and all calls should be made - * from the same thread. - *

- * This is a helper for accessing features in - * {@link android.media.session.MediaSession} introduced after API level 4 in a - * backwards compatible fashion. - */ -public class MediaSessionCompat { - private static final String TAG = "MediaSessionCompat"; - - private final MediaSessionImpl mImpl; - private final MediaControllerCompat mController; - private final ArrayList - mActiveListeners = new ArrayList(); - - /** - * @hide - */ - @IntDef(flag=true, value={FLAG_HANDLES_MEDIA_BUTTONS, FLAG_HANDLES_TRANSPORT_CONTROLS}) - @Retention(RetentionPolicy.SOURCE) - public @interface SessionFlags {} - - /** - * Set this flag on the session to indicate that it can handle media button - * events. - */ - public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1 << 0; - - /** - * Set this flag on the session to indicate that it handles transport - * control commands through its {@link Callback}. - */ - public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1; - - /** - * Custom action to invoke playFromUri() for the forward compatibility. - * - * @hide - */ - public static final String ACTION_PLAY_FROM_URI = - "android.support.v4.media.session.action.PLAY_FROM_URI"; - - /** - * Argument for use with {@link #ACTION_PLAY_FROM_URI} indicating URI to play. - * - * @hide - */ - public static final String ACTION_ARGUMENT_URI = - "android.support.v4.media.session.action.ARGUMENT_URI"; - - /** - * Argument for use with {@link #ACTION_PLAY_FROM_URI} indicating extra bundle. - * - * @hide - */ - public static final String ACTION_ARGUMENT_EXTRAS = - "android.support.v4.media.session.action.ARGUMENT_EXTRAS"; - - /** - * Creates a new session using a media button receiver from your manifest. - * Note that a media button receiver is required to support platform versions - * earlier than {@link android.os.Build.VERSION_CODES#LOLLIPOP}. - * - * @param context The context. - * @param tag A short name for debugging purposes. - */ - public MediaSessionCompat(Context context, String tag) { - this(context, tag, null, null); - } - - /** - * Creates a new session. - * - * @param context The context. - * @param tag A short name for debugging purposes. - * @param mediaButtonEventReceiver The component name for your receiver. - * If null, this will attempt to find an appropriate - * {@link BroadcastReceiver} that handles - * {@link Intent#ACTION_MEDIA_BUTTON} from your manifest. - * A receiver is required to support platform versions earlier - * than {@link android.os.Build.VERSION_CODES#LOLLIPOP}. - * @param mbrIntent The PendingIntent for your receiver component that - * handles media button events. This is optional and will be used - * on {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} and - * later instead of the component name. - */ - public MediaSessionCompat(Context context, String tag, ComponentName mediaButtonEventReceiver, - PendingIntent mbrIntent) { - if (context == null) { - throw new IllegalArgumentException("context must not be null"); - } - if (TextUtils.isEmpty(tag)) { - throw new IllegalArgumentException("tag must not be null or empty"); - } - - if (mediaButtonEventReceiver == null) { - Intent queryIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); - queryIntent.setPackage(context.getPackageName()); - PackageManager pm = context.getPackageManager(); - List resolveInfos = pm.queryBroadcastReceivers(queryIntent, 0); - // If none are found, assume we are running on a newer platform version that does - // not require a media button receiver ComponentName. Later code will double check - // this assumption and throw an error if needed - if (resolveInfos.size() == 1) { - ResolveInfo resolveInfo = resolveInfos.get(0); - mediaButtonEventReceiver = new ComponentName(resolveInfo.activityInfo.packageName, - resolveInfo.activityInfo.name); - } else if (resolveInfos.size() > 1) { - Log.w(TAG, "More than one BroadcastReceiver that handles " + - Intent.ACTION_MEDIA_BUTTON + " was found, using null. Provide a " + - "specific ComponentName to use as this session's media button receiver"); - } - } - if (mediaButtonEventReceiver != null && mbrIntent == null) { - // construct a PendingIntent for the media button - Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); - // the associated intent will be handled by the component being registered - mediaButtonIntent.setComponent(mediaButtonEventReceiver); - mbrIntent = PendingIntent.getBroadcast(context, - 0/* requestCode, ignored */, mediaButtonIntent, 0/* flags */); - } - if (android.os.Build.VERSION.SDK_INT >= 21) { - mImpl = new MediaSessionImplApi21(context, tag); - mImpl.setMediaButtonReceiver(mbrIntent); - } else { - mImpl = new MediaSessionImplBase(context, tag, mediaButtonEventReceiver, mbrIntent); - } - mController = new MediaControllerCompat(context, this); - } - - private MediaSessionCompat(Context context, MediaSessionImpl impl) { - mImpl = impl; - mController = new MediaControllerCompat(context, this); - } - - /** - * Add a callback to receive updates on for the MediaSession. This includes - * media button and volume events. The caller's thread will be used to post - * events. - * - * @param callback The callback object - */ - public void setCallback(Callback callback) { - setCallback(callback, null); - } - - /** - * Set the callback to receive updates for the MediaSession. This includes - * media button and volume events. Set the callback to null to stop - * receiving events. - * - * @param callback The callback to receive updates on. - * @param handler The handler that events should be posted on. - */ - public void setCallback(Callback callback, Handler handler) { - mImpl.setCallback(callback, handler != null ? handler : new Handler()); - } - - /** - * Set an intent for launching UI for this Session. This can be used as a - * quick link to an ongoing media screen. The intent should be for an - * activity that may be started using - * {@link Activity#startActivity(Intent)}. - * - * @param pi The intent to launch to show UI for this Session. - */ - public void setSessionActivity(PendingIntent pi) { - mImpl.setSessionActivity(pi); - } - - /** - * Set a pending intent for your media button receiver to allow restarting - * playback after the session has been stopped. If your app is started in - * this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be sent via - * the pending intent. - *

- * This method will only work on - * {@link android.os.Build.VERSION_CODES#LOLLIPOP} and later. Earlier - * platform versions must include the media button receiver in the - * constructor. - * - * @param mbr The {@link PendingIntent} to send the media button event to. - */ - public void setMediaButtonReceiver(PendingIntent mbr) { - mImpl.setMediaButtonReceiver(mbr); - } - - /** - * Set any flags for the session. - * - * @param flags The flags to set for this session. - */ - public void setFlags(@SessionFlags int flags) { - mImpl.setFlags(flags); - } - - /** - * Set the stream this session is playing on. This will affect the system's - * volume handling for this session. If {@link #setPlaybackToRemote} was - * previously called it will stop receiving volume commands and the system - * will begin sending volume changes to the appropriate stream. - *

- * By default sessions are on {@link AudioManager#STREAM_MUSIC}. - * - * @param stream The {@link AudioManager} stream this session is playing on. - */ - public void setPlaybackToLocal(int stream) { - mImpl.setPlaybackToLocal(stream); - } - - /** - * Configure this session to use remote volume handling. This must be called - * to receive volume button events, otherwise the system will adjust the - * current stream volume for this session. If {@link #setPlaybackToLocal} - * was previously called that stream will stop receiving volume changes for - * this session. - *

- * On platforms earlier than {@link android.os.Build.VERSION_CODES#LOLLIPOP} - * this will only allow an app to handle volume commands sent directly to - * the session by a {@link MediaControllerCompat}. System routing of volume - * keys will not use the volume provider. - * - * @param volumeProvider The provider that will handle volume changes. May - * not be null. - */ - public void setPlaybackToRemote(VolumeProviderCompat volumeProvider) { - if (volumeProvider == null) { - throw new IllegalArgumentException("volumeProvider may not be null!"); - } - mImpl.setPlaybackToRemote(volumeProvider); - } - - /** - * Set if this session is currently active and ready to receive commands. If - * set to false your session's controller may not be discoverable. You must - * set the session to active before it can start receiving media button - * events or transport commands. - *

- * On platforms earlier than - * {@link android.os.Build.VERSION_CODES#LOLLIPOP}, - * a media button event receiver should be set via the constructor to - * receive media button events. - * - * @param active Whether this session is active or not. - */ - public void setActive(boolean active) { - mImpl.setActive(active); - for (OnActiveChangeListener listener : mActiveListeners) { - listener.onActiveChanged(); - } - } - - /** - * Get the current active state of this session. - * - * @return True if the session is active, false otherwise. - */ - public boolean isActive() { - return mImpl.isActive(); - } - - /** - * Send a proprietary event to all MediaControllers listening to this - * Session. It's up to the Controller/Session owner to determine the meaning - * of any events. - * - * @param event The name of the event to send - * @param extras Any extras included with the event - */ - public void sendSessionEvent(String event, Bundle extras) { - if (TextUtils.isEmpty(event)) { - throw new IllegalArgumentException("event cannot be null or empty"); - } - mImpl.sendSessionEvent(event, extras); - } - - /** - * This must be called when an app has finished performing playback. If - * playback is expected to start again shortly the session can be left open, - * but it must be released if your activity or service is being destroyed. - */ - public void release() { - mImpl.release(); - } - - /** - * Retrieve a token object that can be used by apps to create a - * {@link MediaControllerCompat} for interacting with this session. The - * owner of the session is responsible for deciding how to distribute these - * tokens. - *

- * On platform versions before - * {@link android.os.Build.VERSION_CODES#LOLLIPOP} this token may only be - * used within your app as there is no way to guarantee other apps are using - * the same version of the support library. - * - * @return A token that can be used to create a media controller for this - * session. - */ - public Token getSessionToken() { - return mImpl.getSessionToken(); - } - - /** - * Get a controller for this session. This is a convenience method to avoid - * having to cache your own controller in process. - * - * @return A controller for this session. - */ - public MediaControllerCompat getController() { - return mController; - } - - /** - * Update the current playback state. - * - * @param state The current state of playback - */ - public void setPlaybackState(PlaybackStateCompat state) { - mImpl.setPlaybackState(state); - } - - /** - * Update the current metadata. New metadata can be created using - * {@link android.media.MediaMetadata.Builder}. - * - * @param metadata The new metadata - */ - public void setMetadata(MediaMetadataCompat metadata) { - mImpl.setMetadata(metadata); - } - - /** - * Update the list of items in the play queue. It is an ordered list and - * should contain the current item, and previous or upcoming items if they - * exist. Specify null if there is no current play queue. - *

- * The queue should be of reasonable size. If the play queue is unbounded - * within your app, it is better to send a reasonable amount in a sliding - * window instead. - * - * @param queue A list of items in the play queue. - */ - public void setQueue(List queue) { - mImpl.setQueue(queue); - } - - /** - * Set the title of the play queue. The UI should display this title along - * with the play queue itself. e.g. "Play Queue", "Now Playing", or an album - * name. - * - * @param title The title of the play queue. - */ - public void setQueueTitle(CharSequence title) { - mImpl.setQueueTitle(title); - } - - /** - * Set the style of rating used by this session. Apps trying to set the - * rating should use this style. Must be one of the following: - *

    - *
  • {@link RatingCompat#RATING_NONE}
  • - *
  • {@link RatingCompat#RATING_3_STARS}
  • - *
  • {@link RatingCompat#RATING_4_STARS}
  • - *
  • {@link RatingCompat#RATING_5_STARS}
  • - *
  • {@link RatingCompat#RATING_HEART}
  • - *
  • {@link RatingCompat#RATING_PERCENTAGE}
  • - *
  • {@link RatingCompat#RATING_THUMB_UP_DOWN}
  • - *
- */ - public void setRatingType(@RatingCompat.Style int type) { - mImpl.setRatingType(type); - } - - /** - * Set some extras that can be associated with the - * {@link MediaSessionCompat}. No assumptions should be made as to how a - * {@link MediaControllerCompat} will handle these extras. Keys should be - * fully qualified (e.g. com.example.MY_EXTRA) to avoid conflicts. - * - * @param extras The extras associated with the session. - */ - public void setExtras(Bundle extras) { - mImpl.setExtras(extras); - } - - /** - * Gets the underlying framework {@link android.media.session.MediaSession} - * object. - *

- * This method is only supported on API 21+. - *

- * - * @return The underlying {@link android.media.session.MediaSession} object, - * or null if none. - */ - public Object getMediaSession() { - return mImpl.getMediaSession(); - } - - /** - * Gets the underlying framework {@link android.media.RemoteControlClient} - * object. - *

- * This method is only supported on APIs 14-20. On API 21+ - * {@link #getMediaSession()} should be used instead. - * - * @return The underlying {@link android.media.RemoteControlClient} object, - * or null if none. - */ - public Object getRemoteControlClient() { - return mImpl.getRemoteControlClient(); - } - - /** - * Adds a listener to be notified when the active status of this session - * changes. This is primarily used by the support library and should not be - * needed by apps. - * - * @param listener The listener to add. - */ - public void addOnActiveChangeListener(OnActiveChangeListener listener) { - if (listener == null) { - throw new IllegalArgumentException("Listener may not be null"); - } - mActiveListeners.add(listener); - } - - /** - * Stops the listener from being notified when the active status of this - * session changes. - * - * @param listener The listener to remove. - */ - public void removeOnActiveChangeListener(OnActiveChangeListener listener) { - if (listener == null) { - throw new IllegalArgumentException("Listener may not be null"); - } - mActiveListeners.remove(listener); - } - - /** - * Obtain a compat wrapper for an existing MediaSession. - * - * @param mediaSession The {@link android.media.session.MediaSession} to - * wrap. - * @return A compat wrapper for the provided session. - */ - public static MediaSessionCompat obtain(Context context, Object mediaSession) { - return new MediaSessionCompat(context, new MediaSessionImplApi21(mediaSession)); - } - - /** - * Receives transport controls, media buttons, and commands from controllers - * and the system. The callback may be set using {@link #setCallback}. - */ - public abstract static class Callback { - final Object mCallbackObj; - - public Callback() { - if (android.os.Build.VERSION.SDK_INT >= 23) { - mCallbackObj = MediaSessionCompatApi23.createCallback(new StubApi23()); - } else if (android.os.Build.VERSION.SDK_INT >= 21) { - mCallbackObj = MediaSessionCompatApi21.createCallback(new StubApi21()); - } else { - mCallbackObj = null; - } - } - - /** - * Called when a controller has sent a custom command to this session. - * The owner of the session may handle custom commands but is not - * required to. - * - * @param command The command name. - * @param extras Optional parameters for the command, may be null. - * @param cb A result receiver to which a result may be sent by the command, may be null. - */ - public void onCommand(String command, Bundle extras, ResultReceiver cb) { - } - - /** - * Override to handle media button events. - * - * @param mediaButtonEvent The media button event intent. - * @return True if the event was handled, false otherwise. - */ - public boolean onMediaButtonEvent(Intent mediaButtonEvent) { - return false; - } - - /** - * Override to handle requests to begin playback. - */ - public void onPlay() { - } - - /** - * Override to handle requests to play a specific mediaId that was - * provided by your app. - */ - public void onPlayFromMediaId(String mediaId, Bundle extras) { - } - - /** - * Override to handle requests to begin playback from a search query. An - * empty query indicates that the app may play any music. The - * implementation should attempt to make a smart choice about what to - * play. - */ - public void onPlayFromSearch(String query, Bundle extras) { - } - - /** - * Override to handle requests to play a specific media item represented by a URI. - */ - public void onPlayFromUri(Uri uri, Bundle extras) { - } - - /** - * Override to handle requests to play an item with a given id from the - * play queue. - */ - public void onSkipToQueueItem(long id) { - } - - /** - * Override to handle requests to pause playback. - */ - public void onPause() { - } - - /** - * Override to handle requests to skip to the next media item. - */ - public void onSkipToNext() { - } - - /** - * Override to handle requests to skip to the previous media item. - */ - public void onSkipToPrevious() { - } - - /** - * Override to handle requests to fast forward. - */ - public void onFastForward() { - } - - /** - * Override to handle requests to rewind. - */ - public void onRewind() { - } - - /** - * Override to handle requests to stop playback. - */ - public void onStop() { - } - - /** - * Override to handle requests to seek to a specific position in ms. - * - * @param pos New position to move to, in milliseconds. - */ - public void onSeekTo(long pos) { - } - - /** - * Override to handle the item being rated. - * - * @param rating - */ - public void onSetRating(RatingCompat rating) { - } - - /** - * Called when a {@link MediaControllerCompat} wants a - * {@link PlaybackStateCompat.CustomAction} to be performed. - * - * @param action The action that was originally sent in the - * {@link PlaybackStateCompat.CustomAction}. - * @param extras Optional extras specified by the - * {@link MediaControllerCompat}. - */ - public void onCustomAction(String action, Bundle extras) { - } - - private class StubApi21 implements MediaSessionCompatApi21.Callback { - - @Override - public void onCommand(String command, Bundle extras, ResultReceiver cb) { - Callback.this.onCommand(command, extras, cb); - } - - @Override - public boolean onMediaButtonEvent(Intent mediaButtonIntent) { - return Callback.this.onMediaButtonEvent(mediaButtonIntent); - } - - @Override - public void onPlay() { - Callback.this.onPlay(); - } - - @Override - public void onPlayFromMediaId(String mediaId, Bundle extras) { - Callback.this.onPlayFromMediaId(mediaId, extras); - } - - @Override - public void onPlayFromSearch(String search, Bundle extras) { - Callback.this.onPlayFromSearch(search, extras); - } - - @Override - public void onSkipToQueueItem(long id) { - Callback.this.onSkipToQueueItem(id); - } - - @Override - public void onPause() { - Callback.this.onPause(); - } - - @Override - public void onSkipToNext() { - Callback.this.onSkipToNext(); - } - - @Override - public void onSkipToPrevious() { - Callback.this.onSkipToPrevious(); - } - - @Override - public void onFastForward() { - Callback.this.onFastForward(); - } - - @Override - public void onRewind() { - Callback.this.onRewind(); - } - - @Override - public void onStop() { - Callback.this.onStop(); - } - - @Override - public void onSeekTo(long pos) { - Callback.this.onSeekTo(pos); - } - - @Override - public void onSetRating(Object ratingObj) { - Callback.this.onSetRating(RatingCompat.fromRating(ratingObj)); - } - - @Override - public void onCustomAction(String action, Bundle extras) { - if (action.equals(ACTION_PLAY_FROM_URI)) { - Uri uri = (Uri) extras.getParcelable(ACTION_ARGUMENT_URI); - Bundle bundle = (Bundle) extras.getParcelable(ACTION_ARGUMENT_EXTRAS); - Callback.this.onPlayFromUri(uri, bundle); - } else { - Callback.this.onCustomAction(action, extras); - } - } - } - - private class StubApi23 extends StubApi21 implements MediaSessionCompatApi23.Callback { - - @Override - public void onPlayFromUri(Uri uri, Bundle extras) { - Callback.this.onPlayFromUri(uri, extras); - } - } - } - - /** - * Represents an ongoing session. This may be passed to apps by the session - * owner to allow them to create a {@link MediaControllerCompat} to communicate with - * the session. - */ - public static final class Token implements Parcelable { - private final Object mInner; - - Token(Object inner) { - mInner = inner; - } - - /** - * Creates a compat Token from a framework - * {@link android.media.session.MediaSession.Token} object. - *

- * This method is only supported on - * {@link android.os.Build.VERSION_CODES#LOLLIPOP} and later. - *

- * - * @param token The framework token object. - * @return A compat Token for use with {@link MediaControllerCompat}. - */ - public static Token fromToken(Object token) { - if (token == null || android.os.Build.VERSION.SDK_INT < 21) { - return null; - } - return new Token(MediaSessionCompatApi21.verifyToken(token)); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - if (android.os.Build.VERSION.SDK_INT >= 21) { - dest.writeParcelable((Parcelable) mInner, flags); - } else { - dest.writeStrongBinder((IBinder) mInner); - } - } - - /** - * Gets the underlying framework {@link android.media.session.MediaSession.Token} object. - *

- * This method is only supported on API 21+. - *

- * - * @return The underlying {@link android.media.session.MediaSession.Token} object, - * or null if none. - */ - public Object getToken() { - return mInner; - } - - public static final Creator CREATOR - = new Creator() { - @Override - public Token createFromParcel(Parcel in) { - Object inner; - if (android.os.Build.VERSION.SDK_INT >= 21) { - inner = in.readParcelable(null); - } else { - inner = in.readStrongBinder(); - } - return new Token(inner); - } - - @Override - public Token[] newArray(int size) { - return new Token[size]; - } - }; - } - - /** - * A single item that is part of the play queue. It contains a description - * of the item and its id in the queue. - */ - public static final class QueueItem implements Parcelable { - /** - * This id is reserved. No items can be explicitly asigned this id. - */ - public static final int UNKNOWN_ID = -1; - - private final MediaDescriptionCompat mDescription; - private final long mId; - - private Object mItem; - - /** - * Create a new {@link QueueItem}. - * - * @param description The {@link MediaDescriptionCompat} for this item. - * @param id An identifier for this item. It must be unique within the - * play queue and cannot be {@link #UNKNOWN_ID}. - */ - public QueueItem(MediaDescriptionCompat description, long id) { - this(null, description, id); - } - - private QueueItem(Object queueItem, MediaDescriptionCompat description, long id) { - if (description == null) { - throw new IllegalArgumentException("Description cannot be null."); - } - if (id == UNKNOWN_ID) { - throw new IllegalArgumentException("Id cannot be QueueItem.UNKNOWN_ID"); - } - mDescription = description; - mId = id; - mItem = queueItem; - } - - private QueueItem(Parcel in) { - mDescription = MediaDescriptionCompat.CREATOR.createFromParcel(in); - mId = in.readLong(); - } - - /** - * Get the description for this item. - */ - public MediaDescriptionCompat getDescription() { - return mDescription; - } - - /** - * Get the queue id for this item. - */ - public long getQueueId() { - return mId; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - mDescription.writeToParcel(dest, flags); - dest.writeLong(mId); - } - - @Override - public int describeContents() { - return 0; - } - - /** - * Get the underlying - * {@link android.media.session.MediaSession.QueueItem}. - *

- * On builds before {@link android.os.Build.VERSION_CODES#LOLLIPOP} null - * is returned. - * - * @return The underlying - * {@link android.media.session.MediaSession.QueueItem} or null. - */ - public Object getQueueItem() { - if (mItem != null || android.os.Build.VERSION.SDK_INT < 21) { - return mItem; - } - mItem = MediaSessionCompatApi21.QueueItem.createItem(mDescription.getMediaDescription(), - mId); - return mItem; - } - - /** - * Obtain a compat wrapper for an existing QueueItem. - * - * @param queueItem The {@link android.media.session.MediaSession.QueueItem} to - * wrap. - * @return A compat wrapper for the provided item. - */ - public static QueueItem obtain(Object queueItem) { - Object descriptionObj = MediaSessionCompatApi21.QueueItem.getDescription(queueItem); - MediaDescriptionCompat description = MediaDescriptionCompat.fromMediaDescription( - descriptionObj); - long id = MediaSessionCompatApi21.QueueItem.getQueueId(queueItem); - return new QueueItem(queueItem, description, id); - } - - public static final Creator - CREATOR = new Creator() { - - @Override - public QueueItem createFromParcel(Parcel p) { - return new QueueItem(p); - } - - @Override - public QueueItem[] newArray(int size) { - return new QueueItem[size]; - } - }; - - @Override - public String toString() { - return "MediaSession.QueueItem {" + - "Description=" + mDescription + - ", Id=" + mId + " }"; - } - } - - /** - * This is a wrapper for {@link ResultReceiver} for sending over aidl - * interfaces. The framework version was not exposed to aidls until - * {@link android.os.Build.VERSION_CODES#LOLLIPOP}. - */ - static final class ResultReceiverWrapper implements Parcelable { - private ResultReceiver mResultReceiver; - - public ResultReceiverWrapper(ResultReceiver resultReceiver) { - mResultReceiver = resultReceiver; - } - - ResultReceiverWrapper(Parcel in) { - mResultReceiver = ResultReceiver.CREATOR.createFromParcel(in); - } - - public static final Creator - CREATOR = new Creator() { - @Override - public ResultReceiverWrapper createFromParcel(Parcel p) { - return new ResultReceiverWrapper(p); - } - - @Override - public ResultReceiverWrapper[] newArray(int size) { - return new ResultReceiverWrapper[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - mResultReceiver.writeToParcel(dest, flags); - } - } - - public interface OnActiveChangeListener { - void onActiveChanged(); - } - - interface MediaSessionImpl { - void setCallback(Callback callback, Handler handler); - void setFlags(@SessionFlags int flags); - void setPlaybackToLocal(int stream); - void setPlaybackToRemote(VolumeProviderCompat volumeProvider); - void setActive(boolean active); - boolean isActive(); - void sendSessionEvent(String event, Bundle extras); - void release(); - Token getSessionToken(); - void setPlaybackState(PlaybackStateCompat state); - void setMetadata(MediaMetadataCompat metadata); - - void setSessionActivity(PendingIntent pi); - - void setMediaButtonReceiver(PendingIntent mbr); - void setQueue(List queue); - void setQueueTitle(CharSequence title); - - void setRatingType(@RatingCompat.Style int type); - void setExtras(Bundle extras); - - Object getMediaSession(); - - Object getRemoteControlClient(); - } - - static class MediaSessionImplBase implements MediaSessionImpl { - private final Context mContext; - private final ComponentName mComponentName; - private final PendingIntent mMediaButtonEventReceiver; - private final Object mRccObj; - private final MediaSessionStub mStub; - private final Token mToken; - private final String mPackageName; - private final String mTag; - private final AudioManager mAudioManager; - - private final Object mLock = new Object(); - private final RemoteCallbackList mControllerCallbacks - = new RemoteCallbackList(); - - private MessageHandler mHandler; - private boolean mDestroyed = false; - private boolean mIsActive = false; - private boolean mIsRccRegistered = false; - private boolean mIsMbrRegistered = false; - private volatile Callback mCallback; - - private @SessionFlags int mFlags; - - private MediaMetadataCompat mMetadata; - private PlaybackStateCompat mState; - private PendingIntent mSessionActivity; - private List mQueue; - private CharSequence mQueueTitle; - private @RatingCompat.Style int mRatingType; - private Bundle mExtras; - - private int mVolumeType; - private int mLocalStream; - private VolumeProviderCompat mVolumeProvider; - - private VolumeProviderCompat.Callback mVolumeCallback - = new VolumeProviderCompat.Callback() { - @Override - public void onVolumeChanged(VolumeProviderCompat volumeProvider) { - if (mVolumeProvider != volumeProvider) { - return; - } - ParcelableVolumeInfo info = new ParcelableVolumeInfo(mVolumeType, mLocalStream, - volumeProvider.getVolumeControl(), volumeProvider.getMaxVolume(), - volumeProvider.getCurrentVolume()); - sendVolumeInfoChanged(info); - } - }; - - public MediaSessionImplBase(Context context, String tag, ComponentName mbrComponent, - PendingIntent mbr) { - if (mbrComponent == null) { - throw new IllegalArgumentException( - "MediaButtonReceiver component may not be null."); - } - mContext = context; - mPackageName = context.getPackageName(); - mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - mTag = tag; - mComponentName = mbrComponent; - mMediaButtonEventReceiver = mbr; - mStub = new MediaSessionStub(); - mToken = new Token(mStub); - - mRatingType = RatingCompat.RATING_NONE; - mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL; - mLocalStream = AudioManager.STREAM_MUSIC; - if (android.os.Build.VERSION.SDK_INT >= 14) { - mRccObj = MediaSessionCompatApi14.createRemoteControlClient(mbr); - } else { - mRccObj = null; - } - } - - @Override - public void setCallback(Callback callback, Handler handler) { - mCallback = callback; - if (callback == null) { - // There's nothing to unregister on API < 18 since media buttons - // all go through the media button receiver - if (android.os.Build.VERSION.SDK_INT >= 18) { - MediaSessionCompatApi18.setOnPlaybackPositionUpdateListener(mRccObj, null); - } - if (android.os.Build.VERSION.SDK_INT >= 19) { - MediaSessionCompatApi19.setOnMetadataUpdateListener(mRccObj, null); - } - } else { - if (handler == null) { - handler = new Handler(); - } - synchronized (mLock) { - mHandler = new MessageHandler(handler.getLooper()); - } - MediaSessionCompatApi19.Callback cb19 = new MediaSessionCompatApi19.Callback() { - @Override - public void onSetRating(Object ratingObj) { - postToHandler(MessageHandler.MSG_RATE, - RatingCompat.fromRating(ratingObj)); - } - - @Override - public void onSeekTo(long pos) { - postToHandler(MessageHandler.MSG_SEEK_TO, pos); - } - }; - if (android.os.Build.VERSION.SDK_INT >= 18) { - Object onPositionUpdateObj = MediaSessionCompatApi18 - .createPlaybackPositionUpdateListener(cb19); - MediaSessionCompatApi18.setOnPlaybackPositionUpdateListener(mRccObj, - onPositionUpdateObj); - } - if (android.os.Build.VERSION.SDK_INT >= 19) { - Object onMetadataUpdateObj = MediaSessionCompatApi19 - .createMetadataUpdateListener(cb19); - MediaSessionCompatApi19.setOnMetadataUpdateListener(mRccObj, - onMetadataUpdateObj); - } - } - } - - private void postToHandler(int what) { - postToHandler(what, null); - } - - private void postToHandler(int what, Object obj) { - postToHandler(what, obj, null); - } - - private void postToHandler(int what, Object obj, Bundle extras) { - synchronized (mLock) { - if (mHandler != null) { - mHandler.post(what, obj, extras); - } - } - } - - @Override - public void setFlags(@SessionFlags int flags) { - synchronized (mLock) { - mFlags = flags; - } - update(); - } - - @Override - public void setPlaybackToLocal(int stream) { - if (mVolumeProvider != null) { - mVolumeProvider.setCallback(null); - } - mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL; - ParcelableVolumeInfo info = new ParcelableVolumeInfo(mVolumeType, mLocalStream, - VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, - mAudioManager.getStreamMaxVolume(mLocalStream), - mAudioManager.getStreamVolume(mLocalStream)); - sendVolumeInfoChanged(info); - } - - @Override - public void setPlaybackToRemote(VolumeProviderCompat volumeProvider) { - if (volumeProvider == null) { - throw new IllegalArgumentException("volumeProvider may not be null"); - } - if (mVolumeProvider != null) { - mVolumeProvider.setCallback(null); - } - mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE; - mVolumeProvider = volumeProvider; - ParcelableVolumeInfo info = new ParcelableVolumeInfo(mVolumeType, mLocalStream, - mVolumeProvider.getVolumeControl(), mVolumeProvider.getMaxVolume(), - mVolumeProvider.getCurrentVolume()); - sendVolumeInfoChanged(info); - - volumeProvider.setCallback(mVolumeCallback); - } - - @Override - public void setActive(boolean active) { - if (active == mIsActive) { - return; - } - mIsActive = active; - if (update()) { - setMetadata(mMetadata); - setPlaybackState(mState); - } - } - - @Override - public boolean isActive() { - return mIsActive; - } - - @Override - public void sendSessionEvent(String event, Bundle extras) { - sendEvent(event, extras); - } - - @Override - public void release() { - mIsActive = false; - mDestroyed = true; - update(); - sendSessionDestroyed(); - } - - @Override - public Token getSessionToken() { - return mToken; - } - - @Override - public void setPlaybackState(PlaybackStateCompat state) { - synchronized (mLock) { - mState = state; - } - sendState(state); - if (!mIsActive) { - // Don't set the state until after the RCC is registered - return; - } - if (state == null) { - if (android.os.Build.VERSION.SDK_INT >= 14) { - MediaSessionCompatApi14.setState(mRccObj, PlaybackStateCompat.STATE_NONE); - MediaSessionCompatApi14.setTransportControlFlags(mRccObj, 0); - } - } else { - // Set state - if (android.os.Build.VERSION.SDK_INT >= 18) { - MediaSessionCompatApi18.setState(mRccObj, state.getState(), state.getPosition(), - state.getPlaybackSpeed(), state.getLastPositionUpdateTime()); - } else if (android.os.Build.VERSION.SDK_INT >= 14) { - MediaSessionCompatApi14.setState(mRccObj, state.getState()); - } - - // Set transport control flags - if (android.os.Build.VERSION.SDK_INT >= 19) { - MediaSessionCompatApi19.setTransportControlFlags(mRccObj, state.getActions()); - } else if (android.os.Build.VERSION.SDK_INT >= 18) { - MediaSessionCompatApi18.setTransportControlFlags(mRccObj, state.getActions()); - } else if (android.os.Build.VERSION.SDK_INT >= 14) { - MediaSessionCompatApi14.setTransportControlFlags(mRccObj, state.getActions()); - } - } - } - - /** - * Clones the given {@link MediaMetadataCompat}, deep-copying bitmaps in the metadata if - * they exist. If there is no bitmap in the metadata, this method just returns the given - * metadata. - * - * @param metadata A {@link MediaMetadataCompat} to be cloned. - * @return A newly cloned metadata if it contains bitmaps. Otherwise, the given metadata - * will be returned. - */ - private MediaMetadataCompat cloneMetadataIfNeeded(MediaMetadataCompat metadata) { - if (metadata == null) { - return null; - } else if (!metadata.containsKey(MediaMetadataCompat.METADATA_KEY_ART) - && !metadata.containsKey(MediaMetadataCompat.METADATA_KEY_ALBUM_ART)) { - return metadata; - } - MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(metadata); - Bitmap artBitmap = metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ART); - if (artBitmap != null) { - builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, - artBitmap.copy(artBitmap.getConfig(), false)); - } - Bitmap albumArtBitmap = metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART); - if (albumArtBitmap != null) { - builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, - albumArtBitmap.copy(albumArtBitmap.getConfig(), false)); - } - return builder.build(); - } - - @Override - public void setMetadata(MediaMetadataCompat metadata) { - if (android.os.Build.VERSION.SDK_INT >= 14 && metadata != null) { - // Clone bitmaps in metadata for protecting them to be recycled by RCC. - metadata = cloneMetadataIfNeeded(metadata); - } - synchronized (mLock) { - mMetadata = metadata; - } - sendMetadata(metadata); - if (!mIsActive) { - // Don't set metadata until after the rcc has been registered - return; - } - if (android.os.Build.VERSION.SDK_INT >= 19) { - MediaSessionCompatApi19.setMetadata(mRccObj, - metadata == null ? null : metadata.getBundle(), - mState == null ? 0 : mState.getActions()); - } else if (android.os.Build.VERSION.SDK_INT >= 14) { - MediaSessionCompatApi14.setMetadata(mRccObj, - metadata == null ? null : metadata.getBundle()); - } - } - - @Override - public void setSessionActivity(PendingIntent pi) { - synchronized (mLock) { - mSessionActivity = pi; - } - } - - @Override - public void setMediaButtonReceiver(PendingIntent mbr) { - // Do nothing, changing this is not supported before API 21. - } - - @Override - public void setQueue(List queue) { - mQueue = queue; - sendQueue(queue); - } - - @Override - public void setQueueTitle(CharSequence title) { - mQueueTitle = title; - sendQueueTitle(title); - } - - @Override - public Object getMediaSession() { - return null; - } - - @Override - public Object getRemoteControlClient() { - return mRccObj; - } - - @Override - public void setRatingType(@RatingCompat.Style int type) { - mRatingType = type; - } - - @Override - public void setExtras(Bundle extras) { - mExtras = extras; - } - - // Registers/unregisters the RCC and MediaButtonEventReceiver as needed. - private boolean update() { - boolean registeredRcc = false; - if (mIsActive) { - // On API 8+ register a MBR if it's supported, unregister it - // if support was removed. - if (android.os.Build.VERSION.SDK_INT >= 8) { - if (!mIsMbrRegistered && (mFlags & FLAG_HANDLES_MEDIA_BUTTONS) != 0) { - if (android.os.Build.VERSION.SDK_INT >= 18) { - MediaSessionCompatApi18.registerMediaButtonEventReceiver(mContext, - mMediaButtonEventReceiver, mComponentName); - } else { - MediaSessionCompatApi8.registerMediaButtonEventReceiver(mContext, - mComponentName); - } - mIsMbrRegistered = true; - } else if (mIsMbrRegistered && (mFlags & FLAG_HANDLES_MEDIA_BUTTONS) == 0) { - if (android.os.Build.VERSION.SDK_INT >= 18) { - MediaSessionCompatApi18.unregisterMediaButtonEventReceiver(mContext, - mMediaButtonEventReceiver, mComponentName); - } else { - MediaSessionCompatApi8.unregisterMediaButtonEventReceiver(mContext, - mComponentName); - } - mIsMbrRegistered = false; - } - } - // On API 14+ register a RCC if it's supported, unregister it if - // not. - if (android.os.Build.VERSION.SDK_INT >= 14) { - if (!mIsRccRegistered && (mFlags & FLAG_HANDLES_TRANSPORT_CONTROLS) != 0) { - MediaSessionCompatApi14.registerRemoteControlClient(mContext, mRccObj); - mIsRccRegistered = true; - registeredRcc = true; - } else if (mIsRccRegistered - && (mFlags & FLAG_HANDLES_TRANSPORT_CONTROLS) == 0) { - // RCC keeps the state while the system resets its state internally when - // we register RCC. Reset the state so that the states in RCC and the system - // are in sync when we re-register the RCC. - MediaSessionCompatApi14.setState(mRccObj, PlaybackStateCompat.STATE_NONE); - MediaSessionCompatApi14.unregisterRemoteControlClient(mContext, mRccObj); - mIsRccRegistered = false; - } - } - } else { - // When inactive remove any registered components. - if (mIsMbrRegistered) { - if (android.os.Build.VERSION.SDK_INT >= 18) { - MediaSessionCompatApi18.unregisterMediaButtonEventReceiver(mContext, - mMediaButtonEventReceiver, mComponentName); - } else { - MediaSessionCompatApi8.unregisterMediaButtonEventReceiver(mContext, - mComponentName); - } - mIsMbrRegistered = false; - } - if (mIsRccRegistered) { - // RCC keeps the state while the system resets its state internally when - // we register RCC. Reset the state so that the states in RCC and the system - // are in sync when we re-register the RCC. - MediaSessionCompatApi14.setState(mRccObj, PlaybackStateCompat.STATE_NONE); - MediaSessionCompatApi14.unregisterRemoteControlClient(mContext, mRccObj); - mIsRccRegistered = false; - } - } - return registeredRcc; - } - - private void adjustVolume(int direction, int flags) { - if (mVolumeType == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) { - if (mVolumeProvider != null) { - mVolumeProvider.onAdjustVolume(direction); - } - } else { - mAudioManager.adjustStreamVolume(mLocalStream, direction, flags); - } - } - - private void setVolumeTo(int value, int flags) { - if (mVolumeType == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) { - if (mVolumeProvider != null) { - mVolumeProvider.onSetVolumeTo(value); - } - } else { - mAudioManager.setStreamVolume(mLocalStream, value, flags); - } - } - - private PlaybackStateCompat getStateWithUpdatedPosition() { - PlaybackStateCompat state; - long duration = -1; - synchronized (mLock) { - state = mState; - if (mMetadata != null - && mMetadata.containsKey(MediaMetadataCompat.METADATA_KEY_DURATION)) { - duration = mMetadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION); - } - } - - PlaybackStateCompat result = null; - if (state != null) { - if (state.getState() == PlaybackStateCompat.STATE_PLAYING - || state.getState() == PlaybackStateCompat.STATE_FAST_FORWARDING - || state.getState() == PlaybackStateCompat.STATE_REWINDING) { - long updateTime = state.getLastPositionUpdateTime(); - long currentTime = SystemClock.elapsedRealtime(); - if (updateTime > 0) { - long position = (long) (state.getPlaybackSpeed() - * (currentTime - updateTime)) + state.getPosition(); - if (duration >= 0 && position > duration) { - position = duration; - } else if (position < 0) { - position = 0; - } - PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder( - state); - builder.setState(state.getState(), position, state.getPlaybackSpeed(), - currentTime); - result = builder.build(); - } - } - } - return result == null ? state : result; - } - - private void sendVolumeInfoChanged(ParcelableVolumeInfo info) { - int size = mControllerCallbacks.beginBroadcast(); - for (int i = size - 1; i >= 0; i--) { - IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); - try { - cb.onVolumeInfoChanged(info); - } catch (RemoteException e) { - } - } - mControllerCallbacks.finishBroadcast(); - } - - private void sendSessionDestroyed() { - int size = mControllerCallbacks.beginBroadcast(); - for (int i = size - 1; i >= 0; i--) { - IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); - try { - cb.onSessionDestroyed(); - } catch (RemoteException e) { - } - } - mControllerCallbacks.finishBroadcast(); - mControllerCallbacks.kill(); - } - - private void sendEvent(String event, Bundle extras) { - int size = mControllerCallbacks.beginBroadcast(); - for (int i = size - 1; i >= 0; i--) { - IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); - try { - cb.onEvent(event, extras); - } catch (RemoteException e) { - } - } - mControllerCallbacks.finishBroadcast(); - } - - private void sendState(PlaybackStateCompat state) { - int size = mControllerCallbacks.beginBroadcast(); - for (int i = size - 1; i >= 0; i--) { - IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); - try { - cb.onPlaybackStateChanged(state); - } catch (RemoteException e) { - } - } - mControllerCallbacks.finishBroadcast(); - } - - private void sendMetadata(MediaMetadataCompat metadata) { - int size = mControllerCallbacks.beginBroadcast(); - for (int i = size - 1; i >= 0; i--) { - IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); - try { - cb.onMetadataChanged(metadata); - } catch (RemoteException e) { - } - } - mControllerCallbacks.finishBroadcast(); - } - - private void sendQueue(List queue) { - int size = mControllerCallbacks.beginBroadcast(); - for (int i = size - 1; i >= 0; i--) { - IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); - try { - cb.onQueueChanged(queue); - } catch (RemoteException e) { - } - } - mControllerCallbacks.finishBroadcast(); - } - - private void sendQueueTitle(CharSequence queueTitle) { - int size = mControllerCallbacks.beginBroadcast(); - for (int i = size - 1; i >= 0; i--) { - IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); - try { - cb.onQueueTitleChanged(queueTitle); - } catch (RemoteException e) { - } - } - mControllerCallbacks.finishBroadcast(); - } - - class MediaSessionStub extends IMediaSession.Stub { - @Override - public void sendCommand(String command, Bundle args, ResultReceiverWrapper cb) { - postToHandler(MessageHandler.MSG_COMMAND, - new Command(command, args, cb.mResultReceiver)); - } - - @Override - public boolean sendMediaButton(KeyEvent mediaButton) { - boolean handlesMediaButtons = - (mFlags & MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS) != 0; - if (handlesMediaButtons) { - postToHandler(MessageHandler.MSG_MEDIA_BUTTON, mediaButton); - } - return handlesMediaButtons; - } - - @Override - public void registerCallbackListener(IMediaControllerCallback cb) { - // If this session is already destroyed tell the caller and - // don't add them. - if (mDestroyed) { - try { - cb.onSessionDestroyed(); - } catch (Exception e) { - // ignored - } - return; - } - mControllerCallbacks.register(cb); - } - - @Override - public void unregisterCallbackListener(IMediaControllerCallback cb) { - mControllerCallbacks.unregister(cb); - } - - @Override - public String getPackageName() { - // mPackageName is final so doesn't need synchronize block - return mPackageName; - } - - @Override - public String getTag() { - // mTag is final so doesn't need synchronize block - return mTag; - } - - @Override - public PendingIntent getLaunchPendingIntent() { - synchronized (mLock) { - return mSessionActivity; - } - } - - @Override - @SessionFlags - public long getFlags() { - synchronized (mLock) { - return mFlags; - } - } - - @Override - public ParcelableVolumeInfo getVolumeAttributes() { - int controlType; - int max; - int current; - int stream; - int volumeType; - synchronized (mLock) { - volumeType = mVolumeType; - stream = mLocalStream; - VolumeProviderCompat vp = mVolumeProvider; - if (volumeType == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) { - controlType = vp.getVolumeControl(); - max = vp.getMaxVolume(); - current = vp.getCurrentVolume(); - } else { - controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE; - max = mAudioManager.getStreamMaxVolume(stream); - current = mAudioManager.getStreamVolume(stream); - } - } - return new ParcelableVolumeInfo(volumeType, stream, controlType, max, current); - } - - @Override - public void adjustVolume(int direction, int flags, String packageName) { - MediaSessionImplBase.this.adjustVolume(direction, flags); - } - - @Override - public void setVolumeTo(int value, int flags, String packageName) { - MediaSessionImplBase.this.setVolumeTo(value, flags); - } - - @Override - public void play() throws RemoteException { - postToHandler(MessageHandler.MSG_PLAY); - } - - @Override - public void playFromMediaId(String mediaId, Bundle extras) throws RemoteException { - postToHandler(MessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras); - } - - @Override - public void playFromSearch(String query, Bundle extras) throws RemoteException { - postToHandler(MessageHandler.MSG_PLAY_SEARCH, query, extras); - } - - @Override - public void playFromUri(Uri uri, Bundle extras) throws RemoteException { - postToHandler(MessageHandler.MSG_PLAY_URI, uri, extras); - } - - @Override - public void skipToQueueItem(long id) { - postToHandler(MessageHandler.MSG_SKIP_TO_ITEM, id); - } - - @Override - public void pause() throws RemoteException { - postToHandler(MessageHandler.MSG_PAUSE); - } - - @Override - public void stop() throws RemoteException { - postToHandler(MessageHandler.MSG_STOP); - } - - @Override - public void next() throws RemoteException { - postToHandler(MessageHandler.MSG_NEXT); - } - - @Override - public void previous() throws RemoteException { - postToHandler(MessageHandler.MSG_PREVIOUS); - } - - @Override - public void fastForward() throws RemoteException { - postToHandler(MessageHandler.MSG_FAST_FORWARD); - } - - @Override - public void rewind() throws RemoteException { - postToHandler(MessageHandler.MSG_REWIND); - } - - @Override - public void seekTo(long pos) throws RemoteException { - postToHandler(MessageHandler.MSG_SEEK_TO, pos); - } - - @Override - public void rate(RatingCompat rating) throws RemoteException { - postToHandler(MessageHandler.MSG_RATE, rating); - } - - @Override - public void sendCustomAction(String action, Bundle args) - throws RemoteException { - postToHandler(MessageHandler.MSG_CUSTOM_ACTION, action, args); - } - - @Override - public MediaMetadataCompat getMetadata() { - return mMetadata; - } - - @Override - public PlaybackStateCompat getPlaybackState() { - return getStateWithUpdatedPosition(); - } - - @Override - public List getQueue() { - synchronized (mLock) { - return mQueue; - } - } - - @Override - public CharSequence getQueueTitle() { - return mQueueTitle; - } - - @Override - public Bundle getExtras() { - synchronized (mLock) { - return mExtras; - } - } - - @Override - @RatingCompat.Style - public int getRatingType() { - return mRatingType; - } - - @Override - public boolean isTransportControlEnabled() { - return (mFlags & FLAG_HANDLES_TRANSPORT_CONTROLS) != 0; - } - } - - private static final class Command { - public final String command; - public final Bundle extras; - public final ResultReceiver stub; - - public Command(String command, Bundle extras, ResultReceiver stub) { - this.command = command; - this.extras = extras; - this.stub = stub; - } - } - - private class MessageHandler extends Handler { - - private static final int MSG_PLAY = 1; - private static final int MSG_PLAY_MEDIA_ID = 2; - private static final int MSG_PLAY_SEARCH = 3; - private static final int MSG_SKIP_TO_ITEM = 4; - private static final int MSG_PAUSE = 5; - private static final int MSG_STOP = 6; - private static final int MSG_NEXT = 7; - private static final int MSG_PREVIOUS = 8; - private static final int MSG_FAST_FORWARD = 9; - private static final int MSG_REWIND = 10; - private static final int MSG_SEEK_TO = 11; - private static final int MSG_RATE = 12; - private static final int MSG_CUSTOM_ACTION = 13; - private static final int MSG_MEDIA_BUTTON = 14; - private static final int MSG_COMMAND = 15; - private static final int MSG_ADJUST_VOLUME = 16; - private static final int MSG_SET_VOLUME = 17; - private static final int MSG_PLAY_URI = 18; - - // KeyEvent constants only available on API 11+ - private static final int KEYCODE_MEDIA_PAUSE = 127; - private static final int KEYCODE_MEDIA_PLAY = 126; - - public MessageHandler(Looper looper) { - super(looper); - } - - public void post(int what, Object obj, Bundle bundle) { - Message msg = obtainMessage(what, obj); - msg.setData(bundle); - msg.sendToTarget(); - } - - public void post(int what, Object obj) { - obtainMessage(what, obj).sendToTarget(); - } - - public void post(int what) { - post(what, null); - } - - public void post(int what, Object obj, int arg1) { - obtainMessage(what, arg1, 0, obj).sendToTarget(); - } - - @Override - public void handleMessage(Message msg) { - MediaSessionCompat.Callback cb = mCallback; - if (cb == null) { - return; - } - switch (msg.what) { - case MSG_PLAY: - cb.onPlay(); - break; - case MSG_PLAY_MEDIA_ID: - cb.onPlayFromMediaId((String) msg.obj, msg.getData()); - break; - case MSG_PLAY_SEARCH: - cb.onPlayFromSearch((String) msg.obj, msg.getData()); - break; - case MSG_PLAY_URI: - cb.onPlayFromUri((Uri) msg.obj, msg.getData()); - break; - case MSG_SKIP_TO_ITEM: - cb.onSkipToQueueItem((Long) msg.obj); - break; - case MSG_PAUSE: - cb.onPause(); - break; - case MSG_STOP: - cb.onStop(); - break; - case MSG_NEXT: - cb.onSkipToNext(); - break; - case MSG_PREVIOUS: - cb.onSkipToPrevious(); - break; - case MSG_FAST_FORWARD: - cb.onFastForward(); - break; - case MSG_REWIND: - cb.onRewind(); - break; - case MSG_SEEK_TO: - cb.onSeekTo((Long) msg.obj); - break; - case MSG_RATE: - cb.onSetRating((RatingCompat) msg.obj); - break; - case MSG_CUSTOM_ACTION: - cb.onCustomAction((String) msg.obj, msg.getData()); - break; - case MSG_MEDIA_BUTTON: - KeyEvent keyEvent = (KeyEvent) msg.obj; - Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); - intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); - // Let the Callback handle events first before using the default behavior - if (!cb.onMediaButtonEvent(intent)) { - onMediaButtonEvent(keyEvent, cb); - } - break; - case MSG_COMMAND: - Command cmd = (Command) msg.obj; - cb.onCommand(cmd.command, cmd.extras, cmd.stub); - break; - case MSG_ADJUST_VOLUME: - adjustVolume((int) msg.obj, 0); - break; - case MSG_SET_VOLUME: - setVolumeTo((int) msg.obj, 0); - break; - } - } - - private void onMediaButtonEvent(KeyEvent ke, MediaSessionCompat.Callback cb) { - if (ke == null || ke.getAction() != KeyEvent.ACTION_DOWN) { - return; - } - long validActions = mState == null ? 0 : mState.getActions(); - switch (ke.getKeyCode()) { - // Note KeyEvent.KEYCODE_MEDIA_PLAY is API 11+ - case KEYCODE_MEDIA_PLAY: - if ((validActions & PlaybackStateCompat.ACTION_PLAY) != 0) { - cb.onPlay(); - } - break; - // Note KeyEvent.KEYCODE_MEDIA_PAUSE is API 11+ - case KEYCODE_MEDIA_PAUSE: - if ((validActions & PlaybackStateCompat.ACTION_PAUSE) != 0) { - cb.onPause(); - } - break; - case KeyEvent.KEYCODE_MEDIA_NEXT: - if ((validActions & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) { - cb.onSkipToNext(); - } - break; - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - if ((validActions & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) { - cb.onSkipToPrevious(); - } - break; - case KeyEvent.KEYCODE_MEDIA_STOP: - if ((validActions & PlaybackStateCompat.ACTION_STOP) != 0) { - cb.onStop(); - } - break; - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - if ((validActions & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) { - cb.onFastForward(); - } - break; - case KeyEvent.KEYCODE_MEDIA_REWIND: - if ((validActions & PlaybackStateCompat.ACTION_REWIND) != 0) { - cb.onRewind(); - } - break; - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - case KeyEvent.KEYCODE_HEADSETHOOK: - boolean isPlaying = mState != null - && mState.getState() == PlaybackStateCompat.STATE_PLAYING; - boolean canPlay = (validActions & (PlaybackStateCompat.ACTION_PLAY_PAUSE - | PlaybackStateCompat.ACTION_PLAY)) != 0; - boolean canPause = (validActions & (PlaybackStateCompat.ACTION_PLAY_PAUSE - | PlaybackStateCompat.ACTION_PAUSE)) != 0; - if (isPlaying && canPause) { - cb.onPause(); - } else if (!isPlaying && canPlay) { - cb.onPlay(); - } - break; - } - } - } - } - - static class MediaSessionImplApi21 implements MediaSessionImpl { - private final Object mSessionObj; - private final Token mToken; - - private PendingIntent mMediaButtonIntent; - - public MediaSessionImplApi21(Context context, String tag) { - mSessionObj = MediaSessionCompatApi21.createSession(context, tag); - mToken = new Token(MediaSessionCompatApi21.getSessionToken(mSessionObj)); - } - - public MediaSessionImplApi21(Object mediaSession) { - mSessionObj = MediaSessionCompatApi21.verifySession(mediaSession); - mToken = new Token(MediaSessionCompatApi21.getSessionToken(mSessionObj)); - } - - @Override - public void setCallback(Callback callback, Handler handler) { - MediaSessionCompatApi21.setCallback(mSessionObj, - callback == null ? null : callback.mCallbackObj, handler); - } - - @Override - public void setFlags(@SessionFlags int flags) { - MediaSessionCompatApi21.setFlags(mSessionObj, flags); - } - - @Override - public void setPlaybackToLocal(int stream) { - MediaSessionCompatApi21.setPlaybackToLocal(mSessionObj, stream); - } - - @Override - public void setPlaybackToRemote(VolumeProviderCompat volumeProvider) { - MediaSessionCompatApi21.setPlaybackToRemote(mSessionObj, - volumeProvider.getVolumeProvider()); - } - - @Override - public void setActive(boolean active) { - MediaSessionCompatApi21.setActive(mSessionObj, active); - } - - @Override - public boolean isActive() { - return MediaSessionCompatApi21.isActive(mSessionObj); - } - - @Override - public void sendSessionEvent(String event, Bundle extras) { - MediaSessionCompatApi21.sendSessionEvent(mSessionObj, event, extras); - } - - @Override - public void release() { - MediaSessionCompatApi21.release(mSessionObj); - } - - @Override - public Token getSessionToken() { - return mToken; - } - - @Override - public void setPlaybackState(PlaybackStateCompat state) { - MediaSessionCompatApi21.setPlaybackState(mSessionObj, - state == null ? null : state.getPlaybackState()); - } - - @Override - public void setMetadata(MediaMetadataCompat metadata) { - MediaSessionCompatApi21.setMetadata(mSessionObj, - metadata == null ? null : metadata.getMediaMetadata()); - } - - @Override - public void setSessionActivity(PendingIntent pi) { - MediaSessionCompatApi21.setSessionActivity(mSessionObj, pi); - } - - @Override - public void setMediaButtonReceiver(PendingIntent mbr) { - mMediaButtonIntent = mbr; - MediaSessionCompatApi21.setMediaButtonReceiver(mSessionObj, mbr); - } - - @Override - public void setQueue(List queue) { - List queueObjs = null; - if (queue != null) { - queueObjs = new ArrayList(); - for (QueueItem item : queue) { - queueObjs.add(item.getQueueItem()); - } - } - MediaSessionCompatApi21.setQueue(mSessionObj, queueObjs); - } - - @Override - public void setQueueTitle(CharSequence title) { - MediaSessionCompatApi21.setQueueTitle(mSessionObj, title); - } - - @Override - public void setRatingType(@RatingCompat.Style int type) { - if (android.os.Build.VERSION.SDK_INT < 22) { - // TODO figure out 21 implementation - } else { - MediaSessionCompatApi22.setRatingType(mSessionObj, type); - } - } - - @Override - public void setExtras(Bundle extras) { - MediaSessionCompatApi21.setExtras(mSessionObj, extras); - } - - @Override - public Object getMediaSession() { - return mSessionObj; - } - - @Override - public Object getRemoteControlClient() { - return null; - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi14.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi14.java deleted file mode 100644 index 10faf63..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi14.java +++ /dev/null @@ -1,224 +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 p.android.support.v4.media.session; - -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.Bitmap; -import android.media.AudioManager; -import android.media.MediaMetadataRetriever; -import android.media.RemoteControlClient; -import android.os.Bundle; - -class MediaSessionCompatApi14 { - /***** RemoteControlClient States, we only need none as the others were public *******/ - final static int RCC_PLAYSTATE_NONE = 0; - - /***** MediaSession States *******/ - final static int STATE_NONE = 0; - final static int STATE_STOPPED = 1; - final static int STATE_PAUSED = 2; - final static int STATE_PLAYING = 3; - final static int STATE_FAST_FORWARDING = 4; - final static int STATE_REWINDING = 5; - final static int STATE_BUFFERING = 6; - final static int STATE_ERROR = 7; - final static int STATE_CONNECTING = 8; - final static int STATE_SKIPPING_TO_PREVIOUS = 9; - final static int STATE_SKIPPING_TO_NEXT = 10; - final static int STATE_SKIPPING_TO_QUEUE_ITEM = 11; - - /***** PlaybackState actions *****/ - private static final long ACTION_STOP = 1 << 0; - private static final long ACTION_PAUSE = 1 << 1; - private static final long ACTION_PLAY = 1 << 2; - private static final long ACTION_REWIND = 1 << 3; - private static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4; - private static final long ACTION_SKIP_TO_NEXT = 1 << 5; - private static final long ACTION_FAST_FORWARD = 1 << 6; - private static final long ACTION_PLAY_PAUSE = 1 << 9; - - /***** MediaMetadata keys ********/ - private static final String METADATA_KEY_ART = "android.media.metadata.ART"; - private static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART"; - private static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE"; - private static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST"; - private static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION"; - private static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM"; - private static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR"; - private static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER"; - private static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER"; - private static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION"; - private static final String METADATA_KEY_DATE = "android.media.metadata.DATE"; - private static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE"; - private static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER"; - private static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER"; - private static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST"; - - public static Object createRemoteControlClient(PendingIntent mbIntent) { - return new RemoteControlClient(mbIntent); - } - - public static void setState(Object rccObj, int state) { - ((RemoteControlClient) rccObj).setPlaybackState(getRccStateFromState(state)); - } - - public static void setTransportControlFlags(Object rccObj, long actions) { - ((RemoteControlClient) rccObj).setTransportControlFlags( - getRccTransportControlFlagsFromActions(actions)); - } - - public static void setMetadata(Object rccObj, Bundle metadata) { - RemoteControlClient.MetadataEditor editor = ((RemoteControlClient) rccObj).editMetadata( - true); - buildOldMetadata(metadata, editor); - editor.apply(); - } - - public static void registerRemoteControlClient(Context context, Object rccObj) { - AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - am.registerRemoteControlClient((RemoteControlClient) rccObj); - } - - public static void unregisterRemoteControlClient(Context context, Object rccObj) { - AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - am.unregisterRemoteControlClient((RemoteControlClient) rccObj); - } - - static int getRccStateFromState(int state) { - switch (state) { - case STATE_CONNECTING: - case STATE_BUFFERING: - return RemoteControlClient.PLAYSTATE_BUFFERING; - case STATE_ERROR: - return RemoteControlClient.PLAYSTATE_ERROR; - case STATE_FAST_FORWARDING: - return RemoteControlClient.PLAYSTATE_FAST_FORWARDING; - case STATE_NONE: - return RCC_PLAYSTATE_NONE; - case STATE_PAUSED: - return RemoteControlClient.PLAYSTATE_PAUSED; - case STATE_PLAYING: - return RemoteControlClient.PLAYSTATE_PLAYING; - case STATE_REWINDING: - return RemoteControlClient.PLAYSTATE_REWINDING; - case STATE_SKIPPING_TO_PREVIOUS: - return RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS; - case STATE_SKIPPING_TO_NEXT: - case STATE_SKIPPING_TO_QUEUE_ITEM: - return RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS; - case STATE_STOPPED: - return RemoteControlClient.PLAYSTATE_STOPPED; - default: - return -1; - } - } - - static int getRccTransportControlFlagsFromActions(long actions) { - int transportControlFlags = 0; - if ((actions & ACTION_STOP) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_STOP; - } - if ((actions & ACTION_PAUSE) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PAUSE; - } - if ((actions & ACTION_PLAY) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY; - } - if ((actions & ACTION_REWIND) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_REWIND; - } - if ((actions & ACTION_SKIP_TO_PREVIOUS) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS; - } - if ((actions & ACTION_SKIP_TO_NEXT) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_NEXT; - } - if ((actions & ACTION_FAST_FORWARD) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD; - } - if ((actions & ACTION_PLAY_PAUSE) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE; - } - return transportControlFlags; - } - - static void buildOldMetadata(Bundle metadata, RemoteControlClient.MetadataEditor editor) { - if (metadata == null) { - return; - } - if (metadata.containsKey(METADATA_KEY_ART)) { - Bitmap art = metadata.getParcelable(METADATA_KEY_ART); - editor.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, art); - } else if (metadata.containsKey(METADATA_KEY_ALBUM_ART)) { - // Fall back to album art if the track art wasn't available - Bitmap art = metadata.getParcelable(METADATA_KEY_ALBUM_ART); - editor.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, art); - } - if (metadata.containsKey(METADATA_KEY_ALBUM)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, - metadata.getString(METADATA_KEY_ALBUM)); - } - if (metadata.containsKey(METADATA_KEY_ALBUM_ARTIST)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, - metadata.getString(METADATA_KEY_ALBUM_ARTIST)); - } - if (metadata.containsKey(METADATA_KEY_ARTIST)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, - metadata.getString(METADATA_KEY_ARTIST)); - } - if (metadata.containsKey(METADATA_KEY_AUTHOR)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_AUTHOR, - metadata.getString(METADATA_KEY_AUTHOR)); - } - if (metadata.containsKey(METADATA_KEY_COMPILATION)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_COMPILATION, - metadata.getString(METADATA_KEY_COMPILATION)); - } - if (metadata.containsKey(METADATA_KEY_COMPOSER)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_COMPOSER, - metadata.getString(METADATA_KEY_COMPOSER)); - } - if (metadata.containsKey(METADATA_KEY_DATE)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_DATE, - metadata.getString(METADATA_KEY_DATE)); - } - if (metadata.containsKey(METADATA_KEY_DISC_NUMBER)) { - editor.putLong(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER, - metadata.getLong(METADATA_KEY_DISC_NUMBER)); - } - if (metadata.containsKey(METADATA_KEY_DURATION)) { - editor.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, - metadata.getLong(METADATA_KEY_DURATION)); - } - if (metadata.containsKey(METADATA_KEY_GENRE)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_GENRE, - metadata.getString(METADATA_KEY_GENRE)); - } - if (metadata.containsKey(METADATA_KEY_TITLE)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, - metadata.getString(METADATA_KEY_TITLE)); - } - if (metadata.containsKey(METADATA_KEY_TRACK_NUMBER)) { - editor.putLong(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, - metadata.getLong(METADATA_KEY_TRACK_NUMBER)); - } - if (metadata.containsKey(METADATA_KEY_WRITER)) { - editor.putString(MediaMetadataRetriever.METADATA_KEY_WRITER, - metadata.getString(METADATA_KEY_WRITER)); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi18.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi18.java deleted file mode 100644 index 0ba83dd..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi18.java +++ /dev/null @@ -1,124 +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 p.android.support.v4.media.session; - -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.media.AudioManager; -import android.media.RemoteControlClient; -import android.util.Log; -import android.os.SystemClock; - -class MediaSessionCompatApi18 { - private static final String TAG = "MediaSessionCompatApi18"; - - /***** PlaybackState actions *****/ - private static final long ACTION_SEEK_TO = 1 << 8; - - private static boolean sIsMbrPendingIntentSupported = true; - - public static Object createPlaybackPositionUpdateListener(Callback callback) { - return new OnPlaybackPositionUpdateListener(callback); - } - - public static void registerMediaButtonEventReceiver(Context context, PendingIntent pi, - ComponentName cn) { - AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - - // Some Android implementations are not able to register a media button event receiver - // using a PendingIntent but need a ComponentName instead. These will raise a - // NullPointerException. - if (sIsMbrPendingIntentSupported) { - try { - am.registerMediaButtonEventReceiver(pi); - } catch (NullPointerException e) { - Log.w(TAG, "Unable to register media button event receiver with " - + "PendingIntent, falling back to ComponentName."); - sIsMbrPendingIntentSupported = false; - } - } - - if (!sIsMbrPendingIntentSupported) { - am.registerMediaButtonEventReceiver(cn); - } - } - - public static void unregisterMediaButtonEventReceiver(Context context, PendingIntent pi, - ComponentName cn) { - AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - if (sIsMbrPendingIntentSupported) { - am.unregisterMediaButtonEventReceiver(pi); - } else { - am.unregisterMediaButtonEventReceiver(cn); - } - } - - public static void setState(Object rccObj, int state, long position, float speed, - long updateTime) { - long currTime = SystemClock.elapsedRealtime(); - if (state == MediaSessionCompatApi14.STATE_PLAYING && position > 0) { - long diff = 0; - if (updateTime > 0) { - diff = currTime - updateTime; - if (speed > 0 && speed != 1f) { - diff *= speed; - } - } - position += diff; - } - state = MediaSessionCompatApi14.getRccStateFromState(state); - ((RemoteControlClient) rccObj).setPlaybackState(state, position, speed); - } - - public static void setTransportControlFlags(Object rccObj, long actions) { - ((RemoteControlClient) rccObj).setTransportControlFlags( - getRccTransportControlFlagsFromActions(actions)); - } - - public static void setOnPlaybackPositionUpdateListener(Object rccObj, - Object onPositionUpdateObj) { - ((RemoteControlClient) rccObj).setPlaybackPositionUpdateListener( - (RemoteControlClient.OnPlaybackPositionUpdateListener) onPositionUpdateObj); - } - - static int getRccTransportControlFlagsFromActions(long actions) { - int transportControlFlags = - MediaSessionCompatApi14.getRccTransportControlFlagsFromActions(actions); - if ((actions & ACTION_SEEK_TO) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE; - } - return transportControlFlags; - } - - static class OnPlaybackPositionUpdateListener - implements RemoteControlClient.OnPlaybackPositionUpdateListener { - protected final T mCallback; - - public OnPlaybackPositionUpdateListener(T callback) { - mCallback = callback; - } - - @Override - public void onPlaybackPositionUpdate(long newPositionMs) { - mCallback.onSeekTo(newPositionMs); - } - } - - interface Callback { - public void onSeekTo(long pos); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi19.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi19.java deleted file mode 100644 index 2233699..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi19.java +++ /dev/null @@ -1,104 +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 p.android.support.v4.media.session; - -import android.media.MediaMetadataEditor; -import android.media.MediaMetadataRetriever; -import android.media.Rating; -import android.media.RemoteControlClient; -import android.os.Bundle; - -class MediaSessionCompatApi19 { - /***** PlaybackState actions *****/ - private static final long ACTION_SET_RATING = 1 << 7; - - /***** MediaMetadata keys ********/ - private static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING"; - private static final String METADATA_KEY_RATING = "android.media.metadata.RATING"; - private static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR"; - - public static void setTransportControlFlags(Object rccObj, long actions) { - ((RemoteControlClient) rccObj).setTransportControlFlags( - getRccTransportControlFlagsFromActions(actions)); - } - - public static Object createMetadataUpdateListener(Callback callback) { - return new OnMetadataUpdateListener(callback); - } - - public static void setMetadata(Object rccObj, Bundle metadata, long actions) { - RemoteControlClient.MetadataEditor editor = ((RemoteControlClient) rccObj).editMetadata( - true); - MediaSessionCompatApi14.buildOldMetadata(metadata, editor); - addNewMetadata(metadata, editor); - if ((actions & ACTION_SET_RATING) != 0) { - editor.addEditableKey(RemoteControlClient.MetadataEditor.RATING_KEY_BY_USER); - } - editor.apply(); - } - - public static void setOnMetadataUpdateListener(Object rccObj, Object onMetadataUpdateObj) { - ((RemoteControlClient) rccObj).setMetadataUpdateListener( - (RemoteControlClient.OnMetadataUpdateListener) onMetadataUpdateObj); - } - - static int getRccTransportControlFlagsFromActions(long actions) { - int transportControlFlags = - MediaSessionCompatApi18.getRccTransportControlFlagsFromActions(actions); - if ((actions & ACTION_SET_RATING) != 0) { - transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_RATING; - } - return transportControlFlags; - } - - static void addNewMetadata(Bundle metadata, RemoteControlClient.MetadataEditor editor) { - if (metadata == null) { - return; - } - if (metadata.containsKey(METADATA_KEY_YEAR)) { - editor.putLong(MediaMetadataRetriever.METADATA_KEY_YEAR, - metadata.getLong(METADATA_KEY_YEAR)); - } - if (metadata.containsKey(METADATA_KEY_RATING)) { - editor.putObject(MediaMetadataEditor.RATING_KEY_BY_OTHERS, - metadata.getParcelable(METADATA_KEY_RATING)); - } - if (metadata.containsKey(METADATA_KEY_USER_RATING)) { - editor.putObject(MediaMetadataEditor.RATING_KEY_BY_USER, - metadata.getParcelable(METADATA_KEY_USER_RATING)); - } - } - - static class OnMetadataUpdateListener implements - RemoteControlClient.OnMetadataUpdateListener { - protected final T mCallback; - - public OnMetadataUpdateListener(T callback) { - mCallback = callback; - } - - @Override - public void onMetadataUpdate(int key, Object newValue) { - if (key == MediaMetadataEditor.RATING_KEY_BY_USER && newValue instanceof Rating) { - mCallback.onSetRating(newValue); - } - } - } - - interface Callback extends MediaSessionCompatApi18.Callback { - public void onSetRating(Object ratingObj); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi21.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi21.java deleted file mode 100644 index 54f84b1..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi21.java +++ /dev/null @@ -1,249 +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 p.android.support.v4.media.session; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.media.AudioAttributes; -import android.media.MediaDescription; -import android.media.MediaMetadata; -import android.media.Rating; -import android.media.VolumeProvider; -import android.media.session.MediaSession; -import android.media.session.PlaybackState; -import android.os.Bundle; -import android.os.Handler; -import android.os.Parcelable; -import android.os.ResultReceiver; - -import java.util.ArrayList; -import java.util.List; - -class MediaSessionCompatApi21 { - public static Object createSession(Context context, String tag) { - return new MediaSession(context, tag); - } - - public static Object verifySession(Object mediaSession) { - if (mediaSession instanceof MediaSession) { - return mediaSession; - } - throw new IllegalArgumentException("mediaSession is not a valid MediaSession object"); - } - - public static Object verifyToken(Object token) { - if (token instanceof MediaSession.Token) { - return token; - } - throw new IllegalArgumentException("token is not a valid MediaSession.Token object"); - } - - public static Object createCallback(Callback callback) { - return new CallbackProxy(callback); - } - - public static void setCallback(Object sessionObj, Object callbackObj, Handler handler) { - ((MediaSession) sessionObj).setCallback((MediaSession.Callback) callbackObj, handler); - } - - public static void setFlags(Object sessionObj, int flags) { - ((MediaSession)sessionObj).setFlags(flags); - } - - public static void setPlaybackToLocal(Object sessionObj, int stream) { - // TODO update APIs to use support version of AudioAttributes - AudioAttributes.Builder bob = new AudioAttributes.Builder(); - bob.setLegacyStreamType(stream); - ((MediaSession) sessionObj).setPlaybackToLocal(bob.build()); - } - - public static void setPlaybackToRemote(Object sessionObj, Object volumeProviderObj) { - ((MediaSession)sessionObj).setPlaybackToRemote((VolumeProvider)volumeProviderObj); - } - - public static void setActive(Object sessionObj, boolean active) { - ((MediaSession)sessionObj).setActive(active); - } - - public static boolean isActive(Object sessionObj) { - return ((MediaSession)sessionObj).isActive(); - } - - public static void sendSessionEvent(Object sessionObj, String event, Bundle extras) { - ((MediaSession)sessionObj).sendSessionEvent(event, extras); - } - - public static void release(Object sessionObj) { - ((MediaSession)sessionObj).release(); - } - - public static Parcelable getSessionToken(Object sessionObj) { - return ((MediaSession)sessionObj).getSessionToken(); - } - - public static void setPlaybackState(Object sessionObj, Object stateObj) { - ((MediaSession)sessionObj).setPlaybackState((PlaybackState)stateObj); - } - - public static void setMetadata(Object sessionObj, Object metadataObj) { - ((MediaSession)sessionObj).setMetadata((MediaMetadata)metadataObj); - } - - public static void setSessionActivity(Object sessionObj, PendingIntent pi) { - ((MediaSession) sessionObj).setSessionActivity(pi); - } - - public static void setMediaButtonReceiver(Object sessionObj, PendingIntent pi) { - ((MediaSession) sessionObj).setMediaButtonReceiver(pi); - } - - public static void setQueue(Object sessionObj, List queueObjs) { - if (queueObjs == null) { - ((MediaSession) sessionObj).setQueue(null); - return; - } - ArrayList queue = new ArrayList(); - for (Object itemObj : queueObjs) { - queue.add((MediaSession.QueueItem) itemObj); - } - ((MediaSession) sessionObj).setQueue(queue); - } - - public static void setQueueTitle(Object sessionObj, CharSequence title) { - ((MediaSession) sessionObj).setQueueTitle(title); - } - - public static void setExtras(Object sessionObj, Bundle extras) { - ((MediaSession) sessionObj).setExtras(extras); - } - - interface Callback extends MediaSessionCompatApi19.Callback { - public void onCommand(String command, Bundle extras, ResultReceiver cb); - public boolean onMediaButtonEvent(Intent mediaButtonIntent); - public void onPlay(); - public void onPlayFromMediaId(String mediaId, Bundle extras); - public void onPlayFromSearch(String search, Bundle extras); - public void onSkipToQueueItem(long id); - public void onPause(); - public void onSkipToNext(); - public void onSkipToPrevious(); - public void onFastForward(); - public void onRewind(); - public void onStop(); - public void onCustomAction(String action, Bundle extras); - } - - static class CallbackProxy extends MediaSession.Callback { - protected final T mCallback; - - public CallbackProxy(T callback) { - mCallback = callback; - } - - @Override - public void onCommand(String command, Bundle args, ResultReceiver cb) { - mCallback.onCommand(command, args, cb); - } - - @Override - public boolean onMediaButtonEvent(Intent mediaButtonIntent) { - return mCallback.onMediaButtonEvent(mediaButtonIntent) - || super.onMediaButtonEvent(mediaButtonIntent); - } - - @Override - public void onPlay() { - mCallback.onPlay(); - } - - @Override - public void onPlayFromMediaId(String mediaId, Bundle extras) { - mCallback.onPlayFromMediaId(mediaId, extras); - } - - @Override - public void onPlayFromSearch(String search, Bundle extras) { - mCallback.onPlayFromSearch(search, extras); - } - - @Override - public void onSkipToQueueItem(long id) { - mCallback.onSkipToQueueItem(id); - } - - @Override - public void onPause() { - mCallback.onPause(); - } - - @Override - public void onSkipToNext() { - mCallback.onSkipToNext(); - } - - @Override - public void onSkipToPrevious() { - mCallback.onSkipToPrevious(); - } - - @Override - public void onFastForward() { - mCallback.onFastForward(); - } - - @Override - public void onRewind() { - mCallback.onRewind(); - } - - @Override - public void onStop() { - mCallback.onStop(); - } - - @Override - public void onSeekTo(long pos) { - mCallback.onSeekTo(pos); - } - - @Override - public void onSetRating(Rating rating) { - mCallback.onSetRating(rating); - } - - @Override - public void onCustomAction(String action, Bundle extras) { - mCallback.onCustomAction(action, extras); - } - } - - static class QueueItem { - - public static Object createItem(Object mediaDescription, long id) { - return new MediaSession.QueueItem((MediaDescription) mediaDescription, id); - } - - public static Object getDescription(Object queueItem) { - return ((MediaSession.QueueItem) queueItem).getDescription(); - } - - public static long getQueueId(Object queueItem) { - return ((MediaSession.QueueItem) queueItem).getQueueId(); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi22.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi22.java deleted file mode 100644 index 9a63ae0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi22.java +++ /dev/null @@ -1,25 +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 p.android.support.v4.media.session; - -import android.media.session.MediaSession; - -class MediaSessionCompatApi22 { - - public static void setRatingType(Object sessionObj, int type) { - ((MediaSession) sessionObj).setRatingType(type); - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi23.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi23.java deleted file mode 100644 index ddaa69e..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi23.java +++ /dev/null @@ -1,42 +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 p.android.support.v4.media.session; - -import android.net.Uri; -import android.os.Bundle; - -class MediaSessionCompatApi23 { - - public static Object createCallback(Callback callback) { - return new CallbackProxy(callback); - } - - public interface Callback extends MediaSessionCompatApi21.Callback { - public void onPlayFromUri(Uri uri, Bundle extras); - } - - static class CallbackProxy extends MediaSessionCompatApi21.CallbackProxy { - public CallbackProxy(T callback) { - super(callback); - } - - @Override - public void onPlayFromUri(Uri uri, Bundle extras) { - mCallback.onPlayFromUri(uri, extras); - } - } -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi8.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi8.java deleted file mode 100644 index d0211c0..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/MediaSessionCompatApi8.java +++ /dev/null @@ -1,32 +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 p.android.support.v4.media.session; - -import android.content.ComponentName; -import android.content.Context; -import android.media.AudioManager; - -class MediaSessionCompatApi8 { - public static void registerMediaButtonEventReceiver(Context context, ComponentName mbr) { - AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - am.registerMediaButtonEventReceiver(mbr); - } - - public static void unregisterMediaButtonEventReceiver(Context context, ComponentName mbr) { - AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - am.unregisterMediaButtonEventReceiver(mbr); - } -} \ No newline at end of file diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/ParcelableVolumeInfo.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/ParcelableVolumeInfo.aidl deleted file mode 100644 index 4314c3a..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/ParcelableVolumeInfo.aidl +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2014, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.plug.v4.media.session; - -parcelable ParcelableVolumeInfo; diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/ParcelableVolumeInfo.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/ParcelableVolumeInfo.java deleted file mode 100644 index b379f9a..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/ParcelableVolumeInfo.java +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright 2014, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -package p.android.support.v4.media.session; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Convenience class for passing information about the audio configuration of a - * {@link MediaSessionCompat}. - */ -public class ParcelableVolumeInfo implements Parcelable { - public int volumeType; - public int audioStream; - public int controlType; - public int maxVolume; - public int currentVolume; - - public ParcelableVolumeInfo(int volumeType, int audioStream, int controlType, - int maxVolume, - int currentVolume) { - this.volumeType = volumeType; - this.audioStream = audioStream; - this.controlType = controlType; - this.maxVolume = maxVolume; - this.currentVolume = currentVolume; - } - - public ParcelableVolumeInfo(Parcel from) { - volumeType = from.readInt(); - controlType = from.readInt(); - maxVolume = from.readInt(); - currentVolume = from.readInt(); - audioStream = from.readInt(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(volumeType); - dest.writeInt(controlType); - dest.writeInt(maxVolume); - dest.writeInt(currentVolume); - dest.writeInt(audioStream); - } - - - public static final Creator CREATOR - = new Creator() { - @Override - public ParcelableVolumeInfo createFromParcel(Parcel in) { - return new ParcelableVolumeInfo(in); - } - - @Override - public ParcelableVolumeInfo[] newArray(int size) { - return new ParcelableVolumeInfo[size]; - } - }; -} diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/PlaybackStateCompat.aidl b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/PlaybackStateCompat.aidl deleted file mode 100644 index 88a1621..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/PlaybackStateCompat.aidl +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright 2014, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.plug.v4.media.session; - -parcelable PlaybackStateCompat; diff --git a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/PlaybackStateCompat.java b/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/PlaybackStateCompat.java deleted file mode 100644 index 0dca474..0000000 --- a/sample/navercafesdk-sample-android-studio/libraries/src/main/java/p/android/support/v4/media/session/PlaybackStateCompat.java +++ /dev/null @@ -1,1003 +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 p.android.support.v4.media.session; - - -import android.os.Build; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.SystemClock; -import p.android.support.annotation.IntDef; -import p.android.support.annotation.Nullable; -import android.text.TextUtils; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; - -/** - * Playback state for a {@link MediaSessionCompat}. This includes a state like - * {@link PlaybackStateCompat#STATE_PLAYING}, the current playback position, - * and the current control capabilities. - */ -public final class PlaybackStateCompat implements Parcelable { - - /** - * @hide - */ - @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND, - ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING, - ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH, - ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI}) - @Retention(RetentionPolicy.SOURCE) - public @interface Actions {} - - /** - * Indicates this session supports the stop command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_STOP = 1 << 0; - - /** - * Indicates this session supports the pause command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_PAUSE = 1 << 1; - - /** - * Indicates this session supports the play command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_PLAY = 1 << 2; - - /** - * Indicates this session supports the rewind command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_REWIND = 1 << 3; - - /** - * Indicates this session supports the previous command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4; - - /** - * Indicates this session supports the next command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SKIP_TO_NEXT = 1 << 5; - - /** - * Indicates this session supports the fast forward command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_FAST_FORWARD = 1 << 6; - - /** - * Indicates this session supports the set rating command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SET_RATING = 1 << 7; - - /** - * Indicates this session supports the seek to command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SEEK_TO = 1 << 8; - - /** - * Indicates this session supports the play/pause toggle command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_PLAY_PAUSE = 1 << 9; - - /** - * Indicates this session supports the play from media id command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_PLAY_FROM_MEDIA_ID = 1 << 10; - - /** - * Indicates this session supports the play from search command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11; - - /** - * Indicates this session supports the skip to queue item command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12; - /** - * Indicates this session supports the play from URI command. - * - * @see Builder#setActions(long) - */ - public static final long ACTION_PLAY_FROM_URI = 1 << 13; - - /** - * @hide - */ - @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING, - STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING, - STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM}) - @Retention(RetentionPolicy.SOURCE) - public @interface State {} - - /** - * This is the default playback state and indicates that no media has been - * added yet, or the performer has been reset and has no content to play. - * - * @see Builder#setState - */ - public final static int STATE_NONE = 0; - - /** - * State indicating this item is currently stopped. - * - * @see Builder#setState - */ - public final static int STATE_STOPPED = 1; - - /** - * State indicating this item is currently paused. - * - * @see Builder#setState - */ - public final static int STATE_PAUSED = 2; - - /** - * State indicating this item is currently playing. - * - * @see Builder#setState - */ - public final static int STATE_PLAYING = 3; - - /** - * State indicating this item is currently fast forwarding. - * - * @see Builder#setState - */ - public final static int STATE_FAST_FORWARDING = 4; - - /** - * State indicating this item is currently rewinding. - * - * @see Builder#setState - */ - public final static int STATE_REWINDING = 5; - - /** - * State indicating this item is currently buffering and will begin playing - * when enough data has buffered. - * - * @see Builder#setState - */ - public final static int STATE_BUFFERING = 6; - - /** - * State indicating this item is currently in an error state. The error - * message should also be set when entering this state. - * - * @see Builder#setState - */ - public final static int STATE_ERROR = 7; - - /** - * State indicating the class doing playback is currently connecting to a - * route. Depending on the implementation you may return to the previous - * state when the connection finishes or enter {@link #STATE_NONE}. If - * the connection failed {@link #STATE_ERROR} should be used. - *

- * On devices earlier than API 21, this will appear as {@link #STATE_BUFFERING} - *

- * - * @see Builder#setState - */ - public final static int STATE_CONNECTING = 8; - - /** - * State indicating the player is currently skipping to the previous item. - * - * @see Builder#setState - */ - public final static int STATE_SKIPPING_TO_PREVIOUS = 9; - - /** - * State indicating the player is currently skipping to the next item. - * - * @see Builder#setState - */ - public final static int STATE_SKIPPING_TO_NEXT = 10; - - /** - * State indicating the player is currently skipping to a specific item in - * the queue. - *

- * On devices earlier than API 21, this will appear as {@link #STATE_SKIPPING_TO_NEXT} - *

- * - * @see Builder#setState - */ - public final static int STATE_SKIPPING_TO_QUEUE_ITEM = 11; - - /** - * Use this value for the position to indicate the position is not known. - */ - public final static long PLAYBACK_POSITION_UNKNOWN = -1; - - private final int mState; - private final long mPosition; - private final long mBufferedPosition; - private final float mSpeed; - private final long mActions; - private final CharSequence mErrorMessage; - private final long mUpdateTime; - private List mCustomActions; - private final long mActiveItemId; - private final Bundle mExtras; - - private Object mStateObj; - - private PlaybackStateCompat(int state, long position, long bufferedPosition, - float rate, long actions, CharSequence errorMessage, long updateTime, - List customActions, - long activeItemId, Bundle extras) { - mState = state; - mPosition = position; - mBufferedPosition = bufferedPosition; - mSpeed = rate; - mActions = actions; - mErrorMessage = errorMessage; - mUpdateTime = updateTime; - mCustomActions = new ArrayList<>(customActions); - mActiveItemId = activeItemId; - mExtras = extras; - } - - private PlaybackStateCompat(Parcel in) { - mState = in.readInt(); - mPosition = in.readLong(); - mSpeed = in.readFloat(); - mUpdateTime = in.readLong(); - mBufferedPosition = in.readLong(); - mActions = in.readLong(); - mErrorMessage = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mCustomActions = in.createTypedArrayList(CustomAction.CREATOR); - mActiveItemId = in.readLong(); - mExtras = in.readBundle(); - } - - @Override - public String toString() { - StringBuilder bob = new StringBuilder("PlaybackState {"); - bob.append("state=").append(mState); - bob.append(", position=").append(mPosition); - bob.append(", buffered position=").append(mBufferedPosition); - bob.append(", speed=").append(mSpeed); - bob.append(", updated=").append(mUpdateTime); - bob.append(", actions=").append(mActions); - bob.append(", error=").append(mErrorMessage); - bob.append(", custom actions=").append(mCustomActions); - bob.append(", active item id=").append(mActiveItemId); - bob.append("}"); - return bob.toString(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mState); - dest.writeLong(mPosition); - dest.writeFloat(mSpeed); - dest.writeLong(mUpdateTime); - dest.writeLong(mBufferedPosition); - dest.writeLong(mActions); - TextUtils.writeToParcel(mErrorMessage, dest, flags); - dest.writeTypedList(mCustomActions); - dest.writeLong(mActiveItemId); - dest.writeBundle(mExtras); - } - - /** - * Get the current state of playback. One of the following: - *