mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
commit
1f3d817e3b
6 changed files with 46 additions and 23 deletions
7
.github/workflows/android.yml
vendored
7
.github/workflows/android.yml
vendored
|
|
@ -19,11 +19,12 @@ jobs:
|
|||
- name: Load secrets
|
||||
run: |
|
||||
rm ./app/src/main/res/values/mapbox-token.xml
|
||||
echo -e "<resources>\n <string name=\"mapbox_access_token\">$MAPBOXTOKEN</string>\n</resources>" > ./app/src/main/res/values/mapbox-token.xml
|
||||
echo -e "<resources>\n <string name=\"mapbox_access_token\">$MAPBOX_ACCESS_TOKEN</string>\n</resources>" > ./app/src/main/res/values/mapbox-token.xml
|
||||
mkdir -p ~/.gradle
|
||||
echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOXTOKEN" >>~/.gradle/gradle.properties
|
||||
echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOX_DOWNLOADS_TOKEN" >>~/.gradle/gradle.properties
|
||||
env:
|
||||
MAPBOXTOKEN: ${{ secrets.MAPBOXTOKEN }}
|
||||
MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }}
|
||||
MAPBOX_DOWNLOADS_TOKEN: ${{ secrets.MAPBOX_DOWNLOADS_TOKEN }}
|
||||
|
||||
- name: Mock files for CI
|
||||
run: |
|
||||
|
|
|
|||
7
.github/workflows/release.yml
vendored
7
.github/workflows/release.yml
vendored
|
|
@ -22,14 +22,15 @@ jobs:
|
|||
rm ./app/google-services.json
|
||||
echo $GSERVICES > ./app/google-services.json
|
||||
rm ./app/src/main/res/values/mapbox-token.xml
|
||||
echo -e "<resources>\n <string name=\"mapbox_access_token\">$MAPBOXTOKEN</string>\n</resources>" > ./app/src/main/res/values/mapbox-token.xml
|
||||
echo -e "<resources>\n <string name=\"mapbox_access_token\">$MAPBOX_ACCESS_TOKEN</string>\n</resources>" > ./app/src/main/res/values/mapbox-token.xml
|
||||
mkdir -p ~/.gradle
|
||||
echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOXTOKEN" >> ~/.gradle/gradle.properties
|
||||
echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOX_DOWNLOADS_TOKEN" >> ~/.gradle/gradle.properties
|
||||
echo $KEYSTORE | base64 -di > ./app/$KEYSTORE_FILENAME
|
||||
echo "$KEYSTORE_PROPERTIES" > ./keystore.properties
|
||||
env:
|
||||
GSERVICES: ${{ secrets.GSERVICES }}
|
||||
MAPBOXTOKEN: ${{ secrets.MAPBOXTOKEN }}
|
||||
MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }}
|
||||
MAPBOX_DOWNLOADS_TOKEN: ${{ secrets.MAPBOX_DOWNLOADS_TOKEN }}
|
||||
KEYSTORE: ${{ secrets.KEYSTORE }}
|
||||
KEYSTORE_FILENAME: ${{ secrets.KEYSTORE_FILENAME }}
|
||||
KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ android {
|
|||
applicationId "com.geeksville.mesh"
|
||||
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||
targetSdkVersion 30 // 30 can't work until an explicit location permissions dialog is added
|
||||
versionCode 20259 // format is Mmmss (where M is 1+the numeric major number
|
||||
versionName "1.2.59"
|
||||
versionCode 20260 // format is Mmmss (where M is 1+the numeric major number
|
||||
versionName "1.2.60"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
// per https://developer.android.com/studio/write/vector-asset-studio
|
||||
|
|
|
|||
|
|
@ -1309,13 +1309,14 @@ class MeshService : Service(), Logging {
|
|||
if (asStr != null)
|
||||
hwModelStr = asStr
|
||||
}
|
||||
setFirmwareUpdateFilename(hwModelStr)
|
||||
val mi = with(myInfo) {
|
||||
MyNodeInfo(
|
||||
myNodeNum,
|
||||
hasGps,
|
||||
hwModelStr,
|
||||
firmwareVersion,
|
||||
firmwareUpdateFilename != null,
|
||||
firmwareUpdateFilename?.appLoad != null && firmwareUpdateFilename?.spiffs != null,
|
||||
isBluetoothInterface && SoftwareUpdateService.shouldUpdate(
|
||||
this@MeshService,
|
||||
DeviceVersion(firmwareVersion)
|
||||
|
|
@ -1328,9 +1329,7 @@ class MeshService : Service(), Logging {
|
|||
airUtilTx
|
||||
)
|
||||
}
|
||||
|
||||
newMyNodeInfo = mi
|
||||
setFirmwareUpdateFilename(mi)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1670,12 +1669,12 @@ class MeshService : Service(), Logging {
|
|||
/***
|
||||
* Return the filename we will install on the device
|
||||
*/
|
||||
private fun setFirmwareUpdateFilename(info: MyNodeInfo) {
|
||||
private fun setFirmwareUpdateFilename(model: String?) {
|
||||
firmwareUpdateFilename = try {
|
||||
if (info.firmwareVersion != null && info.model != null)
|
||||
if (model != null)
|
||||
SoftwareUpdateService.getUpdateFilename(
|
||||
this,
|
||||
info.model
|
||||
model
|
||||
)
|
||||
else
|
||||
null
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
|||
false // If we fail parsing our update info
|
||||
}
|
||||
|
||||
/** Return a Pair of apploadfilename, spiffs filename this device needs to use as an update (or null if no update needed)
|
||||
/** Return a Pair of appload filename, spiffs filename this device needs to use as an update (or null if no update needed)
|
||||
*/
|
||||
fun getUpdateFilename(
|
||||
context: Context,
|
||||
|
|
@ -290,9 +290,15 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
|||
* you can use it for the software update.
|
||||
*/
|
||||
fun doUpdate(context: Context, sync: SafeBluetooth, assets: UpdateFilenames) {
|
||||
// calculate total firmware size (spiffs + appLoad)
|
||||
var totalFirmwareSize = 0
|
||||
if (assets.appLoad != null && assets.spiffs != null) {
|
||||
totalFirmwareSize += context.assets.open(assets.appLoad).available()
|
||||
totalFirmwareSize += context.assets.open(assets.spiffs).available()
|
||||
}
|
||||
// we must attempt spiffs first, because if we update the appload the device will reboot afterwards
|
||||
try {
|
||||
assets.spiffs?.let { doUpdate(context, sync, it, FLASH_REGION_SPIFFS) }
|
||||
assets.spiffs?.let { doUpdate(context, sync, it, FLASH_REGION_SPIFFS, totalFirmwareSize) }
|
||||
} catch (_: BLECharacteristicNotFoundException) {
|
||||
// If we can't update spiffs (because not supported by target), do not fail
|
||||
errormsg("Ignoring failure to update spiffs on old appload")
|
||||
|
|
@ -301,7 +307,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
|||
errormsg("Device rejected invalid spiffs partition")
|
||||
}
|
||||
|
||||
assets.appLoad?.let { doUpdate(context, sync, it, FLASH_REGION_APPLOAD) }
|
||||
assets.appLoad?.let { doUpdate(context, sync, it, FLASH_REGION_APPLOAD, totalFirmwareSize) }
|
||||
sendProgress(context, ProgressSuccess, true)
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +323,8 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
|||
context: Context,
|
||||
sync: SafeBluetooth,
|
||||
assetName: String,
|
||||
flashRegion: Int = FLASH_REGION_APPLOAD
|
||||
flashRegion: Int = FLASH_REGION_APPLOAD,
|
||||
totalFirmwareSize: Int = 0
|
||||
) {
|
||||
val isAppload = flashRegion == FLASH_REGION_APPLOAD
|
||||
|
||||
|
|
@ -378,13 +385,15 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
|||
// Send all the blocks
|
||||
var oldProgress = -1 // used to limit # of log spam
|
||||
while (firmwareNumSent < firmwareSize) {
|
||||
// If we are doing the spiffs partition, we limit progress to a max of 50%, so that the user doesn't think we are done
|
||||
// yet
|
||||
val maxProgress = if (flashRegion != FLASH_REGION_APPLOAD)
|
||||
50 else 100
|
||||
// If we are doing the spiffs partition, we limit progress to a max of maxProgress
|
||||
// when updating the appload partition, progress from (100 - maxProgress) to 100%
|
||||
// maxProgress = spiffs% = 100% - appLoad%; (int * 10 + 5) / 10 used for rounding
|
||||
val maxProgress = ((firmwareSize * 1000 / totalFirmwareSize) + 5) / 10
|
||||
val minProgress = if (flashRegion != FLASH_REGION_APPLOAD)
|
||||
0 else (100 - maxProgress)
|
||||
sendProgress(
|
||||
context,
|
||||
firmwareNumSent * maxProgress / firmwareSize,
|
||||
minProgress + firmwareNumSent * maxProgress / firmwareSize,
|
||||
isAppload
|
||||
)
|
||||
if (progress != oldProgress) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import android.widget.*
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.geeksville.analytics.DataPair
|
||||
import com.geeksville.android.GeeksvilleApplication
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.android.hideKeyboard
|
||||
|
|
@ -474,6 +475,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
model.meshService?.let { service ->
|
||||
|
||||
debug("User started firmware update")
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"firmware_update",
|
||||
DataPair("content_type", "start")
|
||||
)
|
||||
binding.updateFirmwareButton.isEnabled = false // Disable until things complete
|
||||
binding.updateProgressBar.visibility = View.VISIBLE
|
||||
binding.updateProgressBar.progress = 0 // start from scratch
|
||||
|
|
@ -515,6 +520,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
} else
|
||||
when (progress) {
|
||||
ProgressSuccess -> {
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"firmware_update",
|
||||
DataPair("content_type", "success")
|
||||
)
|
||||
binding.scanStatusText.setText(R.string.update_successful)
|
||||
binding.updateProgressBar.visibility = View.GONE
|
||||
}
|
||||
|
|
@ -523,6 +532,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
binding.updateProgressBar.visibility = View.GONE
|
||||
}
|
||||
else -> {
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"firmware_update",
|
||||
DataPair("content_type", "failure")
|
||||
)
|
||||
binding.scanStatusText.setText(R.string.update_failed)
|
||||
binding.updateProgressBar.visibility = View.VISIBLE
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue