Wear에서 데이터 항목 동기화

DataItem은 시스템이 핸드헬드와 웨어러블 간에 데이터를 동기화하는 데 사용하는 인터페이스를 정의합니다. DataItem은 일반적으로 다음과 같은 요소로 구성됩니다.

  • 페이로드 - 원하는 데이터로 설정할 수 있는 바이트 배열로, 객체 직렬화 및 역직렬화를 수행할 수 있습니다. 페이로드의 크기는 100KB로 제한됩니다.
  • 경로 - 슬래시로 시작해야 하는 고유 문자열(예: "/path/to/data")

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

일반적으로 DataItem을 직접 구현하는 대신 다음과 같이 합니다.

  1. PutDataRequest 객체를 만들고, 항목을 고유하게 식별하기 위한 문자열 경로를 지정합니다.
  2. setData()를 호출하여 페이로드를 설정합니다.
  3. 동기화 지연으로 사용자 환경에 부정적인 영향을 미칠 수 있는 경우 setUrgent()를 호출합니다.
  4. DataClient 클래스의 putDataItem 메서드를 사용하여 시스템이 데이터 항목을 만들도록 요청합니다.

데이터 항목을 요청하면 시스템은 DataItem 인터페이스를 적절하게 구현하는 객체를 반환합니다. 그러나 setData()를 사용하여 원시 바이트로 작업하는 대신, Bundle 같은 인터페이스로 데이터 항목을 표시하는 데이터 맵을 사용하는 것이 좋습니다.

다음의 관련 리소스를 참조하세요.

데이터 맵으로 데이터 동기화

가능한 경우 DataMap 클래스를 사용하세요. 그러면 Android Bundle의 형식으로 데이터 항목을 사용하여 작업할 수 있으므로, 시스템이 사용자 대신 객체 직렬화와 역직렬화를 수행하고 사용자는 키-값 쌍으로 데이터를 조작할 수 있습니다.

데이터 맵을 사용하려면 다음 단계를 따르세요.

  1. PutDataMapRequest 객체를 만들고 데이터 항목의 경로를 설정합니다.

    참고: 경로 문자열은 연결의 어느 한쪽에서 액세스하도록 허용하는 데이터 항목의 고유 식별자입니다. 경로는 슬래시로 시작해야 합니다. 앱에서 계층적 데이터를 사용하는 경우 데이터 구조와 일치하는 경로 체계를 만들어야합니다.

  2. 값을 설정할 수 있는 데이터 맵을 가져오기 위해 PutDataMapRequest.getDataMap()을 호출합니다.
  3. put...() 메서드를 사용하여 데이터 맵에 관해 원하는 값을 설정합니다(예: putString()).
  4. 동기화 지연으로 사용자 환경에 부정적인 영향을 미칠 수 있는 경우 setUrgent()를 호출합니다.
  5. PutDataRequest 객체를 가져오기 위해 PutDataMapRequest.asPutDataRequest()를 호출합니다.
  6. DataClient 클래스의 putDataItem 메서드를 사용하여 시스템이 데이터 항목을 만들도록 요청합니다.

    참고: 핸드셋과 웨어러블 기기의 연결이 끊어진 경우, 연결이 다시 설정되면 데이터가 버퍼링 및 동기화됩니다.

다음 예제의 increaseCounter() 메서드는 데이터 맵을 만들고 데이터를 입력하는 방법을 보여줍니다.

Kotlin

    private const val COUNT_KEY = "com.example.key.count"

    class MainActivity : Activity() {

        private lateinit var dataClient: DataClient
        private var count = 0
        ...
        // Create a data map and put data in it
        private fun increaseCounter() {
            val putDataReq: PutDataRequest = PutDataMapRequest.create("/count").run {
                dataMap.putInt(COUNT_KEY, count++)
                asPutDataRequest()
            }
            val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
        }
        ...
    }
    

자바

    public class MainActivity extends Activity {
        private static final String COUNT_KEY = "com.example.key.count";
        private DataClient dataClient;
        private int count = 0;
        ...
        // Create a data map and put data in it
        private void increaseCounter() {
            PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
            putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
            PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
            Task<DataItem> putDataTask = dataClient.putDataItem(putDataReq);
        }
      ...
    }
    

