Skip to content
This repository was archived by the owner on Jun 28, 2019. It is now read-only.

Commit f688448

Browse files
authored
Merge pull request #10 from studyplus/feature/kotlin_coroutines
Kotlin Coroutinesの導入
2 parents 9fb4a44 + d53d634 commit f688448

File tree

12 files changed

+79
-87
lines changed

12 files changed

+79
-87
lines changed

build.gradle

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22

33
buildscript {
4-
ext.kotlin_version = '1.2.61'
4+
ext.kotlin_version = '1.3.0'
55
ext.versions = [
66
'compileSdk': 27,
77
'minSdk': 16,
88
'targetSdk': 27,
99
'supportLibrary': '27.1.1',
10-
'constraintLayout': '1.1.3',
11-
'gson': '2.8.5',
12-
'okhttp': '3.10.0',
13-
'retrofit' : '2.4.0',
14-
'rx2java' : '2.2.0',
15-
'rx2android' : '2.1.0'
10+
'constraintLayout': '1.1.3'
1611
]
1712
repositories {
1813
google()
1914
jcenter()
2015
}
2116
dependencies {
22-
classpath 'com.android.tools.build:gradle:3.1.4'
17+
classpath 'com.android.tools.build:gradle:3.2.1'
2318
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
2419
}
2520
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Sun Jul 01 16:03:41 JST 2018
1+
#Tue Oct 30 15:28:34 JST 2018
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip

studyplus-android-sdk2/build.gradle

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ android {
3333
version = versionName
3434
group = "jp.studyplus.android.sdk"
3535

36+
consumerProguardFiles 'lib-proguard-rules.txt'
37+
3638
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
3739
}
3840

@@ -44,9 +46,6 @@ android {
4446
initWith(buildTypes.debug)
4547
}
4648
release {
47-
minifyEnabled true
48-
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
49-
5049
buildConfigField "String", "API_ENDPOINT", quote("https://external-api.studyplus.jp")
5150
}
5251
}
@@ -65,23 +64,22 @@ android {
6564

6665
dependencies {
6766
implementation fileTree(dir: 'libs', include: ['*.jar'])
67+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
68+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'
69+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'
6870

69-
implementation "com.google.code.gson:gson:${versions.gson}"
70-
71-
implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}"
72-
implementation "com.squareup.okhttp3:logging-interceptor:${versions.okhttp}"
71+
implementation 'com.google.code.gson:gson:2.8.5'
72+
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
7373

74-
implementation "com.squareup.retrofit2:retrofit:${versions.retrofit}"
75-
implementation "com.squareup.retrofit2:adapter-rxjava2:${versions.retrofit}"
76-
implementation "com.squareup.retrofit2:converter-gson:${versions.retrofit}"
77-
testImplementation "com.squareup.retrofit2:retrofit-mock:${versions.retrofit}"
74+
def retrofit = "2.4.0"
75+
implementation "com.squareup.retrofit2:retrofit:$retrofit"
76+
implementation "com.squareup.retrofit2:converter-gson:$retrofit"
77+
testImplementation "com.squareup.retrofit2:retrofit-mock:$retrofit"
7878

79-
implementation "io.reactivex.rxjava2:rxjava:${versions.rx2java}"
80-
implementation "io.reactivex.rxjava2:rxandroid:${versions.rx2android}"
79+
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
8180

8281
testImplementation 'junit:junit:4.12'
83-
84-
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
82+
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
8583
}
8684

8785
apply from: 'build.publish.gradle'

studyplus-android-sdk2/proguard-rules.pro renamed to studyplus-android-sdk2/lib-proguard-rules.pro

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,14 @@
2020
# hide the original source file name.
2121
#-renamesourcefileattribute SourceFile
2222

23-
-keep public class jp.studyplus.android.sdk.* { public *; }
24-
-keep public class jp.studyplus.android.sdk.record.** { public *; }
23+
# ServiceLoader support
24+
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
25+
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
26+
27+
# Most of volatile fields are updated with AFU and should not be mangled
28+
-keepclassmembernames class kotlinx.** {
29+
volatile <fields>;
30+
}
31+
32+
# Network Rsponse
33+
-keepnames class jp.studyplus.android.sdk.internal.api.response.** { *; }

studyplus-android-sdk2/src/main/java/jp/studyplus/android/sdk/Studyplus.kt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ import android.app.Activity
44
import android.content.Context
55
import android.content.Intent
66
import android.util.Log
7-
import io.reactivex.android.schedulers.AndroidSchedulers
8-
import io.reactivex.schedulers.Schedulers
97
import jp.studyplus.android.sdk.internal.api.ApiClient
108
import jp.studyplus.android.sdk.internal.api.CertificationStore
119
import jp.studyplus.android.sdk.internal.auth.AuthTransit
1210
import jp.studyplus.android.sdk.record.StudyRecord
11+
import kotlinx.coroutines.runBlocking
1312

1413
class Studyplus private constructor() {
1514

@@ -72,13 +71,15 @@ class Studyplus private constructor() {
7271
throw IllegalStateException("Please check your application's authentication before this method call.")
7372
}
7473

75-
ApiClient.apiClient.postStudyRecords(context, studyRecord)
76-
.subscribeOn(Schedulers.newThread())
77-
.observeOn(AndroidSchedulers.mainThread())
78-
.subscribe(
79-
{ listener?.onResult(success = true, recordId = it.recordId) },
80-
{ listener?.onResult(success = false, throwable = it) }
81-
)
74+
runBlocking {
75+
try {
76+
val deferred = ApiClient.postStudyRecords(context, studyRecord)
77+
val result = deferred.await()
78+
listener?.onResult(success = true, recordId = result.recordId)
79+
} catch (t: Throwable) {
80+
listener?.onResult(success = false, throwable = t)
81+
}
82+
}
8283
}
8384

