Add logging with Timber
This commit is contained in:
@@ -65,6 +65,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||||
|
|
||||||
|
implementation 'com.jakewharton.timber:timber:5.0.1'
|
||||||
|
|
||||||
testImplementation "junit:junit:4.13.2"
|
testImplementation "junit:junit:4.13.2"
|
||||||
|
|
||||||
androidTestImplementation "androidx.test.ext:junit:1.1.3"
|
androidTestImplementation "androidx.test.ext:junit:1.1.3"
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import android.os.Bundle
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import gq.kirmanak.mealie.databinding.MainActivityBinding
|
import gq.kirmanak.mealie.databinding.MainActivityBinding
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
Timber.v("onCreate() called with: savedInstanceState = $savedInstanceState")
|
||||||
val binding = MainActivityBinding.inflate(layoutInflater)
|
val binding = MainActivityBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,13 @@ package gq.kirmanak.mealie
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class MealieApp : Application()
|
class MealieApp : Application() {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
|
||||||
|
Timber.v("onCreate() called")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,11 +5,13 @@ import kotlinx.serialization.ExperimentalSerializationApi
|
|||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ExperimentalSerializationApi
|
@ExperimentalSerializationApi
|
||||||
class RetrofitBuilder @Inject constructor() {
|
class RetrofitBuilder @Inject constructor() {
|
||||||
fun buildRetrofit(baseUrl: String): Retrofit {
|
fun buildRetrofit(baseUrl: String): Retrofit {
|
||||||
|
Timber.v("buildRetrofit() called with: baseUrl = $baseUrl")
|
||||||
val url = if (baseUrl.startsWith("http")) baseUrl else "https://$baseUrl"
|
val url = if (baseUrl.startsWith("http")) baseUrl else "https://$baseUrl"
|
||||||
val contentType = MediaType.get("application/json")
|
val contentType = MediaType.get("application/json")
|
||||||
return Retrofit.Builder()
|
return Retrofit.Builder()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package gq.kirmanak.mealie.data.auth
|
|||||||
import gq.kirmanak.mealie.data.RetrofitBuilder
|
import gq.kirmanak.mealie.data.RetrofitBuilder
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import retrofit2.create
|
import retrofit2.create
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ExperimentalSerializationApi
|
@ExperimentalSerializationApi
|
||||||
@@ -14,12 +15,15 @@ class AuthDataSourceImpl @Inject constructor(
|
|||||||
password: String,
|
password: String,
|
||||||
baseUrl: String
|
baseUrl: String
|
||||||
): Result<String> {
|
): Result<String> {
|
||||||
|
Timber.v("authenticate() called with: username = $username, password = $password, baseUrl = $baseUrl")
|
||||||
val authService = retrofitBuilder.buildRetrofit(baseUrl).create<AuthService>()
|
val authService = retrofitBuilder.buildRetrofit(baseUrl).create<AuthService>()
|
||||||
val response = try {
|
val response = try {
|
||||||
authService.getToken(username, password)
|
authService.getToken(username, password)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
Timber.e("Authenticate() exception", e)
|
||||||
return Result.failure(e)
|
return Result.failure(e)
|
||||||
}
|
}
|
||||||
|
Timber.d("authenticate() response is $response")
|
||||||
return Result.success(response.accessToken)
|
return Result.success(response.accessToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,27 @@
|
|||||||
package gq.kirmanak.mealie.data.auth
|
package gq.kirmanak.mealie.data.auth
|
||||||
|
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AuthRepoImpl @Inject constructor(
|
class AuthRepoImpl @Inject constructor(
|
||||||
private val dataSource: AuthDataSource,
|
private val dataSource: AuthDataSource,
|
||||||
private val storage: AuthStorage
|
private val storage: AuthStorage
|
||||||
) : AuthRepo {
|
) : AuthRepo {
|
||||||
override suspend fun isAuthenticated(): Boolean = storage.isAuthenticated()
|
override suspend fun isAuthenticated(): Boolean {
|
||||||
|
Timber.v("isAuthenticated")
|
||||||
|
val authenticated = storage.isAuthenticated()
|
||||||
|
Timber.d("isAuthenticated() response $authenticated")
|
||||||
|
return authenticated
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun authenticate(
|
override suspend fun authenticate(
|
||||||
username: String,
|
username: String,
|
||||||
password: String,
|
password: String,
|
||||||
baseUrl: String
|
baseUrl: String
|
||||||
): Throwable? {
|
): Throwable? {
|
||||||
|
Timber.v("authenticate() called with: username = $username, password = $password, baseUrl = $baseUrl")
|
||||||
val authResult = dataSource.authenticate(username, password, baseUrl)
|
val authResult = dataSource.authenticate(username, password, baseUrl)
|
||||||
|
Timber.d("authenticate result is $authResult")
|
||||||
if (authResult.isFailure) return authResult.exceptionOrNull()
|
if (authResult.isFailure) return authResult.exceptionOrNull()
|
||||||
val token = checkNotNull(authResult.getOrNull())
|
val token = checkNotNull(authResult.getOrNull())
|
||||||
storage.storeToken(token)
|
storage.storeToken(token)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.preference.PreferenceManager
|
|||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val TOKEN_KEY = "AUTH_TOKEN"
|
private const val TOKEN_KEY = "AUTH_TOKEN"
|
||||||
@@ -15,10 +16,14 @@ class AuthStorageImpl @Inject constructor(@ApplicationContext private val contex
|
|||||||
get() = PreferenceManager.getDefaultSharedPreferences(context)
|
get() = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
override suspend fun isAuthenticated(): Boolean = withContext(Dispatchers.IO) {
|
override suspend fun isAuthenticated(): Boolean = withContext(Dispatchers.IO) {
|
||||||
sharedPreferences.getString(TOKEN_KEY, null) != null
|
Timber.v("isAuthenticated() called")
|
||||||
|
val token = sharedPreferences.getString(TOKEN_KEY, null)
|
||||||
|
Timber.d("isAuthenticated: token is $token")
|
||||||
|
token != null
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun storeToken(token: String) {
|
override suspend fun storeToken(token: String) {
|
||||||
|
Timber.d("storeToken() called with: token = $token")
|
||||||
sharedPreferences.edit().putString(TOKEN_KEY, token).apply()
|
sharedPreferences.edit().putString(TOKEN_KEY, token).apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package gq.kirmanak.mealie.ui.auth
|
package gq.kirmanak.mealie.ui.auth
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -13,6 +12,7 @@ import androidx.lifecycle.lifecycleScope
|
|||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import gq.kirmanak.mealie.databinding.FragmentAuthenticationBinding
|
import gq.kirmanak.mealie.databinding.FragmentAuthenticationBinding
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
private const val TAG = "AuthenticationFragment"
|
private const val TAG = "AuthenticationFragment"
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ class AuthenticationFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
Timber.v("onCreate() called with: savedInstanceState = $savedInstanceState")
|
||||||
checkIfAuthenticatedAlready()
|
checkIfAuthenticatedAlready()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,18 +34,19 @@ class AuthenticationFragment : Fragment() {
|
|||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
|
Timber.v("onCreateView() called with: inflater = $inflater, container = $container, savedInstanceState = $savedInstanceState")
|
||||||
_binding = FragmentAuthenticationBinding.inflate(inflater, container, false)
|
_binding = FragmentAuthenticationBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding.button.setOnClickListener {
|
Timber.v("onViewCreated() called with: view = $view, savedInstanceState = $savedInstanceState")
|
||||||
onLoginClicked()
|
binding.button.setOnClickListener { onLoginClicked() }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIfAuthenticatedAlready() {
|
private fun checkIfAuthenticatedAlready() {
|
||||||
|
Timber.v("checkIfAuthenticatedAlready() called")
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
@@ -56,6 +58,7 @@ class AuthenticationFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onLoginClicked() {
|
private fun onLoginClicked() {
|
||||||
|
Timber.v("onLoginClicked() called")
|
||||||
val email: String
|
val email: String
|
||||||
val pass: String
|
val pass: String
|
||||||
val url: String
|
val url: String
|
||||||
@@ -72,7 +75,6 @@ class AuthenticationFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
lifecycleScope.launchWhenResumed {
|
lifecycleScope.launchWhenResumed {
|
||||||
val exception = viewModel.authenticate(email, pass, url)
|
val exception = viewModel.authenticate(email, pass, url)
|
||||||
Log.e(TAG, "onLoginClicked: ", exception)
|
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
"Exception is ${exception?.message ?: "null"}",
|
"Exception is ${exception?.message ?: "null"}",
|
||||||
@@ -86,7 +88,9 @@ class AuthenticationFragment : Fragment() {
|
|||||||
inputLayout: TextInputLayout,
|
inputLayout: TextInputLayout,
|
||||||
errorText: () -> String
|
errorText: () -> String
|
||||||
): String? {
|
): String? {
|
||||||
|
Timber.v("checkIfInputIsEmpty() called with: input = " + input + ", inputLayout = " + inputLayout + ", errorText = " + errorText)
|
||||||
val text = input.text?.toString()
|
val text = input.text?.toString()
|
||||||
|
Timber.d("Input text is \"$text\"")
|
||||||
if (text.isNullOrBlank()) {
|
if (text.isNullOrBlank()) {
|
||||||
inputLayout.error = errorText()
|
inputLayout.error = errorText()
|
||||||
return null
|
return null
|
||||||
@@ -96,6 +100,7 @@ class AuthenticationFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
Timber.v("onDestroyView() called")
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,15 +3,29 @@ package gq.kirmanak.mealie.ui.auth
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import gq.kirmanak.mealie.data.auth.AuthRepo
|
import gq.kirmanak.mealie.data.auth.AuthRepo
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class AuthenticationViewModel @Inject constructor(
|
class AuthenticationViewModel @Inject constructor(
|
||||||
private val authRepo: AuthRepo
|
private val authRepo: AuthRepo
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
suspend fun isAuthenticated(): Boolean = authRepo.isAuthenticated()
|
init {
|
||||||
|
Timber.v("constructor called")
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun isAuthenticated(): Boolean {
|
||||||
|
Timber.v("isAuthenticated() called")
|
||||||
|
val result = authRepo.isAuthenticated()
|
||||||
|
Timber.d("isAuthenticated() returned: $result")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun authenticate(username: String, password: String, baseUrl: String): Throwable? {
|
suspend fun authenticate(username: String, password: String, baseUrl: String): Throwable? {
|
||||||
return authRepo.authenticate(username, password, baseUrl)
|
Timber.v("authenticate() called with: username = $username, password = $password, baseUrl = $baseUrl")
|
||||||
|
val result = authRepo.authenticate(username, password, baseUrl)
|
||||||
|
if (result == null) Timber.d("authenticate() returns null")
|
||||||
|
else Timber.e("authenticate() returns error", result)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user