Make notifications work

hh
Laurent 6 years ago
parent ec71899630
commit c5ba4da06c
  1. 4
      app/build.gradle
  2. 9
      app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt
  3. 28
      app/src/main/java/net/pokeranalytics/android/ui/modules/session/SessionFragment.kt
  4. 7
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/SettingRow.kt
  5. 84
      app/src/main/java/net/pokeranalytics/android/util/NotificationScheduling.kt
  6. 4
      app/src/main/java/net/pokeranalytics/android/util/Preferences.kt
  7. 2
      app/src/main/res/values-fr/strings.xml
  8. 2
      app/src/main/res/values/strings.xml

@ -104,6 +104,7 @@ dependencies {
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
implementation 'androidx.work:work-runtime-ktx:2.3.4'
// Places
implementation 'com.google.android.libraries.places:places:1.1.0'
@ -142,5 +143,8 @@ dependencies {
testImplementation 'com.android.support.test:runner:1.0.2'
testImplementation 'com.android.support.test:rules:1.0.2'
// gross, somehow needed to make the stop notif work
implementation 'com.google.guava:guava:27.0.1-android'
}

@ -76,14 +76,9 @@ class PokerAnalyticsApplication : Application() {
if (BuildConfig.DEBUG) {
Timber.d("UserPreferences.defaultCurrency: ${UserDefaults.currency.symbol}")
// this.createFakeSessions()
this.createFakeSessions()
}
// CashGameOptimalDurationCalculator.start(true) {
// val hours = it / 3600 / 1000
// Timber.d("Optimal duration = ${it}, $hours")
// }
Patcher.patchAll(this.applicationContext)
val locale = Locale.getDefault()
@ -102,7 +97,7 @@ class PokerAnalyticsApplication : Application() {
if (sessionsCount < 10) {
GlobalScope.launch {
FakeDataManager.createFakeSessions(400)
FakeDataManager.createFakeSessions(500)
}
}

@ -9,6 +9,9 @@ import androidx.appcompat.app.AlertDialog
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.DiffUtil
import androidx.work.Data
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.crashlytics.android.Crashlytics
import kotlinx.android.synthetic.main.fragment_session.*
import kotlinx.coroutines.Dispatchers
@ -38,12 +41,14 @@ import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentableDiffCallback
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.ui.view.rowrepresentable.SessionRow
import net.pokeranalytics.android.util.NotificationSchedule
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.extensions.findById
import net.pokeranalytics.android.util.extensions.formattedHourlyDuration
import net.pokeranalytics.android.util.extensions.getNextMinuteInMilliseconds
import timber.log.Timber
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
@ -395,7 +400,10 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate {
if (!isDetached) {
optimalDuration?.let {
// TODO setup a notification
val delay = 1000L // it.toLong()
scheduleNotification(delay, "stop notif tag")
val formattedDuration = (it / 3600 / 1000).formattedHourlyDuration()
Timber.d("Setting stop notification in: $formattedDuration")
val message = requireContext().getString(R.string.stop_notification_in_, formattedDuration)
@ -406,6 +414,24 @@ class SessionFragment : RealmFragment(), RowRepresentableDelegate {
}
private fun scheduleNotification(timeDelay: Long, tag: String) {
val title = requireContext().getString(R.string.stop_notification_title)
val body = requireContext().getString(R.string.stop_notification_body)
val data = Data.Builder()
.putString(NotificationSchedule.ParamKeys.TITLE.value, title)
.putString(NotificationSchedule.ParamKeys.BODY.value, body)
val work = OneTimeWorkRequestBuilder<NotificationSchedule>()
.setInitialDelay(timeDelay, TimeUnit.MILLISECONDS)
.setInputData(data.build())
.addTag(tag)
.build()
WorkManager.getInstance().enqueue(work)
}
/**
* Stop the current session
*/

@ -1,5 +1,6 @@
package net.pokeranalytics.android.ui.view.rowrepresentable
import android.os.Build
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.ui.view.RowRepresentable
@ -63,8 +64,10 @@ enum class SettingRow : RowRepresentable {
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.reports))
rows.addAll(arrayListOf(BANKROLL_REPORT, TOP_10, PLAYERS))
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.cash_game))
rows.addAll(arrayListOf(STOP_NOTIFICATION, STOP_NOTIFICATION_MESSAGE))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // notif mechanism requires 26+
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.cash_game))
rows.addAll(arrayListOf(STOP_NOTIFICATION, STOP_NOTIFICATION_MESSAGE))
}
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.information))
rows.addAll(arrayListOf(SUBSCRIPTION, VERSION, RATE_APP, CONTACT_US, BUG_REPORT, DISCORD))

