Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/Runnect/Runnect-Android
Browse files Browse the repository at this point in the history
…into feature/fix-detail-to-discover-update
  • Loading branch information
leeeha committed Dec 26, 2023
2 parents 3d924fe + b3b767d commit 5ed9428
Show file tree
Hide file tree
Showing 24 changed files with 544 additions and 86 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,20 @@ jobs:
NAVER_CLIENT_ID: ${{ secrets.NAVER_CLIENT_ID }}
run: echo "NAVER_CLIENT_ID = \"$NAVER_CLIENT_ID\"" >> local.properties

- name: Access RUNNECT_BASE_URL
- name: Access RUNNECT_NODE_URL
env:
RUNNECT_BASE_URL: ${{ secrets.RUNNECT_BASE_URL }}
run: echo "RUNNECT_BASE_URL=\"$RUNNECT_BASE_URL\"" >> local.properties
RUNNECT_NODE_URL: ${{ secrets.RUNNECT_NODE_URL }}
run: echo "RUNNECT_NODE_URL=\"$RUNNECT_NODE_URL\"" >> local.properties

- name: Access RUNNECT_DEV_URL
env:
RUNNECT_DEV_URL: ${{ secrets.RUNNECT_DEV_URL }}
run: echo "RUNNECT_DEV_URL=\"$RUNNECT_DEV_URL\"" >> local.properties

- name: Access RUNNECT_PROD_URL
env:
RUNNECT_PROD_URL: ${{ secrets.RUNNECT_PROD_URL }}
run: echo "RUNNECT_PROD_URL=\"$RUNNECT_PROD_URL\"" >> local.properties

- name: Access TMAP_BASE_URL
env:
Expand Down
5 changes: 4 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ android {
versionName "1.0.4"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField "String", "RUNNECT_BASE_URL", properties["RUNNECT_BASE_URL"]
buildConfigField "String", "RUNNECT_DEV_URL", properties["RUNNECT_DEV_URL"]
buildConfigField "String", "RUNNECT_NODE_URL", properties["RUNNECT_NODE_URL"]
buildConfigField "String", "RUNNECT_PROD_URL", properties["RUNNECT_PROD_URL"]
buildConfigField "String", "TMAP_BASE_URL", properties["TMAP_BASE_URL"]
buildConfigField "String", "TMAP_API_KEY", properties["TMAP_API_KEY"]
buildConfigField "String", "NAVER_CLIENT_ID", properties["NAVER_CLIENT_ID"]
Expand Down Expand Up @@ -75,6 +77,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.core:core:1.9.0'
implementation 'com.google.firebase:firebase-common-ktx:20.1.0'
implementation 'androidx.preference:preference-ktx:1.2.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
Expand Down
39 changes: 39 additions & 0 deletions app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
tools:ignore="ProtectedPermissions" />

<application
android:name=".application.ApplicationClass"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_runnect_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_runnect_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Runnect"
android:usesCleartextTraffic="true"
tools:targetApi="tiramisu">

<activity
android:name=".developer.RunnectDeveloperActivity"
android:exported="true"
android:label="개발자 모드"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />

<data
android:host="devmode"
android:scheme="runnect" />

</intent-filter>
</activity>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package com.runnect.runnect.developer

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.WindowInsets
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.runnect.runnect.R
import com.runnect.runnect.application.ApiMode
import com.runnect.runnect.application.ApplicationClass
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.data.service.TokenAuthenticator
import com.runnect.runnect.presentation.mypage.setting.accountinfo.MySettingAccountInfoFragment
import com.runnect.runnect.util.custom.toast.RunnectToast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.system.exitProcess

class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_developer) {

class RunnectDeveloperFragment : PreferenceFragmentCompat() {

private val clipboardManager: ClipboardManager? by lazy {
context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
}

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences_developer_menu, rootKey)

initUserInfo()
initApiMode()
initDeviceInfo()
initDisplayInfo()
}

