Wear에서 애셋 전송

블루투스를 통해 이미지와 같은 대규모 바이너리 데이터 Blob을 전송하려면 Asset을 데이터 항목에 첨부하고 복제된 데이터 저장소에 데이터 항목을 저장할 수 있습니다.

참고: Wear 앱은 아래의 Data Layer API를 사용하여 전화 앱과 통신할 수 있지만, 이 API를 사용하여 네트워크에 연결하는 것은 권장되지 않습니다.

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

참고: 데이터 항목의 크기는 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() 메서드를 사용하여 애셋을 데이터 항목에 첨부한 다음, 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);
    }