add missing APIs

pull/340/head
Lucas Nogueira 2 years ago
parent 0b29107d71
commit cf47c8ef6d
No known key found for this signature in database
GPG Key ID: FFEA6C72E73482F1

@ -1,3 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.tauri.notification">
<application>
<receiver android:name="app.tauri.notification.TimedNotificationPublisher" />
<receiver android:name="app.tauri.notification.NotificationDismissReceiver" />
<receiver
android:name="app.tauri.notification.NotificationRestoreReceiver"
android:directBootAware="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
</manifest>

@ -30,6 +30,8 @@ class Notification {
var schedule: NotificationSchedule? = null
var channelId: String? = null
var source: String? = null
var visibility: Int? = null
var number: Int? = null
fun getSound(context: Context, defaultSound: Int): String? {
var soundPath: String? = null
@ -86,87 +88,6 @@ class Notification {
val isScheduled = schedule != null
override fun toString(): String {
return "Notification{" +
"title='" +
title +
'\'' +
", body='" +
body +
'\'' +
", id=" +
id +
", sound='" +
sound +
'\'' +
", smallIcon='" +
smallIcon +
'\'' +
", iconColor='" +
iconColor +
'\'' +
", actionTypeId='" +
actionTypeId +
'\'' +
", group='" +
group +
'\'' +
", extra=" +
extra +
", attachments=" +
attachments +
", schedule=" +
schedule +
", groupSummary=" +
isGroupSummary +
", ongoing=" +
isOngoing +
", autoCancel=" +
isAutoCancel +
'}'
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false
val that = other as Notification
if (if (title != null) title != that.title else that.title != null) return false
if (if (body != null) body != that.body else that.body != null) return false
if (if (largeBody != null) largeBody != that.largeBody else that.largeBody != null) return false
if (id != that.id) return false
if (if (sound != null) sound != that.sound else that.sound != null) return false
if (if (smallIcon != null) smallIcon != that.smallIcon else that.smallIcon != null) return false
if (if (largeIcon != null) largeIcon != that.largeIcon else that.largeIcon != null) return false
if (if (iconColor != null) iconColor != that.iconColor else that.iconColor != null) return false
if (if (actionTypeId != null) actionTypeId != that.actionTypeId else that.actionTypeId != null) return false
if (if (group != null) group != that.group else that.group != null) return false
if (if (extra != null) extra != that.extra else that.extra != null) return false
if (if (attachments != null) attachments != that.attachments else that.attachments != null) return false
if (if (inboxLines != null) inboxLines != that.inboxLines else that.inboxLines != null) return false
if (isGroupSummary != that.isGroupSummary) return false
if (isOngoing != that.isOngoing) return false
if (isAutoCancel != that.isAutoCancel) return false
return if (schedule != null) schedule?.equals(that.schedule) ?: false else that.schedule == null
}
override fun hashCode(): Int {
var result = if (title != null) title.hashCode() else 0
result = 31 * result + if (body != null) body.hashCode() else 0
result = 31 * result + id.hashCode()
result = 31 * result + if (sound != null) sound.hashCode() else 0
result = 31 * result + if (smallIcon != null) smallIcon.hashCode() else 0
result = 31 * result + if (iconColor != null) iconColor.hashCode() else 0
result = 31 * result + if (actionTypeId != null) actionTypeId.hashCode() else 0
result = 31 * result + if (group != null) group.hashCode() else 0
result = 31 * result + java.lang.Boolean.hashCode(isGroupSummary)
result = 31 * result + java.lang.Boolean.hashCode(isOngoing)
result = 31 * result + java.lang.Boolean.hashCode(isAutoCancel)
result = 31 * result + if (extra != null) extra.hashCode() else 0
result = 31 * result + if (attachments != null) attachments.hashCode() else 0
result = 31 * result + if (schedule != null) schedule.hashCode() else 0
return result
}
companion object {
fun fromJson(jsonNotification: JSONObject): Notification {
val notification: JSObject = try {
@ -205,6 +126,8 @@ class Notification {
notification.extra = jsonObject.getJSObject("extra")
notification.isOngoing = jsonObject.getBoolean("ongoing", false)
notification.isAutoCancel = jsonObject.getBoolean("autoCancel", true)
notification.visibility = jsonObject.getInteger("visibility")
notification.number = jsonObject.getInteger("number")
try {
val inboxLines = jsonObject.getJSONArray("inboxLines")
val inboxStringList: MutableList<String> = ArrayList()

@ -31,7 +31,7 @@ fun getIntervalTime(interval: NotificationInterval, count: Int): Long {
sealed class ScheduleKind {
// At specific moment of time (with repeating option)
class At(val date: Date, val repeating: Boolean): ScheduleKind()
class At(var date: Date, val repeating: Boolean): ScheduleKind()
class Interval(val interval: DateMatch): ScheduleKind()
class Every(val interval: NotificationInterval, val count: Int): ScheduleKind()
}

@ -1,6 +1,5 @@
package app.tauri.notification
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlarmManager
@ -11,12 +10,12 @@ import android.content.BroadcastReceiver
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.media.AudioAttributes
import android.net.Uri
import android.os.Build
import androidx.core.app.ActivityCompat
import android.os.Build.VERSION.SDK_INT
import android.os.UserManager
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.RemoteInput
@ -38,7 +37,7 @@ const val DEFAULT_PRESS_ACTION = "tap"
class TauriNotificationManager(
private val storage: NotificationStorage,
private val activity: Activity,
private val activity: Activity?,
private val context: Context,
private val config: JSObject
) {
@ -140,12 +139,9 @@ class TauriNotificationManager(
// TODO Progressbar support
// TODO System categories (DO_NOT_DISTURB etc.)
// TODO control visibility by flag Notification.VISIBILITY_PRIVATE
// TODO Group notifications (setGroup, setGroupSummary, setNumber)
// TODO use NotificationCompat.MessagingStyle for latest API
// TODO expandable notification NotificationCompat.MessagingStyle
// TODO media style notification support NotificationCompat.MediaStyle
// TODO custom small/large icons
@SuppressLint("MissingPermission")
private fun buildNotification(
notificationManager: NotificationManagerCompat,
@ -198,7 +194,7 @@ class TauriNotificationManager(
mBuilder.setSubText(notification.summary)
}
}
mBuilder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
mBuilder.setVisibility(notification.visibility ?: NotificationCompat.VISIBILITY_PRIVATE)
mBuilder.setOnlyAlertOnce(true)
mBuilder.setSmallIcon(notification.getSmallIcon(context, getDefaultSmallIcon(context)))
mBuilder.setLargeIcon(notification.getLargeIcon(context))
@ -221,13 +217,6 @@ class TauriNotificationManager(
// val notificationJson = JSObject(notification.source ?: "")
} catch (_: JSONException) {
}
if (ActivityCompat.checkSelfPermission(
activity,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
return
}
notificationManager.notify(notification.id, buildNotification)
}
}
@ -297,7 +286,12 @@ class TauriNotificationManager(
}
private fun buildIntent(notification: Notification, action: String?): Intent {
val intent = Intent(context, activity.javaClass)
val intent = if (activity != null) {
Intent(context, activity.javaClass)
} else {
val packageName = context.packageName
context.packageManager.getLaunchIntentForPackage(packageName)!!
}
intent.action = Intent.ACTION_MAIN
intent.addCategory(Intent.CATEGORY_LAUNCHER)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
@ -538,3 +532,40 @@ class TimedNotificationPublisher : BroadcastReceiver() {
var CRON_KEY = "NotificationPublisher.cron"
}
}
class LocalNotificationRestoreReceiver : BroadcastReceiver() {
@SuppressLint("ObsoleteSdkInt")
override fun onReceive(context: Context, intent: Intent) {
if (SDK_INT >= Build.VERSION_CODES.N) {
val um = context.getSystemService(
UserManager::class.java
)
if (um == null || !um.isUserUnlocked) return
}
val storage = NotificationStorage(context)
val ids = storage.getSavedNotificationIds()
val notifications = mutableListOf<Notification>()
val updatedNotifications = mutableListOf<Notification>()
for (id in ids) {
val notification = storage.getSavedNotification(id) ?: continue
val schedule = notification.schedule
if (schedule != null && schedule.kind is ScheduleKind.At) {
val at: Date = schedule.kind.date
if (at.before(Date())) {
// modify the scheduled date in order to show notifications that would have been delivered while device was off.
val newDateTime = Date().time + 15 * 1000
schedule.kind.date = Date(newDateTime)
updatedNotifications.add(notification)
}
}
notifications.add(notification)
}
if (updatedNotifications.size > 0) {
storage.appendNotifications(updatedNotifications)
}
// TODO: deserialize configuration
val notificationManager = TauriNotificationManager(storage, null, context, JSObject())
notificationManager.schedule(notifications)
}
}

@ -131,6 +131,14 @@ interface Options {
* Changes the notification presentation to be silent on iOS (no badge, no sound, not listed).
*/
silent?: boolean
/**
* Notification visibility.
*/
visibility?: Visibility
/**
* Sets the number of items this notification represents on Android.
*/
number?: number
}
type ScheduleInterval = {

Loading…
Cancel
Save