private fun initUserInfo() {
val ctx: Context = context ?: return
val accessToken = PreferenceManager.getString(ctx, TokenAuthenticator.TOKEN_KEY_ACCESS) ?: ""
val refreshToken = PreferenceManager.getString(ctx, TokenAuthenticator.TOKEN_KEY_REFRESH) ?: ""

setPreferenceSummary("dev_pref_key_access_token", accessToken)
setPreferenceSummary("dev_pref_key_refresh_token", refreshToken)
}

private fun initApiMode() {
val ctx:Context = context ?: ApplicationClass.appContext
val currentApi = ApiMode.getCurrentApiMode(ctx)

findPreference<ListPreference>("dev_pref_key_api_mode")?.apply {
val entries = ApiMode.values().map { it.name }.toTypedArray()
val selectIndex = ApiMode.values().indexOf(currentApi)

this.entries = entries
this.entryValues = entries

title = currentApi.name
setValueIndex(selectIndex)
setOnPreferenceChangeListener { preference, newValue ->
val selectItem = newValue.toString()
this.title = selectItem

PreferenceManager.apply {
setString(ctx, ApplicationClass.API_MODE, selectItem)
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_ACCESS, "none")
setString(ctx, MySettingAccountInfoFragment.TOKEN_KEY_REFRESH, "none")
}

destroyApp(ctx)
true
}
}
}

private fun initDeviceInfo() {
setPreferenceSummary("dev_pref_android_version", Build.VERSION.RELEASE)
setPreferenceSummary("dev_pref_model_name", "${Build.BRAND} ${Build.MODEL}")
setPreferenceSummary("dev_pref_sdk_version", "${Build.VERSION.SDK_INT}")
}

private fun initDisplayInfo() {
val metrics = activity?.resources?.displayMetrics ?: return
val windowManager = activity?.windowManager ?: return
val statusBarHeight = getStatusBarHeight(windowManager)
val naviBarHeight = getNaviBarHeight(windowManager)

with(metrics) {
setPreferenceSummary("dev_pref_display_ratio", "$widthPixels x ${heightPixels + statusBarHeight + naviBarHeight}")
setPreferenceSummary("dev_pref_display_density", "${densityDpi}dp")
setPreferenceSummary("dev_pref_display_resource_bucket", getDeviceResourseBucket(this))
}
}

private fun getDeviceResourseBucket(metrics: DisplayMetrics): String {
val densityDpi = metrics.densityDpi

return when {
densityDpi <= DisplayMetrics.DENSITY_LOW -> "ldpi"
densityDpi <= DisplayMetrics.DENSITY_MEDIUM -> "mdpi"
densityDpi <= DisplayMetrics.DENSITY_HIGH -> "hdpi"
densityDpi <= DisplayMetrics.DENSITY_XHIGH -> "xhdpi"
densityDpi <= DisplayMetrics.DENSITY_XXHIGH -> "xxhdpi"
densityDpi <= DisplayMetrics.DENSITY_XXXHIGH -> "xxxhdpi"
else -> "unknown"
}
}

private fun getStatusBarHeight(windowManager: WindowManager): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = windowManager.currentWindowMetrics
val insets = windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
insets.top
} else {
0
}
}

private fun getNaviBarHeight(windowManager: WindowManager): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = windowManager.currentWindowMetrics
val insets = windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars())
insets.bottom
} else {
0
}
}

private fun setPreferenceSummary(key: String, value: String) {
findPreference<Preference>(key)?.let { pref ->
pref.summary = value
pref.setOnPreferenceClickListener {
copyToText(value)
}
}
}

private fun copyToText(text: String): Boolean {
val clipData = ClipData.newPlainText(CLIPBOARD_LABEL, text)
clipboardManager?.setPrimaryClip(clipData)

context?.let {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
RunnectToast.createToast(it, getString(R.string.dev_mode_copy_to_text)).show()
}
}

return true
}

private fun destroyApp(context: Context) {
lifecycleScope.launch(Dispatchers.Main) {
RunnectToast.createToast(context, getString(R.string.dev_mode_require_restart)).show()
delay(3000)

activity?.finishAffinity() //루트액티비티 종료
exitProcess(0)
}
}

