Skip to content

Commit eab8d9a

Browse files
authored
Merge pull request #11 from studyplus/feature/remove_gson
GSON/Retrofitを削除
2 parents d0e0741 + a54a950 commit eab8d9a

File tree

13 files changed

+139
-139
lines changed

13 files changed

+139
-139
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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.3.0'
4+
ext.kotlin_version = '1.3.10'
55
ext.versions = [
66
'compileSdk': 27,
77
'minSdk': 16,

studyplus-android-sdk2/build.gradle

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,25 +60,29 @@ android {
6060
}
6161
}
6262
}
63+
64+
testOptions {
65+
unitTests {
66+
includeAndroidResources = true
67+
}
68+
}
6369
}
6470

6571
dependencies {
6672
implementation fileTree(dir: 'libs', include: ['*.jar'])
6773
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'
7074

71-
implementation 'com.google.code.gson:gson:2.8.5'
72-
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
75+
def coroutines = "1.0.1"
76+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
77+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
7378

74-
def retrofit = "2.4.0"
75-
implementation "com.squareup.retrofit2:retrofit:$retrofit"
76-
implementation "com.squareup.retrofit2:converter-gson:$retrofit"
77-
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
79+
def okhttp = "3.12.0"
80+
implementation "com.squareup.okhttp3:okhttp:$okhttp"
7881

7982
testImplementation 'junit:junit:4.12'
83+
testImplementation 'org.robolectric:robolectric:4.0.2'
8084
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
81-
testImplementation "com.squareup.retrofit2:retrofit-mock:$retrofit"
85+
testImplementation "com.squareup.okhttp3:mockwebserver:$okhttp"
8286
}
8387

8488
apply from: 'build.publish.gradle'

studyplus-android-sdk2/lib-proguard-rules.txt

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

23-
# SDK2
24-
# Network Response
25-
-keepnames class jp.studyplus.android.sdk.record.** { *; }
26-
-keepnames class jp.studyplus.android.sdk.internal.api.response.** { *; }
27-
2823
# Kotlin Coroutines
2924
# ServiceLoader support
3025
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
@@ -35,27 +30,15 @@
3530
volatile <fields>;
3631
}
3732

