kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
new sync bt works better
rodzic
dc8cb8446c
commit
27d0d2aa40
app/src/main
java/com/geeksville/mesh
2
TODO.md
2
TODO.md
|
@ -24,6 +24,8 @@
|
|||
|
||||
# Medium priority
|
||||
|
||||
* test with oldest android
|
||||
* stop using a foreground service
|
||||
* change info() log strings to debug()
|
||||
* use platform theme (dark or light)
|
||||
* remove mixpanel analytics
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
<!-- Only for debug log writing, disable for production FIXME -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<!-- We run our mesh code as a foreground service - FIXME, find a way to stop doing this -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth_le"
|
||||
android:required="true" />
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Debug
|
||||
import android.os.IBinder
|
||||
|
@ -171,9 +172,10 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
requestPermission()
|
||||
}
|
||||
|
||||
var meshService: IMeshService? = null
|
||||
private var meshService: IMeshService? = null
|
||||
private var isBound = false
|
||||
|
||||
private val serviceConnection = object : ServiceConnection {
|
||||
private var serviceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
val m = IMeshService.Stub.asInterface(service)
|
||||
meshService = m
|
||||
|
@ -201,14 +203,25 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
logAssert(meshService == null)
|
||||
|
||||
// bind to our service using the same mechanism an external client would use (for testing coverage)
|
||||
val intent = Intent()
|
||||
intent.setClassName("com.geeksville.mesh", "com.geeksville.mesh.MeshService")
|
||||
|
||||
// The following would work for us, but not external users
|
||||
//val intent = Intent(this, MeshService::class.java)
|
||||
//intent.action = IMeshService::class.java.name
|
||||
val intent = Intent()
|
||||
intent.setClassName("com.geeksville.mesh", "com.geeksville.mesh.MeshService")
|
||||
|
||||
// Before binding we want to explicitly create - so the service stays alive forever (so it can keep
|
||||
// listening for the bluetooth packets arriving from the radio. And when they arrive forward them
|
||||
// to Signal or whatever.
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
startForegroundService(intent)
|
||||
} else {
|
||||
startService(intent)
|
||||
}
|
||||
|
||||
// ALSO bind so we can use the api
|
||||
logAssert(bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE))
|
||||
isBound = true;
|
||||
}
|
||||
|
||||
private fun unbindMeshService() {
|
||||
|
@ -216,7 +229,8 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
// it, then now is the time to unregister.
|
||||
// if we never connected, do nothing
|
||||
debug("Unbinding from mesh service!")
|
||||
unbindService(serviceConnection)
|
||||
if (isBound)
|
||||
unbindService(serviceConnection)
|
||||
meshService = null
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,26 @@
|
|||
package com.geeksville.mesh
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.*
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.PRIORITY_MIN
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.mesh.MeshProtos.MeshPacket
|
||||
import com.geeksville.mesh.MeshProtos.ToRadio
|
||||
import com.geeksville.util.exceptionReporter
|
||||
import com.geeksville.util.toOneLineString
|
||||
import com.geeksville.util.toRemoteExceptions
|
||||
import com.google.protobuf.ByteString
|
||||
import java.nio.charset.Charset
|
||||
|
||||
|
||||
class RadioNotConnectedException() : Exception("Can't find radio")
|
||||
|
||||
/**
|
||||
|
@ -106,13 +116,74 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun createNotificationChannel(): String {
|
||||
val channelId = "my_service"
|
||||
val channelName = "My Background Service"
|
||||
val chan = NotificationChannel(
|
||||
channelId,
|
||||
channelName, NotificationManager.IMPORTANCE_HIGH
|
||||
)
|
||||
chan.lightColor = Color.BLUE
|
||||
chan.importance = NotificationManager.IMPORTANCE_NONE
|
||||
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
|
||||
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
service.createNotificationChannel(chan)
|
||||
return channelId
|
||||
}
|
||||
|
||||
private fun startForeground() {
|
||||
|
||||
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val channelId =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createNotificationChannel()
|
||||
} else {
|
||||
// If earlier version channel ID is not used
|
||||
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
||||
""
|
||||
}
|
||||
|
||||
val notificationBuilder = NotificationCompat.Builder(this, channelId)
|
||||
val notification = notificationBuilder.setOngoing(true)
|
||||
.setPriority(PRIORITY_MIN)
|
||||
.setCategory(Notification.CATEGORY_SERVICE)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
|
||||
//.setContentTitle("Meshtastic") // leave this off for now so our notification looks smaller
|
||||
//.setContentText("Listening for mesh...")
|
||||
.build()
|
||||
startForeground(101, notification)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
info("Creating mesh service")
|
||||
|
||||
/*
|
||||
// This intent will be used if the user clicks on the item in the status bar
|
||||
val notificationIntent = Intent(this, MainActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
this, 0,
|
||||
notificationIntent, 0
|
||||
)
|
||||
|
||||
val notification: Notification = NotificationCompat.Builder(this)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
|
||||
.setContentTitle("Meshtastic")
|
||||
.setContentText("Listening for mesh...")
|
||||
.setContentIntent(pendingIntent).build()
|
||||
|
||||
// We are required to call this within a few seconds of create
|
||||
startForeground(1337, notification)
|
||||
|
||||
*/
|
||||
startForeground()
|
||||
|
||||
// we listen for messages from the radio receiver _before_ trying to create the service
|
||||
val filter = IntentFilter(RadioInterfaceService.RECEIVE_FROMRADIO_ACTION)
|
||||
val filter = IntentFilter()
|
||||
filter.addAction(RadioInterfaceService.RECEIVE_FROMRADIO_ACTION)
|
||||
filter.addAction(RadioInterfaceService.CONNECTCHANGED_ACTION)
|
||||
registerReceiver(radioInterfaceReceiver, filter)
|
||||
|
||||
// We in turn need to use the radiointerface service
|
||||
|
@ -303,6 +374,7 @@ class MeshService : Service(), Logging {
|
|||
|
||||
/// Called when we gain/lose connection to our radio
|
||||
private fun onConnectionChanged(c: Boolean) {
|
||||
debug("onConnectionChanged connected=$c")
|
||||
isConnected = c
|
||||
if (c) {
|
||||
// Do our startup init
|
||||
|
@ -342,7 +414,6 @@ class MeshService : Service(), Logging {
|
|||
infoBytes = connectedRadio.readNodeInfo()
|
||||
}
|
||||
}
|
||||
TODO("FIXME - set our owner, get node infos, set our local nodenum, dont process received packets until we have the full node db")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -351,8 +422,10 @@ class MeshService : Service(), Logging {
|
|||
*/
|
||||
private val radioInterfaceReceiver = object : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
// Important to never throw exceptions out of onReceive
|
||||
override fun onReceive(context: Context, intent: Intent) = exceptionReporter {
|
||||
|
||||
debug("Received broadcast ${intent.action}")
|
||||
when (intent.action) {
|
||||
RadioInterfaceService.CONNECTCHANGED_ACTION -> {
|
||||
onConnectionChanged(intent.getBooleanExtra(EXTRA_CONNECTED, false))
|
||||
|
@ -428,7 +501,7 @@ class MeshService : Service(), Logging {
|
|||
|
||||
override fun isConnected(): Boolean = toRemoteExceptions {
|
||||
val r = this@MeshService.isConnected
|
||||
info("in isConnected=r")
|
||||
info("in isConnected=$r")
|
||||
r
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,6 +150,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
private val clientOperations = DeferredExecution()
|
||||
|
||||
private fun broadcastConnectionChanged(isConnected: Boolean) {
|
||||
debug("Broadcasting connection=$isConnected")
|
||||
val intent = Intent(CONNECTCHANGED_ACTION)
|
||||
intent.putExtra(EXTRA_CONNECTED, isConnected)
|
||||
sendBroadcast(intent)
|
||||
|
@ -195,14 +196,14 @@ class RadioInterfaceService : Service(), Logging {
|
|||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
info("Creating radio interface service")
|
||||
|
||||
// FIXME, let user GUI select which device we are talking to
|
||||
|
||||
// Note: this call does no comms, it just creates the device object (even if the
|
||||
// device is off/not connected)
|
||||
val usetbeam = false
|
||||
val address = if (usetbeam) "B4:E6:2D:EA:32:B7" else "24:6F:28:96:C9:2A"
|
||||
info("Creating radio interface service. device=$address")
|
||||
|
||||
device = bluetoothAdapter.getRemoteDevice(address)
|
||||
// Note this constructor also does no comm
|
||||
safe = SafeBluetooth(this, device)
|
||||
|
|
|
@ -135,6 +135,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
w
|
||||
}
|
||||
|
||||
debug("work ${work.tag} is completed, resuming with status $status")
|
||||
if (status != 0)
|
||||
work.completion.resumeWithException(IOException("Bluetooth status=$status"))
|
||||
else
|
||||
|
|
Ładowanie…
Reference in New Issue