oh foreground worker and some edgecases

This commit is contained in:
Geoffrey Hansen 2020-09-03 19:39:43 +02:00
parent 8a6a3d2283
commit ae980e12f4
5 changed files with 68 additions and 15 deletions

View file

@ -1,12 +1,19 @@
package info.nightscout.androidaps.plugins.general.openhumans
import android.app.Notification
import android.content.Context
import android.net.wifi.WifiManager
import androidx.core.app.NotificationCompat
import androidx.work.ForegroundInfo
import androidx.work.RxWorker
import androidx.work.WorkerParameters
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader.Companion.NOTIFICATION_CHANNEL
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader.Companion.UPLOAD_NOTIFICATION_ID
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.Single
import java.util.concurrent.TimeUnit
import javax.inject.Inject
class OHUploadWorker(context: Context, workerParameters: WorkerParameters)
@ -18,6 +25,9 @@ class OHUploadWorker(context: Context, workerParameters: WorkerParameters)
@Inject
lateinit var openHumansUploader: OpenHumansUploader
@Inject
lateinit var resourceHelper: ResourceHelper
override fun createWork(): Single<Result> = Single.defer {
// Here we inject every time we create work
@ -31,7 +41,8 @@ class OHUploadWorker(context: Context, workerParameters: WorkerParameters)
val wifiOnly = sp.getBoolean("key_oh_wifi_only", true)
val isConnectedToWifi = wifiManager?.isWifiEnabled ?: false && wifiManager?.connectionInfo?.networkId != -1
if (!wifiOnly || (wifiOnly && isConnectedToWifi)) {
openHumansUploader.uploadData()
setForegroundAsync(createForegroundInfo())
openHumansUploader.uploadData().delay(12, TimeUnit.MINUTES) //TODO OH: No Delay
.andThen(Single.just(Result.success()))
.onErrorResumeNext { Single.just(Result.retry()) }
} else {
@ -39,4 +50,17 @@ class OHUploadWorker(context: Context, workerParameters: WorkerParameters)
}
}
private fun createForegroundInfo(): ForegroundInfo {
val title = resourceHelper.gs(info.nightscout.androidaps.R.string.open_humans)
val notification: Notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL)
.setContentTitle(title)
.setTicker(title)
.setContentTitle(resourceHelper.gs(info.nightscout.androidaps.R.string.open_humans))
.setSmallIcon(info.nightscout.androidaps.R.drawable.notif_icon)
.setOngoing(true)
.build()
return ForegroundInfo(UPLOAD_NOTIFICATION_ID, notification)
}
}

View file

@ -7,7 +7,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.work.WorkInfo
import androidx.work.WorkManager
@ -16,7 +15,9 @@ import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
@ -40,6 +41,9 @@ class OpenHumansFragment : DaggerFragment() {
@Inject
lateinit var openHumansUploader: OpenHumansUploader
@Inject
lateinit var resourceHelper: ResourceHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
compositeDisposable += rxBus.toObservable(UpdateQueueEvent::class.java)
@ -85,7 +89,9 @@ class OpenHumansFragment : DaggerFragment() {
queueSize = view.findViewById(R.id.queue_size)
workerState = view.findViewById(R.id.worker_state)
login!!.setOnClickListener { startActivity(Intent(context, OpenHumansLoginActivity::class.java)) }
logout!!.setOnClickListener { openHumansUploader.logout() }
logout!!.setOnClickListener {
activity?.let { activity -> OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.oh_logout_confirmation), Runnable { openHumansUploader.logout() }) }
}
viewsCreated = true
updateGUI()
return view

View file

