kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
commit
417a53e2a5
|
@ -31,8 +31,8 @@ android {
|
||||||
applicationId "com.geeksville.mesh"
|
applicationId "com.geeksville.mesh"
|
||||||
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 20141 // format is Mmmss (where M is 1+the numeric major number
|
versionCode 20142 // format is Mmmss (where M is 1+the numeric major number
|
||||||
versionName "1.1.41"
|
versionName "1.1.42"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
// per https://developer.android.com/studio/write/vector-asset-studio
|
// per https://developer.android.com/studio/write/vector-asset-studio
|
||||||
|
|
|
@ -73,7 +73,9 @@ class MeshService : Service(), Logging {
|
||||||
|
|
||||||
class IdNotFoundException(id: String) : Exception("ID not found $id")
|
class IdNotFoundException(id: String) : Exception("ID not found $id")
|
||||||
class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id")
|
class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id")
|
||||||
class IsUpdatingException() : Exception("Operation prohibited during firmware update")
|
|
||||||
|
/** We treat software update as similar to loss of comms to the regular bluetooth service (so things like sendPosition for background GPS ignores the problem */
|
||||||
|
class IsUpdatingException() : RadioNotConnectedException("Operation prohibited during firmware update")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Talk to our running service and try to set a new device address. And then immediately
|
* Talk to our running service and try to set a new device address. And then immediately
|
||||||
|
@ -342,6 +344,9 @@ class MeshService : Service(), Logging {
|
||||||
radio.close()
|
radio.close()
|
||||||
saveSettings()
|
saveSettings()
|
||||||
|
|
||||||
|
stopForeground(true) // Make sure we aren't using the notification first
|
||||||
|
serviceNotifications.close()
|
||||||
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
serviceJob.cancel()
|
serviceJob.cancel()
|
||||||
}
|
}
|
||||||
|
@ -1085,6 +1090,9 @@ class MeshService : Service(), Logging {
|
||||||
|
|
||||||
setFirmwareUpdateFilename(myInfo)
|
setFirmwareUpdateFilename(myInfo)
|
||||||
|
|
||||||
|
val a = RadioInterfaceService.getBondedDeviceAddress(this)
|
||||||
|
val isBluetoothInterface = a != null && a.startsWith("x")
|
||||||
|
|
||||||
val mi = with(myInfo) {
|
val mi = with(myInfo) {
|
||||||
MyNodeInfo(
|
MyNodeInfo(
|
||||||
myNodeNum,
|
myNodeNum,
|
||||||
|
@ -1093,7 +1101,7 @@ class MeshService : Service(), Logging {
|
||||||
hwModel,
|
hwModel,
|
||||||
firmwareVersion,
|
firmwareVersion,
|
||||||
firmwareUpdateFilename != null,
|
firmwareUpdateFilename != null,
|
||||||
SoftwareUpdateService.shouldUpdate(
|
isBluetoothInterface && SoftwareUpdateService.shouldUpdate(
|
||||||
this@MeshService,
|
this@MeshService,
|
||||||
DeviceVersion(firmwareVersion)
|
DeviceVersion(firmwareVersion)
|
||||||
),
|
),
|
||||||
|
|
|
@ -6,27 +6,40 @@ import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import com.geeksville.mesh.DataPacket
|
import com.geeksville.mesh.DataPacket
|
||||||
import com.geeksville.mesh.MainActivity
|
import com.geeksville.mesh.MainActivity
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
import com.geeksville.mesh.android.notificationManager
|
import com.geeksville.mesh.android.notificationManager
|
||||||
import com.geeksville.mesh.utf8
|
import com.geeksville.mesh.utf8
|
||||||
|
import java.io.Closeable
|
||||||
|
|
||||||
|
|
||||||
class MeshServiceNotifications(
|
class MeshServiceNotifications(
|
||||||
private val context: Context
|
private val context: Context
|
||||||
) {
|
) : Closeable
|
||||||
|
{
|
||||||
private val notificationManager: NotificationManager get() = context.notificationManager
|
private val notificationManager: NotificationManager get() = context.notificationManager
|
||||||
val notifyId = 101
|
val notifyId = 101
|
||||||
|
private var largeIcon: Bitmap? = null
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
private fun createNotificationChannel(): String {
|
private fun createNotificationChannel(): String {
|
||||||
val channelId = "my_service"
|
val channelId = "my_service"
|
||||||
val channelName = context.getString(R.string.meshtastic_service_notifications)
|
val channelName = context.getString(R.string.meshtastic_service_notifications)
|
||||||
val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH).apply {
|
val channel = NotificationChannel(
|
||||||
|
channelId,
|
||||||
|
channelName,
|
||||||
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
|
).apply {
|
||||||
lightColor = Color.BLUE
|
lightColor = Color.BLUE
|
||||||
importance = NotificationManager.IMPORTANCE_NONE
|
importance = NotificationManager.IMPORTANCE_NONE
|
||||||
lockscreenVisibility = Notification.VISIBILITY_PRIVATE
|
lockscreenVisibility = Notification.VISIBILITY_PRIVATE
|
||||||
|
@ -61,6 +74,25 @@ class MeshServiceNotifications(
|
||||||
PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0)
|
PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a bitmap from a vector drawable (even on old builds)
|
||||||
|
* https://stackoverflow.com/questions/33696488/getting-bitmap-from-vector-drawable
|
||||||
|
*/
|
||||||
|
fun getBitmapFromVectorDrawable(drawableId: Int): Bitmap {
|
||||||
|
var drawable = ContextCompat.getDrawable(context, drawableId)!!
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
drawable = DrawableCompat.wrap(drawable).mutate()
|
||||||
|
}
|
||||||
|
val bitmap = Bitmap.createBitmap(
|
||||||
|
drawable.intrinsicWidth,
|
||||||
|
drawable.intrinsicHeight, Bitmap.Config.ARGB_8888
|
||||||
|
)
|
||||||
|
val canvas = Canvas(bitmap)
|
||||||
|
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||||
|
drawable.draw(canvas)
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a new version of our notification - reflecting current app state
|
* Generate a new version of our notification - reflecting current app state
|
||||||
*/
|
*/
|
||||||
|
@ -69,11 +101,16 @@ class MeshServiceNotifications(
|
||||||
summaryString: String,
|
summaryString: String,
|
||||||
senderName: String
|
senderName: String
|
||||||
): Notification {
|
): Notification {
|
||||||
|
// We delay making this bitmap until we know we need it
|
||||||
|
if(largeIcon == null)
|
||||||
|
largeIcon = getBitmapFromVectorDrawable(R.mipmap.ic_launcher2)
|
||||||
|
|
||||||
val category = if (recentReceivedText != null) Notification.CATEGORY_SERVICE else Notification.CATEGORY_MESSAGE
|
val category = if (recentReceivedText != null) Notification.CATEGORY_SERVICE else Notification.CATEGORY_MESSAGE
|
||||||
val builder = NotificationCompat.Builder(context, channelId).setOngoing(true)
|
val builder = NotificationCompat.Builder(context, channelId).setOngoing(true)
|
||||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||||
.setCategory(category)
|
.setCategory(category)
|
||||||
.setSmallIcon(if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) R.drawable.app_icon_novect else R.drawable.app_icon) // vector form icons don't work reliably on older androids
|
.setSmallIcon(if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) R.drawable.app_icon_novect else R.drawable.app_icon) // vector form icons don't work reliably on older androids
|
||||||
|
.setLargeIcon(largeIcon) // we must include a large icon because of a bug in cyanogenmod https://github.com/open-keychain/open-keychain/issues/1356#issue-89493995
|
||||||
.setContentTitle(summaryString) // leave this off for now so our notification looks smaller
|
.setContentTitle(summaryString) // leave this off for now so our notification looks smaller
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
.setContentIntent(openAppIntent)
|
.setContentIntent(openAppIntent)
|
||||||
|
@ -93,4 +130,9 @@ class MeshServiceNotifications(
|
||||||
|
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
largeIcon?.recycle()
|
||||||
|
largeIcon = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
|
||||||
|
|
||||||
class RadioNotConnectedException(message: String = "Not connected to radio") :
|
open class RadioNotConnectedException(message: String = "Not connected to radio") :
|
||||||
BLEException(message)
|
BLEException(message)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f3812d8484c571f62c72d1509a1e02357fda5b8e
|
Subproject commit d7c3fa8ab6a47169e5dc8761d03d24588c3dd845
|
Ładowanie…
Reference in New Issue