From d5369008087d0c84ee53f44e7d34fe88e6c054c8 Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 23 Jan 2020 08:09:50 -0800 Subject: [PATCH] mesh service access kinda works --- TODO.md | 1 + .../java/com/geeksville/mesh/MainActivity.kt | 76 ++++++++++++++++++- .../java/com/geeksville/mesh/MeshService.kt | 7 +- 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index 1f5467113..c1b56bc8c 100644 --- a/TODO.md +++ b/TODO.md @@ -18,6 +18,7 @@ to generate nanopb c code https://jpa.kapsi.fi/nanopb/docs/ nanopb binaries available here: https://jpa.kapsi.fi/nanopb/download/ use nanopb 0.4.0 + # Medium priority * use platform theme (dark or light) diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 3bcefd543..419461047 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -2,15 +2,20 @@ package com.geeksville.mesh import android.Manifest import android.bluetooth.* +import android.content.ComponentName import android.content.Context import android.content.Intent +import android.content.ServiceConnection import android.content.pm.PackageManager import android.os.Bundle +import android.os.IBinder +import android.os.RemoteException import androidx.appcompat.app.AppCompatActivity import android.view.Menu import android.view.MenuItem import android.widget.Toast import androidx.compose.Composable +import androidx.compose.Model import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.ui.core.Text @@ -31,6 +36,10 @@ class MainActivity : AppCompatActivity(), Logging { const val DID_REQUEST_PERM = 11 } + @Model + class MeshServiceState(var connected: Boolean = false, public var onlineIds: Array = arrayOf()) + val meshServiceState = MeshServiceState() + private val bluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE) { val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager.adapter @@ -78,11 +87,21 @@ class MainActivity : AppCompatActivity(), Logging { @Preview @Composable - fun composeView() { + fun previewView() { + composeView(meshServiceState) + } + + @Composable + fun composeView(meshServiceState: MeshServiceState) { MaterialTheme { Column(modifier = Spacing(8.dp)) { Text(text = "Meshtastic", modifier = Spacing(8.dp)) + Text("Radio connected: ${meshServiceState.connected}") + meshServiceState.onlineIds.forEach { + Text("User: $it") + } + Button(text = "Start scan", onClick = { if (bluetoothAdapter != null) { @@ -99,7 +118,7 @@ class MainActivity : AppCompatActivity(), Logging { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - composeView() + composeView(meshServiceState) } // Ensures Bluetooth is available on the device and it is enabled. If not, @@ -116,6 +135,59 @@ class MainActivity : AppCompatActivity(), Logging { requestPermission() } + var meshService: IMeshService? = null + var isBound = false + + private val serviceConnection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName, service: IBinder) { + meshService = IMeshService.Stub.asInterface(service) + + // FIXME this doesn't work because the model has already been copied into compose land? + runOnUiThread { // FIXME - this can be removed? + meshServiceState.connected = meshService!!.isConnected + meshServiceState.onlineIds = meshService!!.online + } + } + + override fun onServiceDisconnected(name: ComponentName) { + meshService = null; + } + } + + private fun bindMeshService() { + info("Binding to mesh service!") + // we bind using the well known name, to make sure 3rd party apps could also + logAssert(meshService == null) + val intent = Intent(this, MeshService::class.java) + intent.action = IMeshService::class.java.name + intent.setPackage("com.geeksville.mesh"); + isBound = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) + logAssert(isBound) + } + + private fun unbindMeshService() { + // If we have received the service, and hence registered with + // it, then now is the time to unregister. + // if we never connected, do nothing + if(isBound) { + info("Unbinding from mesh service!") + unbindService(serviceConnection) + meshService = null + } + } + + override fun onPause() { + unbindMeshService() + + super.onPause() + } + + override fun onResume() { + super.onResume() + + bindMeshService() + } + 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) diff --git a/app/src/main/java/com/geeksville/mesh/MeshService.kt b/app/src/main/java/com/geeksville/mesh/MeshService.kt index b587aa4de..42419a2d0 100644 --- a/app/src/main/java/com/geeksville/mesh/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/MeshService.kt @@ -5,9 +5,14 @@ import android.content.Intent import android.os.IBinder import com.geeksville.android.Logging +/** + * Note: this service will go away once all clients are unbound from it. + */ class MeshService : Service(), Logging { - val prefix = "com.geeksville.mesh" + companion object { + const val prefix = "com.geeksville.mesh" + } /* see com.geeksville.mesh broadcast intents