지난 2편에서는 간단한 앱 위젯을 만들어봤다면 이번 3편에서는 액티비티 실행, 서비스 실행 등 앱 위젯 상호작용에 대해서 알아보자!
# 상호작용 종류
- 활동 실행 (Activity)
- 서비스 실행
- 브로드캐스트 이벤트 전송
- 콜백 실행
상호 작용이 가능한 종류로는 위 4가지가 있다.
위 종류에 대한 작업을 실행하려면 GlanceModifier.clickable 메서드를 사용하거나 Button의 onClick 메서드처럼 Action클래스에서 정의해 주면 된다.
하나하나 살펴보자!
## 활동 실행 (Activity)
만약 어떠한 Action이 들어왔을 때 액티비티를 띄워주고 싶다면 아래와 같이 actionStartActivity라는 메서드를 사용한다.
actionStartActivity에는 총 3가지를 제공할 수 있다.
- 띄워줄 액티비티 클래스
@Composable
fun MyContent() {
// ..
Button(
text = "Go Home",
onClick = actionStartActivity<MainActivity>()
)
}
- ComponentName
@Composable
fun MyContent() {
// ..
Button(
text = "Go Home",
onClick = actionStartActivity(
Intent().setComponent(
ComponentName("com.example.package", "com.example.package.TargetActivity")
)
)
)
}
- Intent
@Composable
fun MyContent() {
// ..
Button(
text = "Go Home",
onClick = actionStartActivity(
Intent(
Intent.ACTION_VIEW,
Uri.parse("https://www.naver.com")
)
)
)
}
## 서비스 실행
액티비티 실행과 비슷하게 서비스는 actionStartService메서드를 사용한다.
actionStartService도 마찬가지로 3가지를 제공할 수 있다.
- 실행할 서비스
@Composable
fun MyButton() {
// ..
Button(
text = "Sync",
onClick = actionStartService<SyncService>(
isForegroundService = true // define how the service is launched
)
)
}
- ComponentName
- Intent
ComponentName, Intent 코드는 활동 실행과 동일하다.
## 브로드캐스트 이벤트 전송
사용자 상호작용 시 브로드캐스트 이벤트를 전송하기 위해 actionSendBroadcast 메서드를 사용한다.
actionSendBroadcast는 총 4가지를 제공할 수 있다.
- 문자열작업
- ComponentName
- Intent
- BroadcastReceiver Class
@Composable
fun MyButton() {
// ..
Button(
text = "Send",
onClick = actionSendBroadcast<MyReceiver>()
)
}
## 콜백 실행
actionRunCallback 메서드의 ActionCallback을 구현한 클래스를 제네릭으로 넣어준다.
@Composable
private fun MyContent() {
// ..
Image(
provider = ImageProvider(R.drawable.ic_hourglass_animated),
modifier = GlanceModifier.clickable(
onClick = actionRunCallback<RefreshAction>()
),
contentDescription = "Refresh"
)
}
class RefreshAction : ActionCallback {
override suspend fun onAction(
context: Context,
glanceId: GlanceId,
parameters: ActionParameters
) {
// 작업 로직
}
}
코드에도 보다 시피 ActionCallback을 구현한 클래스는 onAction 함수를 필수적으로 오버라이드를 하고 콜백이 왔을 시 onAction로 들어오기 때문에 onAction 안에서 필요한 로직 처리를 해주면 된다.
- 작업을 실행한 후 위젯을 업데이트하는 로직 예시
@Composable
private fun MyContent() {
// ..
Image(
provider = ImageProvider(R.drawable.ic_hourglass_animated),
modifier = GlanceModifier.clickable(
onClick = actionRunCallback<RefreshAction>()
),
contentDescription = "Refresh"
)
}
class RefreshAction : ActionCallback {
override suspend fun onAction(
context: Context,
glanceId: GlanceId,
parameters: ActionParameters
) {
// 작업 실행 로직
...
// .update함수로 위젯 업데이트
MyAppWidget().update(context, glanceId)
}
}
# 작업에 매개변수 제공 방법
앱 위젯이 어떠한 상호작용을 했을 때 (액티비티 실행, 서비스 실행, 브로드캐스트 이벤트 실행, 콜백 실행) 값을 넘겨줘야 하는 상황이 생길 수 있다.
이 경우 어떠한 방식으로 매개변수를 넘겨주는지 알아보자!
## 액티비티로 매개변수 제공
기존에는 Intent의 putextra를 활용하여 액티비티로 매개변수를 넘겨줬다면,
앱 위젯에서는 ActionParameters API를 사용하여 키-값 형식으로 만들어주면 된다!
### 구현방법
1. 넘겨줄 액티비티에서 상수 KEY값 생성
2. 앱 위젯 상호 작용 시 키-값 형태로 actionParametersOf를 사용해 전달
3. 해당 액티비티에서 인텐트로 값을 가져옴
1. 넘겨줄 액티비티에서 상수 KEY값 생성
class NavigationActivity : ComponentActivity() {
companion object {
// 상수로 KEY 값 생성
const val KEY_DESTINATION = "destination"
}
}
2. 앱 위젯 상호 작용 시 키를 가져와서 키-값 형태로 actionParametersOf를 사용해 전달
// 전에 만들어준 키값을 ActionParameters.Key로 가져와서 변수에 담음
private val destinationKey = ActionParameters.Key<String>(
NavigationActivity.KEY_DESTINATION
)
class MyAppWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
MyContent()
}
}
@Composable
private fun MyContent() {
Column(
modifier = GlanceModifier.fillMaxSize()
.background(GlanceTheme.colors.background),
verticalAlignment = Alignment.Top,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "어디로 이동할까요?",
modifier = GlanceModifier.padding(12.dp)
)
Button(
text = "Home",
onClick = actionStartActivity<NavigationActivity>(
// actionParametersOf를 사용해 Home이라는 값 전달
actionParametersOf(destinationKey to "Home")
)
)
}
}
}
3. 해당 액티비티에서 인텐트로 값을 가져옴
intent.extras?. getString(키값) 이 함수로 넘어온 매개변수를 받는다.
class NavigationActivity : ComponentActivity() {
companion object {
// 상수로 KEY 값 생성
const val KEY_DESTINATION = "destination"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// intent.extras?.getString로 넘어온 값을 변수에 넣어준다.
val destination = intent.extras?.getString(KEY_DESTINATION) ?: "destination 없음"
Toast.makeText(this, "destination: $destination", Toast.LENGTH_LONG).show()
setContent {
Surface(
modifier = Modifier.fillMaxSize(),
) {
Text(
text = "NavigationActivity 입니다",
fontSize = 22.sp,
textAlign = TextAlign.Center
)
}
}
}
}
결과화면
+ 추가로 ActionCallback에도 키-값을 제공할 수 있다.(아래 예시 코드 참조)
class RefreshAction : ActionCallback {
private val destinationKey = ActionParameters.Key<String>(
NavigationActivity.KEY_DESTINATION
)
override suspend fun onAction(
context: Context,
glanceId: GlanceId,
parameters: ActionParameters
) {
val destination: String = parameters[destinationKey] ?: ""
// ...
}
}