pull/8/head
geeksville 2020-01-22 14:27:22 -08:00
rodzic ee54f9fa36
commit bb39bab1c1
3 zmienionych plików z 36 dodań i 24 usunięć

16
TODO.md
Wyświetl plik

@ -1,17 +1,25 @@
* assert() is apparently a noop - change to use my version of assert
* make frontend using https://developer.android.com/jetpack/compose/tutorial * make frontend using https://developer.android.com/jetpack/compose/tutorial
*fix bluetooth
# Medium priority # Medium priority
* remove secret google settings json before open sourcing * remove secret google settings json before open sourcing
* require user auth to pair with the device (i.e. press button on device to allow a new phone to pair with it). * require user auth to pair with the device (i.e. press button on device to allow a new phone to pair with it).
Don't leave device discoverable. Don't let unpaired users do thing with device Don't leave device discoverable. Don't let unpaired users do thing with device
* add crash reporting
* remove example code boilerplate from the service * remove example code boilerplate from the service
* add analytics (make them optional)
# Low priority # Low priority
* make analytics optional
* possibly use finotes for analytics https://finotes.com/ * possibly use finotes for analytics https://finotes.com/
* also add a receiver that fires after a new update was installed from the play stoe * also add a receiver that fires after a new update was installed from the play stoe
# Done
* assert() is apparently a noop - change to use my version of assert
* DONE add crash reporting
* DONE add analytics (make them optional)

Wyświetl plik

