mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
commit
2614cba6a1
15 changed files with 69 additions and 72 deletions
|
|
@ -31,8 +31,8 @@ android {
|
|||
applicationId "com.geeksville.mesh"
|
||||
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||
targetSdkVersion 29
|
||||
versionCode 20148 // format is Mmmss (where M is 1+the numeric major number
|
||||
versionName "1.1.48"
|
||||
versionCode 20150 // format is Mmmss (where M is 1+the numeric major number
|
||||
versionName "1.1.50"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
// per https://developer.android.com/studio/write/vector-asset-studio
|
||||
|
|
@ -90,7 +90,7 @@ play {
|
|||
// per protobuf-gradle-plugin docs, this is recommended for android
|
||||
protobuf {
|
||||
protoc {
|
||||
artifact = 'com.google.protobuf:protoc:3.13.0'
|
||||
artifact = 'com.google.protobuf:protoc:3.15.3'
|
||||
}
|
||||
generateProtoTasks {
|
||||
all().each { task ->
|
||||
|
|
@ -130,7 +130,7 @@ dependencies {
|
|||
|
||||
// optional - Test helpers
|
||||
testImplementation "androidx.room:room-testing:$room_version"
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
|
||||
// For now I'm not using javalite, because I want JSON printing
|
||||
implementation ('com.google.protobuf:protobuf-java:3.14.0')
|
||||
implementation ('com.google.protobuf:protobuf-java:3.15.3')
|
||||
|
||||
// For UART access
|
||||
// implementation 'com.google.android.things:androidthings:1.0'
|
||||
|
|
@ -158,7 +158,7 @@ dependencies {
|
|||
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
||||
|
||||
// location services
|
||||
implementation 'com.google.android.gms:play-services-location:17.1.0'
|
||||
implementation 'com.google.android.gms:play-services-location:18.0.0'
|
||||
|
||||
// For Google Sign-In (owner name accesss)
|
||||
implementation 'com.google.android.gms:play-services-auth:19.0.0'
|
||||
|
|
|
|||
|
|
@ -20,10 +20,14 @@ import android.os.Build
|
|||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.RemoteException
|
||||
import android.text.SpannableString
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.util.Linkify
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
|
@ -64,6 +68,7 @@ import java.nio.charset.Charset
|
|||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
/*
|
||||
UI design
|
||||
|
||||
|
|
@ -619,26 +624,38 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
|
||||
debug("Getting latest radioconfig from service")
|
||||
try {
|
||||
model.radioConfig.value =
|
||||
MeshProtos.RadioConfig.parseFrom(service.radioConfig)
|
||||
|
||||
val info = service.myNodeInfo
|
||||
model.myNodeInfo.value = info
|
||||
|
||||
val isOld = info.minAppVersion > BuildConfig.VERSION_CODE
|
||||
if (isOld)
|
||||
MaterialAlertDialogBuilder(this)
|
||||
if (isOld) {
|
||||
// make links clickable per https://stackoverflow.com/a/62642807
|
||||
val messageStr = getText(R.string.must_update)
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.app_too_old))
|
||||
.setMessage(getString(R.string.must_update))
|
||||
.setMessage(messageStr)
|
||||
.setPositiveButton("Okay") { _, _ ->
|
||||
info("User acknowledged app is old")
|
||||
}
|
||||
.show()
|
||||
|
||||
updateNodesFromDevice()
|
||||
val dialog = builder.show()
|
||||
|
||||
// we have a connection to our device now, do the channel change
|
||||
perhapsChangeChannel()
|
||||
// Make the textview clickable. Must be called after show()
|
||||
val view = (dialog.findViewById(android.R.id.message) as TextView?)!!
|
||||
// Linkify.addLinks(view, Linkify.ALL) // not needed with this method
|
||||
view.movementMethod = LinkMovementMethod.getInstance()
|
||||
} else {
|
||||
// If our app is too old, we probably don't understand the new radioconfig messages
|
||||
|
||||
model.radioConfig.value =
|
||||
MeshProtos.RadioConfig.parseFrom(service.radioConfig)
|
||||
|
||||
updateNodesFromDevice()
|
||||
|
||||
// we have a connection to our device now, do the channel change
|
||||
perhapsChangeChannel()
|
||||
}
|
||||
} catch (ex: RemoteException) {
|
||||
warn("Abandoning connect $ex, because we probably just lost device connection")
|
||||
model.isConnected.value = oldConnection
|
||||
|
|
@ -931,7 +948,8 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
||||
menu.findItem(R.id.stress_test).isVisible = BuildConfig.DEBUG // only show stress test for debug builds (for now)
|
||||
menu.findItem(R.id.stress_test).isVisible =
|
||||
BuildConfig.DEBUG // only show stress test for debug builds (for now)
|
||||
return super.onPrepareOptionsMenu(menu)
|
||||
}
|
||||
|
||||
|
|
@ -972,7 +990,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
)
|
||||
}
|
||||
item.isChecked = !item.isChecked // toggle ping test
|
||||
if(item.isChecked)
|
||||
if (item.isChecked)
|
||||
postPing()
|
||||
else
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ class MeshService : Service(), Logging {
|
|||
class NodeNumNotFoundException(id: Int) : NodeNotFoundException("NodeNum not found $id")
|
||||
class IdNotFoundException(id: String) : NodeNotFoundException("ID not found $id")
|
||||
|
||||
class NoRadioConfigException(message: String = "No radio settings received (is our app too old?)") :
|
||||
RadioNotConnectedException(message)
|
||||
|
||||
/** 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")
|
||||
|
|
@ -569,7 +572,7 @@ class MeshService : Service(), Logging {
|
|||
val hopLimit = packet.hopLimit
|
||||
|
||||
// If the rxTime was not set by the device (because device software was old), guess at a time
|
||||
val rxTime = if (packet.rxTime == 0) packet.rxTime else currentSecond()
|
||||
val rxTime = if (packet.rxTime != 0) packet.rxTime else currentSecond()
|
||||
|
||||
when {
|
||||
fromId == null -> {
|
||||
|
|
@ -638,11 +641,10 @@ class MeshService : Service(), Logging {
|
|||
if (myInfo.myNodeNum == packet.from) {
|
||||
// Handle position updates from the device
|
||||
if (data.portnumValue == Portnums.PortNum.POSITION_APP_VALUE) {
|
||||
val rxTime = if (packet.rxTime != 0) packet.rxTime else currentSecond()
|
||||
handleReceivedPosition(
|
||||
packet.from,
|
||||
MeshProtos.Position.parseFrom(data.payload),
|
||||
rxTime
|
||||
dataPacket.time
|
||||
)
|
||||
} else
|
||||
debug("Ignoring packet sent from our node, portnum=${data.portnumValue} ${bytes.size} bytes")
|
||||
|
|
@ -660,9 +662,8 @@ class MeshService : Service(), Logging {
|
|||
|
||||
// Handle new style position info
|
||||
Portnums.PortNum.POSITION_APP_VALUE -> {
|
||||
val rxTime = if (packet.rxTime != 0) packet.rxTime else currentSecond()
|
||||
val u = MeshProtos.Position.parseFrom(data.payload)
|
||||
handleReceivedPosition(packet.from, u, rxTime)
|
||||
handleReceivedPosition(packet.from, u, dataPacket.time)
|
||||
}
|
||||
|
||||
// Handle new style user info
|
||||
|
|
@ -702,15 +703,17 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/// Update our DB of users based on someone sending out a Position subpacket
|
||||
/** Update our DB of users based on someone sending out a Position subpacket
|
||||
* @param defaultTime in msecs since 1970
|
||||
*/
|
||||
private fun handleReceivedPosition(
|
||||
fromNum: Int,
|
||||
p: MeshProtos.Position,
|
||||
defaultTime: Int = Position.currentTime()
|
||||
defaultTime: Long = System.currentTimeMillis()
|
||||
) {
|
||||
updateNodeInfo(fromNum) {
|
||||
it.position = Position(p)
|
||||
updateNodeInfoTime(it, defaultTime)
|
||||
updateNodeInfoTime(it, (defaultTime / 1000).toInt())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -791,8 +794,6 @@ class MeshService : Service(), Logging {
|
|||
packet.toString()
|
||||
)
|
||||
insertPacket(packetToSave)
|
||||
// If the rxTime was not set by the device (because device software was old), guess at a time
|
||||
val rxTime = if (packet.rxTime != 0) packet.rxTime else currentSecond()
|
||||
|
||||
// Update last seen for the node that sent the packet, but also for _our node_ because anytime a packet passes
|
||||
// through our node on the way to the phone that means that local node is also alive in the mesh
|
||||
|
|
@ -801,8 +802,11 @@ class MeshService : Service(), Logging {
|
|||
it.position = it.position?.copy(time = currentSecond())
|
||||
}
|
||||
|
||||
if (p.hasPosition())
|
||||
handleReceivedPosition(fromNum, p.position, rxTime)
|
||||
// If the rxTime was not set by the device (because device software was old), guess at a time
|
||||
val rxTime = if (packet.rxTime != 0) packet.rxTime else currentSecond()
|
||||
if (p.hasPosition()) {
|
||||
handleReceivedPosition(fromNum, p.position, rxTime.toLong() * 1000)
|
||||
}
|
||||
else
|
||||
updateNodeInfo(fromNum) {
|
||||
// Update our last seen based on any valid timestamps. If the device didn't provide a timestamp make one
|
||||
|
|
@ -1589,7 +1593,7 @@ class MeshService : Service(), Logging {
|
|||
|
||||
override fun getRadioConfig(): ByteArray = toRemoteExceptions {
|
||||
this@MeshService.radioConfig?.toByteArray()
|
||||
?: throw RadioNotConnectedException()
|
||||
?: throw NoRadioConfigException()
|
||||
}
|
||||
|
||||
override fun setRadioConfig(payload: ByteArray) = toRemoteExceptions {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ open class RadioNotConnectedException(message: String = "Not connected to radio"
|
|||
BLEException(message)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Handles the bluetooth link with a mesh radio device. Does not cache any device state,
|
||||
* just does bluetooth comms etc...
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit b1aed06442025624841b2288fac273d9bc41c438
|
||||
Subproject commit 512d1aca0a066107de749c0c47397c7f9bf9cb99
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M17.5,8c0.46,0 0.91,-0.05 1.34,-0.12C17.44,5.56 14.9,4 12,4c-0.46,0 -0.91,0.05 -1.34,0.12C12.06,6.44 14.6,8 17.5,8zM8.08,5.03C6.37,6 5.05,7.58 4.42,9.47c1.71,-0.97 3.03,-2.55 3.66,-4.44z"
|
||||
android:fillAlpha=".3"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,4c2.9,0 5.44,1.56 6.84,3.88 -0.43,0.07 -0.88,0.12 -1.34,0.12 -2.9,0 -5.44,-1.56 -6.84,-3.88 0.43,-0.07 0.88,-0.12 1.34,-0.12zM8.08,5.03C7.45,6.92 6.13,8.5 4.42,9.47 5.05,7.58 6.37,6 8.08,5.03zM12,20c-4.41,0 -8,-3.59 -8,-8 0,-0.05 0.01,-0.1 0.01,-0.15 2.6,-0.98 4.68,-2.99 5.74,-5.55 1.83,2.26 4.62,3.7 7.75,3.7 0.75,0 1.47,-0.09 2.17,-0.24 0.21,0.71 0.33,1.46 0.33,2.24 0,4.41 -3.59,8 -8,8z"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M9,13m-1.25,0a1.25,1.25 0,1 1,2.5 0a1.25,1.25 0,1 1,-2.5 0"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M15,13m-1.25,0a1.25,1.25 0,1 1,2.5 0a1.25,1.25 0,1 1,-2.5 0"/>
|
||||
</vector>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFFFFF">
|
||||
>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/positionBroadcastPeriodView"
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/constraintLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
android:id="@+id/mapView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:clickable="true" android:focusable="true"
|
||||
mapbox:mapbox_uiZoomGestures="true"
|
||||
mapbox:mapbox_uiScrollGestures="true"></com.mapbox.mapboxsdk.maps.MapView>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@
|
|||
android:id="@+id/stress_test"
|
||||
android:checkable="true"
|
||||
android:checked="false"
|
||||
android:title="Protocol stress test" />
|
||||
android:title="@string/protocol_stress_test" />
|
||||
<item
|
||||
android:id="@+id/advanced_settings"
|
||||
app:showAsAction="withText"
|
||||
android:title="Advanced settings" />
|
||||
android:title="@string/advanced_settings" />
|
||||
<item
|
||||
android:id="@+id/about"
|
||||
android:title="@string/about"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
<resources>
|
||||
<color name="colorPrimary">#3700B3</color>
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
<color name="colorMsg">#F2F2F2</color>
|
||||
<color name="colorMyMsg">#EDEAF4</color>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
<dimen name="message_offset">64dp</dimen>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<resources>
|
||||
<string name="app_name" translatable="false">Meshtastic</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="channel_name">Channel Name</string>
|
||||
<string name="channel_options">Channel options</string>
|
||||
|
|
@ -59,8 +60,8 @@
|
|||
<string name="not_connected">Not connected, select radio below</string>
|
||||
<string name="connected_sleeping">Connected to radio, but it is sleeping</string>
|
||||
<string name="update_to">Update to %s</string>
|
||||
<string name="app_too_old">Application too old</string>
|
||||
<string name="must_update">You must update this application on the Google Play store (or Github). It is too old to talk to this radio.</string>
|
||||
<string name="app_too_old">Application update required</string>
|
||||
<string name="must_update">You must update this application on the Google Play store (or Github). It is too old to talk to this radio firmware. Please read our <a href="https://www.meshtastic.org/software/android-too-old.html">wiki</a> on this topic.</string>
|
||||
<string name="none">None (disable)</string>
|
||||
<string name="modem_config_short">Short range (but fast)</string>
|
||||
<string name="modem_config_medium">Medium range (but fast)</string>
|
||||
|
|
@ -86,4 +87,6 @@
|
|||
<string name="ls_sleep_secs">Device sleep period (in seconds)</string>
|
||||
<string name="meshtastic_messages_notifications">Notifications about messages</string>
|
||||
<string name="broadcast_period_too_small">Minimum broadcast period for this channel is %d</string>
|
||||
<string name="protocol_stress_test">Protocol stress test</string>
|
||||
<string name="advanced_settings">Advanced settings</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.4.30'
|
||||
ext.kotlin_version = '1.4.31'
|
||||
ext.coroutines_version = "1.3.9"
|
||||
|
||||
repositories {
|
||||
|
|
@ -20,11 +20,11 @@ buildscript {
|
|||
// Add the Crashlytics Gradle plugin.
|
||||
// Check that you have the Google Services Gradle plugin v4.3.2 or later
|
||||
// (if not, add it).
|
||||
classpath 'com.google.gms:google-services:4.3.4'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
|
||||
classpath 'com.google.gms:google-services:4.3.5'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.0'
|
||||
|
||||
// protobuf plugin - docs here https://github.com/google/protobuf-gradle-plugin
|
||||
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.14'
|
||||
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.15'
|
||||
|
||||
//classpath "app.brant:amazonappstorepublisher:0.1.0"
|
||||
classpath 'com.github.triplet.gradle:play-publisher:2.8.0'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit cd0d0ab688af967af7e609f6f10fdf2dde1249bc
|
||||
Subproject commit ff93b088b4652f099ab99c0359388f2d0541ddc9
|
||||
Loading…
Add table
Add a link
Reference in a new issue