data layer 을 구현해 보자

Assist·2023년 7월 13일
0

Android

목록 보기
7/24

오늘은 저번에 알아본 data layer에서 message 을 구현해 보도록 하겠습니다.

라이브러리 다운

일단 전 google 에서 제공한 가이드 문서 토대로 라이브러리를 다운 받았습니다.

    //wear
    implementation 'com.google.android.gms:play-services-wearable:18.0.0'
    
    //Gson
    implementation 'com.google.code.gson:gson:2.10.1'
    
    //await()`
    implementation 'com.google.guava:guava:32.0.1-jre'
    implementation "androidx.concurrent:concurrent-futures-ktx:1.1.0"
    

위에서 부터 보면

  • wearable 은 wear 의 node 와 핸드폰 연결 유뮤를 확인 하기 위해 선언 했습니다.
  • Gson 은 데이터를 json형식으로 보내기 위해 선언 했습니다.
  • await 은 데이터를 보낼때 비동기 형식으로 보내기 위해 선언 했습니다.

자 그럼 한번 봅시다.

File -> New -> New Moudle 을 선택해 wear Project을 만들어 줍니다.

그후 wear 에서 activity_main 와 MainActivity을 만들어주고 Mainfest에 선언을 해줍니다.

Build gradle 을 확인해보자

블로그를 쓰기전 제가 코드를 구현 하면서 Data layer message가 작동을 안해
잠시 삽질한 적이 있습니다.

그 이유가 Build gradle 에 applicationId 가 문제 였습니다.

    defaultConfig {
        applicationId "com.example.wearproject_mobile" -> 요거 때문 
        minSdk 30
        targetSdk 33
        versionCode 1
        versionName "1.0.0_mobile"
        wearAppUnbundled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

여러분이 제 글을 따라오면서 wear 에도 이름을 정해줬을텐데요

그때 wear 의 applicationId 을 확인해 주시길 바랍니다.
wear도 applicationId 가 똑같아야 data layer 가 작동됩니다.

  • 이건 구글에 없던 내용 이더라구요

자 그럼 계속 준비를 해보겠습니다.

에뮬레이터 추가

난 실물로 돌릴건데 라고 하시는 분들

안드로이드 스튜디오 우측 상단에 보면 app 밖에 없어서 당활 하실 겁니다.

그럼 당황하지 마시고 app 을 누르시면 edit configuration 을 누르면

이런 창이 보이실 겁니다

그럼 우측 상단에 + 을 눌러 추가를 눌러주시고 이름은 마음대로 하시고 Module은 wear Project을 추가해주시면 되겠습니다.

구현 시작

여기서 한번 정의 하고 가겠습니다.

핸드폰(데이터 받는쪽) - wear (데이터 보내는쪽)

입니다.

그럼 wear 에 함수를 구현해 보겠습니다.

    val messageClient by lazy { Wearable.getMessageClient(this) }
    val capabilityClient by lazy { Wearable.getCapabilityClient(this) }
    
    private fun sendMessage(){
        val data = TestObject("MessageFromWear")
        val gson = Gson()
        val dataJson = gson.toJson(data)
        val sendData = dataJson.toByteArray(Charsets.UTF_8)
        CoroutineScope(Dispatchers.Default).launch {
            try{
                val nodes = capabilityClient.getCapability(Define.MOBILE_CAPABILITY , CapabilityClient.FILTER_REACHABLE).await().nodes

                if(nodes.size == 0){
                    Log.d("tag" , "The node Size is 0")
                }
                nodes.map {node ->
                     async {
                         Log.d("tag", "data send $data")
                         messageClient.sendMessage(node.id ,Define.MESSAGE_URL , sendData )
                     }
                }.awaitAll()
            }catch (e : Exception){
                Log.d("tag" , "Error to send Data_wear")
            }
        }

    }

위에서 부터 messageclient 란 data layer 의 message을 보내는주는 라이브러리 입니다.
capabilityClient 은 wear에 연결된 node 갯수를 return 해줍니다.

        val data = TestObject("MessageFromWear")
        val gson = Gson()
        val dataJson = gson.toJson(data)
        val sendData = dataJson.toByteArray(Charsets.UTF_8)

해당 코드는 data는 string object 로 만들어 주고 그것을 json으로 만들어 bytearray로 만들어줍니다.

        CoroutineScope(Dispatchers.Default).launch {
            try{
                val nodes = capabilityClient.getCapability(Define.MOBILE_CAPABILITY(이게 mobile)  , CapabilityClient.FILTER_REACHABLE).await().nodes

                if(nodes.size == 0){
                    Log.d("tag" , "The node Size is 0")
                }
                nodes.map {node ->
                     async {
                         Log.d("tag", "data send $data")
                         messageClient.sendMessage(node.id ,Define.MESSAGE_URL , sendData )
                     }
                }.awaitAll()
            }catch (e : Exception){
                Log.d("tag" , "Error to send Data_wear")
            }
        }

그후 비동기로 보내기 위해 코루틴을 선언하며 nodes 갯수를 체크 했습니다.
node 사이즈를 봐서 0일시 연결된 핸드폰이 없다고 판단합니다.

아닐시 node을 통해 messageClient을 사용해 연결된 모바일에 메세지를 보내줍니다.

모바일도 준비하자

mobile 에 res / values 에 wear.xml 을 선언해 줍니다.

<resources xmlns:tools="http://schemas.android.com/tools">
    <string-array name="android_wear_capabilities" translatable="false">
        <!-- declaring the provided capabilities -->
        <item>mobile</item> -> 요건 상관 없음 
    </string-array>
</resources>

mobile을 다른것으로 바꿔도 상관 없습니다. 위에 칸으로 보면

  val nodes = capabilityClient.getCapability(Define.MOBILE_CAPABILITY , CapabilityClient.FILTER_REACHABLE).await().nodes

Define.MOBILE_CAPABILITY -> mobile 입니다.

다른것으로 바꿔도 상관 없습니다
define은 제가 만든 함수 이니까요 static

자 그럼 dataLayerLstener을 구현 해 보겠습니다.

class DataLayerListenerService : WearableListenerService() , DataClient.OnDataChangedListener {

  override fun onMessageReceived(messageEvent: MessageEvent) {
      Timber.d("The Message is come from Wear")
  }
}

저희는 메세지만 받기 때문에 override onMessageReceived 만 가졌습니다.

Mobile 에 Menifest 쪽으로 가보겠습니다.

       <service android:name=".DataLayerListenerService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
                <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
                <data
                    android:host="*"
                    android:pathPrefix="/message"
                    android:scheme="wear" />
            </intent-filter>
        </service>

android:scheme="wear" 은 지켜주시고
android:pathPrefix="/message" 은 마음대로 하셔도 상관 없습니다.

  messageClient.sendMessage(node.id ,Define.MESSAGE_URL , sendData )

wear 쪽에 messageClient 코드 입니다.

그럼 오늘도 읽어주셔사 감사합니다
-피드백와 비판은 언제나 환영입니다-

        
profile
안드로이드만 좋아하는 특이한 개발자

0개의 댓글

관련 채용 정보