Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

습관관리 앱 구현 과정 : Jetpack Compose에서 TopAppBar 구현 과정, 동적 버전 표시 및 웹 연동

Billcorea 2025. 10. 18. 15:30
반응형

 

습관관리 앱 구현 과정 : Jetpack Compose에서 TopAppBar 구현 과정, 동적 버전 표시 및 웹 연동

앱 추가 및 수정 화면

 

Jetpack Compose를 사용한 안드로이드 앱 개발 중, 사용자에게 일관된 경험을 제공하기 위해 공통 TopAppBar를 구현한 과정을 공유합니다. 이 글에서는 TopAppBar에 앱 아이콘, 동적으로 가져온 앱 이름과 버전, 그리고 외부 URL로 연결되는 정보 아이콘을 추가하는 방법을 단계별로 설명합니다.

1. TopAppBar 구현 위치 결정: MainActivity

처음에는 각 화면(HomeScreen)에 TopAppBar를 추가할까 고민했지만, 앱 전체의 일관성 및 확장성을 위해 MainActivity.ktMainScreen Composable 내에 Scaffold를 사용해 구현하기로 결정했습니다. 이렇게 하면 모든 NavHost 화면에 동일한 TopAppBar가 적용됩니다.


// MainActivity.kt

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen() {
    // ... NavController, Context 등 초기화
    
    Scaffold(
        modifier = Modifier.fillMaxSize(),
        topBar = {
            // TopAppBar가 위치할 곳
        },
        bottomBar = {
            // BottomNavigation
        }
    ) { innerPadding ->
        NavHost(
            navController = navController,
            startDestination = Screen.Home.route,
            modifier = Modifier.padding(innerPadding) // TopAppBar, BottomBar 영역을 제외한 컨텐츠 영역
        ) {
            // ... composable 화면들
        }
    }
}
        

2. 앱 이름 및 버전 정보 동적으로 표시하기

TopAppBar에 표시될 앱 이름은 strings.xml 리소스에서, 버전 이름은 앱의 빌드 정보에서 동적으로 가져오도록 구현했습니다.

문제 발생: BuildConfig 참조 오류

처음에는 build.gradle.ktsversionName을 가져오기 위해 BuildConfig.VERSION_NAME을 사용하려고 했습니다. 이를 위해 build.gradle.kts 파일에 buildConfig = true 옵션을 추가하고 Gradle 동기화를 수행했지만, IDE에서 BuildConfig 클래스를 찾지 못하는 문제가 계속 발생했습니다.

해결 방안: PackageManager 사용

BuildConfig 문제의 대안으로, PackageManager를 사용하여 런타임에 직접 앱의 버전 정보를 가져오는 안정적인 방법을 선택했습니다. 이 방식은 Gradle 빌드 과정의 영향을 받지 않아 더 유연합니다.

수정된 MainActivity.kt


@Composable
fun MainScreen() {
    // ...
    val context = LocalContext.current
    val versionName = remember {
        try {
            val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
            packageInfo.versionName
        } catch (e: Exception) {
            "1.0" // 예외 발생 시 기본값
        }
    }

    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Row(verticalAlignment = Alignment.CenterVertically) {
                        Image(
                            painter = painterResource(id = R.drawable.ic_launcher_v1_round),
                            contentDescription = "App Icon",
                            modifier = Modifier.size(40.dp)
                        )
                        Spacer(modifier = Modifier.width(8.dp))
                        Text(text = "${stringResource(id = R.string.app_name)} v$versionName")
                    }
                },
                // ...
            )
        },
        // ...
    ) {
        // ...
    }
}
        

3. 정보 아이콘 추가 및 외부 웹 브라우저 연동

마지막으로, TopAppBar의 우측에 정보 아이콘을 추가하고, 이 아이콘을 클릭하면 지정된 URL이 웹 브라우저에서 열리도록 구현했습니다.

TopAppBaractions 파라미터에 IconButton을 추가하고, Intent(Intent.ACTION_VIEW)를 사용하여 클릭 시 웹 페이지를 열도록 했습니다.

MainActivity.kt의 TopAppBar actions 부분


// ...
topBar = {
    TopAppBar(
        title = { /* ... */ },
        actions = {
            val url = "https://billcorea.tistory.com/747"
            val context = LocalContext.current
            val intent = remember { Intent(Intent.ACTION_VIEW, Uri.parse(url)) }

            IconButton(onClick = { context.startActivity(intent) }) {
                Icon(
                    imageVector = Icons.Default.Info,
                    contentDescription = "Information"
                )
            }
        }
    )
},
//...
        

결론

이번 과정을 통해 Jetpack Compose에서 일관된 UI를 제공하는 TopAppBar를 구현하고, PackageManager를 이용해 동적으로 앱 정보를 표시하며, Intent를 통해 외부 앱과 연동하는 방법을 적용해 보았습니다. 특히 BuildConfig 문제 발생 시 대안을 찾아 해결하는 과정이 좋은 경험이 되었습니다.

반응형