이전 회에 이어 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이 표시되어 있다
'AndroidStudio' 카테고리의 다른 글
Wi-fi Aware를 이용한 채팅 앱 제작 (5) (0) | 2024.03.24 |
---|---|
Wi-fi Aware를 이용한 채팅 앱 제작 (4) (0) | 2024.03.24 |
Wi-fi Aware를 이용한 채팅 앱 제작 (2) (0) | 2024.03.24 |
Wi-fi Aware를 이용한 채팅 앱 제작 (1) (0) | 2024.03.23 |
Wi-Fi 연결을 이용한 채팅앱 제작 (0) | 2024.03.23 |