8485
companion object {
Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,14 @@
11
package jp.studyplus.android.sdk.internal.api
22

33
import android.content.Context
4-
import io.reactivex.Observable
54
import jp.studyplus.android.sdk.internal.api.response.PostStudyRecordsResponse
65
import jp.studyplus.android.sdk.record.StudyRecord
7-
import retrofit2.Retrofit
6+
import kotlinx.coroutines.Deferred
87

9-
internal class ApiClient
10-
constructor(retrofit: Retrofit) {
8+
internal object ApiClient {
9+
private val apiService by lazy { ApiManager.retrofit.create(ApiService::class.java) }
1110

12-
companion object {
13-
val apiClient by lazy { ApiClient(ApiManager.retrofit) }
14-
lateinit var apiService: ApiService
15-
16-
private fun getOAuthAccessToken(context: Context): Observable<String> {
17-
return Observable.just(CertificationStore.create(context))
18-
.map { it.apiCertification() }
19-
.map { "OAuth $it" }
20-
}
21-
}
22-
23-
init {
24-
apiService = retrofit.create(ApiService::class.java)
25-
}
26-
27-
fun postStudyRecords(context: Context, studyRecord: StudyRecord): Observable<PostStudyRecordsResponse> {
28-
return getOAuthAccessToken(context).flatMap { apiService.postStudyRecords(it, studyRecord) }
11+
fun postStudyRecords(context: Context, studyRecord: StudyRecord): Deferred<PostStudyRecordsResponse> {
12+
return apiService.postStudyRecords(CertificationStore.create(context).getOAuthAccessToken(), studyRecord)
2913
}
30-
}
14+
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
package jp.studyplus.android.sdk.internal.api
22

3+
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
34
import jp.studyplus.android.sdk.BuildConfig
45
import okhttp3.OkHttpClient
56
import retrofit2.Retrofit
6-
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
77
import retrofit2.converter.gson.GsonConverterFactory
88
import java.util.concurrent.TimeUnit
99

1010
internal object ApiManager {
1111

12-
private val client by lazy {
12+
private val client: OkHttpClient by lazy {
1313
OkHttpClient.Builder()
1414
.connectTimeout(60, TimeUnit.SECONDS)
1515
.writeTimeout(60, TimeUnit.SECONDS)
1616
.readTimeout(60, TimeUnit.SECONDS)
1717
.build()
1818
}
1919

20-
val retrofit by lazy {
20+
val retrofit: Retrofit by lazy {
2121
Retrofit.Builder()
2222
.client(client)
2323
.baseUrl(BuildConfig.API_ENDPOINT)
24-
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
24+
.addCallAdapterFactory(CoroutineCallAdapterFactory())
2525
.addConverterFactory(GsonConverterFactory.create())
26-
.build()!!
26+
.build()
2727
}
2828
}
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package jp.studyplus.android.sdk.internal.api
22

3-
import io.reactivex.Observable
43
import jp.studyplus.android.sdk.internal.api.response.PostStudyRecordsResponse
54
import jp.studyplus.android.sdk.record.StudyRecord
6-
import retrofit2.http.*
5+
import kotlinx.coroutines.Deferred
6+
import retrofit2.http.Body
7+
import retrofit2.http.Header
8+
import retrofit2.http.Headers
9+
import retrofit2.http.POST
710

811
internal interface ApiService {
912
@Headers(value = [
@@ -13,6 +16,6 @@ internal interface ApiService {
1316
@POST("/v1/study_records")
1417
fun postStudyRecords(
1518
@Header("Authorization") oauth: String,
16-
@Body studyRecord: StudyRecord)
17-
: Observable<PostStudyRecordsResponse>
19+
@Body studyRecord: StudyRecord
20+
): Deferred<PostStudyRecordsResponse>
1821
}

studyplus-android-sdk2/src/main/java/jp/studyplus/android/sdk/internal/api/CertificationStore.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ private constructor(private val preferences: SharedPreferences) {
2929
return !token.isNullOrEmpty()
3030
}
3131

32-
fun apiCertification(): String = preferences.getString(KEY_ACCESS_TOKEN, "")
32+
fun getOAuthAccessToken(): String {
33+
val certification = preferences.getString(KEY_ACCESS_TOKEN, "")
34+
return "OAuth $certification"
35+
}
3336

3437
fun update(data: Intent) {
3538
val code = data.getStringExtra(EXTRA_SP_AUTH_RESULT_CODE).orEmpty()

studyplus-android-sdk2/src/test/java/jp/studyplus/android/sdk/ApiUnitTest.kt

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,25 @@ package jp.studyplus.android.sdk
22

33
import jp.studyplus.android.sdk.internal.api.MockApiClient
44
import jp.studyplus.android.sdk.record.StudyRecordBuilder
5+
import kotlinx.coroutines.runBlocking
56
import org.junit.Test
7+
import kotlin.test.assertEquals
8+
import kotlin.test.assertNull
69

710
class ApiUnitTest {
811

912
@Test
1013
fun mockApi() {
1114
val record = StudyRecordBuilder().build()
12-
MockApiClient.apiClient.postStudyRecords(null, record)
13-
.test()
14-
.assertNoErrors()
15-
.assertValue {
16-
it.recordId?.let {
17-
it == 9999L
18-
} ?: run {
19-
false
20-
}
21-
}
15+
runBlocking {
16+
try {
17+
val deferred = MockApiClient.apiClient.postStudyRecords(null, record)
18+
val result = deferred.await()
19+
20+
assertEquals(result.recordId, 9999L)
21+
} catch (t: Throwable) {
22+
assertNull(t)
23+
}
24+
}
2225
}
2326
}

0 commit comments

Comments
 (0)