갤럭시 워치에 버스 도착 정보를 띄우자!(6) - 갤럭시 워치 앱 만들기

김흰돌·2023년 8월 14일
0

마지막으로 지금까지 만들었던 버스 도착 확인 앱에서

내가 즐겨찾기에 등록했던 노선 정보를 확인하는 갤럭시 워치 앱을 만들 차례이다.

먼저 Firebase에 관련 정보를 등록했으므로 폰과 워치간 BLE 통신 대신

워치 스스로 Firebase와 통신하여 내 즐겨찾기 노선을 불러올 생각이다.



화면은 간단하게 두 개를 만들 것이다.

로그인 화면 한 개



즐겨찾기 목록 한 개



먼저 로그인 화면 관련 코드부터 살펴보자

class LoginActivity : Activity() {

    private lateinit var binding: ActivityLoginBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.btnLogin.setOnClickListener {
            if (binding.editId.text.toString().isEmpty() && binding.editPw.text.toString().isEmpty()) {
                Toast.makeText(this, "빈칸을 전부 채워주세요", Toast.LENGTH_SHORT).show()
            } else {
                signIn(binding.editId.text.toString(), binding.editPw.text.toString())
            }
        }
    }

    private fun signIn(email: String, passwd: String) {
        FirebaseAuth.getInstance().signInWithEmailAndPassword(email, passwd)
            .addOnCompleteListener  { task ->
                if (task.isSuccessful) {
                    Toast.makeText(this, "로그인이 완료되었습니다.", Toast.LENGTH_SHORT).show()
                    finish()
                } else {
                    Toast.makeText(this, "로그인에 실패하였습니다.", Toast.LENGTH_SHORT).show()
                }
            }
    }
}

특이한 점이 있다면 보통 Activity에 상속받는 AppCompatActivity() 대신 Activity()를 상속받았다는 점이다.

이유는 AppCompatActivity를 사용하려면 액티비티에 해당하는 AppCompat 테마를 적용해야한다.

간단하게 만드는 앱인만큼 테마를 만드는게 번거롭기 때문에 Activity를 상속 받아서 간단하게 작성했다.

참고로 예전 자료들을 보면 WearableActivity를 상속받아서 작성한다는데 현재는 Deprecated 되었다.



그 다음으론 즐겨찾기 목록을 보여줄 화면을 만들자

class MainActivity() : Activity() {

    private lateinit var binding: ActivityMainBinding
    private val adapter by lazy { Adapter() }

    private var firebaseList: MutableList<BookmarkEntity> = mutableListOf()
    private var apiList: MutableList<BusArrivalResponse> = mutableListOf()
    private var bookmarkList: MutableList<BusInfoEntity> = mutableListOf()

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

        if (FirebaseAuth.getInstance().currentUser == null) {
            Intent(this, LoginActivity::class.java).run {
                startActivity(this)
            }
        }

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.recyclerviewBookmark.adapter = adapter
        binding.recyclerviewBookmark.layoutManager = LinearLayoutManager(this)

        binding.btnRefresh.setOnClickListener {
            bookmarkList.clear()
            getMyBookmark()
        }

        binding.btnLogout.setOnClickListener {
            FirebaseAuth.getInstance().signOut()
            Intent(this, LoginActivity::class.java).run {
                startActivity(this)
            }
        }
        getMyBookmark()
    }

    override fun onResume() {
        super.onResume()
        getMyBookmark()
    }

    private fun getMyBookmark() {
        FirebaseAuth.getInstance().uid?.let {
            FirebaseFirestore.getInstance()
                .collection(it)
                .get()
                .addOnSuccessListener { results ->
                    val items = results.toObjects(BookmarkEntity::class.java)
                    firebaseList.clear()
                    for (item in items) {
                        firebaseList.add(item)
                    }
                    getBusArrivalTime()
                }
                .addOnFailureListener { e ->
                    Log.e("Failed to get Data", e.toString())
                }
        }
    }

    private fun getBusArrivalTime() {
        for (i in firebaseList) {
            getBusArrivalTimeAPI(i.stationID)
        }
    }

    private fun getBusArrivalTimeAPI(stationID: String) {
        val retrofit = RetrofitConnection.getInstance().create(BusService::class.java)
        retrofit.getBusArrivalTime(
            "Ly2IHtl1aGXioF/sk3QPO8m0vKzS0zMpHGsaq3gfvRWJ7wHg1Pim+YJW7mchXjPxvt/s1BHsszlod8Qqv8CVVA==",
            stationID
        ).enqueue(object : Callback<BusArrivalResponse> {
            override fun onResponse(
                call: Call<BusArrivalResponse>,
                response: Response<BusArrivalResponse>
            ) {
                if (response.isSuccessful) {
                    apiList.clear()
                    response.body()?.let {
                        apiList.add(it)
                        filterBookmarkBus()
                    }
                } else {
                    Toast.makeText(this@MainActivity, "API 요청에 실패하였습니다.", Toast.LENGTH_SHORT).show()
                }
            }

            override fun onFailure(call: Call<BusArrivalResponse>, t: Throwable) {
                Log.e("onFailure", t.toString())
                t.printStackTrace()
            }

        })
    }

    private fun filterBookmarkBus() {
        for (i in apiList) {
            for (j in i.body?.busArrivalList!!) {
                for (k in firebaseList) {
                    if (k.routeID == j.routeId.toString() && k.stationID == j.stationId.toString()) {
                        bookmarkList.add(
                            BusInfoEntity(
                                busNum = k.routeNm,
                                predictTime1 = j.predictTime1,
                                predictTime2 = j.predictTime2
                            )
                        )
                    }
                }
            }
        }

        adapter.submitList(bookmarkList.distinct())
        Log.e("tag", bookmarkList.toString())
    }
}

ViewModel을 따로 만들지 않았으므로 코드가 좀 길다.

복잡하지 않은 코드로 Wear OS 앱을 만들 수 있었다.

개인적으로 다음 위치 앱은 BLE 통신과 Compose를 활용해서 만들어 볼 생각이다.

코드 전체는 여기에서

1개의 댓글

comment-user-thumbnail
2023년 8월 14일

잘 봤습니다. 좋은 글 감사합니다.

답글 달기