Skip to content

Commit

Permalink
Updates project to AndroidX
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaeltoledo committed Dec 13, 2018
1 parent deba92a commit 34a3ef7
Show file tree
Hide file tree
Showing 23 changed files with 148 additions and 161 deletions.
7 changes: 4 additions & 3 deletions .circleci/config.yml
Expand Up @@ -2,14 +2,15 @@ version: 2
jobs:
build:
docker:
- image: circleci/android:api-27-alpha
- image: circleci/android:api-28-alpha

working_directory: ~/social-app

environment:
JVM_OPTS: -Xmx3200m
TERM: dumb
JAVA_TOOL_OPTIONS: "-Xmx1g"
CIRCLE_JDK_VERSION: oraclejdk8
GRADLE_OPTS: -Dorg.gradle.daemon=false
GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2 -Dkotlin.incremental=false"

steps:
- checkout
Expand Down
42 changes: 21 additions & 21 deletions app/build.gradle
Expand Up @@ -5,12 +5,12 @@ apply plugin: 'org.jetbrains.kotlin.kapt'
apply from: "$rootDir/gradle/coverage.gradle"

android {
compileSdkVersion 27
compileSdkVersion 28

defaultConfig {
applicationId 'net.rafaeltoledo.social'
minSdkVersion 19
targetSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName '1.0'

Expand Down Expand Up @@ -65,48 +65,48 @@ android {
}

testOptions {
execution 'ANDROID_TEST_ORCHESTRATOR'
execution 'ANDROIDX_TEST_ORCHESTRATOR'
animationsDisabled true

unitTests.includeAndroidResources true
}
}

kotlin.experimental.coroutines 'enable'

dependencies {
implementation "com.android.support:appcompat-v7:$versions.supportLibrary"
implementation "com.android.support:design:$versions.supportLibrary"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.material:material:1.0.0'

implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

implementation "android.arch.lifecycle:extensions:$versions.archComponents"
kapt "android.arch.lifecycle:compiler:$versions.archComponents"
implementation "androidx.lifecycle:lifecycle-extensions:$versions.lifecycle"
kapt "androidx.lifecycle:lifecycle-compiler:$versions.lifecycle"

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$versions.kotlin"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.23.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

implementation 'com.google.firebase:firebase-core:16.0.1'
implementation 'com.google.firebase:firebase-auth:16.0.2'
implementation 'com.google.firebase:firebase-core:16.0.6'
implementation 'com.google.firebase:firebase-auth:16.1.0'

implementation 'com.google.android.gms:play-services-auth:15.0.1'
implementation 'com.google.android.gms:play-services-auth:16.0.1'

implementation "org.koin:koin-android:$versions.koin"
implementation "org.koin:koin-android-architecture:$versions.koin"
implementation "org.koin:koin-androidx-viewmodel:$versions.koin"

testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:3.8'
testImplementation 'org.robolectric:robolectric:4.1'
testImplementation 'com.google.truth:truth:0.42'
testImplementation "org.koin:koin-test:$versions.koin"
testImplementation "io.mockk:mockk:$versions.mockk"
testImplementation "android.arch.core:core-testing:$versions.archComponents"

androidTestImplementation "com.android.support.test:runner:$versions.astl"
androidTestImplementation "com.android.support.test:rules:$versions.astl"
androidTestImplementation "com.android.support.test.espresso:espresso-core:$versions.espresso"
androidTestImplementation "com.android.support.test.espresso:espresso-intents:$versions.espresso"
androidTestImplementation "androidx.test:core:$versions.testcore"
androidTestImplementation "androidx.test.ext:junit:$versions.testcore"
androidTestImplementation "androidx.test:runner:$versions.astl"
androidTestImplementation "androidx.test:rules:$versions.astl"
androidTestImplementation "androidx.test.espresso:espresso-core:$versions.espresso"
androidTestImplementation "androidx.test.espresso:espresso-intents:$versions.espresso"
androidTestImplementation "io.mockk:mockk-android:$versions.mockk"
androidTestUtil "com.android.support.test:orchestrator:$versions.astl"
androidTestUtil "androidx.test:orchestrator:$versions.astl"
}

apply plugin: 'com.google.gms.google-services'
Expand Up @@ -3,19 +3,16 @@ package net.rafaeltoledo.social
import android.app.Activity
import android.app.Instrumentation
import android.content.Intent
import android.support.test.espresso.Espresso.onView
import android.support.test.espresso.action.ViewActions.click
import android.support.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.intent.Intents.intending
import android.support.test.espresso.intent.matcher.BundleMatchers.hasEntry
import android.support.test.espresso.intent.matcher.IntentMatchers.hasExtras
import android.support.test.espresso.intent.rule.IntentsTestRule
import android.support.test.espresso.matcher.ViewMatchers.*
import android.support.test.runner.AndroidJUnit4
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.experimental.async
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents.intending
import androidx.test.espresso.intent.matcher.BundleMatchers.hasEntry
import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtras
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.mockk.*
import net.rafaeltoledo.social.data.User
import net.rafaeltoledo.social.data.auth.*
import net.rafaeltoledo.social.setup.BaseInstrumentedTest
Expand Down Expand Up @@ -52,7 +49,7 @@ class SignInActivityTest : BaseInstrumentedTest() {
every { delegatedAuth.signIn(any()) } answers { (it.invocation.args[0] as Activity).startActivityForResult(Intent().putExtra("key", "value"), 0) }
every { delegatedAuth.onResult(any(), any(), any()) } returns AuthResult(Status.SUCCESS, token = "ok")

every { authManager.socialSignIn(any(), any()) } returns async { User("1") }
coEvery { authManager.socialSignIn(any(), any()) } returns User("1")
every { authManager.isUserLoggedIn() } returns true

activityRule.launchActivity(Intent())
Expand All @@ -67,8 +64,7 @@ class SignInActivityTest : BaseInstrumentedTest() {
onView(withText(app.stringValue)).check(matches(isDisplayed()))

verify(exactly = 1) { delegatedAuth.signIn(activityRule.activity) }
verify(exactly = 1) { authManager.socialSignIn("ok", SocialProvider.GOOGLE) }

coVerify(exactly = 1) { authManager.socialSignIn("ok", SocialProvider.GOOGLE) }
}

@Test
Expand All @@ -89,7 +85,7 @@ class SignInActivityTest : BaseInstrumentedTest() {
onView(withText(R.string.error_sign_in)).check(matches(isDisplayed()))

verify(exactly = 1) { delegatedAuth.signIn(activityRule.activity) }
verify(exactly = 0) { authManager.socialSignIn(any(), any()) }
coVerify(exactly = 0) { authManager.socialSignIn(any(), any()) }
}
}

Expand Up @@ -2,15 +2,14 @@ package net.rafaeltoledo.social.setup

import android.app.Application
import android.content.Context
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnitRunner
import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnitRunner
import net.rafaeltoledo.social.TestSocialApp
import org.junit.After
import org.koin.standalone.StandAloneContext

abstract class BaseInstrumentedTest {

protected val app: TestSocialApp by lazy { InstrumentationRegistry.getTargetContext().applicationContext as TestSocialApp }
protected val app: TestSocialApp by lazy { ApplicationProvider.getApplicationContext() as TestSocialApp }
}

class SocialAppTestRunner : AndroidJUnitRunner() {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/net/rafaeltoledo/social/SocialApp.kt
Expand Up @@ -11,7 +11,7 @@ open class SocialApp : Application() {

override fun onCreate() {
super.onCreate()
startKoin(listOf(
startKoin(this, listOf(
viewModelModule,
firstModule,
authModule,
Expand Down
@@ -1,11 +1,10 @@
package net.rafaeltoledo.social.data.auth

import kotlinx.coroutines.experimental.Deferred
import net.rafaeltoledo.social.data.User

interface AuthManager {

fun socialSignIn(token: String, provider: SocialProvider): Deferred<User>
suspend fun socialSignIn(token: String, provider: SocialProvider): User

fun isUserLoggedIn(): Boolean
}
Expand Down
Expand Up @@ -33,7 +33,7 @@ class GoogleAuth : DelegatedAuth {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
return try {
val account = task.getResult(ApiException::class.java)
AuthResult(Status.SUCCESS, account.idToken)
AuthResult(Status.SUCCESS, account!!.idToken)
} catch (e: ApiException) {
AuthResult(Status.FAILURE)
}
Expand Down
@@ -1,9 +1,8 @@
package net.rafaeltoledo.social.data.firebase

import com.google.android.gms.tasks.Tasks
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.GoogleAuthProvider
import kotlinx.coroutines.experimental.CompletableDeferred
import kotlinx.coroutines.experimental.Deferred
import net.rafaeltoledo.social.data.User
import net.rafaeltoledo.social.data.auth.AuthManager
import net.rafaeltoledo.social.data.auth.SocialProvider
Expand All @@ -12,26 +11,21 @@ class FirebaseAuthManager : AuthManager {

private val auth = FirebaseAuth.getInstance()

override fun socialSignIn(token: String, provider: SocialProvider): Deferred<User> {
override suspend fun socialSignIn(token: String, provider: SocialProvider): User {
if (provider == SocialProvider.GOOGLE) {
return googleSignIn(token)
}
throw NotImplementedError("Unknown provider")
}

private fun googleSignIn(token: String): Deferred<User> {
val deferred = CompletableDeferred<User>()

auth.signInWithCredential(GoogleAuthProvider.getCredential(token, null))
.addOnCompleteListener {
if (it.isSuccessful) {
deferred.complete(User(it.result.user.uid))
} else {
deferred.completeExceptionally(it.exception!!)
}
}
private fun googleSignIn(token: String): User {
val task = auth.signInWithCredential(GoogleAuthProvider.getCredential(token, null))
Tasks.await(task)
if (task.isSuccessful.not()) {
throw task.exception!!
}

return deferred
return User(task.result!!.user.uid)
}

override fun isUserLoggedIn() = auth.currentUser != null
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/kotlin/net/rafaeltoledo/social/di/AuthModule.kt
Expand Up @@ -2,8 +2,8 @@ package net.rafaeltoledo.social.di

import net.rafaeltoledo.social.data.auth.DelegatedAuth
import net.rafaeltoledo.social.data.auth.GoogleAuth
import org.koin.dsl.module.applicationContext
import org.koin.dsl.module.module

val authModule = applicationContext {
bean { GoogleAuth() as DelegatedAuth }
val authModule = module {
single<DelegatedAuth> { GoogleAuth() }
}
Expand Up @@ -2,9 +2,9 @@ package net.rafaeltoledo.social.di

import net.rafaeltoledo.social.data.auth.AuthManager
import net.rafaeltoledo.social.data.firebase.FirebaseAuthManager
import org.koin.dsl.module.applicationContext
import org.koin.dsl.module.module

val firebaseModule = applicationContext {
val firebaseModule = module {

bean { FirebaseAuthManager() as AuthManager }
single<AuthManager> { FirebaseAuthManager() }
}
6 changes: 3 additions & 3 deletions app/src/main/kotlin/net/rafaeltoledo/social/di/FirstModule.kt
@@ -1,7 +1,7 @@
package net.rafaeltoledo.social.di

import org.koin.dsl.module.applicationContext
import org.koin.dsl.module.module

val firstModule = applicationContext {
bean { "Social App" }
val firstModule = module {
single { "Social App" }
}
Expand Up @@ -2,10 +2,10 @@ package net.rafaeltoledo.social.di

import net.rafaeltoledo.social.ui.feature.main.MainViewModel
import net.rafaeltoledo.social.ui.feature.signin.SignInViewModel
import org.koin.android.architecture.ext.viewModel
import org.koin.dsl.module.applicationContext
import org.koin.androidx.viewmodel.ext.koin.viewModel
import org.koin.dsl.module.module

val viewModelModule = applicationContext {
val viewModelModule = module {
viewModel { MainViewModel(get()) }
viewModel { SignInViewModel(get(), get()) }
}
32 changes: 30 additions & 2 deletions app/src/main/kotlin/net/rafaeltoledo/social/ui/BaseViewModel.kt
@@ -1,14 +1,42 @@
package net.rafaeltoledo.social.ui

import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import net.rafaeltoledo.social.R

abstract class BaseViewModel : ViewModel() {

val loading = MutableLiveData<Boolean>()
val error = MutableLiveData<Int>()

private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

init {
loading.postValue(false)
}

protected fun launchDataLoad(block: suspend CoroutineScope.() -> Unit): Job {
return uiScope.launch {
try {
loading.postValue(true)
block()
} catch (error: Exception) {
errorHandler(error)
} finally {
loading.postValue(false)
}
}
}

private val errorHandler = { e: Throwable ->
Log.e("BaseViewModel", "Failed to execute", e)
loading.postValue(false)
error.postValue(R.string.error_default_message)
}
}
Expand Up @@ -2,13 +2,13 @@ package net.rafaeltoledo.social.ui.feature.main

import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import net.rafaeltoledo.social.R
import net.rafaeltoledo.social.data.auth.AuthManager
import net.rafaeltoledo.social.ui.feature.signin.SignInActivity
import org.koin.android.architecture.ext.viewModel
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel

class MainActivity : AppCompatActivity() {

Expand Down

0 comments on commit 34a3ef7

Please sign in to comment.