@ -15,12 +15,13 @@ import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.geeksville.android.Logging
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import java.util.* import java.util.*
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity(), Logging {
companion object { companion object {
const val REQUEST_ENABLE_BT = 10 const val REQUEST_ENABLE_BT = 10
@ -33,6 +34,8 @@ class MainActivity : AppCompatActivity() {
} }
fun requestPermission() { fun requestPermission() {
debug("Checking permissions")
val perms = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, val perms = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH,
@ -72,7 +75,10 @@ class MainActivity : AppCompatActivity() {
/* Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) /* Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show() */ .setAction("Action", null).show() */
// test crash reporting
// logAssert(false)
// throw NotImplementedError("I like crap") // throw NotImplementedError("I like crap")
if(bluetoothAdapter != null) { if(bluetoothAdapter != null) {
SoftwareUpdateService.enqueueWork(this, SoftwareUpdateService.scanDevicesIntent) SoftwareUpdateService.enqueueWork(this, SoftwareUpdateService.scanDevicesIntent)
} }

Wyświetl plik

@ -7,10 +7,10 @@ import android.content.Intent
import android.os.Handler import android.os.Handler
import android.os.ParcelUuid import android.os.ParcelUuid
import android.os.SystemClock import android.os.SystemClock
import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.JobIntentService import androidx.core.app.JobIntentService
import com.geeksville.android.Logging
import java.io.InputStream import java.io.InputStream
import java.util.* import java.util.*
@ -29,7 +29,7 @@ import java.util.*
* FIXME - broadcast when we found devices, made progress sending blocks or when the update is complete * FIXME - broadcast when we found devices, made progress sending blocks or when the update is complete
* FIXME - make the user decide to start an update on a particular device * FIXME - make the user decide to start an update on a particular device
*/ */
class SoftwareUpdateService : JobIntentService() { class SoftwareUpdateService : JobIntentService(), Logging {
private val bluetoothAdapter: BluetoothAdapter by lazy(LazyThreadSafetyMode.NONE) { private val bluetoothAdapter: BluetoothAdapter by lazy(LazyThreadSafetyMode.NONE) {
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
@ -49,9 +49,9 @@ class SoftwareUpdateService : JobIntentService() {
// Start the update by writing the # of bytes in the image // Start the update by writing the # of bytes in the image
val numBytes = firmwareStream.available() val numBytes = firmwareStream.available()
assert(totalSizeDesc.setValue(numBytes, BluetoothGattCharacteristic.FORMAT_UINT32, 0)) logAssert(totalSizeDesc.setValue(numBytes, BluetoothGattCharacteristic.FORMAT_UINT32, 0))
assert(updateGatt.writeCharacteristic(totalSizeDesc)) logAssert(updateGatt.writeCharacteristic(totalSizeDesc))
assert(updateGatt.readCharacteristic(totalSizeDesc)) logAssert(updateGatt.readCharacteristic(totalSizeDesc))
} }
// Send the next block of our file to the device // Send the next block of our file to the device
@ -64,15 +64,15 @@ class SoftwareUpdateService : JobIntentService() {
val buffer = ByteArray(blockSize) val buffer = ByteArray(blockSize)
// slightly expensive to keep reallocing this buffer, but whatever // slightly expensive to keep reallocing this buffer, but whatever
assert(firmwareStream.read(buffer) == blockSize) logAssert(firmwareStream.read(buffer) == blockSize)
dataDesc = updateService.getCharacteristic(SW_UPDATE_DATA_CHARACTER)!! dataDesc = updateService.getCharacteristic(SW_UPDATE_DATA_CHARACTER)!!
// updateGatt.beginReliableWrite() // updateGatt.beginReliableWrite()
dataDesc.value = buffer dataDesc.value = buffer
assert(updateGatt.writeCharacteristic(dataDesc)) logAssert(updateGatt.writeCharacteristic(dataDesc))
} }
else { else {
assert(false) // fixme logAssert(false) // fixme
} }
} }
@ -110,7 +110,7 @@ class SoftwareUpdateService : JobIntentService() {
//intentAction = ACTION_GATT_CONNECTED //intentAction = ACTION_GATT_CONNECTED
//connectionState = STATE_CONNECTED //connectionState = STATE_CONNECTED
// broadcastUpdate(intentAction) // broadcastUpdate(intentAction)
assert(bluetoothGatt.discoverServices()) logAssert(bluetoothGatt.discoverServices())
} }
BluetoothProfile.STATE_DISCONNECTED -> { BluetoothProfile.STATE_DISCONNECTED -> {
//intentAction = ACTION_GATT_DISCONNECTED //intentAction = ACTION_GATT_DISCONNECTED
@ -122,7 +122,7 @@ class SoftwareUpdateService : JobIntentService() {
// New services discovered // New services discovered
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
assert(status == BluetoothGatt.GATT_SUCCESS) logAssert(status == BluetoothGatt.GATT_SUCCESS)
// broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED) // broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED)
@ -142,13 +142,13 @@ class SoftwareUpdateService : JobIntentService() {
characteristic: BluetoothGattCharacteristic, characteristic: BluetoothGattCharacteristic,
status: Int status: Int
) { ) {
assert(status == BluetoothGatt.GATT_SUCCESS) logAssert(status == BluetoothGatt.GATT_SUCCESS)
if (characteristic == totalSizeDesc) { if (characteristic == totalSizeDesc) {
// Our read of this has completed, either fail or continue updating // Our read of this has completed, either fail or continue updating
val readvalue = val readvalue =
characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0)
assert(readvalue != 0) // FIXME - handle this case logAssert(readvalue != 0) // FIXME - handle this case
enqueueWork(this@SoftwareUpdateService, sendNextBlockIntent) enqueueWork(this@SoftwareUpdateService, sendNextBlockIntent)
} }
@ -160,7 +160,7 @@ class SoftwareUpdateService : JobIntentService() {
characteristic: BluetoothGattCharacteristic?, characteristic: BluetoothGattCharacteristic?,
status: Int status: Int
) { ) {
assert(status == BluetoothGatt.GATT_SUCCESS) logAssert(status == BluetoothGatt.GATT_SUCCESS)
if (characteristic == dataDesc) { if (characteristic == dataDesc) {
enqueueWork(this@SoftwareUpdateService, sendNextBlockIntent) enqueueWork(this@SoftwareUpdateService, sendNextBlockIntent)
@ -169,7 +169,7 @@ class SoftwareUpdateService : JobIntentService() {
} }
bluetoothGatt = result.device.connectGatt(this@SoftwareUpdateService, false, gattCallback)!! bluetoothGatt = result.device.connectGatt(this@SoftwareUpdateService, false, gattCallback)!!
toast("FISH " + bluetoothGatt) toast("FISH " + bluetoothGatt)
assert(bluetoothGatt.discoverServices()) logAssert(bluetoothGatt.discoverServices())
} }
} }
@ -209,7 +209,7 @@ class SoftwareUpdateService : JobIntentService() {
override fun onHandleWork(intent: Intent) { // We have received work to do. The system or framework is already override fun onHandleWork(intent: Intent) { // We have received work to do. The system or framework is already
// holding a wake lock for us at this point, so we can just go. // holding a wake lock for us at this point, so we can just go.
Log.i("SimpleJobIntentService", "Executing work: $intent") info("Executing work: $intent")
var label = intent.getStringExtra("label") var label = intent.getStringExtra("label")
if (label == null) { if (label == null) {
label = intent.toString() label = intent.toString()
@ -220,12 +220,10 @@ class SoftwareUpdateService : JobIntentService() {
scanDevicesIntent.action -> scanLeDevice(true) scanDevicesIntent.action -> scanLeDevice(true)
startUpdateIntent.action -> startUpdate() startUpdateIntent.action -> startUpdate()
sendNextBlockIntent.action -> sendNextBlock() sendNextBlockIntent.action -> sendNextBlock()
else -> assert(false) else -> logAssert(false)
} }
Log.i( info("Completed service @ " + SystemClock.elapsedRealtime()
"SimpleJobIntentService",
"Completed service @ " + SystemClock.elapsedRealtime()
) )
} }