이전 회에 이어 WifiAwareSession을 얻는 과정이다

 

1.  ViewModel 초기화 및 observer 추가

WifiAwareSession의 instance 값을 화면에서 볼 수 있도록 변수에 대한 observer를 설정했다

더불어 connect 와 disconnect 버튼도 활성화 및 비활성화 하도록  했다

class MainActivity : AppCompatActivity() {

    lateinit var bindMain : ActivityMainBinding

    ...........

    lateinit var viewModel : MainViewModel

    private fun initViewModel(){
        viewModel = ViewModelProvider(this)[MainViewModel::class.java]

        viewModel.wifiAwareSession.observe(this){
            var strDisplay = "wifiAwareSession : "
            strDisplay += it?.toString() ?: "null"
                bindMain.tvWifiAwareSession.text = strDisplay
            // session이 있으면 연결 버튼 disable
            bindMain.btnConnect.isEnabled = (it==null)
            bindMain.btnDisconnect.isEnabled = (it!=null)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        .............

        initViewModel()

        initWifiAwareManager()

        checkPermission()

    }
}

 

 

2. Session 가져 오기

Developer page의 내용은 다음과 같다

 

Wi-Fi Aware 사용을 시작하려면 앱에서 attach()를 호출하여 WifiAwareSession를 가져와야 합니다. 이 메서드는 다음을 실행합니다.

  • Wi-Fi Aware 하드웨어를 켭니다.
  • Wi-Fi Aware 클러스터에 참여하거나 클러스터를 형성합니다.
  • 생성된 모든 검색 세션의 컨테이너 역할을 하는 고유한 네임스페이스를 사용하여 Wi-Fi Aware 세션을 만듭니다.

앱이 성공적으로 연결되면 시스템은 onAttached() 콜백을 실행합니다. 이 콜백은 앱이 모든 추가 세션 작업에 사용해야 하는 WifiAwareSession 객체를 제공합니다. 앱은 이 세션을 사용하여 서비스를 게시하거나 서비스를 구독할 수 있습니다.

앱은 attach()를 한 번만 호출해야 합니다. 앱에서 attach()를 여러 번 호출하는 경우 앱은 호출마다 고유한 네임스페이스를 가진 다른 세션을 수신합니다. 이는 복잡한 시나리오에서 유용할 수 있지만 일반적으로는 피해야 합니다.

 

3. Callback class 작성

WifiAwareManager.attach() 를 이용하여  WifiAwareSession을 가져오기 위해 Callback 함수를 작성

 

onAttached() method가 실행될 때 parameter 로 WifiAwareSession을 얻을 수 있다

새로운 session이 생기면 먼저 removeCurrentWifiAwareSession을 이용해 모든 연결을 닫고 변수를 초기화 해 주고 난뒤

seWifiAwareSession method를 시행 시킴

class CustomAttachCallback(private val activity: MainActivity) : AttachCallback() {
    override fun onAttachFailed() {
        super.onAttachFailed()
        Log.i(">>>>", "onAttachFailed")
    }

    override fun onAttached(session: WifiAwareSession?) {
        super.onAttached(session)
        Log.i(">>>>", "onAttached")
        session?.let{
            Log.i(">>>>", "onAttached session : $it")
            activity.removeCurrentWifiAwareSession()
            activity.setWifiAwareSession(it)
        }
    }

    override fun onAwareSessionTerminated() {
        super.onAwareSessionTerminated()
        Log.i(">>>>", "onAwareSessionTerminated")
    }
}

 

4. Button들에 Listener를 달아 주었다

attach() 기능을 실행 전 server or client 인지,  만들거나 접속할 서비스의 이름이 설정되었는지 확인 해 주었다.

class MainActivity : AppCompatActivity() {

    lateinit var viewModel : MainViewModel

    private var asServer : Boolean? = null

    @RequiresApi(Build.VERSION_CODES.S)
    fun initUIListener() {
        bindMain.btnConnect.setOnClickListener{
            if(asServer == null) {
                Toast.makeText(this, "server or client를 선택하세요", Toast.LENGTH_LONG).show()
                return@setOnClickListener
            }
            if(bindMain.editServiceName.text.isEmpty()) {
                Toast.makeText(this, "service 이름을 입력하세요", Toast.LENGTH_LONG).show()
                return@setOnClickListener
            }
            attach()
        }
        bindMain.btnDisconnect.setOnClickListener{
            removeCurrentWifiAwareSession()
        }
        bindMain.rbServer.setOnClickListener{
            asServer = true
        }
        bindMain.rbClient.setOnClickListener{
            asServer = false
        }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    override fun onCreate(savedInstanceState: Bundle?) {

        ...............
        initViewModel()
        initUIListener()
        initWifiAwareManager()
        checkPermission()

    }

}

 

5.  WifiAwareSession을 구하기 - attach()

attach button을 누르면 AttachCallback을 등록하고

CustomAttachCallback의 onAttach()에서 WifiAwareSession의 instance를 구해

일단 ViewModel내의 wifiAwareSesssion 변수에 등록 해 주었다

 


class MainActivity : AppCompatActivity() {

    ..............

    private val customAttachCallback=  CustomAttachCallback(this)
    private var asServer : Boolean? = null

    ...............
    
    @RequiresApi(Build.VERSION_CODES.S)
    override fun onCreate(savedInstanceState: Bundle?) {
        ..........

        initViewModel()
        initUIListener()
        initWifiAwareManager()
        checkPermission()
    }

    fun setWifiAwareSession(wifiAwareSession: WifiAwareSession?){
        Log.i(">>>>", "setting wifiAwareSession")
        if(wifiAwareSession == null) Log.i(">>>>", "wifiAwareSession null")
        removeCurrentWifiAwareSession()
        // wifiAwareSession에 값 등록
        viewModel.setWifiAwareSession(wifiAwareSession)
        //......  다음에 계속
    }

    // AttachCallback을 등록하고 attach 기능을 시도
    @RequiresApi(Build.VERSION_CODES.S)
    fun attach(){
        wifiAwareManager.attach(customAttachCallback, null)
    }

    // 새로운 session을 얻으면 이전 session을 모두 없앰
    fun removeCurrentWifiAwareSession(){
        try{
            viewModel.publishDiscoverySession.value?.close()
            viewModel.setPublishDiscoverySession(null)
            viewModel.subscribeDiscoverySession.value?.close()
            viewModel.setSubscribeDiscoverySession(null)
            viewModel.wifiAwareSession.value?.close()
            viewModel.setWifiAwareSession(null)
            viewModel.setPeerHandle(null)
        } catch (e: Exception) {
            Log.e(">>>>", "removeWifiAwareSession : ${e.message}")
        }
    }

    .............
}

 

5.  wifi 상태 변화에 따른 대비 추가

wifAwareBroadastReceiver에 내용을 추가 했다

내용을 추가하면 wifi가 끊어 졌다 연결되면 자동으로 재 연결 된다.

class WifiAwareBroadcastReceiver(
    private val activity: MainActivity,
    private val wifiAwareManager: WifiAwareManager,
    private val wifiAwareSession: WifiAwareSession?,
) : BroadcastReceiver() {
    @SuppressLint("MissingPermission")
    @RequiresApi(Build.VERSION_CODES.S)
    override fun onReceive(context: Context?, intent: Intent?) {
        if(wifiAwareManager.isAvailable){
            Log.i(">>>>", "wifiAwareManager is available")
            activity.attach()
        } else {
            wifiAwareSession.let {
                activity.removeCurrentWifiAwareSession()
            }
            Log.e(">>>>", "wifiAwareManager is not available")
        }
    }
}

 

6. 결과

Connect button을 누르면 

2024-03-24 15:51:16.105 14239-14239 >>>>                    com.example.wifi_aware_test          I  onAttached
2024-03-24 15:51:16.105 14239-14239 >>>>                    com.example.wifi_aware_test          I  onAttached session : android.net.wifi.aware.WifiAwareSession@6c37598
2024-03-24 15:51:16.106 14239-14239 >>>>                    com.example.wifi_aware_test          I  setting wifiAwareSession

 

Disconnect Button을 누르면 

2024-03-24 15:52:06.835 14239-14239 WifiAwareManager        com.example.wifi_aware_test          V  disconnect()

 

예상과 다르게 onAwareSessionTerminated()는 불리지 않았다.  이 건 다음에 쓸 일이 있다

 

Device에도 정상적으로 wifiAwareSession이 표시되어 있다

+ Recent posts