이 문서에서는 Wear OS 기기와 기기 간에 데이터를 동기화하는 방법을 설명합니다. 휴대용 기기입니다.
네트워크에서 직접 데이터 전송 및 동기화
네트워크와 직접 통신하는 Wear OS 앱을 빌드합니다. 같은 모바일 개발에 사용하지만 일부 Wear OS 전용 API 차이를 염두에 두어야 합니다.
Wear OS Data Layer API를 사용하여 데이터 동기화
DataClient
는 구성요소가 DataItem
를 읽거나 쓸 수 있도록 API를 노출합니다.
Asset
입니다.
기기에 연결되어 있지 않은 상태에서 데이터 항목 및 애셋을 설정할 수 있습니다. 기기가 네트워크 연결을 설정할 때 동기화됩니다. 이 데이터 내 앱에만 공개되며 다른 기기에 있는 내 앱에서만 액세스할 수 있습니다.
DataItem
는 Wear OS 네트워크의 모든 기기에서 동기화됩니다. 일반적으로 크기가 작습니다.Asset
를 사용하여 이미지와 같은 더 큰 객체를 전송합니다. 시스템 이미 이전된 애셋을 추적하고 자동 중복 삭제
서비스에서 이벤트 수신 대기
WearableListenerService
클래스를 확장합니다. 시스템은
기본 WearableListenerService
의 수명 주기로, 실행 시 서비스에 바인딩됩니다.
데이터 항목 또는 메시지를 전송하고 작업이 없어 서비스 바인딩을 해제해야 하는 경우
할 수 있습니다
활동의 이벤트 수신 대기
OnDataChangedListener
인터페이스를 구현합니다. 대신 이 인터페이스 사용
WearableListenerService
를 호출하면
알 수 있습니다.
데이터 전송
블루투스 전송을 통해 음성 녹음 파일과 같은 바이너리 대형 객체를 전송하기 위해
다른 기기에서
<ph type="x-smartling-placeholder"></ph>
Asset
를 데이터 항목에 배치한 다음 데이터 항목을 복제된 Datastore에 배치합니다.
재전송을 방지하고 블루투스 대역폭을 보존하기 위해 애셋은 데이터 캐싱을 자동으로 처리합니다. 일반적인 패턴은 휴대기기 앱이 이미지를 다운로드하고, 웨어러블에 표시하기 위한 적절한 크기로 축소한 다음, 웨어러블 앱에 애셋으로 전송하는 것입니다. 다음 예는 이 패턴을 보여줍니다.
참고: 데이터 항목의 크기는 이론적으로 100KB로 제한되지만 실제로는 더 큰 데이터 항목을 사용할 수 있습니다. 큰 데이터 항목의 경우 고유한 경로로 데이터를 구분하고 모든 데이터에 단일 경로를 사용하지 않아야 합니다. 대용량 애셋을 전송하면 대부분의 경우 사용자 환경에 영향을 미치므로 앱을 테스트하여 대용량 애셋을 전송할 때 성능이 저하되지 않는지 확인할 수 있습니다.
애셋 전송
Asset
클래스의 create...()
메서드 중 하나를 사용하여 애셋을 만듭니다.
비트맵을 바이트 스트림으로 변환한 후 다음 샘플과 같이
createFromBytes()
를 호출하여 애셋을 만듭니다.
Kotlin
private fun createAssetFromBitmap(bitmap: Bitmap): Asset = ByteArrayOutputStream().let { byteStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream) Asset.createFromBytes(byteStream.toByteArray()) }
자바
private static Asset createAssetFromBitmap(Bitmap bitmap) { final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream); return Asset.createFromBytes(byteStream.toByteArray()); }
이제 DataMap
또는 PutDataRequest
에서 putAsset()
메서드를 사용하여 데이터 항목에 애셋을 연결합니다. 그런 다음
<ph type="x-smartling-placeholder"></ph>
putDataItem()
메서드를 참조하세요.
다음 샘플에서는 PutDataRequest
를 사용합니다.
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataRequest.create("/image").apply { putAsset("profileImage", asset) } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
자바
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataRequest request = PutDataRequest.create("/image"); request.putAsset("profileImage", asset); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
다음 샘플에서는 PutDataMapRequest
를 사용합니다.
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataMapRequest.create("/image").run { dataMap.putAsset("profileImage", asset) asPutDataRequest() } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
자바
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataMapRequest dataMap = PutDataMapRequest.create("/image"); dataMap.getDataMap().putAsset("profileImage", asset); PutDataRequest request = dataMap.asPutDataRequest(); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
애셋 수신
애셋이 생성되면 연결의 다른 쪽에서 애셋을 읽고 추출해야 할 수 있습니다. 다음은 애셋 변경을 감지하고 애셋을 추출하기 위해 콜백을 구현하는 방법의 예입니다.
Kotlin
override fun onDataChanged(dataEvents: DataEventBuffer) { dataEvents .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" } .forEach { event -> val bitmap: Bitmap? = DataMapItem.fromDataItem(event.dataItem) .dataMap.getAsset("profileImage") .let { asset -> loadBitmapFromAsset(asset) } // Do something with the bitmap } } fun loadBitmapFromAsset(asset: Asset): Bitmap? { // Convert asset into a file descriptor and block until it's ready val assetInputStream: InputStream? = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) ?.inputStream return assetInputStream?.let { inputStream -> // Decode the stream into a bitmap BitmapFactory.decodeStream(inputStream) } ?: run { Log.w(TAG, "Requested an unknown Asset.") null } }
자바
@Override public void onDataChanged(DataEventBuffer dataEvents) { for (DataEvent event : dataEvents) { if (event.getType() == DataEvent.TYPE_CHANGED && event.getDataItem().getUri().getPath().equals("/image")) { DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); Asset profileAsset = dataMapItem.getDataMap().getAsset("profileImage"); Bitmap bitmap = loadBitmapFromAsset(profileAsset); // Do something with the bitmap } } } public Bitmap loadBitmapFromAsset(Asset asset) { if (asset == null) { throw new IllegalArgumentException("Asset must be non-null"); } // Convert asset into a file descriptor and block until it's ready InputStream assetInputStream = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) .getInputStream(); if (assetInputStream == null) { Log.w(TAG, "Requested an unknown Asset."); return null; } // Decode the stream into a bitmap return BitmapFactory.decodeStream(assetInputStream); }
자세한 내용은 GitHub의 DataLayer 샘플 프로젝트를 참고하세요.