接續Day04,在確認連上Ptt後,會將頁面跳轉至Login頁,原本Day04應該要把這些都寫進去的,結果前幾天家人來找急著發文就忘了Orz
這篇預計先把Parsing的部分補充完,並加入Loading Layout供接下來登入流程使用。
需先補充之前遺漏的部分。在透過PipedOutputStream、PipedInputStream、Reader將Ptt Server回傳的byte array轉成二維的CharArray及字串後,我們需要一個方法來判斷目前的頁面到哪邊了。實作上是以Pattern和Matcher來判斷目前的頁面是否有符合我們需要的特徵。
fun <T> expect(patterns: Array<T>): Int {
val list = ArrayList<Pattern>()
patterns.forEach {
when(it){
is String ->{
list.add(Pattern.compile(it))
}
is Pattern->{
list.add(it)
}
else -> {
list.add(Pattern.compile(Pattern.quote(it.toString())));
}
}
}
return expect(list)
}
private fun expect(list: List<Pattern>): Int {
val endTime = System.currentTimeMillis() + defaultTimeout
while (true) {
val currentScreen: String = getScreen()
for (i in list.indices) {
val m: Matcher = list[i].matcher(currentScreen)
if (m.find()) {
return i
}
}
Log.d(tag, "expect: no pattern match.")
val waitTime = endTime - System.currentTimeMillis()
if (waitTime <= 0) {
return EXPECT_TIMEOUT
}
try {
Thread.sleep(100)
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
}
expect方法會在設定的timeout到達前,每100毫秒檢查一次目前的頁面是否有符合我們需要的特徵,若有符合的話就回傳該特徵的index值,反之回傳EXPECT_TIMEOUT告知timeout。
以最初的Welcome跳轉至Login頁面為例,使用上方法如下:
PttClient.getInstance().start()
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
if (PttClient.getInstance()
.expect(arrayOf("請輸入代號,或以 guest 參觀,或以 new 註冊:")) == 0) {
withContext(Dispatchers.Main) {
NavHostFragment.findNavController(this@WelcomeFragment)
.navigate(R.id.action_welcomeFragment_to_loginFragment)
}
}
}
也就是當畫面內容有顯示"請輸入代號,或以 guest 參觀,或以 new 註冊:"這個字串時,代表可以進行登入了,於是跳轉到下一頁的Login頁面讓使用者輸入帳密來做接續的登入。
因為預期登入會是比較花時間的流程,所以決定先在MainActivity這邊加上一個Loading的Layout,在開始登入時顯示。
xml加入:
<!-- ... -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/loadingLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#66888888"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:indeterminateTint="@color/white"
app:layout_constraintBottom_toTopOf="@id/loadingMsg"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/loadingMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progress"
tools:text="Loading..." />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- ... -->
MainActivity加入:
public fun showLoading(msg: String) {
loadingLayout.visibility = View.VISIBLE
loadingMsg.text = msg
}
public fun showLoading(@StringRes msgId: Int) {
loadingLayout.visibility = View.VISIBLE
loadingMsg.setText(msgId)
}
public fun dismissLoading() {
loadingLayout.visibility = View.GONE
loadingMsg.text = ""
}
實際顯示如下:
明天就是完成登入的部分了,也在這邊祝大家中秋節快樂~!