[O] Split code into service
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
||||
|
||||
@@ -39,6 +40,7 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:name=".MyService"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.hydev.wearsync
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Service
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -17,6 +18,7 @@ import com.influxdb.client.domain.WritePrecision
|
||||
import com.influxdb.client.kotlin.InfluxDBClientKotlin
|
||||
import com.influxdb.client.kotlin.InfluxDBClientKotlinFactory
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
|
||||
fun View.snack(msg: String) = Snackbar.make(this, msg, Snackbar.LENGTH_LONG)
|
||||
@@ -62,8 +64,15 @@ val Context.prefs get() = object : Prefs {
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Activity> Context.intent() = Intent(this, T::class.java)
|
||||
inline fun <reified T : Activity> Context.act() = startActivity(intent<T>())
|
||||
inline fun <reified T> Context.intent() = Intent(this, T::class.java)
|
||||
inline fun <reified T> Context.act()
|
||||
{
|
||||
if (T::class.isSubclassOf(Activity::class))
|
||||
startActivity(intent<T>())
|
||||
else if (T::class.isSubclassOf(Service::class))
|
||||
startService(intent<T>())
|
||||
else TODO("Unimplemented: ${T::class}")
|
||||
}
|
||||
fun ComponentActivity.actCallback(fn: ActivityResultCallback<ActivityResult>) =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult(), fn)
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.hydev.wearsync
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
@@ -13,15 +15,18 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.influxdb.client.kotlin.InfluxDBClientKotlin
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.consumeAsFlow
|
||||
import org.hydev.wearsync.ActivityPermissions.Companion.hasPermissions
|
||||
import org.hydev.wearsync.bles.BluetoothHandler.Companion.ble
|
||||
import org.hydev.wearsync.databinding.ActivityMainBinding
|
||||
import java.util.*
|
||||
|
||||
class MainActivity : AppCompatActivity()
|
||||
{
|
||||
companion object {
|
||||
var instance: MainActivity? = null
|
||||
}
|
||||
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
|
||||
lateinit var binding: ActivityMainBinding
|
||||
lateinit var influx: InfluxDBClientKotlin
|
||||
|
||||
@@ -41,15 +46,24 @@ class MainActivity : AppCompatActivity()
|
||||
{
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Bind activity
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
||||
// Create recycler
|
||||
binding.content.recycler.let {
|
||||
it.adapter = RecordAdapter(records)
|
||||
it.layoutManager = LinearLayoutManager(this)
|
||||
}
|
||||
|
||||
// Create notification channel
|
||||
val chan = NotificationChannel(MyService.NOTIF_CHANNEL_ID, "Keep-alive Notification",
|
||||
NotificationManager.IMPORTANCE_MIN)
|
||||
getSysServ<NotificationManager>().createNotificationChannel(chan)
|
||||
|
||||
instance = this
|
||||
|
||||
if (!hasPermissions()) permissionCallback.launch(intent<ActivityPermissions>())
|
||||
else afterPermissions()
|
||||
}
|
||||
@@ -83,7 +97,7 @@ class MainActivity : AppCompatActivity()
|
||||
binding.content.tvDevice.text = "Configured Device: ${prefs.chosenDevice}"
|
||||
binding.content.tvValue.text = "Service started!"
|
||||
|
||||
startCollect()
|
||||
act<MyService>()
|
||||
}
|
||||
|
||||
override fun onResume()
|
||||
@@ -119,7 +133,6 @@ class MainActivity : AppCompatActivity()
|
||||
}
|
||||
}
|
||||
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
private val records = ArrayList<Any>()
|
||||
|
||||
class RecordAdapter(val records: List<Any>) : RecyclerView.Adapter<RecordAdapter.ViewHolder>() {
|
||||
@@ -154,24 +167,4 @@ class MainActivity : AppCompatActivity()
|
||||
records.add(t)
|
||||
runOnUiThread { binding.content.recycler.adapter?.notifyDataSetChanged() }
|
||||
}
|
||||
|
||||
fun startCollect()
|
||||
{
|
||||
collect(ble.heartRateChannel)
|
||||
collect(ble.batteryChannel)
|
||||
}
|
||||
|
||||
private fun <T : Any> collect(channel: Channel<T>) {
|
||||
scope.launch {
|
||||
channel.consumeAsFlow().collect {
|
||||
try {
|
||||
addRecord(it)
|
||||
influx add it
|
||||
}
|
||||
catch (e: Exception) {
|
||||
addRecord(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.hydev.wearsync
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.influxdb.client.kotlin.InfluxDBClientKotlin
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.consumeAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.hydev.wearsync.bles.BluetoothHandler.Companion.ble
|
||||
|
||||
class MyService : Service()
|
||||
{
|
||||
private lateinit var influx: InfluxDBClientKotlin
|
||||
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
|
||||
override fun onBind(intent: Intent?) = null
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int
|
||||
{
|
||||
influx = prefs.createInflux()
|
||||
startCollect()
|
||||
|
||||
startForeground()
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
fun startCollect()
|
||||
{
|
||||
collect(ble.heartRateChannel)
|
||||
collect(ble.batteryChannel)
|
||||
}
|
||||
|
||||
private fun <T : Any> collect(channel: Channel<T>) {
|
||||
scope.launch {
|
||||
channel.consumeAsFlow().collect {
|
||||
try {
|
||||
MainActivity.instance?.addRecord(it)
|
||||
influx add it
|
||||
}
|
||||
catch (e: Exception) {
|
||||
MainActivity.instance?.addRecord(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startForeground()
|
||||
{
|
||||
val notificationIntent = Intent(this, MainActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(this, 0,
|
||||
notificationIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
startForeground(NOTIF_ID, NotificationCompat.Builder(this, NOTIF_CHANNEL_ID)
|
||||
.setOngoing(true)
|
||||
.setSmallIcon(R.drawable.ic_watch_24)
|
||||
.setContentTitle("🐱 Running!")
|
||||
.setContentIntent(pendingIntent)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
companion object
|
||||
{
|
||||
private const val NOTIF_ID = 1
|
||||
const val NOTIF_CHANNEL_ID = "Channel_Id"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user