Skip to content

Commit 0d15a09

Browse files
committed
target 34,35 대응
1 parent 5aaeb78 commit 0d15a09

File tree

15 files changed

+214
-11
lines changed

15 files changed

+214
-11
lines changed

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ properties.load(project.rootProject.file('local.properties').newDataInputStream(
2222

2323
android {
2424
namespace 'com.runnect.runnect'
25-
compileSdk 34
25+
compileSdk 35
2626

2727
defaultConfig {
2828
applicationId "com.runnect.runnect"
2929
minSdk 28
30-
targetSdk 34
30+
targetSdk 35
3131
versionCode 22
3232
versionName "2.0.1"
3333

app/src/main/AndroidManifest.xml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,27 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools">
44

5-
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
6-
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
75
<uses-permission android:name="android.permission.INTERNET" />
86
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
97
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
10-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
8+
9+
<!-- 미디어 접근 권한 (API 레벨별 조건부) -->
10+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
11+
android:maxSdkVersion="32" />
12+
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
13+
14+
<!-- Foreground Service 관련 -->
1115
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
16+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
17+
18+
<!-- 알림 권한 (API 33+) -->
19+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
20+
21+
<!-- 정확한 알람 권한 (API 31+에서만 필요) -->
22+
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
23+
24+
<!-- 광고 ID 권한 (필요한 경우만) -->
25+
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
1226

1327
<!--queries에 카카오톡 패키지 추가-->
1428
<queries>
@@ -32,7 +46,8 @@
3246
<service
3347
android:name=".presentation.run.TimerService"
3448
android:enabled="true"
35-
android:exported="true" />
49+
android:exported="false"
50+
android:foregroundServiceType="location" />
3651

3752
<activity
3853
android:name=".presentation.login.GiveNicknameActivity"

app/src/main/java/com/runnect/runnect/binding/BindingActivity.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.annotation.LayoutRes
55
import androidx.appcompat.app.AppCompatActivity
66
import androidx.databinding.DataBindingUtil
77
import androidx.viewbinding.ViewBinding
8+
import com.runnect.runnect.util.EdgeToEdgeUtil
89

910
abstract class BindingActivity<B : ViewBinding>(@LayoutRes private val layoutResId: Int) :
1011
AppCompatActivity() {
@@ -13,5 +14,8 @@ abstract class BindingActivity<B : ViewBinding>(@LayoutRes private val layoutRes
1314
override fun onCreate(savedInstanceState: Bundle?) {
1415
super.onCreate(savedInstanceState)
1516
binding = DataBindingUtil.setContentView(this, layoutResId)
17+
18+
// Edge-to-Edge 설정 (모든 BindingActivity에 적용)
19+
EdgeToEdgeUtil.setupEdgeToEdge(this, binding.root)
1620
}
1721
}

app/src/main/java/com/runnect/runnect/di/RetrofitModule.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.runnect.runnect.data.service.*
1212
import com.runnect.runnect.data.source.remote.*
1313
import com.runnect.runnect.domain.*
1414
import com.runnect.runnect.util.ApiLogger
15+
import com.runnect.runnect.util.NetworkSecurityUtil
1516
import dagger.Module
1617
import dagger.Provides
1718
import dagger.hilt.InstallIn
@@ -66,7 +67,7 @@ object RetrofitModule {
6667
fun provideOkHttpClient(
6768
logger: HttpLoggingInterceptor,
6869
@Auth authInterceptor: Interceptor
69-
): OkHttpClient = OkHttpClient.Builder()
70+
): OkHttpClient = NetworkSecurityUtil.createSecureOkHttpClient()
7071
.addInterceptor(logger)
7172
.addInterceptor(authInterceptor)
7273
.build()
@@ -78,7 +79,7 @@ object RetrofitModule {
7879
logger: HttpLoggingInterceptor,
7980
@Auth authInterceptor: Interceptor,
8081
responseInterceptor: ResponseInterceptor,
81-
): OkHttpClient = OkHttpClient.Builder()
82+
): OkHttpClient = NetworkSecurityUtil.createSecureOkHttpClient()
8283
.addInterceptor(logger)
8384
.addInterceptor(authInterceptor)
8485
.addInterceptor(responseInterceptor)

app/src/main/java/com/runnect/runnect/presentation/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
3434

3535
override fun onCreate(savedInstanceState: Bundle?) {
3636
super.onCreate(savedInstanceState)
37+
3738
Analytics.logClickedItemEvent(EVENT_VIEW_HOME)
3839
initRemoteConfig()
3940
checkVisitorMode()

app/src/main/java/com/runnect/runnect/presentation/composesample/ComposeSampleActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.runnect.runnect.presentation.composesample
33
import android.os.Bundle
44
import androidx.activity.ComponentActivity
55
import androidx.activity.compose.setContent
6+
import androidx.activity.enableEdgeToEdge
67
import androidx.compose.foundation.layout.fillMaxSize
78
import androidx.compose.material3.MaterialTheme
89
import androidx.compose.material3.Surface
@@ -14,6 +15,7 @@ import com.runnect.runnect.presentation.composesample.ui.theme.ComposeSampleThem
1415

1516
class ComposeSampleActivity : ComponentActivity() {
1617
override fun onCreate(savedInstanceState: Bundle?) {
18+
enableEdgeToEdge()
1719
super.onCreate(savedInstanceState)
1820
setContent {
1921
ComposeSampleTheme {

app/src/main/java/com/runnect/runnect/presentation/run/TimerService.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import androidx.core.app.NotificationCompat
1414
import androidx.core.content.ContextCompat
1515
import com.runnect.runnect.R
1616
import com.runnect.runnect.data.dto.TimerData
17+
import com.runnect.runnect.util.ForegroundServiceUtil
18+
import com.runnect.runnect.util.IntentUtil
1719
import timber.log.Timber
1820
import java.util.Timer
1921
import java.util.TimerTask
@@ -102,11 +104,12 @@ class TimerService : Service() {
102104
val notificationIntent = Intent(this@TimerService, RunActivity::class.java)
103105
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
104106

105-
val pendingIntent = PendingIntent.getActivity(
107+
val pendingIntent = IntentUtil.createSafePendingIntent(
106108
this@TimerService,
107109
0,
108110
notificationIntent,
109-
FLAG_IMMUTABLE
111+
FLAG_IMMUTABLE,
112+
false
110113
)
111114
notificationBuilder.setContentIntent(pendingIntent) // 알림 클릭 시 이동
112115

@@ -127,7 +130,12 @@ class TimerService : Service() {
127130
notificationBuilder.build()
128131
) // id : 정의해야하는 각 알림의 고유한 int값
129132
val notification = notificationBuilder.build()
130-
startForeground(NOTI_ID, notification)
133+
ForegroundServiceUtil.startForegroundSafely(
134+
this,
135+
NOTI_ID,
136+
notification,
137+
android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
138+
)
131139
}
132140

133141
companion object {

app/src/main/java/com/runnect/runnect/presentation/scheme/SchemeActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.app.Activity
44
import android.content.Intent
55
import android.net.Uri
66
import android.os.Bundle
7+
import androidx.activity.enableEdgeToEdge
78
import androidx.appcompat.app.AppCompatActivity
89
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks
910
import com.runnect.runnect.application.PreferenceManager
@@ -18,6 +19,7 @@ import timber.log.Timber
1819
@AndroidEntryPoint
1920
class SchemeActivity : AppCompatActivity() {
2021
override fun onCreate(savedInstanceState: Bundle?) {
22+
enableEdgeToEdge()
2123
super.onCreate(savedInstanceState)
2224

2325
if (isUserLoggedIn()) {

app/src/main/java/com/runnect/runnect/presentation/splash/SplashActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.Intent
44
import android.os.Bundle
55
import android.os.Handler
66
import android.os.Looper
7+
import androidx.activity.enableEdgeToEdge
78
import androidx.appcompat.app.AppCompatActivity
89
import com.runnect.runnect.R
910
import com.runnect.runnect.presentation.login.LoginActivity
@@ -14,6 +15,7 @@ class SplashActivity : AppCompatActivity() {
1415
private val handler = Handler(Looper.getMainLooper())
1516

1617
override fun onCreate(savedInstanceState: Bundle?) {
18+
enableEdgeToEdge()
1719
super.onCreate(savedInstanceState)
1820
setContentView(R.layout.activity_splash)
1921
navigateToLoginScreen()
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.runnect.runnect.util
2+
3+
import android.os.Build
4+
import android.view.View
5+
import androidx.activity.ComponentActivity
6+
import androidx.activity.enableEdgeToEdge
7+
import androidx.core.view.ViewCompat
8+
import androidx.core.view.WindowInsetsCompat
9+
10+
object EdgeToEdgeUtil {
11+
12+
/**
13+
* Edge-to-Edge를 활성화하고 시스템바 insets을 처리합니다.
14+
* @param activity 대상 Activity
15+
* @param rootView insets을 적용할 루트 뷰
16+
* @param applyPadding 시스템바에 대한 패딩 적용 여부 (기본: true)
17+
*/
18+
fun setupEdgeToEdge(
19+
activity: ComponentActivity,
20+
rootView: View,
21+
applyPadding: Boolean = true
22+
) {
23+
// API 30+ (Android 11+)에서 Edge-to-Edge 활성화
24+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
25+
activity.enableEdgeToEdge()
26+
}
27+
28+
// WindowInsets 처리
29+
ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, insets ->
30+
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
31+
32+
if (applyPadding) {
33+
view.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
34+
}
35+
36+
insets
37+
}
38+
}
39+
40+
}

0 commit comments

Comments
 (0)