Wear에서 애셋 전송

블루투스 전송을 통해 다른 기기의 음성 녹음 파일과 같은 바이너리 대형 객체를 전송하려면 Asset을 데이터 항목에 연결하고 이 데이터 항목을 복제된 데이터 스토어에 넣으면 됩니다.

재전송을 방지하고 블루투스 대역폭을 보존하기 위해 애셋은 데이터 캐싱을 자동으로 처리합니다. 일반적인 패턴은 휴대기기 앱이 이미지를 다운로드하고, 웨어러블에 표시하기 위한 적절한 크기로 축소한 다음, 웨어러블 앱에 애셋으로 전송하는 것입니다. 다음 예는 이 패턴을 보여줍니다.

참고: 데이터 항목의 크기는 이론적으로 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())
    }

Java

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() 메서드를 사용하여 데이터 항목에 애셋을 연결합니다. 그런 다음, 다음 샘플과 같이 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)

Java

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
    }
}

Java

@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 샘플 프로젝트를 참고하세요.