companion object {
private const val CLIPBOARD_LABEL = "keyword"
}
}
}
68 changes: 68 additions & 0 deletions app/src/debug/res/xml/preferences_developer_menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<PreferenceCategory
android:title="사용자 정보"
app:iconSpaceReserved="false">

<Preference
android:key="dev_pref_key_access_token"
android:title="엑세스 토큰"
app:iconSpaceReserved="false" />

<Preference
android:key="dev_pref_key_refresh_token"
android:title="리프레시 토큰"
app:iconSpaceReserved="false" />
</PreferenceCategory>

<PreferenceCategory
android:title="서버 모드 설정"
app:iconSpaceReserved="false">

<ListPreference
android:defaultValue="0"
android:key="dev_pref_key_api_mode"
android:title="서버 모드 설정"
app:iconSpaceReserved="false" />
</PreferenceCategory>

<PreferenceCategory
android:title="디바이스 정보"
app:iconSpaceReserved="false">

<Preference
android:key="dev_pref_android_version"
android:title="안드로이드 버전"
app:iconSpaceReserved="false" />
<Preference
android:key="dev_pref_sdk_version"
android:title="SDK 버전"
app:iconSpaceReserved="false"/>
<Preference
android:key="dev_pref_model_name"
android:title="모델 명"
app:iconSpaceReserved="false" />
</PreferenceCategory>

<PreferenceCategory
android:title="화면 정보"
app:iconSpaceReserved="false">

<Preference
android:key="dev_pref_display_ratio"
android:title="화면 비율"
app:iconSpaceReserved="false" />

<Preference
android:key="dev_pref_display_density"
android:title="화면 밀도"
app:iconSpaceReserved="false" />

<Preference
android:key="dev_pref_display_resource_bucket"
android:title="리소스 버킷"
app:iconSpaceReserved="false" />
</PreferenceCategory>
</PreferenceScreen>
23 changes: 23 additions & 0 deletions app/src/main/java/com/runnect/runnect/application/ApiMode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.runnect.runnect.application

import android.content.Context

enum class ApiMode {
NODE,
TEST,
JAVA;

companion object {
private fun asValue(mode: String): ApiMode = when(mode.uppercase()) {
"NODE" -> NODE
"JAVA" -> JAVA
else -> TEST
}

fun getCurrentApiMode(context: Context): ApiMode {
return asValue(
PreferenceManager.getString(context, ApplicationClass.API_MODE) ?: ""
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,31 @@ class ApplicationClass : Application() {
}
appContext = applicationContext
KakaoSdk.init(this,getString(R.string.kakao_native_app_key))
initApiMode()
}

private fun initApiMode() {
val currentApi = ApiMode.getCurrentApiMode(appContext)
PreferenceManager.setString(appContext, API_MODE, currentApi.name)
}

companion object {
lateinit var appContext: Context
const val API_MODE = "API_MODE"

fun getBaseUrl(): String {
return when {
!BuildConfig.DEBUG -> BuildConfig.RUNNECT_NODE_URL // 추후 Prod 서버로 변경
!::appContext.isInitialized -> BuildConfig.RUNNECT_NODE_URL
else -> {
val mode = ApiMode.getCurrentApiMode(appContext)
when(mode) {
ApiMode.JAVA -> BuildConfig.RUNNECT_PROD_URL
ApiMode.TEST -> BuildConfig.RUNNECT_DEV_URL
else -> BuildConfig.RUNNECT_NODE_URL
}
}
}
}
}
}
4 changes: 2 additions & 2 deletions app/src/main/java/com/runnect/runnect/data/dto/CourseData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ data class CourseData(
val publicCourseId: Int?,
val touchList: ArrayList<LatLng>,
val startLatLng: LatLng,
val departure: String,
val distance: Float,
val departure: String?,
val distance: Float?,
val image: String,
val dataFrom: String
) : Parcelable
Loading

0 comments on commit 5ed9428

Please sign in to comment.