diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 512f8bc..7e578f4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,9 @@ xmlns:tools="http://schemas.android.com/tools" package="io.github.z3r0c00l_2k.aquadroid"> + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..7e51852 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/InitUserInfoActivity.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/InitUserInfoActivity.kt index 7772b4b..8b58550 100644 --- a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/InitUserInfoActivity.kt +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/InitUserInfoActivity.kt @@ -11,6 +11,7 @@ import android.view.View import android.view.inputmethod.InputMethodManager import androidx.appcompat.app.AppCompatActivity import com.google.android.material.snackbar.Snackbar +import io.github.z3r0c00l_2k.aquadroid.utils.AppUtils import kotlinx.android.synthetic.main.activity_init_user_info.* import java.math.RoundingMode import java.text.DecimalFormat diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/MainActivity.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/MainActivity.kt index 3689a54..5832a78 100644 --- a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/MainActivity.kt +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/MainActivity.kt @@ -5,6 +5,10 @@ import android.content.SharedPreferences import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.google.android.material.snackbar.Snackbar +import io.github.z3r0c00l_2k.aquadroid.fragments.BottomSheetFragment +import io.github.z3r0c00l_2k.aquadroid.helpers.AlarmHelper +import io.github.z3r0c00l_2k.aquadroid.helpers.SqliteHelper +import io.github.z3r0c00l_2k.aquadroid.utils.AppUtils import kotlinx.android.synthetic.main.activity_main.* @@ -78,6 +82,11 @@ class MainActivity : AppCompatActivity() { } } + val alarm = AlarmHelper() + alarm.cancelAlarm(this) + alarm.setAlarm(this, sharedPref.getInt(AppUtils.NOTIFICATION_FREQUENCY_KEY, 30).toLong()) + + } private fun setWaterLevel(inTook: Int, totalIntake: Int) { diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/SplashActivity.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/SplashActivity.kt index d942d3f..d32067e 100644 --- a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/SplashActivity.kt +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/SplashActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.view.Window import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity +import io.github.z3r0c00l_2k.aquadroid.utils.AppUtils class SplashActivity : AppCompatActivity() { diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/BottomSheetFragment.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/fragments/BottomSheetFragment.kt similarity index 98% rename from app/src/main/java/io/github/z3r0c00l_2k/aquadroid/BottomSheetFragment.kt rename to app/src/main/java/io/github/z3r0c00l_2k/aquadroid/fragments/BottomSheetFragment.kt index 7ad8835..1ddc63c 100644 --- a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/BottomSheetFragment.kt +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/fragments/BottomSheetFragment.kt @@ -1,4 +1,4 @@ -package io.github.z3r0c00l_2k.aquadroid +package io.github.z3r0c00l_2k.aquadroid.fragments import android.app.TimePickerDialog import android.content.Context @@ -10,6 +10,8 @@ import android.view.View import android.view.ViewGroup import android.widget.Toast import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import io.github.z3r0c00l_2k.aquadroid.R +import io.github.z3r0c00l_2k.aquadroid.utils.AppUtils import kotlinx.android.synthetic.main.bottom_sheet_fragment.* import java.math.RoundingMode import java.text.DecimalFormat diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/AlarmHelper.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/AlarmHelper.kt new file mode 100644 index 0000000..60f471e --- /dev/null +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/AlarmHelper.kt @@ -0,0 +1,75 @@ +package io.github.z3r0c00l_2k.aquadroid.helpers + +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.util.Log +import io.github.z3r0c00l_2k.aquadroid.recievers.BootReceiver +import io.github.z3r0c00l_2k.aquadroid.recievers.NotifierReceiver +import java.util.concurrent.TimeUnit + +class AlarmHelper { + private var alarmManager: AlarmManager? = null + + private val ACTION_BD_NOTIFICATION = "io.github.z3r0c00l_2k.aquadroid.NOTIFICATION" + + fun setAlarm(context: Context, notificationFrequency: Long) { + val notificationFrequencyMs = TimeUnit.MINUTES.toMillis(notificationFrequency) + + alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + + val alarmIntent = Intent(context, NotifierReceiver::class.java) + alarmIntent.action = ACTION_BD_NOTIFICATION + + val pendingAlarmIntent = PendingIntent.getBroadcast( + context, + 0, + alarmIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ) + + Log.i("AlarmHelper", "Setting Alarm Interval to: $notificationFrequency minutes") + + alarmManager!!.setRepeating( + AlarmManager.RTC_WAKEUP, + System.currentTimeMillis(), + notificationFrequencyMs, + pendingAlarmIntent + ) + + /* Restart if rebooted */ + val receiver = ComponentName(context, BootReceiver::class.java) + context.packageManager.setComponentEnabledSetting( + receiver, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP + ) + } + + fun cancelAlarm(context: Context) { + alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + + val alarmIntent = Intent(context, NotifierReceiver::class.java) + alarmIntent.action = ACTION_BD_NOTIFICATION + + val pendingAlarmIntent = PendingIntent.getBroadcast( + context, + 0, + alarmIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ) + alarmManager!!.cancel(pendingAlarmIntent) + + /* Alarm won't start again if device is rebooted */ + val receiver = ComponentName(context, BootReceiver::class.java) + val pm = context.packageManager + pm.setComponentEnabledSetting( + receiver, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/NotificationHelper.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/NotificationHelper.kt new file mode 100644 index 0000000..f662991 --- /dev/null +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/NotificationHelper.kt @@ -0,0 +1,148 @@ +package io.github.z3r0c00l_2k.aquadroid.helpers + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.graphics.BitmapFactory +import android.graphics.Color +import android.media.AudioAttributes +import android.net.Uri +import android.os.Build +import android.preference.PreferenceManager +import android.util.Log +import io.github.z3r0c00l_2k.aquadroid.R +import io.github.z3r0c00l_2k.aquadroid.utils.AppUtils +import java.util.* + +class NotificationHelper(val ctx: Context) { + private var notificationManager: NotificationManager? = null + + private val CHANNEL_ONE_ID = "io.github.z3r0c00l_2k.aquadroid.CHANNELONE" + private val CHANNEL_ONE_NAME = "Channel One" + + + private fun createChannels() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val prefs = ctx.getSharedPreferences(AppUtils.USERS_SHARED_PREF, AppUtils.PRIVATE_MODE) + val notificationsNewMessageRingtone = prefs.getString("notifications_new_message_ringtone", "") + val notificationChannel = NotificationChannel( + CHANNEL_ONE_ID, + CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_HIGH + ) + notificationChannel.enableLights(true) + notificationChannel.lightColor = Color.BLUE + notificationChannel.setShowBadge(true) + notificationChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC + + if (notificationsNewMessageRingtone!!.isNotEmpty()) { + val audioAttributes = AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .setUsage(AudioAttributes.USAGE_NOTIFICATION) + .build() + notificationChannel.setSound(Uri.parse(notificationsNewMessageRingtone), audioAttributes) + } + + getManager()!!.createNotificationChannel(notificationChannel) + } + } + + fun getNotification( + title: String, + body: String + ): Notification.Builder { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return Notification.Builder(ctx.applicationContext, CHANNEL_ONE_ID) + .setContentTitle(title) + .setContentText(body) + .setColorized(true) + .setColor(Color.BLUE) + .setShowWhen(true) + .setLargeIcon( + BitmapFactory.decodeResource( + ctx.resources, + R.mipmap.ic_launcher + ) + ) + .setSmallIcon(R.drawable.ic_small_logo) + .setAutoCancel(true) + } else { + val prefs = PreferenceManager.getDefaultSharedPreferences(ctx) + val notificationsNewMessageRingtone = prefs.getString("notifications_new_message_ringtone", "") + + val notification = Notification.Builder(ctx.applicationContext) + .setContentTitle(title) + .setContentText(body) + .setLargeIcon( + BitmapFactory.decodeResource( + ctx.resources, + R.mipmap.ic_launcher + ) + ) + .setSmallIcon(R.drawable.ic_small_logo) + .setAutoCancel(true) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + notification.setShowWhen(true) + } + + if (notificationsNewMessageRingtone!!.length > 0) { + + notification.setSound(Uri.parse(notificationsNewMessageRingtone)) + } + return notification + } + } + + private fun shallNotify(): Boolean { + val prefs = ctx.getSharedPreferences(AppUtils.USERS_SHARED_PREF, AppUtils.PRIVATE_MODE) + + val notificationsNewMessage = prefs.getBoolean("notifications_new_message", true) + var doNotDisturbOff = true + + val startTimestamp = prefs.getLong("pref_notification_start", 0) + val stopTimestamp = prefs.getLong("pref_notification_stop", 0) + + if (startTimestamp > 0 && stopTimestamp > 0) { + val now = Calendar.getInstance().time + + val start = Date(startTimestamp) + val stop = Date(stopTimestamp) + + doNotDisturbOff = compareTimes(now, start) >= 0 && compareTimes(now, stop) <= 0 + } + + return notificationsNewMessage && doNotDisturbOff + } + + /* Thanks to: + * https://stackoverflow.com/questions/7676149/compare-only-the-time-portion-of-two-dates-ignoring-the-date-part + */ + private fun compareTimes(currentTime: Date, timeToRun: Date): Long { + val currentCal = Calendar.getInstance() + currentCal.time = currentTime + + val runCal = Calendar.getInstance() + runCal.time = timeToRun + runCal.set(Calendar.DAY_OF_MONTH, currentCal.get(Calendar.DAY_OF_MONTH)) + runCal.set(Calendar.MONTH, currentCal.get(Calendar.MONTH)) + runCal.set(Calendar.YEAR, currentCal.get(Calendar.YEAR)) + + return currentCal.timeInMillis - runCal.timeInMillis + } + + fun notify(id: Long, notification: Notification.Builder) { + if (shallNotify()) { + getManager()!!.notify(id.toInt(), notification.build()) + } else { + Log.i("WateryDroid", "dnd period") + } + } + + private fun getManager(): NotificationManager? { + if (notificationManager == null) { + notificationManager = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + } + return notificationManager + } +} diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/SqliteHelper.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/SqliteHelper.kt similarity index 93% rename from app/src/main/java/io/github/z3r0c00l_2k/aquadroid/SqliteHelper.kt rename to app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/SqliteHelper.kt index d7a7578..2cb8b1d 100644 --- a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/SqliteHelper.kt +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/helpers/SqliteHelper.kt @@ -1,11 +1,15 @@ -package io.github.z3r0c00l_2k.aquadroid +package io.github.z3r0c00l_2k.aquadroid.helpers import android.content.ContentValues import android.content.Context import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper -class SqliteHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { +class SqliteHelper(context: Context) : SQLiteOpenHelper( + context, + DATABASE_NAME, null, + DATABASE_VERSION +) { companion object { private val DATABASE_VERSION = 1 diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/recievers/BootReceiver.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/recievers/BootReceiver.kt new file mode 100644 index 0000000..b6aaea4 --- /dev/null +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/recievers/BootReceiver.kt @@ -0,0 +1,25 @@ +package io.github.z3r0c00l_2k.aquadroid.recievers + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import io.github.z3r0c00l_2k.aquadroid.helpers.AlarmHelper +import io.github.z3r0c00l_2k.aquadroid.utils.AppUtils + +class BootReceiver : BroadcastReceiver() { + private val alarm = AlarmHelper() + + override fun onReceive(context: Context?, intent: Intent?) { + if (intent != null && intent.action != null) { + if (intent.action == "android.intent.action.BOOT_COMPLETED") { + val prefs = context!!.getSharedPreferences(AppUtils.USERS_SHARED_PREF, AppUtils.PRIVATE_MODE) + val notificationFrequency = prefs.getInt(AppUtils.NOTIFICATION_FREQUENCY_KEY, 60) + val notificationsNewMessage = prefs.getBoolean("notifications_new_message", true) + alarm.cancelAlarm(context) + if (notificationsNewMessage) { + alarm.setAlarm(context, notificationFrequency.toLong()) + } + } + } + } +} diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/recievers/NotifierReceiver.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/recievers/NotifierReceiver.kt new file mode 100644 index 0000000..357d740 --- /dev/null +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/recievers/NotifierReceiver.kt @@ -0,0 +1,30 @@ +package io.github.z3r0c00l_2k.aquadroid.recievers + +import android.annotation.SuppressLint +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import io.github.z3r0c00l_2k.aquadroid.R +import io.github.z3r0c00l_2k.aquadroid.helpers.NotificationHelper +import io.github.z3r0c00l_2k.aquadroid.utils.AppUtils + +class NotifierReceiver : BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent) { + + val prefs = context.getSharedPreferences(AppUtils.USERS_SHARED_PREF, AppUtils.PRIVATE_MODE) + + val title = context.resources.getString(R.string.app_name) + val messageToShow = prefs.getString( + "message_to_show", + context.resources.getString(R.string.pref_notification_message_value) + ) + + /* Notify */ + val nHelper = NotificationHelper(context) + @SuppressLint("ResourceType") val nBuilder = nHelper + .getNotification(title, messageToShow) + nHelper.notify(1, nBuilder) + + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/AppUtils.kt b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/utils/AppUtils.kt similarity index 96% rename from app/src/main/java/io/github/z3r0c00l_2k/aquadroid/AppUtils.kt rename to app/src/main/java/io/github/z3r0c00l_2k/aquadroid/utils/AppUtils.kt index a829eef..f018944 100644 --- a/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/AppUtils.kt +++ b/app/src/main/java/io/github/z3r0c00l_2k/aquadroid/utils/AppUtils.kt @@ -1,4 +1,4 @@ -package io.github.z3r0c00l_2k.aquadroid +package io.github.z3r0c00l_2k.aquadroid.utils import java.text.SimpleDateFormat import java.util.* diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..435046a --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_small_logo.xml b/app/src/main/res/drawable/ic_small_logo.xml new file mode 100644 index 0000000..326e3ca --- /dev/null +++ b/app/src/main/res/drawable/ic_small_logo.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index bbd3e02..7353dbd 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index bbd3e02..7353dbd 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index 898f3ed..2238690 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index dffca36..f671d68 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index 64ba76f..8bcaf6c 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index dae5e08..efb0097 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index e5ed465..9d32cf6 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 14ed0af..82fe2eb 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index b0907ca..138ac4f 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index d8ae031..a1ddd82 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 2c18de9..30f20b6 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index beed3cd..750ec97 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..09a756b --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #26A69A + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c08771c..a1aaecf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ AquaDroid + Hey... Lets drink some water....