Use sqlite in Android code for alarm settings

Closes #129
This commit is contained in:
Brandon Presley 2023-01-02 18:54:35 +13:00
parent bafdecd3e3
commit a2721e9f12
6 changed files with 65 additions and 45 deletions

View File

@ -52,9 +52,7 @@ export default function EditSet() {
const first = await setRepo.findOne({where: {name: value}}) const first = await setRepo.findOne({where: {name: value}})
const milliseconds = const milliseconds =
(first?.minutes ?? 3) * 60 * 1000 + (first?.seconds ?? 0) * 1000 (first?.minutes ?? 3) * 60 * 1000 + (first?.seconds ?? 0) * 1000
const {vibrate, sound, noSound} = settings NativeModules.AlarmModule.timer(milliseconds)
const args = [milliseconds, vibrate, sound, noSound]
NativeModules.AlarmModule.timer(...args)
}, },
[settings], [settings],
) )

View File

@ -100,9 +100,7 @@ export default function StartPlan() {
if (!settings.alarm) return if (!settings.alarm) return
const milliseconds = const milliseconds =
Number(best.minutes) * 60 * 1000 + Number(best.seconds) * 1000 Number(best.minutes) * 60 * 1000 + Number(best.seconds) * 1000
const {vibrate, sound, noSound} = settings NativeModules.AlarmModule.timer(milliseconds)
const args = [milliseconds, vibrate, sound, noSound]
NativeModules.AlarmModule.timer(...args)
} }
return ( return (

View File

@ -32,8 +32,7 @@ export default function TimerPage() {
const add = async () => { const add = async () => {
console.log(`${TimerPage.name}.add:`, settings) console.log(`${TimerPage.name}.add:`, settings)
const params = [settings.vibrate, settings.sound, settings.noSound] NativeModules.AlarmModule.add()
NativeModules.AlarmModule.add(...params)
} }
const progress = useMemo(() => { const progress = useMemo(() => {

View File

@ -19,7 +19,7 @@ import kotlin.math.floor
class AlarmModule constructor(context: ReactApplicationContext?) : class AlarmModule constructor(context: ReactApplicationContext?) :
ReactContextBaseJavaModule(context) { ReactContextBaseJavaModule(context) {
var countdownTimer: CountDownTimer? = null private var countdownTimer: CountDownTimer? = null
var currentMs: Long = 0 var currentMs: Long = 0
var running = false var running = false
@ -38,11 +38,7 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
private val addReceiver = object : BroadcastReceiver() { private val addReceiver = object : BroadcastReceiver() {
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
val vibrate = intent?.extras?.getBoolean("vibrate") == true add()
val sound = intent?.extras?.getString("sound")
val noSound = intent?.extras?.getBoolean("noSound") == true
Log.d("AlarmModule", "vibrate=$vibrate,sound=$sound,noSound=$noSound")
add(vibrate, sound, noSound)
} }
} }
@ -59,11 +55,11 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
@ReactMethod @ReactMethod
fun add(vibrate: Boolean, sound: String?, noSound: Boolean = false) { fun add() {
Log.d("AlarmModule", "Add 1 min to alarm.") Log.d("AlarmModule", "Add 1 min to alarm.")
countdownTimer?.cancel() countdownTimer?.cancel()
val newMs = if (running) currentMs.toInt().plus(60000) else 60000 val newMs = if (running) currentMs.toInt().plus(60000) else 60000
countdownTimer = getTimer(newMs, vibrate, sound, noSound) countdownTimer = getTimer(newMs)
countdownTimer?.start() countdownTimer?.start()
running = true running = true
val manager = getManager() val manager = getManager()
@ -94,14 +90,14 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
@ReactMethod @ReactMethod
fun timer(milliseconds: Int, vibrate: Boolean, sound: String?, noSound: Boolean = false) { fun timer(milliseconds: Int) {
Log.d("AlarmModule", "Queue alarm for $milliseconds delay") Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
val manager = getManager() val manager = getManager()
manager.cancel(NOTIFICATION_ID_DONE) manager.cancel(NOTIFICATION_ID_DONE)
val intent = Intent(reactApplicationContext, AlarmService::class.java) val intent = Intent(reactApplicationContext, AlarmService::class.java)
reactApplicationContext.stopService(intent) reactApplicationContext.stopService(intent)
countdownTimer?.cancel() countdownTimer?.cancel()
countdownTimer = getTimer(milliseconds, vibrate, sound, noSound) countdownTimer = getTimer(milliseconds)
countdownTimer?.start() countdownTimer?.start()
running = true running = true
} }
@ -109,11 +105,8 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
@RequiresApi(Build.VERSION_CODES.M) @RequiresApi(Build.VERSION_CODES.M)
private fun getTimer( private fun getTimer(
endMs: Int, endMs: Int,
vibrate: Boolean,
sound: String?,
noSound: Boolean
): CountDownTimer { ): CountDownTimer {
val builder = getBuilder(vibrate, sound, noSound) val builder = getBuilder()
return object : CountDownTimer(endMs.toLong(), 1000) { return object : CountDownTimer(endMs.toLong(), 1000) {
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
override fun onTick(current: Long) { override fun onTick(current: Long) {
@ -156,12 +149,7 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
val manager = getManager() val manager = getManager()
manager.notify(NOTIFICATION_ID_DONE, builder.build()) manager.notify(NOTIFICATION_ID_DONE, builder.build())
manager.cancel(NOTIFICATION_ID_PENDING) manager.cancel(NOTIFICATION_ID_PENDING)
Log.d("AlarmModule", "Finished: vibrate=$vibrate,sound=$sound,noSound=$noSound") val alarmIntent = Intent(context, AlarmService::class.java)
val alarmIntent = Intent(context, AlarmService::class.java).apply {
putExtra("vibrate", vibrate)
putExtra("sound", sound)
putExtra("noSound", noSound)
}
context.startService(alarmIntent) context.startService(alarmIntent)
reactApplicationContext reactApplicationContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
@ -175,20 +163,13 @@ class AlarmModule constructor(context: ReactApplicationContext?) :
@SuppressLint("UnspecifiedImmutableFlag") @SuppressLint("UnspecifiedImmutableFlag")
@RequiresApi(Build.VERSION_CODES.M) @RequiresApi(Build.VERSION_CODES.M)
private fun getBuilder( private fun getBuilder(): NotificationCompat.Builder {
vibrate: Boolean,
sound: String?,
noSound: Boolean
): NotificationCompat.Builder {
val context = reactApplicationContext val context = reactApplicationContext
val contentIntent = Intent(context, MainActivity::class.java) val contentIntent = Intent(context, MainActivity::class.java)
val pendingContent = val pendingContent =
PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE) PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE)
val addBroadcast = Intent(ADD_BROADCAST).apply { val addBroadcast = Intent(ADD_BROADCAST).apply {
setPackage(reactApplicationContext.packageName) setPackage(reactApplicationContext.packageName)
putExtra("vibrate", vibrate)
putExtra("sound", sound)
putExtra("noSound", noSound)
} }
val pendingAdd = val pendingAdd =
PendingIntent.getBroadcast(context, 0, addBroadcast, PendingIntent.FLAG_MUTABLE) PendingIntent.getBroadcast(context, 0, addBroadcast, PendingIntent.FLAG_MUTABLE)

View File

@ -1,27 +1,44 @@
package com.massive package com.massive
import android.annotation.SuppressLint
import android.app.Service import android.app.Service
import android.content.Context import android.content.Context
import android.media.MediaPlayer.OnPreparedListener
import android.media.MediaPlayer
import androidx.annotation.RequiresApi
import android.content.Intent import android.content.Intent
import android.media.AudioAttributes import android.media.AudioAttributes
import android.media.MediaPlayer
import android.media.MediaPlayer.OnPreparedListener
import android.net.Uri import android.net.Uri
import android.os.* import android.os.*
import android.util.Log
import androidx.annotation.RequiresApi
class AlarmService : Service(), OnPreparedListener { class AlarmService : Service(), OnPreparedListener {
var mediaPlayer: MediaPlayer? = null private var mediaPlayer: MediaPlayer? = null
private var vibrator: Vibrator? = null private var vibrator: Vibrator? = null
@SuppressLint("Recycle")
@RequiresApi(api = Build.VERSION_CODES.O) @RequiresApi(api = Build.VERSION_CODES.O)
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (intent.action == "stop") { if (intent.action == "stop") {
onDestroy() onDestroy()
return START_STICKY return START_STICKY
} }
val sound = intent.extras?.getString("sound")
val noSound = intent.extras?.getBoolean("noSound") == true val db = DatabaseHelper(applicationContext).readableDatabase
val sound = db.rawQuery("SELECT sound FROM settings", null)
.let {
it.moveToFirst()
it.getString(0)
}
Log.d("AlarmService", "sound=$sound")
val noSound = db.rawQuery("SELECT noSound FROM settings", null)
.let {
it.moveToFirst()
it.getInt(0) == 1
}
Log.d("AlarmService", "noSound=$noSound")
if (sound == null && !noSound) { if (sound == null && !noSound) {
mediaPlayer = MediaPlayer.create(applicationContext, R.raw.argon) mediaPlayer = MediaPlayer.create(applicationContext, R.raw.argon)
@ -42,6 +59,13 @@ class AlarmService : Service(), OnPreparedListener {
} }
} }
val vibrate = db.rawQuery("SELECT vibrate FROM settings", null)
.let {
it.moveToFirst()
it.getInt(0) == 1
}
if (!vibrate) return START_STICKY
val pattern = longArrayOf(0, 300, 1300, 300, 1300, 300) val pattern = longArrayOf(0, 300, 1300, 300, 1300, 300)
vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager = val vibratorManager =
@ -55,9 +79,7 @@ class AlarmService : Service(), OnPreparedListener {
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM) .setUsage(AudioAttributes.USAGE_ALARM)
.build() .build()
val vibrate = intent.extras!!.getBoolean("vibrate") vibrator!!.vibrate(VibrationEffect.createWaveform(pattern, 1), audioAttributes)
if (vibrate)
vibrator!!.vibrate(VibrationEffect.createWaveform(pattern, 1), audioAttributes)
return START_STICKY return START_STICKY
} }

View File

@ -0,0 +1,22 @@
package com.massive
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
class DatabaseHelper(context: Context) :
SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
companion object {
private const val DATABASE_NAME = "massive.db"
private const val DATABASE_VERSION = 1
}
override fun onCreate(db: SQLiteDatabase) {
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
}
override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
}
}