안드로이드 와치 Wear OS 데이터 전송할 때 발생하는 java.lang.IllegalArgumentException: Buffer is closed
예외 해결 방법.
문제 상황
Wear OS에서 데이터 전송 및 동기화 가이드 대로 코드를 작성해도 예외가 발생한다.
2023-11-28 00:11:37.243 15775-15920/? D/DataLayerService: onDataChanged
2023-11-28 00:11:37.268 15775-15775/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.your_app, PID: 15775
java.lang.IllegalArgumentException: Buffer is closed.
at com.google.android.gms.common.data.DataHolder.zae(com.google.android.gms:play-services-base@@18.0.1:4)
at com.google.android.gms.common.data.DataHolder.getString(com.google.android.gms:play-services-base@@18.0.1:1)
at com.google.android.gms.common.data.DataBufferRef.getString(com.google.android.gms:play-services-base@@18.0.1:1)
at com.google.android.gms.wearable.internal.zzdk.getUri(com.google.android.gms:play-services-wearable@@18.0.0:1)
at com.google.android.gms.wearable.DataMapItem.<init>(com.google.android.gms:play-services-wearable@@18.0.0:1)
at com.google.android.gms.wearable.DataMapItem.fromDataItem(com.google.android.gms:play-services-wearable@@18.0.0:2)
at com.example.your_app.DataLayerListenerService$onDataChanged$1$1.invokeSuspend(DataLayerListenerService.kt:38)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7962)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:550)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@474d8fd, Dispatchers.Main.immediate]
문제가 발생한 코드는 아래와 같다. Android DataLayer 샘플 코드 거의 그대로 사용 중인데도 문제가 발생한다.
class DataLayerListenerService : WearableListenerService() {
...
override fun onDataChanged(dataEvents: DataEventBuffer) {
Log.d(TAG, "onDataChanged")
super.onDataChanged(dataEvents)
// Do additional work for specific events
dataEvents.forEach { dataEvent ->
when (dataEvent.type) {
DataEvent.TYPE_CHANGED -> {
when (dataEvent.dataItem.uri.path) {
IMAGE_PATH -> {
scope.launch {
val filename = DataMapItem.fromDataItem(dataEvent.dataItem)
.dataMap
.getString(FILENAME_KEY)
filename?.let { filename ->
val bitmap = loadBitmap(
DataMapItem.fromDataItem(dataEvent.dataItem)
.dataMap
.getAsset(IMAGE_KEY)
)
bitmap?.let {
saveBitmapToJpeg(
it,
applicationContext.dataDir,
"$FILE_DIR${filename}"
)
}
}
}
}
}
}
}
}
}
해결 방법
딱 봐도 Buffer가 내가 쓰려는데 닫혀버리는 것 같은데, 복사를 해서 써야하나 해서 수정해봐도 잘 안되는데, 복사하는 방법을 가이드 하고 있다.
데이터 관리를 com.google.android.gms.wearable.DataMapItem.fromDataItem
여기서 하니까 google service lib 쪽으로 확인해서 해결 방안을 찾았다.
Google Play services - WearableListenerService 에 보면 DataEvent
를 Freezable.freeze()
를 사용해서 코루틴 스코프에서 버퍼를 계속 사용할 수 있도록 해야 한다고 한다.
Freezable.freeze()
의 사용법은 다음과 같다.
문제의 코드를 살짝 고쳐서 해결했다. val frozenEvent = dataEvent.freeze()
해서 그 반환값을 사용하도록 수정.
override fun onDataChanged(dataEvents: DataEventBuffer) {
Log.d(TAG, "onDataChanged")
super.onDataChanged(dataEvents)
// Do additional work for specific events
dataEvents.forEach { dataEvent ->
val frozenEvent = dataEvent.freeze()
when (frozenEvent.type) {
DataEvent.TYPE_CHANGED -> {
when (frozenEvent.dataItem.uri.path) {
IMAGE_PATH -> {
scope.launch {
val filename = DataMapItem.fromDataItem(frozenEvent.dataItem)
.dataMap
.getString(FILENAME_KEY)
filename?.let { filename ->
val bitmap = loadBitmap(
DataMapItem.fromDataItem(frozenEvent.dataItem)
.dataMap
.getAsset(IMAGE_KEY)
)
bitmap?.let {
saveBitmapToJpeg(
it,
applicationContext.dataDir,
"$FILE_DIR${filename}"
)
}
}
}
}
}
}
}
}
}
별 문제 아니였지만 외부 코드(구글 플레이 서비스 패키지)에서 문제가 나왔는데, 샘플 가이드가 안되어 있어서 검색하는데 시간이 좀 걸렸다. 지피티도 모름. 문제가 되는 지점을 명확히하고 단계별로 범위를 좁혀서 디버깅 + 검색!
'나의 경험담' 카테고리의 다른 글
2022 가을 캠핑의 기록 (0) | 2022.11.07 |
---|---|
관악산 등산 사당역-연주대-과천역 4시간 코스 (0) | 2021.09.26 |
Tizen Log Viewer T.Viewer를 소개합니다. (0) | 2021.08.18 |
[T.Viewer 개발일기] 부록. CI/CD feat.travis (0) | 2021.07.13 |
라즈베리파이 Jupyter notebook 외부 접속 안될때 (0) | 2021.05.15 |
라즈베리파이 우분투 openssh-server Failed with result 'exit-code' (0) | 2021.05.10 |
[T.Viewer] electron + jest desktop application에 codecov 적용기 (0) | 2021.01.13 |
댓글