Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RMET-1203 Delete background job Android implementation #51

Merged
merged 4 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class OSHealthFitness : CordovaImplementation() {
"setBackgroundJob" -> {
setBackgroundJob(args)
}
"deleteBackgroundJob" -> {
deleteBackgroundJob(args)
}
"listBackgroundJobs" -> {
listBackgroundJobs()
}
Expand All @@ -70,7 +73,6 @@ class OSHealthFitness : CordovaImplementation() {

//create array of permission oauth
private fun initAndRequestPermissions(args : JSONArray) {

val customPermissions = args.getString(0)
val allVariables = args.getString(1)
val fitnessVariables = args.getString(2)
Expand All @@ -91,7 +93,6 @@ class OSHealthFitness : CordovaImplementation() {
catch (hse : HealthStoreException) {
sendPluginResult(null, Pair(hse.error.code, hse.error.message))
}

}

private fun areAndroidPermissionsGranted(permissions: List<String>): Boolean {
Expand Down Expand Up @@ -191,6 +192,19 @@ class OSHealthFitness : CordovaImplementation() {
)
}

private fun deleteBackgroundJob(args: JSONArray) {
val parameters = args.getString(0)
healthStore?.deleteBackgroundJob(
parameters,
{ response ->
sendPluginResult(response)
},
{ error ->
sendPluginResult(null, Pair(error.code, error.message))
}
)
}

private fun listBackgroundJobs() {
healthStore?.listBackgroundJobs(
{ response ->
Expand All @@ -212,7 +226,6 @@ class OSHealthFitness : CordovaImplementation() {
val error = hse.error
sendPluginResult(null, Pair(error.code, error.message))
}

}

override fun areGooglePlayServicesAvailable(): Boolean {
Expand All @@ -236,8 +249,7 @@ class OSHealthFitness : CordovaImplementation() {
override fun onRequestPermissionResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
grantResults: IntArray) {
when (requestCode) {
ACTIVITY_LOCATION_PERMISSIONS_REQUEST_CODE -> {
// If request is cancelled, the result arrays are empty.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ enum class HealthFitnessError(val code: Int, val message: String) {
WRITE_DATA_ERROR(104, "Error while writing data."),
BACKGROUND_JOB_ALREADY_EXISTS_ERROR(105, "The background job you are trying to set already exists."),
BACKGROUND_JOB_GENERIC_ERROR(106, "The background job could not be created."),
BACKGROUND_JOB_DOES_NOT_EXISTS_ERROR(107, "The background job could not be found."),
UNSUBSCRIBE_ERROR(107, "The background job could not be deleted"),
LIST_BACKGROUND_JOBS_GENERIC_ERROR(107, "The list of background jobs could not be fetched."),


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.outsystems.plugins.healthfitnesslib.background.database.BackgroundJob
Expand Down Expand Up @@ -56,7 +57,7 @@ class VariableUpdateService : BroadcastReceiver() {
val currentTimestamp = System.currentTimeMillis()
val nextNotificationTimestamp = job.nextNotificationTimestamp

if(currentTimestamp >= nextNotificationTimestamp || job.notificationFrequency == "ALWAYS") {
if(job.isActive && (currentTimestamp >= nextNotificationTimestamp || job.notificationFrequency == "ALWAYS")) {

val nextNotificationCalendar = Calendar.getInstance()
nextNotificationCalendar.timeInMillis = currentTimestamp
Expand Down Expand Up @@ -140,6 +141,7 @@ class VariableUpdateService : BroadcastReceiver() {
}
},
{ error ->
Log.e("Err", error.message)
//TODO: What should we do with errors?
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ abstract class AppDatabase : RoomDatabase() {
"ADD COLUMN next_notification_timestamp INTEGER NOT NULL DEFAULT 0")
database.execSQL(
"ALTER TABLE ${BackgroundJob.TABLE_NAME} " +
"ADD COLUMN active INTEGER NOT NULL DEFAULT 1")
"ADD COLUMN isActive INTEGER NOT NULL DEFAULT 1")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ open class BackgroundJob {

enum class ComparisonOperationEnum(val id : String) {
GREATER("HIGHER"),
GREATER_OR_EQUALS("HIGHER_EQUALS"),
GREATER_OR_EQUALS("HIGHER_EQUAL"),
LESSER("LOWER"),
LESSER_OR_EQUALS("LOWER_EQUALS"),
EQUALS("EQUALS"),
LESSER_OR_EQUALS("LOWER_EQUAL"),
EQUALS("EQUAL"),
}

@ColumnInfo(name = "variable") var variable: String = ""
Expand All @@ -44,7 +44,7 @@ open class BackgroundJob {
@ColumnInfo(name = "notification_frequency") var notificationFrequency: String = "ALWAYS"
@ColumnInfo(name = "notification_frequency_grouping") var notificationFrequencyGrouping: Int = 1
@ColumnInfo(name = "next_notification_timestamp") var nextNotificationTimestamp: Long = 0
@ColumnInfo(name = "active") var active: Boolean = true
@ColumnInfo(name = "isActive") var isActive: Boolean = true

@Ignore
var id: String = ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ interface BackgroundJobDao {
@Query("SELECT * FROM ${BackgroundJob.TABLE_NAME}")
fun getAll(): List<BackgroundJob>

//@Query("SELECT * FROM backgroundJob WHERE variable = :variable AND comparison = :comparison AND value = :value")
//fun findByPrimaryKey(variable: String, comparison: String, value: Float)
@Query("SELECT COUNT(*) FROM ${BackgroundJob.TABLE_NAME} WHERE variable = :name")
fun getBackgroundJobCountForVariable(name : String): Int

@Query("SELECT * FROM ${BackgroundJob.TABLE_NAME} WHERE variable = :variable AND comparison = :comparison AND value = :value")
fun findByPrimaryKey(variable: String, comparison: String, value: Float): BackgroundJob?

@Query("SELECT * FROM ${BackgroundJob.TABLE_NAME} WHERE variable = :name")
fun findByVariableName(name : String): List<BackgroundJob>

@Insert
fun insert(backgroundJob: BackgroundJob) : Long
fun insert(backgroundJob: BackgroundJob): Long

@Delete
fun delete(backgroundJob: BackgroundJob)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,27 @@ class DatabaseManager(context : Context) : DatabaseManagerInterface {
return notificationDao?.getAll()
}

override fun fetchBackgroundJobs(variable : String) : List<BackgroundJob>? {
override fun fetchBackgroundJob(variable: String, comparison: String, value: Float) : BackgroundJob? {
return backgroundJobDao?.findByPrimaryKey(variable, comparison, value)
}

override fun fetchBackgroundJobCountForVariable(variable: String) : Int {
return backgroundJobDao?.getBackgroundJobCountForVariable(variable) ?: 0
}

override fun fetchBackgroundJobs(variable: String) : List<BackgroundJob>? {
return backgroundJobDao?.findByVariableName(variable)
}

override fun fetchBackgroundJobs() : List<BackgroundJob>? {
return backgroundJobDao?.getAll()
}

//fun fetchBackgroundJob(variable: String, comparison: String, value: Float) {
// return backgroundJobDao?.findByPrimaryKey(variable, comparison, value)
//}

override fun fetchNotification(id : Long) : Notification? {
return notificationDao?.findById(id)?.first()
}

override fun deleteBackgroundJob(backgroundJob : BackgroundJob) {
override fun deleteBackgroundJob(backgroundJob: BackgroundJob) {
backgroundJobDao?.delete(backgroundJob)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ interface DatabaseManagerInterface {
fun insert(notification: Notification) : Long?
fun fetchNotifications() : List<Notification>?
fun fetchBackgroundJobs(variable : String) : List<BackgroundJob>?
fun fetchBackgroundJob(variable: String, comparison: String, value: Float) : BackgroundJob?
fun fetchBackgroundJobCountForVariable(variable: String) : Int
fun fetchBackgroundJobs() : List<BackgroundJob>?
fun fetchNotification(id : Long) : Notification?
fun deleteBackgroundJob(backgroundJob : BackgroundJob)
fun deleteBackgroundJob(backgroundJob: BackgroundJob)
fun updateBackgroundJob(backgroundJob: BackgroundJob)
fun runInTransaction(closude : () -> Unit)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.fitness.Fitness
import com.google.android.gms.fitness.FitnessOptions
import com.google.android.gms.fitness.HistoryClient
import com.google.android.gms.fitness.data.DataSet
import com.google.android.gms.fitness.data.DataSource
import com.google.android.gms.fitness.request.DataUpdateListenerRegistrationRequest
import com.google.android.gms.fitness.request.SensorRequest
import com.google.android.gms.fitness.result.DataReadResponse
import com.google.android.gms.fitness.result.SessionReadResponse
import com.google.android.gms.tasks.Tasks.await
import com.outsystems.plugins.healthfitness.HealthFitnessError
import com.outsystems.plugins.healthfitnesslib.background.BackgroundJobParameters
import com.outsystems.plugins.healthfitnesslib.background.VariableUpdateService
import kotlinx.coroutines.awaitAll
import java.util.concurrent.TimeUnit

class HealthFitnessManager(var context : Context, var activity : Activity? = null): HealthFitnessManagerInterface {
Expand Down Expand Up @@ -139,6 +142,45 @@ class HealthFitnessManager(var context : Context, var activity : Activity? = nul
}
}

override fun unsubscribeFromAllUpdates(variable: GoogleFitVariable,
variableName : String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit) {

val account = getLastAccount()
if(account == null){
onFailure(HealthStoreException(HealthFitnessError.VARIABLE_NOT_AUTHORIZED_ERROR))
return
}

val request = getSubscritionPendingIntent(variableName)
val dataSource = DataSource.Builder()
.setDataType(variable.dataType)
.setType(DataSource.TYPE_RAW)
.build()

var success = true
await(Fitness.getRecordingClient(context, account)
.unsubscribe(dataSource)
.addOnFailureListener { success = false })

await(Fitness.getSensorsClient(context, account)
.remove(request)
.addOnFailureListener { success = false })

await(Fitness.getHistoryClient(context, account)
.unregisterDataUpdateListener(request)
.addOnFailureListener { success = false })

if(success){
onSuccess()
}
else {
onFailure(HealthStoreException(HealthFitnessError.BACKGROUND_JOB_GENERIC_ERROR))
}

}

private fun areGoogleFitPermissionsGranted(account : GoogleSignInAccount?, options: FitnessOptions?): Boolean {
account.let {
options.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,10 @@ interface HealthFitnessManagerInterface {
variableName: String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit)

fun unsubscribeFromAllUpdates(variable: GoogleFitVariable,
variableName : String,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit)
}

Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ enum class EnumTimeUnit(val value : Pair<String, TimeUnit>) {
MONTH(Pair("MONTH", TimeUnit.DAYS)),
YEAR(Pair("YEAR", TimeUnit.DAYS))
}

enum class EnumJobFrequency(val value : String) {
IMMEDIATE("IMMEDIATE"),
HOUR("HOUR"),
Expand Down Expand Up @@ -742,8 +741,55 @@ class HealthStore(
//maybe throw an error because variable is not a sensorVariable nor a historyVariable??
}
}

fun deleteBackgroundJob(jogId: String,
onSuccess : (String) -> Unit,
onError : (HealthFitnessError) -> Unit) {

val parameters = jogId.split("-")
val variableName: String
val comparison: String
val value: Float
val variable: GoogleFitVariable

try {
variableName = parameters[0]
comparison = parameters[1]
value = parameters[2].toFloat()
variable = getVariableByName(variableName)!!
}
catch(e: Exception) {
onError(HealthFitnessError.BACKGROUND_JOB_DOES_NOT_EXISTS_ERROR)
return
}

runBlocking {
launch(Dispatchers.IO) {

val job = database.fetchBackgroundJob(variableName, comparison, value)
if(job != null) {
database.deleteBackgroundJob(job)
val jobCount = database.fetchBackgroundJobCountForVariable(variableName)
if(jobCount == 0) {
manager.unsubscribeFromAllUpdates(
variable,
variableName,
onSuccess = {
onSuccess("success")
},
onFailure = {
onError(HealthFitnessError.UNSUBSCRIBE_ERROR)
})
}
}
else {
onError(HealthFitnessError.BACKGROUND_JOB_DOES_NOT_EXISTS_ERROR)
}
}
}
}

fun listBackgroundJobs(onSuccess : (BackgroundJobsResponse) -> Unit,
fun listBackgroundJobs(onSuccess : (BackgroundJobsResponse) -> Unit,
onError: (HealthFitnessError) -> Unit){

try {
Expand Down Expand Up @@ -775,7 +821,7 @@ class HealthStore(
}
return responseJobList
}

companion object {
const val GOOGLE_FIT_PERMISSIONS_REQUEST_CODE = 2
}
Expand Down
4 changes: 4 additions & 0 deletions www/OSHealthFitness.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ exports.setBackgroundJob = function (success, error, params) {
exec(success, error, 'OSHealthFitness', 'setBackgroundJob', [params]);
};

exports.deleteBackgroundJob = function (success, error, params) {
exec(success, error, 'OSHealthFitness', 'deleteBackgroundJob', [params]);
};

exports.listBackgroundJobs = function (success, error) {
exec(success, error, 'OSHealthFitness', 'listBackgroundJobs');
};