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 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 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) // 选择输入法按钮图片 } 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) } } override fun onPause() { super.onPause() try { unregisterImeObserver() } catch (e: Exception) { Log.e(TAG, "unregisterImeObserver 崩了", e) } } private fun registerImeObserver() { if (imeObserver != null) return 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) } } } 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) } } private fun unregisterImeObserver() { imeObserver?.let { try { contentResolver.unregisterContentObserver(it) } catch (e: Exception) { Log.e(TAG, "unregisterContentObserver 异常", e) } } 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 } // 根据状态设置按钮的点击行为 if (enabled) { // 输入法已启用时,禁用启用按钮的点击事件 enableLayout.setOnClickListener(null) } else { // 输入法未启用时,设置启用按钮的点击事件 enableLayout.setOnClickListener { startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS)) } } if (selected) { // 输入法已切换时,禁用选择按钮的点击事件 selectLayout.setOnClickListener(null) } else { // 输入法未切换时,设置选择按钮的点击事件 selectLayout.setOnClickListener { 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" 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) } 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 } } /** 是否已切换为当前输入法 */ 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( 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 } } }