Data Layer API를 사용하여 데이터 항목 동기화

DataItem은 시스템이 휴대기기와 웨어러블 기기 간에 데이터를 동기화하는 데 사용하는 인터페이스를 정의합니다. DataItem은 일반적으로 다음 구성요소로 이루어져 있습니다.

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

참고: Data Layer API는 Android 휴대전화 또는 Wear OS 시계에서만 메시지를 전송하고 데이터를 동기화할 수 있습니다. Wear OS 기기가 iOS 기기와 페어링된 경우 Data Layer API는 작동하지 않습니다.

따라서 네트워크와 통신하는 기본 방법으로 Data Layer API를 사용하면 안 됩니다. 대신 모바일 앱과 동일한 패턴(약간의 차이는 있음)을 따르세요.

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

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

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

자세한 내용은 DataLayer 샘플 앱을 참고하세요.

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

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

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

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

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

  2. PutDataMapRequest.getDataMap()을 호출하여 값을 설정할 수 있는 데이터 맵을 가져옵니다.
  3. putString()과 같은 put...() 메서드를 사용하여 데이터 맵의 값을 설정합니다.
  4. 동기화 지연으로 사용자 환경에 부정적인 영향을 미칠 수 있는 경우 setUrgent()를 호출합니다.
  5. PutDataMapRequest.asPutDataRequest()를 호출하여 PutDataRequest 객체를 가져옵니다.
  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를 사용하면 DataItem 객체의 동기화를 긴급하게 요청할 수 있습니다. 일반적으로 시스템은 사용자 기기의 배터리 수명을 개선하기 위해 데이터 항목을 Wear OS 네트워크로 전송하는 작업을 지연시킵니다. 그러나 데이터 항목의 동기화 지연이 사용자 환경에 부정적인 영향을 미친다면 이를 긴급으로 표시할 수 있습니다. 예를 들어 사용자의 작업이 즉시 반영되어야 하는 리모컨 앱에서는 setUrgent()를 호출하여 시스템과 데이터 항목을 즉시 동기화할 수 있습니다.

setUrgent()를 호출하지 않으면 시스템은 긴급하지 않은 데이터 항목 동기화 작업을 최대 30분 지연시킬 수도 있습니다. 그러나 일반적으로는 몇 분 정도만 지연된다고 예상하면 됩니다. 긴급하지 않은 것이 기본값이므로 이전 버전의 Wear OS 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
            }
        }
    }

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

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

이 활동은 DataClient.OnDataChangedListener 인터페이스를 구현합니다. 또한 onResume() 메서드 내에서 데이터 항목 이벤트의 리스너로 스스로를 추가하고 onPause() 메서드에서 리스너를 삭제합니다. 이미지, 뷰 모델, 서비스를 사용한 구현 작업을 보려면 DataLayer 샘플 앱을 참고하세요.

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