@ -24,6 +24,7 @@ import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
@ -53,7 +54,8 @@ class OpenHumansUploader @Inject constructor(
aapsLogger: AAPSLogger,
val sp: SP,
val rxBus: RxBusWrapper,
val context: Context
val context: Context,
val treatmentsPlugin: TreatmentsPlugin
) : PluginBase(
PluginDescription()
.mainType(PluginType.GENERAL)
@ -72,10 +74,12 @@ class OpenHumansUploader @Inject constructor(
private const val REDIRECT_URL = "androidaps://setup-openhumans"
const val AUTH_URL = "https://www.openhumans.org/direct-sharing/projects/oauth2/authorize/?client_id=$CLIENT_ID&response_type=code"
const val WORK_NAME = "Open Humans"
const val NOTIFICATION_CHANNEL = "OpenHumans"
private const val COPY_NOTIFICATION_ID = 3122
private const val FAILURE_NOTIFICATION_ID = 3123
private const val SUCCESS_NOTIFICATION_ID = 3124
private const val SIGNED_OUT_NOTIFICATION_ID = 3125
const val UPLOAD_NOTIFICATION_ID = 3126
}
private val openHumansAPI = OpenHumansAPI(OPEN_HUMANS_URL, CLIENT_ID, CLIENT_SECRET, REDIRECT_URL)
@ -323,7 +327,7 @@ class OpenHumansUploader @Inject constructor(
.flatMap { openHumansAPI.getProjectMemberId(it.accessToken) }
.doOnSuccess {
projectMemberId = it
// TODO: halted for now. Might create too much upload data. copyExistingDataToQueue()
copyExistingDataToQueue()
rxBus.send(OpenHumansFragment.UpdateViewEvent)
}
.doOnError {
@ -353,7 +357,10 @@ class OpenHumansUploader @Inject constructor(
copyDisposable = Completable.fromCallable { MainApp.getDbHelper().clearOpenHumansQueue() }
.andThen(Single.defer { Single.just(MainApp.getDbHelper().countOfAllRows) })
.doOnSuccess { maxProgress = it }
.flatMapObservable { Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allBgReadings) } }
.flatMapObservable { Observable.defer { Observable.fromIterable(treatmentsPlugin.service.treatmentData) } }
.map { enqueueTreatment(it); increaseCounter() }
.ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allBgReadings) })
.map { enqueueBGReading(it); increaseCounter() }
.ignoreElements()
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allCareportalEvents) })
@ -384,6 +391,7 @@ class OpenHumansUploader @Inject constructor(
showSetupFinishedNotification()
}
.doOnError {
logout()
showSetupFailedNotification()
}
.doFinally {
@ -397,7 +405,7 @@ class OpenHumansUploader @Inject constructor(
}
private fun showOngoingNotification(maxProgress: Long? = null, currentProgress: Long? = null) {
val notification = NotificationCompat.Builder(context, "OpenHumans")
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(resourceHelper.gs(R.string.finishing_open_humans_setup))
.setContentText(resourceHelper.gs(R.string.this_may_take_a_while))
.setStyle(NotificationCompat.BigTextStyle())
@ -411,9 +419,9 @@ class OpenHumansUploader @Inject constructor(
}
private fun showSetupFinishedNotification() {
val notification = NotificationCompat.Builder(context, "OpenHumans")
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(resourceHelper.gs(R.string.setup_finished))
.setContentText(resourceHelper.gs(R.string.your_phone_is_upload_data))
.setContentText(resourceHelper.gs(R.string.your_phone_will_upload_data))
.setStyle(NotificationCompat.BigTextStyle())
.setSmallIcon(R.drawable.notif_icon)
.build()
@ -422,7 +430,7 @@ class OpenHumansUploader @Inject constructor(
}
private fun showSetupFailedNotification() {
val notification = NotificationCompat.Builder(context, "OpenHumans")
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(resourceHelper.gs(R.string.setup_failed))
.setContentText(resourceHelper.gs(R.string.there_was_an_error))
.setStyle(NotificationCompat.BigTextStyle())
@ -559,7 +567,7 @@ class OpenHumansUploader @Inject constructor(
}
private fun handleSignOut() {
val notification = NotificationCompat.Builder(context, "OpenHumans")
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(resourceHelper.gs(R.string.you_have_been_signed_out_of_open_humans))
.setContentText(resourceHelper.gs(R.string.click_here_to_sign_in_again_if_this_wasnt_on_purpose))
.setStyle(NotificationCompat.BigTextStyle())
@ -587,9 +595,9 @@ class OpenHumansUploader @Inject constructor(
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresCharging(sp.getBoolean("key_oh_charging_only", false))
.build()
val workRequest = PeriodicWorkRequestBuilder<OHUploadWorker>(1, TimeUnit.DAYS)
val workRequest = PeriodicWorkRequestBuilder<OHUploadWorker>(1, TimeUnit.MINUTES) // TODO OH: DAYS
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.LINEAR, 1, TimeUnit.HOURS)
.setBackoffCriteria(BackoffPolicy.LINEAR, 1, TimeUnit.MINUTES) //TODO OH: HOURS
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(WORK_NAME, if (replace) ExistingPeriodicWorkPolicy.REPLACE else ExistingPeriodicWorkPolicy.KEEP, workRequest)
}
@ -598,7 +606,7 @@ class OpenHumansUploader @Inject constructor(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManagerCompat = NotificationManagerCompat.from(context)
notificationManagerCompat.createNotificationChannel(NotificationChannel(
"OpenHumans",
NOTIFICATION_CHANNEL,
resourceHelper.gs(R.string.open_humans),
NotificationManager.IMPORTANCE_DEFAULT
))

View file

@ -160,6 +160,10 @@ public class TreatmentService extends OrmLiteBaseService<DatabaseHelper> {
public List<Treatment> query(PreparedQuery<Treatment> data) throws SQLException {
return wrapped.query(data);
}
public long countOf() throws SQLException {
return wrapped.countOf();
}
}
@Override
@ -295,6 +299,15 @@ public class TreatmentService extends OrmLiteBaseService<DatabaseHelper> {
return new ArrayList<>();
}
public long count() {
try {
return this.getDao().countOf();
} catch (SQLException e) {
aapsLogger.error("Unhandled exception", e);
}
return 0L;
}
/*
{
"_id": "551ee3ad368e06e80856e6a9",

View file

@ -1411,13 +1411,15 @@
<string name="finishing_open_humans_setup">Finishing Open Humans setup…</string>
<string name="this_may_take_a_while">This may take a while. Do not turn your phone off.</string>
<string name="setup_finished">Setup finished</string>
<string name="your_phone_will_upload_data">Your phone will upload data to Open Humans soon.</string>
<string name="your_phone_is_upload_data">Your phone is uploading data to Open Humans now.</string>
<string name="setup_failed">Setup failed</string>
<string name="there_was_an_error">There was an error.</string>
<string name="there_was_an_error">There was an error. Please try to log in again in order to proceed. Sorry &amp; Thank you!</string>
<string name="open_humans_terms">This is an open source tool that will copy your data to Open Humans. We retain no rights to share your data with third parties without your explicit authorization. The data the project and app receive are identified via a random user ID and will only be securely transmitted to an Open Humans account with your authorization of that process. You can stop uploading and delete your upload data at any time via www.openhumans.org.</string>
<string name="i_understand_and_agree">I understand and agree.</string>
<string name="login">Login</string>
<string name="logout">Logout</string>
<string name="oh_logout_confirmation">Do you really want to log out and stop donating data to science?</string>
<string name="project_member_id">Project Member ID: %s</string>
<string name="queue_size">Queue Size: %d</string>
<string name="terms_of_use">Terms of Use</string>