38-
# Stuire
33+
# OkHttp
3934
# JSR 305 annotations are for embedding nullability information.
4035
-dontwarn javax.annotation.**
36+
4137
# A resource is loaded with a relative path so the package of this class must be preserved.
4238
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
39+
4340
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
4441
-dontwarn org.codehaus.mojo.animal_sniffer.*
42+
4543
# OkHttp platform used only on JVM and when Conscrypt dependency is available.
4644
-dontwarn okhttp3.internal.platform.ConscryptPlatform
47-
48-
# Retrofit does reflection on generic parameters and InnerClass is required to use Signature.
49-
-keepattributes Signature, InnerClasses
50-
# Retain service method parameters when optimizing.
51-
-keepclassmembers,allowshrinking,allowobfuscation interface * {
52-
@retrofit2.http.* <methods>;
53-
}
54-
# Ignore annotation used for build tooling.
55-
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
56-
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
57-
-dontwarn kotlin.Unit
58-
# Top-level functions that can only be used by Kotlin.
59-
-dontwarn retrofit2.-KotlinExtensions
60-
61-

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ class Studyplus private constructor() {
7474
runBlocking {
7575
try {
7676
val deferred = ApiClient.postStudyRecords(context, studyRecord)
77-
val result = deferred.await()
78-
listener?.onResult(success = true, recordId = result.recordId)
77+
val recordId = deferred.await()
78+
listener?.onResult(success = true, recordId = recordId)
7979
} catch (t: Throwable) {
8080
listener?.onResult(success = false, throwable = t)
8181
}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
package jp.studyplus.android.sdk.internal.api
22

33
import android.content.Context
4-
import jp.studyplus.android.sdk.internal.api.response.PostStudyRecordsResponse
54
import jp.studyplus.android.sdk.record.StudyRecord
65
import kotlinx.coroutines.Deferred
76

87
internal object ApiClient {
9-
private val apiService by lazy { ApiManager.retrofit.create(ApiService::class.java) }
10-
11-
fun postStudyRecords(context: Context, studyRecord: StudyRecord): Deferred<PostStudyRecordsResponse> {
12-
return apiService.postStudyRecords(CertificationStore.create(context).getOAuthAccessToken(), studyRecord)
8+
fun postStudyRecords(context: Context, studyRecord: StudyRecord): Deferred<Long?> {
9+
return ApiService(ApiManager.client).post(CertificationStore.create(context).getOAuthAccessToken(), studyRecord.toJson())
1310
}
1411
}
Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,14 @@
11
package jp.studyplus.android.sdk.internal.api
22

3-
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
4-
import jp.studyplus.android.sdk.BuildConfig
53
import okhttp3.OkHttpClient
6-
import retrofit2.Retrofit
7-
import retrofit2.converter.gson.GsonConverterFactory
84
import java.util.concurrent.TimeUnit
95

106
internal object ApiManager {
11-
12-
private val client: OkHttpClient by lazy {
7+
val client: OkHttpClient by lazy {
138
OkHttpClient.Builder()
149
.connectTimeout(60, TimeUnit.SECONDS)
1510
.writeTimeout(60, TimeUnit.SECONDS)
1611
.readTimeout(60, TimeUnit.SECONDS)
1712
.build()
1813
}
19-
20-
val retrofit: Retrofit by lazy {
21-
Retrofit.Builder()
22-
.client(client)
23-
.baseUrl(BuildConfig.API_ENDPOINT)
24-
.addCallAdapterFactory(CoroutineCallAdapterFactory())
25-
.addConverterFactory(GsonConverterFactory.create())
26-
.build()
27-
}
2814
}
Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,69 @@
11
package jp.studyplus.android.sdk.internal.api
22

3-
import jp.studyplus.android.sdk.internal.api.response.PostStudyRecordsResponse
4-
import jp.studyplus.android.sdk.record.StudyRecord
3+
import jp.studyplus.android.sdk.BuildConfig
4+
import kotlinx.coroutines.CompletableDeferred
55
import kotlinx.coroutines.Deferred
6-
import retrofit2.http.Body
7-
import retrofit2.http.Header
8-
import retrofit2.http.Headers
9-
import retrofit2.http.POST
10-
11-
internal interface ApiService {
12-
@Headers(value = [
13-
"Accept: application/json",
14-
"Content-type: application/json"
15-
])
16-
@POST("/v1/study_records")
17-
fun postStudyRecords(
18-
@Header("Authorization") oauth: String,
19-
@Body studyRecord: StudyRecord
20-
): Deferred<PostStudyRecordsResponse>
21-
}
6+
import okhttp3.*
7+
import org.json.JSONObject
8+
import java.io.IOException
9+
10+
internal class ApiService(private val client: OkHttpClient) {
11+
fun post(auth: String, json: String): Deferred<Long?> {
12+
val body = createPostBody(json)
13+
val request = Request.Builder()
14+
.header("Accept", HEADER_JSON)
15+
.header("Content-type", HEADER_JSON)
16+
.addHeader("Authorization", auth)
17+
.url("$ENDPOINT/v1/study_records")
18+
.post(body)
19+
.build()
20+
21+
return execute(client.newCall(request))
22+
}
23+
24+
companion object {
25+
private const val ENDPOINT = BuildConfig.API_ENDPOINT
26+
private const val HEADER_JSON = "application/json"
27+
}
28+
}
29+
30+
private val JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8")
31+
32+
internal fun createPostBody(json: String) =
33+
RequestBody.create(JSON_MEDIA_TYPE, json)
34+
35+
internal fun execute(call: Call): Deferred<Long?> {
36+
val deferred = CompletableDeferred<Long?>()
37+
deferred.invokeOnCompletion {
38+
if (deferred.isCancelled) {
39+
call.cancel()
40+
}
41+
}
42+
43+
call.enqueue(object : Callback {
44+
private val EMPTY_JSON = "{}"
45+
private val RECORD_ID = "record_id"
46+
private val INVALID_RECORD_ID = -1L
47+
48+
override fun onFailure(call: Call, e: IOException) {
49+
deferred.completeExceptionally(e)
50+
}
51+
52+
override fun onResponse(call: Call, response: Response) {
53+
if (response.isSuccessful) {
54+
val parsedJson = JSONObject(response.body()?.string() ?: EMPTY_JSON)
55+
val recordId = parsedJson.optLong(RECORD_ID, INVALID_RECORD_ID)
56+
57+
if (recordId != INVALID_RECORD_ID) {
58+
deferred.complete(recordId)
59+
} else {
60+
deferred.complete(null)
61+
}
62+
} else {
63+
deferred.completeExceptionally(IOException(response.toString()))
64+
}
65+
}
66+
})
67+
68+
return deferred
69+
}

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

Lines changed: 0 additions & 8 deletions
This file was deleted.

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

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,40 @@
11
package jp.studyplus.android.sdk.record
22

3-
import com.google.gson.annotations.SerializedName
43
import jp.studyplus.android.sdk.record.StudyRecord.Companion.getTime
4+
import org.json.JSONObject
55
import java.security.InvalidParameterException
66
import java.text.SimpleDateFormat
77
import java.util.*
88

99
class StudyRecord {
10-
companion object {
10+
var recordedTime: String = getTime(GregorianCalendar(DATE_TIME_ZONE, DATE_LOCALE))
11+
12+
var duration: Int = 0
13+
var comment: String = ""
14+
var amountTotal: Int? = null
15+
var startPosition: Int? = null
16+
var endPosition: Int? = null
17+
18+
fun toJson() = JSONObject().apply {
19+
put("recorded_at", recordedTime)
20+
put("duration", duration)
21+
put("comment", comment)
22+
put("amountTotal", amountTotal)
23+
put("start_position", startPosition)
24+
put("end_position", endPosition)
25+
}.toString()
1126

27+
companion object {
1228
private const val DATE_FORMAT = "yyyy'-'MM'-'dd' 'HH':'mm':'ss"
13-
val DATE_LOCALE: Locale = Locale.US
14-
val DATE_TIME_ZONE: TimeZone = TimeZone.getTimeZone("UTC")
29+
private val DATE_LOCALE: Locale = Locale.US
30+
private val DATE_TIME_ZONE: TimeZone = TimeZone.getTimeZone("UTC")
1531

16-
fun getTime(calendar: Calendar): String {
32+
internal fun getTime(calendar: Calendar): String {
1733
val format = SimpleDateFormat(DATE_FORMAT, DATE_LOCALE)
1834
format.timeZone = calendar.timeZone
1935
return format.format(calendar.time)
2036
}
2137
}
22-
23-
@SerializedName("recorded_at")
24-
var recordedTime: String = getTime(GregorianCalendar(DATE_TIME_ZONE, DATE_LOCALE))
25-
@SerializedName("duration")
26-
var duration: Int = 0
27-
@SerializedName("comment")
28-
var comment: String = ""
29-
@SerializedName("amount")
30-
var amountTotal: Int? = null
31-
@SerializedName("start_position")
32-
var startPosition: Int? = null
33-
@SerializedName("end_position")
34-
var endPosition: Int? = null
3538
}
3639

3740
class StudyRecordBuilder {

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@ import jp.studyplus.android.sdk.internal.api.MockApiClient
44
import jp.studyplus.android.sdk.record.StudyRecordBuilder
55
import kotlinx.coroutines.runBlocking
66
import org.junit.Test
7+
import org.junit.runner.RunWith
8+
import org.robolectric.RobolectricTestRunner
79
import kotlin.test.assertEquals
810
import kotlin.test.assertNull
911

12+
@RunWith(RobolectricTestRunner::class)
1013
class ApiUnitTest {
1114

1215
@Test
1316
fun mockApi() {
1417
val record = StudyRecordBuilder().build()
1518
runBlocking {
1619
try {
17-
val deferred = MockApiClient.apiClient.postStudyRecords(null, record)
18-
val result = deferred.await()
20+
val deferred = MockApiClient.postStudyRecords(null, record)
21+
val recordId = deferred.await()
1922

20-
assertEquals(result.recordId, 9999L)
23+
assertEquals(recordId, 9999L)
2124
} catch (t: Throwable) {
2225
assertNull(t)
2326
}

0 commit comments

Comments
 (0)