Android 自动启动 Activity
package com.example.msdksample.activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.msdksample.MyApplication
import com.example.msdksample.R
import com.google.android.material.snackbar.Snackbar
class MainActivity : AppCompatActivity() {
private lateinit var tvAppActivation: TextView
private lateinit var btnFlightController: Button
// Use enum for better type safety
private enum class ActivationState {
ACTIVATED,
NOT_ACTIVATED
}
private var appActivationState: ActivationState = ActivationState.NOT_ACTIVATED
// BroadcastReceiver to monitor application registration and product connection
private val registerReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
MyApplication.REGISTER_SUCCESS -> {
appActivationState = ActivationState.ACTIVATED
updateActivationUI()
showMessage(getString(R.string.register_success))
}
MyApplication.REGISTER_FAILURE -> {
val errorMessage = intent.getStringExtra("error_message") ?: getString(R.string.unknown_error)
appActivationState = ActivationState.NOT_ACTIVATED
updateActivationUI()
showMessage(getString(R.string.register_failure, errorMessage))
}
MyApplication.PRODUCT_CONNECT -> {
showMessage(getString(R.string.product_connect))
}
MyApplication.PRODUCT_DISCONNECT -> {
showMessage(getString(R.string.product_disconnect))
}
MyApplication.PRODUCT_CHANGED -> {
showMessage(getString(R.string.product_changed))
}
}
}
}
private var isReceiverRegistered = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initViews()
checkAndRequestPermissions()
}
private fun initViews() {
tvAppActivation = findViewById(R.id.tv_status_application)
btnFlightController = findViewById(R.id.btn_flight_controller)
btnFlightController.setOnClickListener {
if (appActivationState == ActivationState.ACTIVATED) {
val intent = Intent(this, FlightActivity::class.java)
startActivity(intent)
} else {
showMessage(getString(R.string.app_not_activated))
}
}
updateActivationUI()
}
private fun updateActivationUI() {
val statusText = when (appActivationState) {
ActivationState.ACTIVATED -> getString(R.string.activation_status_activated)
ActivationState.NOT_ACTIVATED -> getString(R.string.activation_status_not_activated)
}
tvAppActivation.text = getString(R.string.activation_status_label, statusText)
}
override fun onStart() {
super.onStart()
registerBroadcastReceiver()
}
override fun onStop() {
unregisterBroadcastReceiver()
super.onStop()
}
private fun registerBroadcastReceiver() {
if (!isReceiverRegistered) {
val filter = IntentFilter().apply {
addAction(MyApplication.REGISTER_SUCCESS)
addAction(MyApplication.REGISTER_FAILURE)
addAction(MyApplication.PRODUCT_CONNECT)
addAction(MyApplication.PRODUCT_DISCONNECT)
addAction(MyApplication.PRODUCT_CHANGED)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(registerReceiver, filter, Context.RECEIVER_NOT_EXPORTED)
} else {
registerReceiver(registerReceiver, filter)
}
isReceiverRegistered = true
}
}
private fun unregisterBroadcastReceiver() {
if (isReceiverRegistered) {
try {
unregisterReceiver(registerReceiver)
isReceiverRegistered = false
} catch (e: IllegalArgumentException) {
// Receiver was already unregistered
}
}
}
/* Permission Handling */
private fun getRequiredPermissions(): Array<String> {
val basePermissions = mutableListOf(
android.Manifest.permission.RECORD_AUDIO,
android.Manifest.permission.INTERNET,
android.Manifest.permission.CHANGE_WIFI_STATE,
android.Manifest.permission.ACCESS_WIFI_STATE,
android.Manifest.permission.ACCESS_NETWORK_STATE,
android.Manifest.permission.CAMERA,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.ACCESS_FINE_LOCATION
)
// Only add storage permissions for older Android versions
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
basePermissions.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
basePermissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE)
}
return basePermissions.toTypedArray()
}
private fun checkAndRequestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!hasAllPermissions()) {
requestAllPermissions()
} else {
proceedWithAppFunctionality()
}
} else {
proceedWithAppFunctionality()
}
}
private fun hasAllPermissions(): Boolean {
return getRequiredPermissions().all {
ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
}
private fun requestAllPermissions() {
ActivityCompat.requestPermissions(this, getRequiredPermissions(), PERMISSIONS_REQUEST_CODE)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSIONS_REQUEST_CODE) {
if (grantResults.isNotEmpty() && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
proceedWithAppFunctionality()
} else {
showMessage(getString(R.string.permissions_required))
}
}
}
private fun proceedWithAppFunctionality() {
showMessage(getString(R.string.permissions_granted))
}
private fun showMessage(message: String) {
// Use Snackbar instead of Toast for better UX
Snackbar.make(
findViewById(android.R.id.content),
message,
Snackbar.LENGTH_SHORT
).show()
}
companion object {
private const val PERMISSIONS_REQUEST_CODE = 102
}
}How to auto enter FlightActivity without manual click?
To launch FlightActivity automatically as soon as the app is activated, you can trigger the navigation inside the broadcast receiver when the REGISTER_SUCCESS intent arrives. To avoid launching it multiple times (for example if the broadcast fires again after configuration changes), it’s good practice to guard the navigation behind a boolean flag.
Here’s one clean way to do it:
- Add a private flag
hasLaunchedFlightActivityto ensure you only navigate once per activity lifecycle. - Create a helper method
openFlightActivityIfActivated()so you can reuse the logic from multiple places (e.g., when the broadcast arrives and when permissions are granted). - Call that helper both after a successful registration broadcast and from
proceedWithAppFunctionality()in case the activation happened earlier (e.g., persisted state across restarts).
Full modified MainActivity showing the changes:
package com.example.msdksample.activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.msdksample.MyApplication
import com.example.msdksample.R
import com.google.android.material.snackbar.Snackbar
class MainActivity : AppCompatActivity() {
private lateinit var tvAppActivation: TextView
private lateinit var btnFlightController: Button
private enum class ActivationState {
ACTIVATED,
NOT_ACTIVATED
}
private var appActivationState: ActivationState = ActivationState.NOT_ACTIVATED
private var hasLaunchedFlightActivity = false
private val registerReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
MyApplication.REGISTER_SUCCESS -> {
appActivationState = ActivationState.ACTIVATED
updateActivationUI()
showMessage(getString(R.string.register_success))
openFlightActivityIfActivated()
}
MyApplication.REGISTER_FAILURE -> {
val errorMessage = intent.getStringExtra("error_message") ?: getString(R.string.unknown_error)
appActivationState = ActivationState.NOT_ACTIVATED
updateActivationUI()
showMessage(getString(R.string.register_failure, errorMessage))
}
MyApplication.PRODUCT_CONNECT -> {
showMessage(getString(R.string.product_connect))
}
MyApplication.PRODUCT_DISCONNECT -> {
showMessage(getString(R.string.product_disconnect))
}
MyApplication.PRODUCT_CHANGED -> {
showMessage(getString(R.string.product_changed))
}
}
}
}
private var isReceiverRegistered = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initViews()
checkAndRequestPermissions()
}
private fun initViews() {
tvAppActivation = findViewById(R.id.tv_status_application)
btnFlightController = findViewById(R.id.btn_flight_controller)
btnFlightController.setOnClickListener {
if (appActivationState == ActivationState.ACTIVATED) {
openFlightActivityIfActivated()
} else {
showMessage(getString(R.string.app_not_activated))
}
}
updateActivationUI()
}
private fun updateActivationUI() {
val statusText = when (appActivationState) {
ActivationState.ACTIVATED -> getString(R.string.activation_status_activated)
ActivationState.NOT_ACTIVATED -> getString(R.string.activation_status_not_activated)
}
tvAppActivation.text = getString(R.string.activation_status_label, statusText)
}
override fun onStart() {
super.onStart()
registerBroadcastReceiver()
}
override fun onStop() {
unregisterBroadcastReceiver()
super.onStop()
}
private fun registerBroadcastReceiver() {
if (!isReceiverRegistered) {
val filter = IntentFilter().apply {
addAction(MyApplication.REGISTER_SUCCESS)
addAction(MyApplication.REGISTER_FAILURE)
addAction(MyApplication.PRODUCT_CONNECT)
addAction(MyApplication.PRODUCT_DISCONNECT)
addAction(MyApplication.PRODUCT_CHANGED)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(registerReceiver, filter, Context.RECEIVER_NOT_EXPORTED)
} else {
registerReceiver(registerReceiver, filter)
}
isReceiverRegistered = true
}
}
private fun unregisterBroadcastReceiver() {
if (isReceiverRegistered) {
try {
unregisterReceiver(registerReceiver)
isReceiverRegistered = false
} catch (e: IllegalArgumentException) {
// Receiver was already unregistered
}
}
}
private fun getRequiredPermissions(): Array<String> {
val basePermissions = mutableListOf(
android.Manifest.permission.RECORD_AUDIO,
android.Manifest.permission.INTERNET,
android.Manifest.permission.CHANGE_WIFI_STATE,
android.Manifest.permission.ACCESS_WIFI_STATE,
android.Manifest.permission.ACCESS_NETWORK_STATE,
android.Manifest.permission.CAMERA,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.ACCESS_FINE_LOCATION
)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
basePermissions.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
basePermissions.add(android.Manifest.permission.READ_EXTERNAL_STORAGE)
}
return basePermissions.toTypedArray()
}
private fun checkAndRequestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!hasAllPermissions()) {
requestAllPermissions()
} else {
proceedWithAppFunctionality()
}
} else {
proceedWithAppFunctionality()
}
}
private fun hasAllPermissions(): Boolean {
return getRequiredPermissions().all {
ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
}
private fun requestAllPermissions() {
ActivityCompat.requestPermissions(this, getRequiredPermissions(), PERMISSIONS_REQUEST_CODE)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSIONS_REQUEST_CODE) {
if (grantResults.isNotEmpty() && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
proceedWithAppFunctionality()
} else {
showMessage(getString(R.string.permissions_required))
}
}
}
private fun proceedWithAppFunctionality() {
showMessage(getString(R.string.permissions_granted))
openFlightActivityIfActivated()
}
private fun openFlightActivityIfActivated() {
if (appActivationState == ActivationState.ACTIVATED && !hasLaunchedFlightActivity) {
hasLaunchedFlightActivity = true
val intent = Intent(this, FlightActivity::class.java)
startActivity(intent)
}
}
private fun showMessage(message: String) {
Snackbar.make(
findViewById(android.R.id.content),
message,
Snackbar.LENGTH_SHORT
).show()
}
companion object {
private const val PERMISSIONS_REQUEST_CODE = 102
}
}With this setup:
- As soon as the app receives the
REGISTER_SUCCESSbroadcast,FlightActivityis launched automatically. - If the app already got activated earlier (e.g., during a previous session) and the broadcast fires before the permissions flow completes,
openFlightActivityIfActivated()will still run once the permissions are granted. - The button remains as a manual fallback, but it reuses the same helper to avoid duplicated logic.
Create by GPT-5-Codex
评论已关闭