diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f84b335..2a69e70 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,6 +13,7 @@ android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> + - - + android:theme="@style/Theme.Inbound" /> - - - @@ -66,19 +62,20 @@ android:name="com.sw.inbound.MainActivity" android:screenOrientation="landscape" /> - - - - - - - - - + + + + - - - + + + \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/activity/HomeActivity.kt b/app/src/main/java/com/sw/inbound/activity/HomeActivity.kt index 293271e..735e1cc 100644 --- a/app/src/main/java/com/sw/inbound/activity/HomeActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/HomeActivity.kt @@ -3,6 +3,7 @@ package com.sw.inbound.activity import android.os.Bundle import android.os.Handler import android.os.Looper +import android.view.KeyEvent import androidx.activity.viewModels import com.sw.inbound.base.BaseActivity import androidx.lifecycle.Lifecycle @@ -16,6 +17,7 @@ import com.sw.inbound.utils.DateTimeUtils import com.sw.inbound.utils.ThreadUtils import com.sw.inbound.utils.ext.gone import com.sw.inbound.utils.ext.startActivity +import com.sw.inbound.utils.ext.toast import com.sw.inbound.utils.ext.visible import com.sw.inbound.viewmodel.UserViewModel import dagger.hilt.android.AndroidEntryPoint @@ -45,6 +47,10 @@ class HomeActivity : BaseActivity() { } } + /** 用于检测双击返回键的时间戳 */ + private var lastBackPressTime = 0L + private val backPressInterval = 2000L // 2 秒内连续按下返回键视为双击 + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityHomeBinding.inflate(layoutInflater) @@ -133,4 +139,27 @@ class HomeActivity : BaseActivity() { // 页面不可见时停止刷新,避免内存泄漏 handler.removeCallbacks(timeRunnable) } + + /** + * 处理返回键事件 + * 双击返回键退出应用,单击返回键提示再次点击退出 + */ + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + val currentTime = System.currentTimeMillis() + if (currentTime - lastBackPressTime < backPressInterval) { + // 双击返回键,退出应用 + finish() + true + } else { + // 单击返回键,显示提示 + lastBackPressTime = currentTime + this.toast("再按一次返回键退出应用") + true + } + } else { + super.onKeyDown(keyCode, event) + } + } } + diff --git a/app/src/main/java/com/sw/inbound/activity/InitActivity.kt b/app/src/main/java/com/sw/inbound/activity/InitActivity.kt new file mode 100644 index 0000000..dc2536f --- /dev/null +++ b/app/src/main/java/com/sw/inbound/activity/InitActivity.kt @@ -0,0 +1,169 @@ +package com.sw.inbound.activity + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.SystemClock +import android.view.KeyEvent +import android.view.animation.RotateAnimation +import com.sw.inbound.base.BaseActivity +import com.sw.inbound.databinding.ActivityInitBinding +import com.sw.inbound.utils.NetworkUtils + +/** + * 初始化页面 Activity + * 用于应用启动时的初始化流程 + * - 显示 60 秒倒计时 + * - 每 10 秒检测一次网络连接 + * - 网络连接成功则跳转到 HomeActivity + * - 60 秒后仍未连接则显示"连接网络"按钮 + */ +class InitActivity : BaseActivity() { + + private lateinit var binding: ActivityInitBinding + private val handler = Handler(Looper.getMainLooper()) + private var startTime = 0L // 倒计时开始时间 + private var lastNetworkCheckTime = 0L // 上次检测网络的时间 + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityInitBinding.inflate(layoutInflater) + setContentView(binding.root) + initViews() + } + + /** + * 初始化控件事件 + */ + private fun initViews() { + // 连接网络按钮点击事件 + binding.btnConnectNetwork.setOnClickListener { + openNetworkSettings() + } + + // 启动加载动画 - 持续旋转 + startLoadingAnimation() + } + + /** + * 启动加载动画 - ImageView 持续旋转 + */ + private fun startLoadingAnimation() { + val rotateAnimation = RotateAnimation( + 0f, 360f, + RotateAnimation.RELATIVE_TO_SELF, 0.5f, + RotateAnimation.RELATIVE_TO_SELF, 0.5f + ).apply { + duration = 1200 // 旋转周期 1.2 秒 + repeatCount = RotateAnimation.INFINITE // 无限循环 + repeatMode = RotateAnimation.RESTART + } + binding.ivLoading.startAnimation(rotateAnimation) + } + + override fun onResume() { + super.onResume() + startCountdown() + } + + override fun onPause() { + super.onPause() + // 页面不可见时停止倒计时 + handler.removeCallbacksAndMessages(null) + } + + /** + * 启动 60 秒倒计时 + */ + private fun startCountdown() { + startTime = SystemClock.elapsedRealtime() + lastNetworkCheckTime = 0 + binding.llLoading.visibility = android.view.View.VISIBLE + binding.llNetworkButton.visibility = android.view.View.GONE + binding.tvCountdown.text = "60秒" + scheduleCountdown() + } + + /** + * 定时更新倒计时 + * 使用 SystemClock.elapsedRealtime() 确保精确计时 + */ + private fun scheduleCountdown() { + handler.postDelayed({ + val elapsedTime = SystemClock.elapsedRealtime() - startTime + val remainingTime = 60 - (elapsedTime / 1000).toInt() + val currentNetworkCheckTime = (elapsedTime / 1000).toInt() + + // 每 10 秒检测一次网络 + if (currentNetworkCheckTime > 0 && currentNetworkCheckTime % 10 == 0 && currentNetworkCheckTime != lastNetworkCheckTime.toInt()) { + lastNetworkCheckTime = currentNetworkCheckTime.toLong() + checkNetworkConnection() + } + + // 倒计时未结束,继续更新 UI + if (remainingTime > 0) { + binding.tvCountdown.text = "${remainingTime}秒" + scheduleCountdown() + } else { + // 倒计时结束,最后检测一次网络 + if (NetworkUtils.isNetworkConnected(this)) { + navigateToHome() + } else { + // 网络未连接,显示"连接网络"按钮 + showNetworkButton() + } + } + }, 100) // 每 100ms 检查一次,确保精确性 + } + + /** + * 检测网络连接 + */ + private fun checkNetworkConnection() { + if (NetworkUtils.isNetworkConnected(this)) { + // 网络连接成功,停止倒计时并跳转到 HomeActivity + handler.removeCallbacksAndMessages(null) + navigateToHome() + } + } + + /** + * 跳转到 HomeActivity + */ + private fun navigateToHome() { + val intent = Intent(this, HomeActivity::class.java) + startActivity(intent) + finish() + } + + /** + * 显示"连接网络"按钮 + */ + private fun showNetworkButton() { + binding.llLoading.visibility = android.view.View.GONE + binding.llNetworkButton.visibility = android.view.View.VISIBLE + } + + /** + * 打开系统网络设置页面 + */ + private fun openNetworkSettings() { + val intent = Intent(android.provider.Settings.ACTION_WIFI_SETTINGS) + startActivity(intent) + } + + /** + * 禁用返回键 + */ + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + // 禁用返回键,不执行任何操作 + true + } else { + super.onKeyDown(keyCode, event) + } + } +} + diff --git a/app/src/main/java/com/sw/inbound/receiver/BootReceiver.kt b/app/src/main/java/com/sw/inbound/receiver/BootReceiver.kt index 67c98dc..b4edb6c 100644 --- a/app/src/main/java/com/sw/inbound/receiver/BootReceiver.kt +++ b/app/src/main/java/com/sw/inbound/receiver/BootReceiver.kt @@ -3,7 +3,7 @@ package com.sw.inbound.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import com.sw.inbound.activity.HomeActivity +import com.sw.inbound.activity.InitActivity import timber.log.Timber /** @@ -14,7 +14,7 @@ class BootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (Intent.ACTION_BOOT_COMPLETED == intent.action) { Timber.d("设备启动完成,开始执行自启动逻辑") - val intent = Intent(context, HomeActivity::class.java) + val intent = Intent(context, InitActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(intent) } diff --git a/app/src/main/java/com/sw/inbound/utils/NetworkUtils.kt b/app/src/main/java/com/sw/inbound/utils/NetworkUtils.kt new file mode 100644 index 0000000..d773328 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/utils/NetworkUtils.kt @@ -0,0 +1,24 @@ +package com.sw.inbound.utils + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities + +/** + * 网络连接检测工具类 + * 提供检测设备网络连接状态的功能 + */ +object NetworkUtils { + + /** + * 检测设备是否连接到网络 + * @param context 应用上下文 + * @return true 表示已连接网络,false 表示未连接 + */ + fun isNetworkConnected(context: Context): Boolean { + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + val network = connectivityManager.activeNetwork ?: return false + val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false + return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + } +} diff --git a/app/src/main/res/drawable/btn_connect_network.xml b/app/src/main/res/drawable/btn_connect_network.xml new file mode 100644 index 0000000..14a7909 --- /dev/null +++ b/app/src/main/res/drawable/btn_connect_network.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_network_error.xml b/app/src/main/res/drawable/ic_network_error.xml new file mode 100644 index 0000000..6bb312d --- /dev/null +++ b/app/src/main/res/drawable/ic_network_error.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/loading_spinner.xml b/app/src/main/res/drawable/loading_spinner.xml new file mode 100644 index 0000000..7ad8f85 --- /dev/null +++ b/app/src/main/res/drawable/loading_spinner.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/app/src/main/res/layout/activity_init.xml b/app/src/main/res/layout/activity_init.xml new file mode 100644 index 0000000..fa7fbfe --- /dev/null +++ b/app/src/main/res/layout/activity_init.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +