kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
workaround for slow booting Samsung phones
rodzic
33265c7c2e
commit
407a38594f
|
@ -146,5 +146,11 @@ dependencies {
|
||||||
implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
|
implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
|
||||||
implementation 'com.google.zxing:core:3.4.0'
|
implementation 'com.google.zxing:core:3.4.0'
|
||||||
|
|
||||||
|
def work_version = "2.3.4"
|
||||||
|
|
||||||
|
// Work Request - used to delay boot event handling
|
||||||
|
// implementation "androidx.work:work-runtime:$work_version"
|
||||||
|
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||||
|
|
||||||
implementation project(':geeksville-androidlib')
|
implementation project(':geeksville-androidlib')
|
||||||
}
|
}
|
||||||
|
|
|
@ -674,10 +674,10 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
if (model.meshService != null)
|
if (model.meshService != null)
|
||||||
Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)")
|
Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)")
|
||||||
|
|
||||||
MeshService.startService(this)?.let { intent ->
|
MeshService.startService(this) // Start the service so it stays running even after we unbind
|
||||||
// ALSO bind so we can use the api
|
|
||||||
mesh.connect(this, intent, Context.BIND_AUTO_CREATE + Context.BIND_ABOVE_CLIENT)
|
// ALSO bind so we can use the api
|
||||||
}
|
mesh.connect(this, MeshService.intent, Context.BIND_AUTO_CREATE + Context.BIND_ABOVE_CLIENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unbindMeshService() {
|
private fun unbindMeshService() {
|
||||||
|
|
|
@ -8,8 +8,7 @@ import com.geeksville.android.Logging
|
||||||
|
|
||||||
class BootCompleteReceiver : BroadcastReceiver(), Logging {
|
class BootCompleteReceiver : BroadcastReceiver(), Logging {
|
||||||
override fun onReceive(mContext: Context, intent: Intent) {
|
override fun onReceive(mContext: Context, intent: Intent) {
|
||||||
// FIXME - start listening for bluetooth messages from our device
|
// start listening for bluetooth messages from our device
|
||||||
info("Received boot complete announcement, starting mesh service")
|
MeshService.startLater(mContext)
|
||||||
MeshService.startService(mContext)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,6 +16,7 @@ import androidx.annotation.UiThread
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationCompat.PRIORITY_MIN
|
import androidx.core.app.NotificationCompat.PRIORITY_MIN
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import androidx.work.*
|
||||||
import com.geeksville.analytics.DataPair
|
import com.geeksville.analytics.DataPair
|
||||||
import com.geeksville.android.GeeksvilleApplication
|
import com.geeksville.android.GeeksvilleApplication
|
||||||
import com.geeksville.android.Logging
|
import com.geeksville.android.Logging
|
||||||
|
@ -33,6 +34,7 @@ import kotlinx.coroutines.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
|
@ -67,33 +69,67 @@ class MeshService : Service(), Logging {
|
||||||
class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id")
|
class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id")
|
||||||
class NotInMeshException() : Exception("We are not yet in a mesh")
|
class NotInMeshException() : Exception("We are not yet in a mesh")
|
||||||
|
|
||||||
/// Helper function to start running our service, returns the intent used to reach it
|
/** A little helper that just calls startService
|
||||||
/// or null if the service could not be started (no bluetooth or no bonded device set)
|
*/
|
||||||
fun startService(context: Context): Intent? {
|
class ServiceStarter(appContext: Context, workerParams: WorkerParameters) :
|
||||||
|
Worker(appContext, workerParams) {
|
||||||
|
|
||||||
|
override fun doWork(): Result = try {
|
||||||
|
startService(this.applicationContext)
|
||||||
|
|
||||||
|
// Indicate whether the task finished successfully with the Result
|
||||||
|
Result.success()
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
errormsg("failure starting service, will retry", ex)
|
||||||
|
Result.retry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just after boot the android OS is super busy, so if we call startForegroundService then, our
|
||||||
|
* thread might be stalled long enough to expose this google/samsung bug:
|
||||||
|
* https://issuetracker.google.com/issues/76112072#comment56
|
||||||
|
*/
|
||||||
|
fun startLater(context: Context) {
|
||||||
|
info("Received boot complete announcement, starting mesh service in one minute")
|
||||||
|
val delayRequest = OneTimeWorkRequestBuilder<ServiceStarter>()
|
||||||
|
.setInitialDelay(1, TimeUnit.MINUTES)
|
||||||
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
|
.addTag("startLater")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
WorkManager.getInstance(context).enqueue(delayRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
val intent = Intent().apply {
|
||||||
|
setClassName(
|
||||||
|
"com.geeksville.mesh",
|
||||||
|
"com.geeksville.mesh.service.MeshService"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to start running our service
|
||||||
|
fun startService(context: Context) {
|
||||||
// bind to our service using the same mechanism an external client would use (for testing coverage)
|
// bind to our service using the same mechanism an external client would use (for testing coverage)
|
||||||
// The following would work for us, but not external users
|
// The following would work for us, but not external users
|
||||||
//val intent = Intent(this, MeshService::class.java)
|
//val intent = Intent(this, MeshService::class.java)
|
||||||
//intent.action = IMeshService::class.java.name
|
//intent.action = IMeshService::class.java.name
|
||||||
val intent = Intent()
|
|
||||||
intent.setClassName(
|
|
||||||
"com.geeksville.mesh",
|
|
||||||
"com.geeksville.mesh.service.MeshService"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Before binding we want to explicitly create - so the service stays alive forever (so it can keep
|
// 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
|
// listening for the bluetooth packets arriving from the radio. And when they arrive forward them
|
||||||
// to Signal or whatever.
|
// to Signal or whatever.
|
||||||
|
|
||||||
logAssert(
|
info("Trying to start service")
|
||||||
|
val compName =
|
||||||
(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
// we have some samsung devices failing with https://issuetracker.google.com/issues/76112072#comment56 not sure what the fix is yet
|
|
||||||
context.startForegroundService(intent)
|
context.startForegroundService(intent)
|
||||||
} else {
|
} else {
|
||||||
context.startService(intent)
|
context.startService(intent)
|
||||||
}) != null
|
})
|
||||||
)
|
|
||||||
|
|
||||||
return intent
|
if (compName == null)
|
||||||
|
throw Exception("Failed to start service")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue