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:

  1. Add a private flag hasLaunchedFlightActivity to ensure you only navigate once per activity lifecycle.
  2. 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).
  3. 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_SUCCESS broadcast, FlightActivity is 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

标签: none

评论已关闭