24.12.13 개발일지

이윤설·2024년 12월 13일
0

안드로이드 연구소

목록 보기
11/33

JSON에 직렬화


private fun createInitialProfile(
        firebaseUser: FirebaseUser,
        userId: String
    ): Map<String, Any?> {
        val now = Timestamp.now()

        return mapOf(
            "id" to userId,
            "nickname" to generateRandomNickname(),
            "email" to (firebaseUser.email ?: ""),
            "role" to "USER",
            "gender" to null,
            "lastLoginDate" to now,
            "notificationEnabled" to true,
            "marketingConsentEnabled" to null,
            "privacyPolicyEnabled" to null,
            "termsOfServiceEnabled" to null,
            "lastSyncDate" to null,
            "isAccountDeleted" to false,
            "createdDate" to now,
            "modifiedDate" to now,
        )
    }
-----------------------------------------------------------------
// 수정 전
    private fun convertMapToJson(map: Map<String, Any?>): String {
        val gson = Gson()
        return gson.toJson(map)
    }
    
// 수정 후
    private fun convertMapToJson(map: Map<String, Any?>): String {
        val gson = GsonBuilder()
            .serializeNulls()
            .create()
        return gson.toJson(map)
    }

map이 JSON으로 변환될 때, 값을 null로 넣은 쌍은 모두 제거되는 문제가 발생했다.
나는 값이 null인 쌍들도 모두 JSON으로 포함하고 싶었다.

이 문제는 serializeNulls()로 null을 허용해주면 간단하게 해결된다.

"보기" 클릭 시, URL 렌더링

@Composable
fun View(
    url: String,
    sharedSignInViewModel: SharedSignInViewModel = hiltViewModel()
) {
    val context = LocalContext.current

    Text(
        text = "보기",
        modifier = Modifier.clickable {
            sharedSignInViewModel.openUrl(context, url)
        },
        style = TextStyle(
            fontSize = 14.sp,
            fontFamily = FontFamily(Font(R.font.inter_24pt_regular)),
            color = Color(0xFFB3B3B3),
            textDecoration = TextDecoration.Underline,
        )
    )
}

@Composable
fun MarketingConsent() {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Image(
            painter = painterResource(id = R.drawable.check_without_circle),
            contentDescription = "check_without_circle",
            contentScale = ContentScale.Crop
        )
        Text(
            text = stringResource(id = R.string.marketing_consent),
            style =
            TextStyle(
                fontSize = 16.sp,
                fontFamily = FontFamily(Font(R.font.inter_24pt_regular)),
                fontWeight = FontWeight(500),
                color = GrayScaleWhite,
            )
        )
        View(url = stringResource(id = R.string.marketing_consent_url))
    }
}
--------------------------------------
// 뷰모델

    fun openUrl(context: Context, url: String) {
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
    }

Intent란?

Intent는 Android 시스템에서 컴포넌트 간의 통신을 관리하는 주요 객체이다. 다음과 같은 두 가지 주요 용도로 사용된다.

  1. Activity 간의 이동

    • 한 Activity에서 다른 Activity를 시작하거나 데이터를 전달할 때 사용한다.
  2. 작업 요청

    • 시스템이나 다른 앱에 작업을 요청한다.
      • 웹 브라우저를 열어 특정 URL을 표시.
      • 연락처 앱 열기.
      • 특정 작업을 다른 앱에서 처리하도록 요청.

Intent의 주요 종류

  1. 명시적(Intent Explicit)

    • 시작하려는 컴포넌트를 명확히 지정한다. 주로 내부 컴포넌트 간 통신에 사용된다.
    • 예: 특정 Activity를 시작할 때.
      val intent = Intent(this, TargetActivity::class.java)
      startActivity(intent)
  2. 암시적(Intent Implicit)

    • 작업의 목적만 정의하고, 이를 처리할 수 있는 앱을 시스템이 선택하도록 맡긴다.
    • 예: 웹 브라우저에서 URL 열기.
      val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"))
      startActivity(intent)

Compose에서 Intent를 사용하는 경우

  1. 외부 애플리케이션 실행

    • 브라우저, 지도, 연락처 등 외부 앱과 연동할 때 사용합니다.
    • 예: 브라우저에서 특정 URL 열기.
      val context = LocalContext.current
      Button(onClick = {
          val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"))
          context.startActivity(intent)
      }) {
          Text("Open Google")
      }
  2. 내부 컴포넌트 이동

    • 기존 XML 기반의 Activity와 Compose의 Composable 간 연결이 필요할 때 사용할 수 있습니다.
  3. 특정 시스템 작업 요청

    • 전화 걸기, 메시지 보내기, 이메일 전송 등 시스템 작업 요청 시 사용됩니다.
    • 예: 전화 걸기
      val context = LocalContext.current
      Button(onClick = {
          val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:123456789"))
          context.startActivity(intent)
      }) {
          Text("Call")
      }
  4. 데이터 공유

    • Compose에서 데이터를 공유하거나 파일을 다른 앱으로 전송할 때도 Intent를 활용합니다.
    • 예: 공유 Intent.
      val context = LocalContext.current
      Button(onClick = {
          val shareIntent = Intent(Intent.ACTION_SEND).apply {
              type = "text/plain"
              putExtra(Intent.EXTRA_TEXT, "Hello from Compose!")
          }
          context.startActivity(Intent.createChooser(shareIntent, "Share via"))
      }) {
          Text("Share Text")
      }

Compose에서 Intent가 필요 없는 경우

Compose의 내비게이션 시스템인 Jetpack Navigation Compose를 사용하는 경우, 화면 간의 이동은 NavController를 통해 처리합니다. 이 경우 Intent를 사용할 필요가 없습니다.

val navController = rememberNavController()
NavHost(navController, startDestination = "screen1") {
    composable("screen1") { Screen1(navController) }
    composable("screen2") { Screen2() }
}

@Composable
fun Screen1(navController: NavController) {
    Button(onClick = { navController.navigate("screen2") }) {
        Text("Go to Screen 2")
    }
}

요약

  • Intent는 Jetpack Compose에서도 사용할 수 있으며, 외부 애플리케이션 연동, 시스템 작업 요청, 데이터 공유 등의 상황에서 주로 사용됩니다.
  • 화면 간 이동에는 Jetpack Navigation Compose를 사용하는 것이 더 적합합니다.
  • Compose와 기존 Android 기능은 호환성이 좋으므로 상황에 따라 적절한 방식을 선택하면 됩니다.
profile
화려한 외면이 아닌 단단한 내면

0개의 댓글

관련 채용 정보