package com.geeksville.mesh import android.Manifest import android.bluetooth.* import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import android.view.Menu import android.view.MenuItem import android.widget.Toast import androidx.compose.Composable import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.ui.core.Text import androidx.ui.core.dp import androidx.ui.core.setContent import androidx.ui.layout.Column import androidx.ui.layout.Spacing import androidx.ui.material.Button import androidx.ui.material.MaterialTheme import androidx.ui.tooling.preview.Preview import com.geeksville.android.Logging class MainActivity : AppCompatActivity(), Logging { companion object { const val REQUEST_ENABLE_BT = 10 const val DID_REQUEST_PERM = 11 } private val bluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE) { val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager.adapter } fun requestPermission() { debug("Checking permissions") val perms = arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.WAKE_LOCK ) val missingPerms = perms.filter { ContextCompat.checkSelfPermission( this, it ) != PackageManager.PERMISSION_GRANTED } if (missingPerms.isNotEmpty()) { missingPerms.forEach { // Permission is not granted // Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(this, it)) { // FIXME // Show an explanation to the user *asynchronously* -- don't block // this thread waiting for the user's response! After the user // sees the explanation, try again to request the permission. } } // Ask for all the missing perms ActivityCompat.requestPermissions(this, missingPerms.toTypedArray(), DID_REQUEST_PERM) // DID_REQUEST_PERM is an // app-defined int constant. The callback method gets the // result of the request. } else { // Permission has already been granted } } @Preview @Composable fun composeView() { MaterialTheme { Column(modifier = Spacing(8.dp)) { Text(text = "Meshtastic", modifier = Spacing(8.dp)) Button(text = "Start scan", onClick = { if (bluetoothAdapter != null) { SoftwareUpdateService.enqueueWork( this@MainActivity, SoftwareUpdateService.scanDevicesIntent ) } }) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { composeView() } // Ensures Bluetooth is available on the device and it is enabled. If not, // displays a dialog requesting user permission to enable Bluetooth. if (bluetoothAdapter != null) { bluetoothAdapter!!.takeIf { !it.isEnabled }?.apply { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) } } else { Toast.makeText(this, "Error - this app requires bluetooth", Toast.LENGTH_LONG).show() } requestPermission() } override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.menu_main, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. return when (item.itemId) { R.id.action_settings -> true else -> super.onOptionsItemSelected(item) } } }