From 211b8b125354c26c87d91590292c4fb6c921cea6 Mon Sep 17 00:00:00 2001 From: Chris Waldon Date: Sat, 20 Jun 2020 12:03:30 -0400 Subject: [PATCH] feat: enable variable channel importance --- android/NotificationHelper.java | 3 +- android/notify_android.go | 76 ++++++++++++++++++++++++++++++--- example/hello.go | 2 +- go.mod | 5 ++- go.sum | 7 +++ 5 files changed, 84 insertions(+), 9 deletions(-) diff --git a/android/NotificationHelper.java b/android/NotificationHelper.java index 6bac5dd..214865f 100644 --- a/android/NotificationHelper.java +++ b/android/NotificationHelper.java @@ -10,9 +10,8 @@ import android.graphics.drawable.Icon; public class NotificationHelper { private final static String tag = "NotificationHelper"; - public static void newChannel(Context ctx, String channelID, String name, String description) { + public static void newChannel(Context ctx, int importance, String channelID, String name, String description) { Log.w(tag,String.format("newChannel invoked")); - int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(channelID, name, importance); Log.e(tag,String.format("channel: %s",channel)); channel.setDescription(description); diff --git a/android/notify_android.go b/android/notify_android.go index cb3be29..cbdd4ba 100644 --- a/android/notify_android.go +++ b/android/notify_android.go @@ -2,21 +2,73 @@ package android import ( "fmt" + "log" "sync" "gioui.org/app" - "github.com/tailscale/tailscale-android/jni" + "git.wow.st/gmp/jni" ) +type Importance int + const ( - helperClass = "ht/sr/git/whereswaldon/niotify/NotificationHelper" + ImportanceDefault Importance = iota + ImportanceHigh + ImportanceLow + ImportanceMax + ImportanceMin + ImportanceNone + ImportanceUnspecified + importanceEnd // compile-time hack to track the number of importance constants and size the + // array holding their values correctly. If new constants need to be added, add them above + // this. +) + +// value returns the JVM value for this importance constant. It must not be invoked before the +// importances have been resolved. +func (i Importance) value() int32 { + return importances[i] +} + +const ( + helperClass = "ht/sr/git/whereswaldon/niotify/NotificationHelper" + importanceDefaultName = "IMPORTANCE_DEFAULT" + importanceHighName = "IMPORTANCE_HIGH" + importanceLowName = "IMPORTANCE_LOW" + importanceMaxName = "IMPORTANCE_MAX" + importanceMinName = "IMPORTANCE_MIN" + importanceNoneName = "IMPORTANCE_NONE" + importanceUnspecifiedName = "IMPORTANCE_UNSPECIFIED" ) var ( + // idlock protects the nextNotificationID to ensure that no notification is ever + // sent with a duplicate id. + // + // BUG(whereswaldon): does not handle integer overflow idlock sync.Mutex nextNotificationID int32 + + // jvmConstLock protects the mapping of JVM constants that must be resolved at runtime + jvmConstLock sync.Once + // importances tracks the IMPORTANCE_* constants from the JVM's values. Since they must + // be resolved at runtime, this array tracks their actual runtime values and the exported + // constants are simply indicies into this array. + importances [importanceEnd]int32 + // map the JVM constant name to the index in the array + importancesMap = map[string]Importance{ + importanceDefaultName: ImportanceDefault, + importanceHighName: ImportanceHigh, + importanceLowName: ImportanceLow, + importanceMaxName: ImportanceMax, + importanceMinName: ImportanceMin, + importanceNoneName: ImportanceNone, + importanceUnspecifiedName: ImportanceUnspecified, + } ) +// nextID safely returns the next unused notification id number. This function should +// always be used to get a notificationID. func nextID() int32 { idlock.Lock() defer idlock.Unlock() @@ -34,7 +86,7 @@ type NotificationChannel struct { // NewChannel creates a new notification channel identified by the provided id // and with the given user-visible name and description. -func NewChannel(id, name, description string) (*NotificationChannel, error) { +func NewChannel(importance Importance, id, name, description string) (*NotificationChannel, error) { if err := jni.Do(jni.JVMFor(app.JavaVM()), func(env jni.Env) error { appCtx := jni.Object(app.AppContext()) classLoader := jni.ClassLoaderFor(env, appCtx) @@ -42,11 +94,25 @@ func NewChannel(id, name, description string) (*NotificationChannel, error) { if err != nil { return err } - newChannelMethod := jni.GetStaticMethodID(env, notifyClass, "newChannel", "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V") + jvmConstLock.Do(func() { + var managerClass jni.Class + managerClass, err = jni.LoadClass(env, classLoader, "android/app/NotificationManager") + if err != nil { + return + } + for name, index := range importancesMap { + fieldID := jni.GetStaticFieldID(env, managerClass, name, "I") + importances[index] = jni.GetStaticIntField(env, managerClass, fieldID) + } + log.Printf("importances: %v", importances) + + }) + newChannelMethod := jni.GetStaticMethodID(env, notifyClass, "newChannel", "(Landroid/content/Context;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V") jname := jni.Value(jni.JavaString(env, name)) jdescription := jni.Value(jni.JavaString(env, description)) jID := jni.Value(jni.JavaString(env, id)) - err = jni.CallStaticVoidMethod(env, notifyClass, newChannelMethod, jni.Value(app.AppContext()), jID, jname, jdescription) + jimportance := jni.Value(importance.value()) + err = jni.CallStaticVoidMethod(env, notifyClass, newChannelMethod, jni.Value(app.AppContext()), jimportance, jID, jname, jdescription) if err != nil { return err } diff --git a/example/hello.go b/example/hello.go index df94c23..73f965f 100644 --- a/example/hello.go +++ b/example/hello.go @@ -53,7 +53,7 @@ func loop(w *app.Window) error { if first { first = false go func() { - channel, err := android.NewChannel("CHANNEL", "hello", "description") + channel, err := android.NewChannel(android.ImportanceMax, "CHANNEL", "hello", "description") if err != nil { log.Printf("channel creation failed: %v", err) } diff --git a/go.mod b/go.mod index 2217d4b..a2898e3 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,8 @@ go 1.14 require ( gioui.org v0.0.0-20200619180744-e2f3bbdfc367 - github.com/tailscale/tailscale-android v0.1.9 + gioui.org/cmd v0.0.0-20200619180744-e2f3bbdfc367 // indirect + git.wow.st/gmp/jni v0.0.0-20200619201040-d0d3f316ae09 ) + +replace git.wow.st/gmp/jni => git.wow.st/whereswaldon/jni v0.0.0-20200620152723-b380472956a0 diff --git a/go.sum b/go.sum index 8c14a35..bebc6ce 100644 --- a/go.sum +++ b/go.sum @@ -2,10 +2,15 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= eliasnaur.com/font v0.0.0-20200617114307-e02d32decb4b/go.mod h1:CYwJpIhpzVfoHpFXGlXjSx9mXMWtHt4XXmZb6RjumRc= gioui.org v0.0.0-20200530124200-1377bea3cdc5/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= +gioui.org v0.0.0-20200619103721-0b713032fbff/go.mod h1:jiUwifN9cRl/zmco43aAqh0aV+s9GbhG13KcD+gEpkU= gioui.org v0.0.0-20200619180744-e2f3bbdfc367 h1:uLmvlsenFUA5XkLheXgdQnX3T/oeYzO9aokBrbSsi/w= gioui.org v0.0.0-20200619180744-e2f3bbdfc367/go.mod h1:jiUwifN9cRl/zmco43aAqh0aV+s9GbhG13KcD+gEpkU= gioui.org/cmd v0.0.0-20200530141830-d2c67cdf8039 h1:mO1CTk+PwcDQGMXpN1JJiFflYBvwqSQ6+3Gvp64IKHo= gioui.org/cmd v0.0.0-20200530141830-d2c67cdf8039/go.mod h1:B1g+HOceSj7g3S4Yao3skwInTpcK978KANys5YuapMc= +gioui.org/cmd v0.0.0-20200619180744-e2f3bbdfc367 h1:YClsDYIOzphBRi6t9N9wjPhQKTnW+B7oxxIK+DtlbJc= +gioui.org/cmd v0.0.0-20200619180744-e2f3bbdfc367/go.mod h1:ECXnwbmqh7yrY50m4xQfFws2TsErFAXgiRmj8UHkb2U= +git.wow.st/whereswaldon/jni v0.0.0-20200620152723-b380472956a0 h1:+S/LqMv8h+w4LE/3XtAq1roX8OAZ/E6rqsl/EQ1eaK8= +git.wow.st/whereswaldon/jni v0.0.0-20200620152723-b380472956a0/go.mod h1:ro8WfqxHdXc4wFC+3uP98fVT5uZqrq3yQPMV+LjP6MA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= @@ -92,6 +97,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -110,6 +116,7 @@ golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e h1:hq86ru83GdWTlfQFZGO4nZJTU4Bs2wfHl8oFHRaXsfc= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=