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

Commit

Permalink
Merge pull request #7 from studyplus/develop
Browse files Browse the repository at this point in the history
Docの追加、内部処理改善
  • Loading branch information
koji-1009 authored Sep 14, 2018
2 parents a1bdc91 + 3f75847 commit 9fb4a44
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 101 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Studyplus-Android-SDK-V2

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/jp.studyplus.android.sdk/studyplus-android-sdk2/badge.svg)](https://maven-badges.herokuapp.com/maven-central/jp.studyplus.android.sdk/studyplus-android-sdk2)

## Requirements
- Android 4.1+
- [Studyplus App 2.14+](https://play.google.com/store/apps/details?id=jp.studyplus.android.app)
Expand All @@ -8,23 +10,23 @@
## Import in your Project

### Gradle file (app)

```
repositories {
mavenCentral()
}
dependencies {
implementation ('jp.studyplus.android.sdk:studyplus-android-sdk2:2.0.0@aar') {
transitive = true
}
implementation 'jp.studyplus.android.sdk:studyplus-android-sdk2:2.0.2'
}
```

### Maven

```
<dependency>
<groupId>jp.studyplus.android.sdk</groupId>
<artifactId>studyplus-android-sdk2</artifactId>
<version>2.0.0</version>
<version>2.0.2</version>
</dependency>
```

Expand All @@ -33,13 +35,15 @@ or download the latest JAR [via Central Repository](http://search.maven.org/#sea
## Usage

### Setup

```
Studyplus.instance.setup("consumer_key", "consumer_secret")
```

### Authenticate

Open an Activity to connect with Studyplus.

```
try {
Studyplus.instance.startAuth(this@MainActivity, REQUEST_CODE_AUTH)
Expand All @@ -50,6 +54,7 @@ try {
```

Then save its result.

```
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
Expand All @@ -64,7 +69,9 @@ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
```

### Post a record to Studyplus

Create a record and post.

```
val record = StudyRecordBuilder()
.setComment("勉強した!!!")
Expand Down
4 changes: 2 additions & 2 deletions studyplus-android-sdk2/build.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
VERSION_MAJOR = 2
VERSION_MINOR = 0
VERSION_PATCH = 1
VERSION_PATCH = 2

DEBUG_API_ENDPOINT =
DEBUG_API_ENDPOINT =
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,90 @@ package jp.studyplus.android.sdk
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.util.Log
import io.reactivex.android.schedulers.AndroidSchedulers
import jp.studyplus.android.sdk.internal.auth.AuthTransit
import jp.studyplus.android.sdk.internal.api.ApiClient
import jp.studyplus.android.sdk.internal.api.notNull
import jp.studyplus.android.sdk.record.StudyRecord
import io.reactivex.schedulers.Schedulers
import jp.studyplus.android.sdk.internal.api.ApiClient
import jp.studyplus.android.sdk.internal.api.CertificationStore
import jp.studyplus.android.sdk.internal.auth.AuthTransit
import jp.studyplus.android.sdk.record.StudyRecord

class Studyplus
private constructor() {
companion object {
interface OnPostRecordListener {
fun onResult(success: Boolean, recordId: Long?, throwable: Throwable?)
}

@JvmStatic
val instance by lazy { Studyplus() }
}
class Studyplus private constructor() {

private var consumerKey: String? = null
private var consumerSecret: String? = null

/**
* ConsumerKey, ConsumerSecretKeyをStudyplus SDKに設定
*
* @since 2.0.0
*/
fun setup(consumerKey: String, consumerSecret: String) {
this.consumerKey = consumerKey
this.consumerSecret = consumerSecret
}

fun isAuthenticated(context: Context): Boolean {
return CertificationStore.create(context).isAuthenticated()
}
/**
* [setup]で設定されたConsumerKeyがすでに認証済みかどうかを判定
*
* @return true: 認証済み、 false: 未認証
* @since 2.0.0
*/
fun isAuthenticated(context: Context): Boolean =
CertificationStore.create(context.applicationContext).isAuthenticated()

/**
* [setup]で設定されたConsumerKey, ConsumerSecretKeyによるStudyplus連携認証
*
* @since 2.0.0
*/
fun startAuth(activity: Activity, requestCode: Int) {
notNull(consumerKey, consumerSecret) { consumerKey, consumerSecret ->
AuthTransit(consumerKey, consumerSecret).apply {
start(activity, requestCode)
}
if (consumerKey == null || consumerSecret == null) {
throw IllegalStateException("Please call setup method before this method call.")
}

AuthTransit(consumerKey!!, consumerSecret!!).start(activity, requestCode)
}

/**
* [startAuth]の結果をStudyplusSDKに保存
*
* @since 2.0.0
*/
fun setAuthResult(context: Context, data: Intent?) {
data?.also {
CertificationStore.create(context).update(it)
if (data == null) {
Log.e("StudyplusSDK", "The data is null. Please check your code. If the data that received from Studyplus app is null, please contact Studyplus Dev team.")
return
}

CertificationStore.create(context.applicationContext).update(data)
}

/**
* Studyplusとの認証情報を利用して学習記録をStudyplusへ投稿
*
* @since 2.0.0
*/
fun postRecord(context: Context, studyRecord: StudyRecord, listener: OnPostRecordListener?) {
if (!isAuthenticated(context)) {
throw IllegalStateException("Please check your application's authentication before this method call.")
}

ApiClient.apiClient.postStudyRecords(context, studyRecord)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ response ->
listener?.apply {
onResult(true, response.recordId, null)
}
},
{ throwable ->
listener?.apply {
onResult(false, null, throwable)
}
}
{ listener?.onResult(success = true, recordId = it.recordId) },
{ listener?.onResult(success = false, throwable = it) }
)
}

companion object {
interface OnPostRecordListener {
fun onResult(success: Boolean, recordId: Long? = null, throwable: Throwable? = null)
}

@JvmStatic
val instance by lazy { Studyplus() }
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import jp.studyplus.android.sdk.internal.api.response.PostStudyRecordsResponse
import jp.studyplus.android.sdk.record.StudyRecord
import retrofit2.Retrofit

class ApiClient
internal class ApiClient
constructor(retrofit: Retrofit) {

companion object {
Expand All @@ -15,7 +15,7 @@ constructor(retrofit: Retrofit) {

private fun getOAuthAccessToken(context: Context): Observable<String> {
return Observable.just(CertificationStore.create(context))
.map { it.apiCertification.accessToken }
.map { it.apiCertification() }
.map { "OAuth $it" }
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,19 @@
package jp.studyplus.android.sdk.internal.api

import com.google.gson.FieldNamingPolicy
import com.google.gson.GsonBuilder
import jp.studyplus.android.sdk.BuildConfig
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

object ApiManager {

private val loggingLevel: HttpLoggingInterceptor.Level
get() = if (BuildConfig.DEBUG) {
HttpLoggingInterceptor.Level.BODY
} else {
HttpLoggingInterceptor.Level.NONE
}

private val gson by lazy {
GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create()
}
internal object ApiManager {

private val client by lazy {
OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.addInterceptor(HttpLoggingInterceptor().setLevel(loggingLevel))
.build()
}

Expand All @@ -39,7 +22,7 @@ object ApiManager {
.client(client)
.baseUrl(BuildConfig.API_ENDPOINT)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.addConverterFactory(GsonConverterFactory.create())
.build()!!
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import jp.studyplus.android.sdk.internal.api.response.PostStudyRecordsResponse
import jp.studyplus.android.sdk.record.StudyRecord
import retrofit2.http.*

interface ApiService {
internal interface ApiService {
@Headers(value = [
"Accept: application/json",
"Content-type: application/json"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@ import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import jp.studyplus.android.sdk.BuildConfig
import jp.studyplus.android.sdk.internal.auth.AccessTokenNotFound

interface ApiCertification {
val accessToken: String
}

class CertificationStore
internal class CertificationStore
private constructor(private val preferences: SharedPreferences) {

companion object {
Expand All @@ -34,17 +29,9 @@ private constructor(private val preferences: SharedPreferences) {
return !token.isNullOrEmpty()
}

val apiCertification: ApiCertification
get() {
val token = preferences.getString(KEY_ACCESS_TOKEN, "")
if (token.isNullOrEmpty()) {
throw AccessTokenNotFound()
}
return ApiCertificationImpl(token)
}
fun apiCertification(): String = preferences.getString(KEY_ACCESS_TOKEN, "")

fun update(data: Intent?) {
if (data == null) { return }
fun update(data: Intent) {
val code = data.getStringExtra(EXTRA_SP_AUTH_RESULT_CODE).orEmpty()
if (RESULT_CODE_AUTHENTICATED == code) {
preferences.edit()?.apply {
Expand All @@ -53,7 +40,4 @@ private constructor(private val preferences: SharedPreferences) {
}
}
}

private class ApiCertificationImpl
constructor(override val accessToken: String) : ApiCertification
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package jp.studyplus.android.sdk.internal.api.response

import com.google.gson.annotations.SerializedName

data class PostStudyRecordsResponse(
internal data class PostStudyRecordsResponse(
@SerializedName("record_id")
val recordId: Long? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import android.content.Intent
import android.net.Uri
import jp.studyplus.android.sdk.R

class AccessTokenNotFound : RuntimeException()

class AuthTransit
internal class AuthTransit
/**
* @param consumerKey for API
* @param consumerSecret for API
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package jp.studyplus.android.sdk

import jp.studyplus.android.sdk.internal.api.MockApiClient
import jp.studyplus.android.sdk.record.StudyRecordBuilder
import org.junit.Test

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package jp.studyplus.android.sdk
package jp.studyplus.android.sdk.internal.api

import android.content.Context
import io.reactivex.Observable
import jp.studyplus.android.sdk.internal.api.ApiService
import jp.studyplus.android.sdk.internal.api.response.PostStudyRecordsResponse
import jp.studyplus.android.sdk.record.StudyRecord
import retrofit2.mock.MockRetrofit

class MockApiClient
internal class MockApiClient
constructor(retrofit: MockRetrofit) {

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package jp.studyplus.android.sdk
package jp.studyplus.android.sdk.internal.api

import jp.studyplus.android.sdk.internal.api.ApiManager
import retrofit2.mock.MockRetrofit
import retrofit2.mock.NetworkBehavior
import java.util.concurrent.TimeUnit

object MockApiManager {
internal object MockApiManager {
val retrofit by lazy {
val behavior = NetworkBehavior.create()
behavior.setDelay(100, TimeUnit.MILLISECONDS)
Expand Down
Loading

0 comments on commit 9fb4a44

Please sign in to comment.