├── core ├── .gitignore ├── src │ └── main │ │ ├── java │ │ └── nl │ │ │ └── adaptivity │ │ │ └── android │ │ │ ├── coroutines │ │ │ ├── impl │ │ │ │ └── DelegateLayoutContainer.kt │ │ │ ├── contexts │ │ │ │ ├── FragmentContext.kt │ │ │ │ └── AndroidContext.kt │ │ │ ├── SimpleContextCoroutineScopeWrapper.kt │ │ │ ├── CoroutineFragment.kt │ │ │ ├── RetainedContinuationFragment.kt │ │ │ ├── RequestPermissionContinuationFragment.kt │ │ │ ├── ActivityCoroutineScopeWrapper.kt │ │ │ ├── launchers.kt │ │ │ ├── AndroidContextCoroutineScope.kt │ │ │ ├── FragmentCoroutineScope.kt │ │ │ ├── BaseRetainedContinuationFragment.kt │ │ │ ├── WrappedContextCoroutineScope.kt │ │ │ ├── Maybe.kt │ │ │ ├── FragmentCoroutineScopeWrapper.kt │ │ │ ├── SuspendableDialog.kt │ │ │ ├── ParcelableContinuationCompat.kt │ │ │ ├── accountmanager.kt │ │ │ ├── CoroutineActivity.kt │ │ │ ├── ParcelableContinuation.kt │ │ │ └── DownloadFragment.kt │ │ │ ├── kryo │ │ │ ├── serializers │ │ │ │ ├── KryoAndroidConstants.kt │ │ │ │ ├── CoroutineImplSerializer.kt │ │ │ │ ├── ContinuationImplSerializer.kt │ │ │ │ ├── StandaloneCoroutineSerializer.kt │ │ │ │ ├── PseudoObjectSerializer.kt │ │ │ │ ├── ObjectSerializer.kt │ │ │ │ ├── ReferenceSerializer.kt │ │ │ │ ├── InitialResultSerializer.kt │ │ │ │ ├── ContextSerializer.kt │ │ │ │ ├── FragmentSerializer.kt │ │ │ │ ├── SupportFragmentSerializer.kt │ │ │ │ └── SafeContinuationSerializer.kt │ │ │ ├── KotlinObjectInstantiatorStrategy.kt │ │ │ ├── ParcelOutput.kt │ │ │ ├── ParcelInput.kt │ │ │ ├── KryoIO.kt │ │ │ ├── KryoParcelable.kt │ │ │ └── AndroidKotlinResolver.kt │ │ │ └── util │ │ │ └── GrantResult.kt │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle.kts ├── testapp ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── layout │ │ │ │ ├── activity_test6.xml │ │ │ │ ├── activity_test7.xml │ │ │ │ ├── activity_test2.xml │ │ │ │ ├── activity_test1.xml │ │ │ │ └── fragment_test6.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── nl │ │ │ │ └── adaptivity │ │ │ │ └── android │ │ │ │ ├── test │ │ │ │ ├── TestActivity2.kt │ │ │ │ ├── TestActivity1.kt │ │ │ │ ├── TestActivity4.kt │ │ │ │ ├── TestActivity5.kt │ │ │ │ ├── TestActivity3.kt │ │ │ │ ├── TestActivity6.kt │ │ │ │ └── TestActivity7.kt │ │ │ │ └── kryo │ │ │ │ └── LineOutput.kt │ │ └── AndroidManifest.xml │ ├── androidTest │ │ └── java │ │ │ └── nl │ │ │ └── adaptivity │ │ │ └── android │ │ │ └── test │ │ │ ├── PlainCoroutineTestAndroid.kt │ │ │ └── TestActivity1Test.kt │ └── test │ │ └── java │ │ └── uk │ │ └── ac │ │ └── bmth │ │ └── aprog │ │ └── testapp │ │ └── PlainCoroutineTest.kt ├── proguard-rules.pro └── build.gradle.kts ├── _config.yml ├── appcompat ├── .gitignore ├── src │ └── main │ │ ├── java │ │ └── nl │ │ │ └── adaptivity │ │ │ └── android │ │ │ └── coroutinesCompat │ │ │ ├── AppcompatFragmentContext.kt │ │ │ ├── AppcompatCoroutineFragment.kt │ │ │ ├── AppcompatLaunchers.kt │ │ │ ├── CompatCoroutineActivity.kt │ │ │ ├── AppcompatFragmentCoroutineScope.kt │ │ │ └── AppcompatFragmentCoroutineScopeWrapper.kt │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle.kts ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── gradle.properties ├── proguard-project.txt ├── settings.gradle.kts ├── gradlew.bat ├── README.md ├── gradlew └── LICENSE /core/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml -------------------------------------------------------------------------------- /testapp/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /appcompat/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | local.properties 2 | /.gradle 3 | /build 4 | /gen 5 | /bin 6 | *.iml 7 | /.idea/* 8 | /wiki 9 | /pages 10 | /testapp/build 11 | -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdvrieze/android-coroutines/HEAD/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /testapp/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/coroutines/impl/DelegateLayoutContainer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutines.impl 2 | 3 | import android.view.View 4 | import kotlinx.android.extensions.LayoutContainer 5 | 6 | class DelegateLayoutContainer(override val containerView: View?) : 7 | LayoutContainer -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /testapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /testapp/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TestApp 3 | Cancelled 4 | Restored 5 | Test activity callback 6 | Test activity coroutine 7 | 8 | -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/KryoAndroidConstants.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | internal enum class KryoAndroidConstants { 4 | UNDECIDED, 5 | RESUMED, 6 | COROUTINE_SUSPENDED, 7 | APPLICATIONCONTEXT, 8 | OTHERCONTEXT, 9 | CONTEXT, 10 | FRAGMENTBYTAG, 11 | FRAGMENTBYID, 12 | FRAGMENTWITHOUTHANDLE 13 | } -------------------------------------------------------------------------------- /testapp/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.configureondemand=false 2 | android.useAndroidX=true 3 | kotlin.code.style=official 4 | kotlinVersion=1.5.20 5 | kryoVersion=4.0.2 6 | coroutinesVersion=1.5.0 7 | androidBuildToolsVersion=4.1.3 8 | dokkaVersion=1.4.30 9 | bintrayVersion=1.8.3 10 | selfVersion=0.7.992 11 | constraintLayoutVersion=1.1.3 12 | reqMinSdkVersion=16 13 | reqTargetSdkVersion=30 14 | reqCompileSdkVersion=30 15 | androidCompatVersion=28.0.0 16 | junitVersion=4.12 17 | espressoCoreVersion=3.1.0 18 | androidTestSupportVersion=1.1.0 19 | -------------------------------------------------------------------------------- /testapp/src/main/res/layout/activity_test6.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | -------------------------------------------------------------------------------- /testapp/src/main/res/layout/activity_test7.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/coroutines/contexts/FragmentContext.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutines.contexts 2 | 3 | import android.app.Fragment 4 | import java.io.Serializable 5 | import kotlin.coroutines.AbstractCoroutineContextElement 6 | import kotlin.coroutines.CoroutineContext 7 | 8 | class FragmentContext(fragment: F) : 9 | AbstractCoroutineContextElement(FragmentContext) { 10 | var fragment = fragment 11 | internal set 12 | 13 | companion object Key : CoroutineContext.Key>, 14 | Serializable 15 | 16 | override fun toString(): String = "FragmentContext" 17 | 18 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/coroutines/contexts/AndroidContext.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutines.contexts 2 | 3 | import android.content.Context 4 | import java.io.Serializable 5 | import kotlin.coroutines.AbstractCoroutineContextElement 6 | import kotlin.coroutines.CoroutineContext 7 | 8 | class AndroidContext(androidContext: C) : 9 | AbstractCoroutineContextElement(AndroidContext) { 10 | var androidContext = androidContext 11 | internal set 12 | 13 | companion object Key : CoroutineContext.Key>, 14 | Serializable 15 | 16 | override fun toString(): String = "AndroidContext" 17 | 18 | } -------------------------------------------------------------------------------- /appcompat/src/main/java/nl/adaptivity/android/coroutinesCompat/AppcompatFragmentContext.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutinesCompat 2 | 3 | import android.support.v4.app.Fragment 4 | import java.io.Serializable 5 | import kotlin.coroutines.AbstractCoroutineContextElement 6 | import kotlin.coroutines.CoroutineContext 7 | 8 | 9 | class AppcompatFragmentContext(fragment: F) : 10 | AbstractCoroutineContextElement(AppcompatFragmentContext) { 11 | var fragment = fragment 12 | internal set 13 | 14 | companion object Key : CoroutineContext.Key>, 15 | Serializable 16 | 17 | override fun toString(): String = "AppcompatFragmentContext" 18 | 19 | } -------------------------------------------------------------------------------- /appcompat/src/main/java/nl/adaptivity/android/coroutinesCompat/AppcompatCoroutineFragment.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutinesCompat 2 | 3 | import android.support.v4.app.Fragment 4 | import kotlinx.coroutines.* 5 | import kotlin.coroutines.CoroutineContext 6 | 7 | open class AppcompatCoroutineFragment>: Fragment(), 8 | AppcompatFragmentCoroutineScope { 9 | override val coroutineContext: CoroutineContext = Job() + Dispatchers.Default + AppcompatFragmentContext(this) 10 | 11 | @Suppress("UNCHECKED_CAST") 12 | override val fragment: F get() = this as F 13 | 14 | override fun onDestroy() { 15 | coroutineContext.cancel(CancellationException("Fragment is being destroyed")) 16 | super.onDestroy() 17 | } 18 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/coroutines/SimpleContextCoroutineScopeWrapper.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutines 2 | 3 | import android.content.Context 4 | import kotlinx.coroutines.CoroutineScope 5 | import nl.adaptivity.android.coroutines.contexts.AndroidContext 6 | 7 | class SimpleContextCoroutineScopeWrapper( 8 | parentScope: CoroutineScope 9 | ) : 10 | WrappedContextCoroutineScope>(parentScope) { 11 | 12 | override fun getAndroidContext() = coroutineContext[AndroidContext]!!.androidContext as C 13 | 14 | override fun createScopeWrapper(parentScope: CoroutineScope): SimpleContextCoroutineScopeWrapper { 15 | return SimpleContextCoroutineScopeWrapper(parentScope) 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/coroutines/CoroutineFragment.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutines 2 | 3 | import android.app.Fragment 4 | import kotlinx.coroutines.Dispatchers 5 | import kotlinx.coroutines.Job 6 | import kotlinx.coroutines.cancel 7 | import nl.adaptivity.android.coroutines.contexts.FragmentContext 8 | import kotlin.coroutines.CoroutineContext 9 | 10 | open class CoroutineFragment>: Fragment(), 11 | FragmentCoroutineScope { 12 | override val coroutineContext: CoroutineContext = Job() + Dispatchers.Default + FragmentContext(this) 13 | 14 | @Suppress("UNCHECKED_CAST") 15 | override val fragment: F get() = this as F 16 | 17 | override fun onDestroy() { 18 | super.onDestroy() 19 | coroutineContext.cancel() 20 | } 21 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/CoroutineImplSerializer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | import com.esotericsoftware.kryo.Kryo 4 | import com.esotericsoftware.kryo.io.Input 5 | import com.esotericsoftware.kryo.io.Output 6 | import com.esotericsoftware.kryo.serializers.FieldSerializer 7 | import com.esotericsoftware.kryo.serializers.FieldSerializerConfig 8 | 9 | internal class CoroutineImplSerializer(kryo: Kryo, type: Class<*>): FieldSerializer(kryo, type, null, FieldSerializerConfig().apply { isIgnoreSyntheticFields=false }) { 10 | override fun write(kryo: Kryo, output: Output, obj: Any?) { 11 | super.write(kryo, output, obj) 12 | } 13 | 14 | override fun read(kryo: Kryo, input: Input, type: Class): Any { 15 | return super.read(kryo, input, type) 16 | } 17 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/ContinuationImplSerializer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | import com.esotericsoftware.kryo.Kryo 4 | import com.esotericsoftware.kryo.io.Input 5 | import com.esotericsoftware.kryo.io.Output 6 | import com.esotericsoftware.kryo.serializers.FieldSerializer 7 | import com.esotericsoftware.kryo.serializers.FieldSerializerConfig 8 | 9 | internal class ContinuationImplSerializer(kryo: Kryo, type: Class<*>): FieldSerializer(kryo, type, null, FieldSerializerConfig().apply { isIgnoreSyntheticFields=false }) { 10 | override fun write(kryo: Kryo, output: Output, obj: Any?) { 11 | super.write(kryo, output, obj) 12 | } 13 | 14 | override fun read(kryo: Kryo, input: Input, type: Class): Any { 15 | return super.read(kryo, input, type) 16 | } 17 | } -------------------------------------------------------------------------------- /testapp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /core/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /appcompat/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /appcompat/src/main/java/nl/adaptivity/android/coroutinesCompat/AppcompatLaunchers.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutinesCompat 2 | 3 | import android.content.Intent 4 | import nl.adaptivity.android.coroutines.FragmentCoroutineScopeWrapper 5 | import android.support.v4.app.Fragment as SupportFragment 6 | 7 | 8 | @Suppress("unused", "DEPRECATION") 9 | inline fun SupportFragment.startActivityForResult(requestCode: Int) = this.startActivityForResult(Intent(activity, A::class.java), requestCode) 10 | 11 | 12 | @Suppress("unused", "DEPRECATION") 13 | inline fun SupportFragment.startActivity() = startActivity(Intent(activity, A::class.java)) 14 | 15 | 16 | 17 | @Suppress("unused") 18 | suspend inline fun AppcompatFragmentCoroutineScopeWrapper<*>.startActivityForResult() = 19 | startActivityForResult(Intent(fragment.activity, A::class.java)) 20 | -------------------------------------------------------------------------------- /testapp/src/main/java/nl/adaptivity/android/test/TestActivity2.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.test 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import kotlinx.android.synthetic.main.activity_test2.* 7 | 8 | /** 9 | * Simple activity that has a text box that can be passed as result. 10 | */ 11 | class TestActivity2 : Activity() { 12 | 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | setContentView(R.layout.activity_test2) 16 | button2.setOnClickListener { _ -> 17 | val result = Intent("result").apply { putExtra(KEY_DATA, textView2.text) } 18 | this@TestActivity2.setResult(Activity.RESULT_OK, result) 19 | finish() 20 | } 21 | } 22 | 23 | companion object { 24 | const val KEY_DATA="data" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | -------------------------------------------------------------------------------- /appcompat/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/StandaloneCoroutineSerializer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | import com.esotericsoftware.kryo.Kryo 4 | import com.esotericsoftware.kryo.io.Input 5 | import com.esotericsoftware.kryo.io.Output 6 | import com.esotericsoftware.kryo.serializers.FieldSerializer 7 | 8 | internal class StandaloneCoroutineSerializer(kryo: Kryo, type: Class<*>): FieldSerializer(kryo, type) { 9 | private val _parentContext: CachedField<*> = fields.first { it.field.declaringClass == type && it.field.name == "parentContext" }.also { removeField(it) } 10 | 11 | override fun create(kryo: Kryo, input: Input, type: Class): Any { 12 | val parentContext = kryo.readClassAndObject(input) 13 | return type.constructors.first().apply { isAccessible=true }.newInstance(parentContext, true) 14 | } 15 | 16 | override fun write(kryo: Kryo, output: Output, obj: Any) { 17 | _parentContext.write(output, obj) 18 | 19 | super.write(kryo, output, obj) 20 | } 21 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/PseudoObjectSerializer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | import com.esotericsoftware.kryo.Kryo 4 | import com.esotericsoftware.kryo.Serializer 5 | import com.esotericsoftware.kryo.io.Input 6 | import com.esotericsoftware.kryo.io.Output 7 | 8 | /** 9 | * Serializer for Kotlin objects that stores nothing and just retrieves the current instance from 10 | * the field. 11 | */ 12 | internal class PseudoObjectSerializer(kryo: Kryo, val type: Class, val value: T): Serializer(false, true) { 13 | /** 14 | * The correct way of getting an object is getting it's instance. 15 | */ 16 | override fun read(kryo: Kryo, input: Input, type: Class): T { 17 | return value 18 | } 19 | 20 | override fun write(kryo: Kryo, output: Output, obj: T?) { 21 | // The class is already written by the caller so no need to write anything 22 | } 23 | } 24 | 25 | internal inline fun Kryo.pseudoObjectSerializer(value:T) = PseudoObjectSerializer(this, T::class.java, value) -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/KotlinObjectInstantiatorStrategy.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo 2 | 3 | import org.objenesis.instantiator.ObjectInstantiator 4 | import org.objenesis.strategy.InstantiatorStrategy 5 | import java.lang.reflect.Modifier 6 | 7 | class KotlinObjectInstantiatorStrategy(private val fallback: InstantiatorStrategy) : InstantiatorStrategy { 8 | 9 | class KotlinObjectInstantiator(type: Class): ObjectInstantiator { 10 | @Suppress("UNCHECKED_CAST") 11 | private val objectInstance = type.getField("INSTANCE").get(null) as T 12 | 13 | override fun newInstance() = objectInstance 14 | } 15 | 16 | override fun newInstantiatorOf(type: Class): ObjectInstantiator { 17 | if (type.isKObject) { 18 | return KotlinObjectInstantiator(type) 19 | } else { 20 | return fallback.newInstantiatorOf(type) 21 | } 22 | } 23 | } 24 | 25 | internal val Class<*>.isKObject: Boolean get() { 26 | return Modifier.isFinal(modifiers) && constructors.isEmpty() && fields.any { it.name=="INSTANCE" && Modifier.isStatic(it.modifiers) } 27 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/coroutines/RetainedContinuationFragment.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutines 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | 6 | class RetainedContinuationFragment : BaseRetainedContinuationFragment>() { 7 | 8 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 9 | when { 10 | requestCode != this.requestCode && this.requestCode!=-1 -> super.onActivityResult(requestCode, resultCode, data) 11 | resultCode == Activity.RESULT_OK -> dispatchResult(Maybe.Ok(data), requestCode) 12 | resultCode == Activity.RESULT_CANCELED -> dispatchResult(Maybe.cancelled(), requestCode) 13 | else -> super.onActivityResult(requestCode, resultCode, data) 14 | } 15 | } 16 | 17 | companion object { 18 | const val TAG = "__RETAINED_CONTINUATION_FRAGMENT__" 19 | } 20 | } 21 | 22 | @Suppress("FunctionName") 23 | fun RetainedContinuationFragment(activityContinuation: ParcelableContinuation>) = RetainedContinuationFragment().also { 24 | it.addContinuation(activityContinuation) 25 | } -------------------------------------------------------------------------------- /appcompat/src/main/java/nl/adaptivity/android/coroutinesCompat/CompatCoroutineActivity.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutinesCompat 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import kotlinx.coroutines.* 5 | import nl.adaptivity.android.coroutines.ActivityCoroutineScopeWrapper 6 | import nl.adaptivity.android.coroutines.AndroidContextCoroutineScope 7 | import nl.adaptivity.android.coroutines.contexts.AndroidContext 8 | import kotlin.coroutines.CoroutineContext 9 | 10 | open class CompatCoroutineActivity>: AppCompatActivity(), 11 | AndroidContextCoroutineScope> { 12 | 13 | override fun getAndroidContext(): A = this as A 14 | 15 | override val coroutineContext: CoroutineContext = 16 | Job() + Dispatchers.Default + AndroidContext(this) 17 | 18 | override fun createScopeWrapper(parentScope: CoroutineScope): ActivityCoroutineScopeWrapper { 19 | return ActivityCoroutineScopeWrapper(parentScope) 20 | } 21 | 22 | override fun onDestroy() { 23 | coroutineContext.cancel(CancellationException("Activity is being destroyed")) 24 | super.onDestroy() 25 | } 26 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/coroutines/RequestPermissionContinuationFragment.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.coroutines 2 | 3 | import android.content.Intent 4 | import android.content.pm.PackageManager 5 | import nl.adaptivity.android.util.GrantResult 6 | 7 | class RequestPermissionContinuationFragment : BaseRetainedContinuationFragment() { 8 | 9 | override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { 10 | super.onRequestPermissionsResult(requestCode, permissions, grantResults) 11 | when { 12 | requestCode != this.requestCode -> super.onRequestPermissionsResult(requestCode, permissions, grantResults) 13 | grantResults.isEmpty() || grantResults.all { it==PackageManager.PERMISSION_DENIED } -> dispatchResult(null, requestCode) 14 | else -> dispatchResult(GrantResult(permissions, grantResults), requestCode) 15 | } 16 | } 17 | 18 | companion object { 19 | const val TAG = "__REQUEST_PERMISSION_CONTINUATION_FRAGMENT__" 20 | } 21 | } 22 | 23 | @Suppress("FunctionName") 24 | fun RequestPermissionContinuationFragment(activityContinuation: ParcelableContinuation) = RequestPermissionContinuationFragment().also { 25 | it.addContinuation(activityContinuation) 26 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/ParcelOutput.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo 2 | 3 | import android.os.Parcel 4 | import com.esotericsoftware.kryo.io.Output 5 | import java.io.OutputStream 6 | 7 | /** 8 | * Output class that uses a parcel to serialize. Perhaps not sustainable and ByteArrayStreams are better. 9 | */ 10 | class ParcelOutput: Output { 11 | private val parcel: Parcel 12 | 13 | @JvmOverloads 14 | constructor(parcel: Parcel, bufferSize: Int = DEFAULT_BUFFER) : super(bufferSize) { this.parcel = parcel } 15 | constructor(parcel: Parcel, bufferSize: Int, maxBufferSize: Int) : super(bufferSize, maxBufferSize) { this.parcel = parcel } 16 | constructor(parcel: Parcel, buffer: ByteArray?) : super(buffer) { this.parcel = parcel } 17 | constructor(parcel: Parcel, buffer: ByteArray?, maxBufferSize: Int) : super(buffer, maxBufferSize) { this.parcel = parcel } 18 | 19 | override fun setOutputStream(outputStream: OutputStream) { 20 | throw UnsupportedOperationException("ParcelInput writes to parcels, not streams") 21 | } 22 | 23 | override fun flush() { 24 | for(i in 0 until position) { 25 | parcel.writeByte(buffer[i]) 26 | } 27 | } 28 | 29 | override fun close() { 30 | // Do nothing 31 | } 32 | 33 | companion object { 34 | const val DEFAULT_BUFFER = 1024 35 | } 36 | } -------------------------------------------------------------------------------- /testapp/src/main/java/nl/adaptivity/android/test/TestActivity1.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.test 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.Activity 5 | import android.content.Intent 6 | import android.os.Bundle 7 | import kotlinx.android.synthetic.main.activity_test1.* 8 | import nl.adaptivity.android.coroutines.Maybe 9 | import nl.adaptivity.android.coroutines.withActivityResult 10 | 11 | /** 12 | * Version of the test activity that uses a callback rather than a coroutine. 13 | */ 14 | @SuppressLint("RestrictedApi") 15 | class TestActivity1 : Activity() { 16 | 17 | private val resultHandler2: TestActivity1.(Maybe) -> Unit = { result -> 18 | result.onOk { data -> textView.text = data?.getCharSequenceExtra(TestActivity2.KEY_DATA)} 19 | result.onCancelled { textView.text = getString(R.string.lbl_cancelled) } 20 | } 21 | 22 | override fun onRestoreInstanceState(savedInstanceState: Bundle) { 23 | super.onRestoreInstanceState(savedInstanceState) 24 | restoredView.text = getString(R.string.lbl_restored) 25 | } 26 | 27 | override fun onCreate(savedInstanceState: Bundle?) { 28 | super.onCreate(savedInstanceState) 29 | setContentView(R.layout.activity_test1) 30 | button.setOnClickListener({ _ -> 31 | 32 | withActivityResult(Intent(this@TestActivity1, TestActivity2::class.java), resultHandler2) 33 | }) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /testapp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/ParcelInput.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo 2 | 3 | import android.os.Parcel 4 | import com.esotericsoftware.kryo.io.Input 5 | import java.io.InputStream 6 | 7 | /** 8 | * Input class that uses a parcel to serialize. Perhaps not sustainable and ByteArrayStreams are better. 9 | */ 10 | class ParcelInput : Input { 11 | 12 | private val parcel: Parcel 13 | 14 | @JvmOverloads 15 | constructor(parcel: Parcel, bufferSize: Int = DEFAULT_BUFFER) : super(bufferSize) { this.parcel = parcel } 16 | constructor(parcel: Parcel, buffer: ByteArray?) : super(buffer) { this.parcel = parcel } 17 | constructor(parcel: Parcel, buffer: ByteArray?, offset: Int, count: Int) : super(buffer, offset, count) { this.parcel = parcel } 18 | 19 | 20 | override fun setInputStream(inputStream: InputStream?) { 21 | throw UnsupportedOperationException("ParcelInput reads from parcels, not streams") 22 | } 23 | 24 | override fun fill(buffer: ByteArray, offset: Int, count: Int): Int { 25 | val realCount = minOf(count, parcel.dataAvail()) 26 | for (i in offset until realCount) { 27 | buffer[i] = parcel.readByte() 28 | } 29 | return realCount 30 | } 31 | 32 | override fun available(): Int { 33 | return limit - position + parcel.dataAvail() 34 | } 35 | 36 | override fun close() { 37 | // Don't do anything for now. Don't do our own recycling here. 38 | } 39 | 40 | companion object { 41 | const val DEFAULT_BUFFER = 1024 42 | } 43 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/util/GrantResult.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.util 2 | 3 | import android.content.pm.PackageManager 4 | import java.util.* 5 | 6 | /** 7 | * Class representing the result of a permission request 8 | * @property permissions The permissions requested 9 | * @property grantResults The result of the request 10 | */ 11 | data class GrantResult(val permissions: Array, val grantResults: IntArray) { 12 | /** 13 | * Convenience method to check whether a permission was granted. 14 | */ 15 | fun wasGranted(permission:String): Boolean { 16 | val index = permissions.indexOf(permission).also { if (it<0) return false } 17 | return grantResults[index] == PackageManager.PERMISSION_GRANTED 18 | } 19 | 20 | /** 21 | * Convenience property to determine whether all permissions requested were granted. 22 | */ 23 | val allGranted: Boolean = grantResults.all { it== PackageManager.PERMISSION_GRANTED } 24 | 25 | override fun equals(other: Any?): Boolean { 26 | if (this === other) return true 27 | if (javaClass != other?.javaClass) return false 28 | 29 | other as GrantResult 30 | 31 | if (!Arrays.equals(permissions, other.permissions)) return false 32 | if (!Arrays.equals(grantResults, other.grantResults)) return false 33 | 34 | return true 35 | } 36 | 37 | override fun hashCode(): Int { 38 | var result = Arrays.hashCode(permissions) 39 | result = 31 * result + Arrays.hashCode(grantResults) 40 | return result 41 | } 42 | } -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | pluginManagement { 3 | val androidBuildToolsVersion: String by settings 4 | val kotlinVersion: String by settings 5 | val dokkaVersion: String by settings 6 | val bintrayVersion: String by settings 7 | 8 | repositories { 9 | gradlePluginPortal() 10 | google() 11 | maven(url = "https://dl.bintray.com/kotlin/kotlin-eap") 12 | // maven("https://dl.bintray.com/kotlin/kotlin-dev") 13 | } 14 | 15 | resolutionStrategy { 16 | eachPlugin { 17 | when (requested.id.id) { 18 | "com.android.library", 19 | "com.android.application" -> { 20 | val ver = requested.version ?: androidBuildToolsVersion 21 | useModule("com.android.tools.build:gradle:${ver}"); 22 | } 23 | "org.jetbrains.kotlin.android", 24 | "kotlin-android-extensions" -> { 25 | val ver = requested.version ?: kotlinVersion 26 | useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${ver}"); 27 | } 28 | "org.jetbrains.dokka" -> { 29 | val ver = requested.version ?: dokkaVersion 30 | useVersion(ver) 31 | // useModule("${requested.module}:${ver}") 32 | } 33 | "com.jfrog.bintray" -> { 34 | val ver = requested.version ?: bintrayVersion 35 | useVersion(ver) 36 | } 37 | } 38 | } 39 | } 40 | } 41 | 42 | include(":testapp", ":core", ":appcompat") 43 | -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/ObjectSerializer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | import android.accounts.AccountManager 4 | import android.content.Context 5 | import com.esotericsoftware.kryo.Kryo 6 | import com.esotericsoftware.kryo.Serializer 7 | import com.esotericsoftware.kryo.io.Input 8 | import com.esotericsoftware.kryo.io.Output 9 | 10 | /** 11 | * Serializer for Kotlin objects that stores nothing and just retrieves the current instance from 12 | * the field. 13 | */ 14 | internal class ObjectSerializer(kryo: Kryo, val type: Class<*>): Serializer(false, true) { 15 | /** 16 | * The correct way of getting an object is getting it's instance. 17 | */ 18 | override fun read(kryo: Kryo, input: Input, type: Class): Any { 19 | return type.fields.first { it.name=="INSTANCE" }.get(null) 20 | } 21 | 22 | override fun write(kryo: Kryo, output: Output, obj: Any?) { 23 | // The class is already written by the caller so no need to write anything 24 | } 25 | } 26 | 27 | /** 28 | * Serializer for Kotlin objects that stores nothing and just retrieves the current instance from 29 | * the field. 30 | */ 31 | internal class AccountManagerSerializer(kryo: Kryo, val type: Class<*>, context: Context?): Serializer(false, true) { 32 | private val context = context?.applicationContext 33 | /** 34 | * The correct way of getting an object is getting it's instance. 35 | */ 36 | override fun read(kryo: Kryo, input: Input, type: Class): Any { 37 | return AccountManager.get(context) 38 | } 39 | 40 | override fun write(kryo: Kryo, output: Output, obj: Any?) { 41 | // The class is already written by the caller so no need to write anything 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/ReferenceSerializer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | import com.esotericsoftware.kryo.Kryo 4 | import com.esotericsoftware.kryo.Serializer 5 | import com.esotericsoftware.kryo.io.Input 6 | import com.esotericsoftware.kryo.io.Output 7 | import nl.adaptivity.android.kryo.serializers.ReferenceType.* 8 | import java.lang.ref.Reference 9 | import java.lang.ref.SoftReference 10 | import java.lang.ref.WeakReference 11 | 12 | /** 13 | * Serializer for Kotlin objects that stores nothing and just retrieves the current instance from 14 | * the field. 15 | */ 16 | internal class ReferenceSerializer(kryo: Kryo, val type: Class>): Serializer>(false, true) { 17 | /** 18 | * The correct way of getting an object is getting it's instance. 19 | */ 20 | override fun read(kryo: Kryo, input: Input, type: Class>): Reference<*> { 21 | val result = when (kryo.readObject(input, ReferenceType::class.java)) { 22 | SOFTREF -> SoftReference(null) 23 | WEAKREF -> WeakReference(null) 24 | else -> throw IllegalArgumentException("Unsupported reference") 25 | } 26 | return result 27 | } 28 | 29 | override fun write(kryo: Kryo, output: Output, obj: Reference<*>?) { 30 | val substitute = when (obj) { 31 | is SoftReference<*> -> SOFTREF 32 | is WeakReference<*> -> WEAKREF 33 | else -> IllegalArgumentException("Serializing contexts only works for Soft and Weak references") 34 | } 35 | kryo.writeObject(output, substitute) 36 | // The class is already written by the caller so no need to write anything 37 | } 38 | } 39 | 40 | private enum class ReferenceType { 41 | SOFTREF, 42 | WEAKREF 43 | } -------------------------------------------------------------------------------- /core/src/main/java/nl/adaptivity/android/kryo/serializers/InitialResultSerializer.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.kryo.serializers 2 | 3 | import com.esotericsoftware.kryo.Kryo 4 | import com.esotericsoftware.kryo.Serializer 5 | import com.esotericsoftware.kryo.io.Input 6 | import com.esotericsoftware.kryo.io.Output 7 | import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED 8 | 9 | internal class InitialResultSerializer(val parent: Serializer): Serializer() { 10 | override fun read(kryo: Kryo, input: Input, type: Class): Any? { 11 | val readValue = kryo.readClassAndObject(input) 12 | return when (readValue) { 13 | KryoAndroidConstants.COROUTINE_SUSPENDED -> COROUTINE_SUSPENDED 14 | else -> readValue 15 | } 16 | } 17 | 18 | override fun write(kryo: Kryo, output: Output, obj: Any?) { 19 | when (obj) { 20 | // COROUTINE_SUSPENDED -> kryo.writeClassAndObject(output, KryoAndroidConstants.COROUTINE_SUSPENDED) 21 | // _Resumed -> kryo.writeClassAndObject(output, KryoAndroidConstants.RESUMED) 22 | // _Undecided -> kryo.writeClassAndObject(output, KryoAndroidConstants.UNDECIDED) 23 | else -> parent.write(kryo, output, obj) 24 | } 25 | } 26 | 27 | override fun isImmutable(): Boolean = parent.isImmutable() 28 | 29 | override fun setImmutable(immutable: Boolean) = parent.setImmutable(immutable) 30 | 31 | override fun setAcceptsNull(acceptsNull: Boolean) = parent.setAcceptsNull(acceptsNull) 32 | 33 | override fun copy(kryo: Kryo?, original: Any?): Any? = parent.copy(kryo, original) 34 | 35 | override fun getAcceptsNull(): Boolean = parent.getAcceptsNull() 36 | 37 | override fun setGenerics(kryo: Kryo?, generics: Array>?) = 38 | parent.setGenerics(kryo, generics) 39 | } 40 | 41 | -------------------------------------------------------------------------------- /testapp/src/main/java/nl/adaptivity/android/test/TestActivity4.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.test 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import kotlinx.android.synthetic.main.activity_test1.* 6 | import kotlinx.coroutines.CoroutineStart 7 | import kotlinx.coroutines.Dispatchers 8 | import nl.adaptivity.android.coroutines.CoroutineActivity 9 | import nl.adaptivity.android.coroutines.startActivityForResult 10 | 11 | /** 12 | * Implementation of an activity that uses an async launch to get a result from an activity using 13 | * coroutines. It uses the "safe" launch function and a synthetic accessor for the contained views. 14 | */ 15 | class TestActivity4 : CoroutineActivity() { 16 | 17 | override fun onRestoreInstanceState(savedInstanceState: Bundle) { 18 | super.onRestoreInstanceState(savedInstanceState) 19 | restoredView.text = getString(R.string.lbl_restored) 20 | } 21 | 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | super.onCreate(savedInstanceState) 24 | setContentView(R.layout.activity_test1) 25 | button.setOnClickListener { onButtonClick() } 26 | } 27 | 28 | fun onButtonClick() { 29 | Log.w(TAG, "Activity is: $this") 30 | launch(start = CoroutineStart.UNDISPATCHED, context = Dispatchers.Main) { 31 | val activityResult = startActivityForResult() 32 | 33 | Log.w(TAG, "Deserialised Activity is: $activity") 34 | val newText = activityResult.flatMap { it?.getCharSequenceExtra(TestActivity2.KEY_DATA) } ?: getString(R.string.lbl_cancelled) 35 | Log.w(TAG, "newText: $newText") 36 | 37 | Log.w(TAG, "textview value: $textView") 38 | textView.text = newText 39 | } 40 | } 41 | 42 | companion object { 43 | const val TAG="TestActivity4" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /testapp/src/main/java/nl/adaptivity/android/test/TestActivity5.kt: -------------------------------------------------------------------------------- 1 | package nl.adaptivity.android.test 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import kotlinx.android.synthetic.main.activity_test1.* 6 | import kotlinx.coroutines.CoroutineStart 7 | import kotlinx.coroutines.Dispatchers 8 | import nl.adaptivity.android.coroutines.startActivityForResult 9 | import nl.adaptivity.android.coroutinesCompat.CompatCoroutineActivity 10 | 11 | /** 12 | * Implementation of an activity that uses an async launch to get a result from an activity using 13 | * coroutines. It uses the "safe" launch function and a synthetic accessor for the contained views. 14 | */ 15 | class TestActivity5 : CompatCoroutineActivity() { 16 | 17 | override fun onRestoreInstanceState(savedInstanceState: Bundle) { 18 | super.onRestoreInstanceState(savedInstanceState) 19 | restoredView.text = getString(R.string.lbl_restored) 20 | } 21 | 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | super.onCreate(savedInstanceState) 24 | setContentView(R.layout.activity_test1) 25 | button.setOnClickListener { onButtonClick() } 26 | } 27 | 28 | fun onButtonClick() { 29 | Log.w(TAG, "Activity is: $this") 30 | launch(start = CoroutineStart.UNDISPATCHED, context = Dispatchers.Main) { 31 | val activityResult = startActivityForResult() 32 | 33 | Log.w(TAG, "Deserialised Activity is: $activity") 34 | val newText = activityResult.flatMap { it?.getCharSequenceExtra(TestActivity2.KEY_DATA) } ?: getString(R.string.lbl_cancelled) 35 | Log.w(TAG, "newText: $newText") 36 | 37 | Log.w(TAG, "textview value: $textView") 38 | textView.text = newText 39 | } 40 | } 41 | 42 | companion object { 43 | const val TAG="TestActivity5" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /testapp/src/main/res/layout/activity_test2.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 24 | 25 |