Tasks 처리에 관한 자세한 내용은 참조 설명서를 참조하세요.

DataItem 우선순위 설정

DataClient API를 사용하면 DataItems의 동기화를 긴급하게 요청할 수 있습니다. 일반적으로 시스템은 사용자 기기의 배터리 수명을 연장하기 위해 Wear 네트워크로 DataItems를 전송하는 작업을 지연시킬 수 있습니다. 그러나 DataItems 동기화가 지연되면 사용자 환경에 부정적인 영향을 미칠 수 있는 경우 이를 긴급으로 표시할 수 있습니다. 예를 들어 사용자의 작업이 즉시 반영되어야 하는 리모컨 앱에서는 setUrgent()를 호출하여 시스템과 DataItems를 즉시 동기화할 수 있습니다.

setUrgent()를 호출하지 않으면 긴급하지 않은 DataItems를 동기화하기까지 최대 30분이 지연될 수 있지만, 일반적으로는 몇 분 정도 지연되는 것으로 예상할 수 있습니다. 긴급하지 않은 것이 기본값이므로 Wear API의 이전 버전에 있던 즉시 동기화 동작을 유지하려면 setUrgent()를 사용해야 합니다.

데이터 항목 이벤트 수신

데이터 영역 연결의 한 쪽에서 데이터 항목이 변경되는 경우 연결의 다른 쪽에 변경 사항을 알려야 할 수 있습니다. 데이터 항목 이벤트에 관한 리스너를 구현하여 이 작업을 실행할 수 있습니다.

다음 예제의 코드 스니펫은 이전 예제에서 정의한 카운터 값이 변경되면 앱에 이를 알립니다.

Kotlin

    private const val COUNT_KEY = "com.example.key.count"

    class MainActivity : Activity(), DataClient.OnDataChangedListener {

        private var count = 0

        override fun onResume() {
            super.onResume()
            Wearable.getDataClient(this).addListener(this)
        }

        override fun onPause() {
            super.onPause()
            Wearable.getDataClient(this).removeListener(this)
        }

        override fun onDataChanged(dataEvents: DataEventBuffer) {
            dataEvents.forEach { event ->
                // DataItem changed
                if (event.type == DataEvent.TYPE_CHANGED) {
                    event.dataItem.also { item ->
                        if (item.uri.path.compareTo("/count") == 0) {
                            DataMapItem.fromDataItem(item).dataMap.apply {
                                updateCount(getInt(COUNT_KEY))
                            }
                        }
                    }
                } else if (event.type == DataEvent.TYPE_DELETED) {
                    // DataItem deleted
                }
            }
        }

        // Our method to update the count
        private fun updateCount(int: Int) { ... }

        ...
    }
    

자바

    public class MainActivity extends Activity implements DataClient.OnDataChangedListener {
        private static final String COUNT_KEY = "com.example.key.count";
        private int count = 0;

        @Override
        protected void onResume() {
            super.onResume();
            Wearable.getDataClient(this).addListener(this);
        }

        @Override
        protected void onPause() {
            super.onPause();
            Wearable.getDataClient(this).removeListener(this);
        }

        @Override
        public void onDataChanged(DataEventBuffer dataEvents) {
            for (DataEvent event : dataEvents) {
                if (event.getType() == DataEvent.TYPE_CHANGED) {
                    // DataItem changed
                    DataItem item = event.getDataItem();
                    if (item.getUri().getPath().compareTo("/count") == 0) {
                        DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                        updateCount(dataMap.getInt(COUNT_KEY));
                    }
                } else if (event.getType() == DataEvent.TYPE_DELETED) {
                    // DataItem deleted
                }
            }
        }

        // Our method to update the count
        private void updateCount(int c) { ... }

        ...
    }
    

이 작업은 DataClient.OnDataChangedListener 인터페이스를 구현합니다. 또한 onResume() 메서드 내에서 데이터 항목 이벤트의 리스너로 스스로를 추가하고 onPause() 메서드에서 리스너를 삭제합니다.

리스너를 서비스로서 구현할 수도 있습니다. 자세한 내용은 데이터 영역 이벤트 수신을 참조하세요.