Files
Android-key-of-love/app/src/main/java/com/example/myapplication/ImeGuideActivity.kt

258 lines
10 KiB
Kotlin
Raw Normal View History

2025-12-05 20:48:22 +08:00
package com.example.myapplication
import android.content.ComponentName
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.provider.Settings
import android.util.Log
2025-12-05 20:48:22 +08:00
import android.view.inputmethod.InputMethodManager
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class ImeGuideActivity : AppCompatActivity() {
private val TAG = "ImeGuideActivity"
// 改成可空,避免 findViewById 返回 null 时直接 NPE
private var btnEnable: LinearLayout? = null
private var btnSelect: LinearLayout? = null
private var tvStep1Status: TextView? = null
private var tvStep2Status: TextView? = null
private var btnEnabledText: TextView? = null
private var btnSelectText: TextView? = null
private var btnEnabledimg: ImageView? = null
private var btnSelectimg: ImageView? = null
2025-12-05 20:48:22 +08:00
private var imeObserver: android.database.ContentObserver? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ime_guide)
Log.d(TAG, "onCreate")
btnEnable = findViewById(R.id.enabled) // btn启用输入法
btnSelect = findViewById(R.id.select) // btn选择输入法
tvStep1Status = findViewById(R.id.Steps) // 第一步的提示
tvStep2Status = findViewById(R.id.stepTips) // 第二步的提示
btnEnabledText = findViewById(R.id.btnEnabledText) // 启用输入法按钮文字
btnSelectText = findViewById(R.id.btnSelectText) // 选择输入法按钮文字
btnEnabledimg = findViewById(R.id.btnEnabledimg) // 启用输入法按钮图片
btnSelectimg = findViewById(R.id.btnSelectimg) // 选择输入法按钮图片
2025-12-05 20:48:22 +08:00
}
override fun onResume() {
super.onResume()
try {
refreshStatus()
} catch (e: Exception) {
Log.e(TAG, "refreshStatus 崩了", e)
}
try {
registerImeObserver()
} catch (e: Exception) {
Log.e(TAG, "registerImeObserver 崩了", e)
}
2025-12-05 20:48:22 +08:00
}
override fun onPause() {
super.onPause()
try {
unregisterImeObserver()
} catch (e: Exception) {
Log.e(TAG, "unregisterImeObserver 崩了", e)
}
2025-12-05 20:48:22 +08:00
}
private fun registerImeObserver() {
if (imeObserver != null) return
2025-12-05 20:48:22 +08:00
imeObserver = object : android.database.ContentObserver(
android.os.Handler(android.os.Looper.getMainLooper())
) {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
try {
refreshStatus()
} catch (e: Exception) {
Log.e(TAG, "onChange -> refreshStatus 崩了", e)
}
2025-12-05 20:48:22 +08:00
}
}
try {
contentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.DEFAULT_INPUT_METHOD),
false,
imeObserver!!
)
} catch (e: SecurityException) {
// 部分 ROM/系统可能在这里抛异常
Log.e(TAG, "registerContentObserver SecurityException", e)
} catch (e: Exception) {
Log.e(TAG, "registerContentObserver 其他异常", e)
}
2025-12-05 20:48:22 +08:00
}
2025-12-05 20:48:22 +08:00
private fun unregisterImeObserver() {
imeObserver?.let {
try {
contentResolver.unregisterContentObserver(it)
} catch (e: Exception) {
Log.e(TAG, "unregisterContentObserver 异常", e)
}
2025-12-05 20:48:22 +08:00
}
imeObserver = null
}
/** 刷新步骤状态(是否启用/选择) */
private fun refreshStatus() {
val enabled = isImeEnabled()
val selected = isImeSelected()
// 把所有 view 拿成局部变量并判空,避免 NPE
val enableLayout = btnEnable
val selectLayout = btnSelect
val step1 = tvStep1Status
val step2 = tvStep2Status
val enableText = btnEnabledText
val selectText = btnSelectText
val enableImg = btnEnabledimg
val selectImg = btnSelectimg
if (enableLayout == null || selectLayout == null ||
step1 == null || step2 == null ||
enableText == null || selectText == null ||
enableImg == null || selectImg == null
) {
Log.e(TAG, "有 View 为 null检查 activity_ime_guide.xml 的 id 是否匹配")
return
}
2025-12-05 20:48:22 +08:00
// 根据状态设置按钮的点击行为
if (enabled) {
// 输入法已启用时,禁用启用按钮的点击事件
enableLayout.setOnClickListener(null)
2025-12-05 20:48:22 +08:00
} else {
// 输入法未启用时,设置启用按钮的点击事件
enableLayout.setOnClickListener {
2025-12-05 20:48:22 +08:00
startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS))
}
}
if (selected) {
// 输入法已切换时,禁用选择按钮的点击事件
selectLayout.setOnClickListener(null)
2025-12-05 20:48:22 +08:00
} else {
// 输入法未切换时,设置选择按钮的点击事件
selectLayout.setOnClickListener {
2025-12-05 20:48:22 +08:00
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.showInputMethodPicker()
}
}
if (!enabled && !selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
enableText.setTextColor(Color.parseColor("#FFFFFF"))
selectText.setTextColor(Color.parseColor("#FFFFFF"))
enableImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
step1.text = "Step one"
step2.text = "Check to enable key of love"
} else if (!enabled && selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
enableImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
enableText.setTextColor(Color.parseColor("#FFFFFF"))
selectText.setTextColor(Color.parseColor("#FFFFFF"))
step1.text = "Step one"
step2.text = "Check to enable key of love"
} else if (enabled && !selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
enableImg.setImageResource(R.drawable.ime_guide_activity_btn_completed_img)
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
enableText.setTextColor(Color.parseColor("#A1A1A1"))
selectText.setTextColor(Color.parseColor("#FFFFFF"))
step1.text = "Step two"
step2.text = "Select key of love as your default input method"
} else if (enabled && selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
enableImg.setImageResource(R.drawable.ime_guide_activity_btn_completed_img)
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_completed_img)
enableText.setTextColor(Color.parseColor("#A1A1A1"))
selectText.setTextColor(Color.parseColor("#A1A1A1"))
step1.text = "Completed"
step2.text = "You have completed the relevant Settings"
2025-12-05 20:48:22 +08:00
Toast.makeText(this, "The input method is all set!", Toast.LENGTH_SHORT).show()
try {
startActivity(Intent(this, GuideActivity::class.java))
} catch (e: Exception) {
Log.e(TAG, "启动 GuideActivity 失败,检查是否在 Manifest 中声明", e)
}
2025-12-05 20:48:22 +08:00
finish()
}
}
/** 是否启用了本输入法 */
private fun isImeEnabled(): Boolean {
return try {
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
val myComponent = ComponentName(this, MyInputMethodService::class.java)
val result = imm.enabledInputMethodList.any { imeInfo ->
imeInfo.packageName == myComponent.packageName &&
imeInfo.serviceName == myComponent.className
}
Log.d(TAG, "isImeEnabled = $result")
result
} catch (e: Exception) {
Log.e(TAG, "isImeEnabled 出错", e)
false
2025-12-05 20:48:22 +08:00
}
}
2025-12-05 20:48:22 +08:00
/** 是否已切换为当前输入法 */
private fun isImeSelected(): Boolean {
return try {
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
val myComponent = ComponentName(this, MyInputMethodService::class.java)
val currentImeId = Settings.Secure.getString(
2025-12-05 20:48:22 +08:00
contentResolver,
Settings.Secure.DEFAULT_INPUT_METHOD
) ?: return false
Log.d(TAG, "DEFAULT_INPUT_METHOD = $currentImeId")
// 找到“当前默认 IME”对应的 InputMethodInfo
val currentImeInfo = imm.enabledInputMethodList.firstOrNull { imeInfo ->
imeInfo.id == currentImeId
}
if (currentImeInfo == null) {
Log.d(TAG, "currentImeInfo == null")
return false
}
val isMine = currentImeInfo.packageName == myComponent.packageName &&
currentImeInfo.serviceName == myComponent.className
Log.d(TAG, "isImeSelected = $isMine")
isMine
} catch (e: Exception) {
Log.e(TAG, "isImeSelected 出错", e)
false
2025-12-05 20:48:22 +08:00
}
}
2025-12-05 20:48:22 +08:00
}