@ -0,0 +1,84 @@
package net.pokeranalytics.android.util
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.Color
import android.media.RingtoneManager
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.work.Worker
import androidx.work.WorkerParameters
import net.pokeranalytics.android.R
import timber.log.Timber
import java.util.*
class NotificationSchedule(var context: Context, var params: WorkerParameters) : Worker(context, params) {
enum class ParamKeys(val value: String) {
TITLE("title"),
BODY("body")
}
override fun doWork(): Result {
val data = params.inputData
val title = data.getString(ParamKeys.TITLE.value)
val body = data.getString(ParamKeys.BODY.value)
if (title != null && body != null) {
TriggerNotification(context, title, body)
} else {
Timber.d("Missing title and or title for notification")
}
return Result.success()
}
}
class TriggerNotification(context: Context, title: String, body: String) {
init {
sendNotification(context, title, body)
}
private fun createNotificationChannel(context: Context, name: String, description: String): String {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
val channelId = UUID.randomUUID().toString()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(channelId, name, importance)
channel.enableLights(true)
channel.enableVibration(true)
channel.description = description
channel.lightColor = Color.GREEN
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
val notificationManager = context.getSystemService(NotificationManager::class.java)
notificationManager?.createNotificationChannel(channel)
}
return channelId
}
private fun sendNotification(context: Context, title: String, body: String) {
val notificationManager = NotificationManagerCompat.from(context)
val mBuilder = NotificationCompat.Builder(context, createNotificationChannel(context, title, body))
val notificationId = (System.currentTimeMillis() and 0xfffffff).toInt()
mBuilder.setDefaults(Notification.DEFAULT_ALL)
.setContentTitle(title)
.setContentText(body)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSmallIcon(R.drawable.release_note_icon)
// .setContentInfo("Content Info")
.setAutoCancel(true)
notificationManager.notify(notificationId, mBuilder.build())
}
}

@ -1,6 +1,7 @@
package net.pokeranalytics.android.util
import android.content.Context
import android.os.Build
import android.preference.PreferenceManager
import android.view.View
import io.realm.Realm
@ -152,7 +153,8 @@ class Preferences {
}
fun showStopNotifications(context: Context): Boolean {
return getBoolean(Keys.SHOW_STOP_NOTIFICATIONS, context, true)
val defaultValue = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
return getBoolean(Keys.SHOW_STOP_NOTIFICATIONS, context, defaultValue)
}
fun setStopShowingMessage(message: FeedMessage, context: Context) {

@ -651,7 +651,7 @@
<string name="releasenote_invitation">Dites nous ce que vous en pensez</string>
<string name="releasenote_rating">Notez-nous !</string>
<string name="no_thanks">Non merci</string>
<string name="stop_notification_body">D\'après votre historique, il apparait que vous commencez à fatiguer. Il est peut-être temps de s\'arrêter!</string>
<string name="stop_notification_body">D\'après votre historique, il est peut-être temps de s\'arrêter!</string>
<string name="stop_notification_title">C\'est l\'heure!</string>
<string name="stop_notifications">Notifications d\'arrêt</string>
<string name="stop_notification_in_">Une notification d\'arrêt sera envoyée dans %s</string>

@ -645,7 +645,7 @@
<string name="releasenote_rating">Rate us!</string>
<string name="no_thanks">No thanks</string>
<string name="stop_notification_title">It\'s time!</string>
<string name="stop_notification_body">Based on your history, it looks like your start to fatigue. It might be time to stop!</string>
<string name="stop_notification_body">You might want to stop the session now!</string>
<string name="stop_notifications">Stop notifications</string>
<string name="stop_notification_in_">A stop notification has been set in %s</string>
<string name="save_authorize">Save &amp; authorize</string>

Loading…
Cancel
Save