diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 4d16620d..cc765118 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,7 +1,7 @@ - + @@ -66,10 +66,10 @@ - + - + diff --git a/android/res/drawable-hdpi/ic_launcher.png b/android/res/drawable-hdpi/ic_launcher.png deleted file mode 100644 index 37bcf0fe..00000000 Binary files a/android/res/drawable-hdpi/ic_launcher.png and /dev/null differ diff --git a/android/res/drawable-mdpi/ic_launcher.png b/android/res/drawable-mdpi/ic_launcher.png deleted file mode 100644 index 37bcf0fe..00000000 Binary files a/android/res/drawable-mdpi/ic_launcher.png and /dev/null differ diff --git a/android/res/drawable-xhdpi/ic_launcher.png b/android/res/drawable-xhdpi/ic_launcher.png deleted file mode 100644 index 37bcf0fe..00000000 Binary files a/android/res/drawable-xhdpi/ic_launcher.png and /dev/null differ diff --git a/android/res/drawable-xxhdpi/ic_launcher.png b/android/res/drawable-xxhdpi/ic_launcher.png deleted file mode 100644 index 37bcf0fe..00000000 Binary files a/android/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/res/drawable-xxxhdpi/ic_launcher.png b/android/res/drawable-xxxhdpi/ic_launcher.png deleted file mode 100644 index 37bcf0fe..00000000 Binary files a/android/res/drawable-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/res/drawable/ic_launcher.png b/android/res/drawable/ic_launcher.png new file mode 100644 index 00000000..f35daeff Binary files /dev/null and b/android/res/drawable/ic_launcher.png differ diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java new file mode 100644 index 00000000..4623ae15 --- /dev/null +++ b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java @@ -0,0 +1,125 @@ +package ca.openprivacy.cwtch.ui; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.NotificationChannel; +import android.content.Context; +import android.util.Log; + + +import static android.app.Notification.DEFAULT_LIGHTS; +import static android.app.Notification.DEFAULT_SOUND; +import static android.app.Notification.DEFAULT_VIBRATE; +import static android.app.NotificationManager.IMPORTANCE_DEFAULT; +import static android.app.NotificationManager.IMPORTANCE_LOW; +import static android.content.Context.NOTIFICATION_SERVICE; +import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.os.Build.VERSION.SDK_INT; +import static android.app.Notification.CATEGORY_SERVICE; + + +/*import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE; +import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE; +import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL; +import static android.support.v4.app.NotificationCompat.PRIORITY_LOW; +import static android.support.v4.app.NotificationCompat.PRIORITY_MIN; +import static android.support.v4.app.NotificationCompat.PRIORITY_DEFAULT; +import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; +import static android.support.v4.content.ContextCompat.getColor;*/ + + + + +public class CwtchActivity extends org.qtproject.qt5.android.bindings.QtActivity +{ + private static NotificationManager m_notificationManager; + private static Notification.Builder m_builder; + private static Notification.Builder m_builderOngoing; + private static CwtchActivity m_instance; + + private static int PRIORITY_MIN = -2; // From NotificationCompat + private static int PRIORITY_DEFAULT = 0; // From NotificationCompat + + private static String NOTIFICATION_CHANNEL_ID = "cwtch_notification_channel"; + + private static int ONGOING_NOTIFICATION_ID = 0; + private static String ONGOING_NOTIFICATION_ID_NAME = "ongoing"; + + private static int CONTENT_NOTIFICATION_ID = 1; + private static String CONTENT_NOTIFICATION_ID_NAME = "content"; + + + public CwtchActivity() + { + m_instance = this; + } + + public static void notify(String s) + { + if (m_notificationManager == null) { + m_notificationManager = (NotificationManager)m_instance.getSystemService(Context.NOTIFICATION_SERVICE); + createNotificationChannel(); + } + + if (m_builder == null) { + m_builder = new Notification.Builder(m_instance); + m_builder.setSmallIcon(R.drawable.ic_launcher); + m_builder.setContentTitle("Cwtch"); + m_builder.setPriority(PRIORITY_DEFAULT); + + } + + m_builder.setContentText(s); + m_notificationManager.notify(CONTENT_NOTIFICATION_ID, m_builder.build()); + } + + public static void ongoingNotify(String s) + { + if (m_notificationManager == null) { + m_notificationManager = (NotificationManager)m_instance.getSystemService(Context.NOTIFICATION_SERVICE); + createNotificationChannel(); + } + + if (m_builderOngoing == null) { + m_builderOngoing = new Notification.Builder(m_instance); + m_builderOngoing.setSmallIcon(R.drawable.ic_launcher); + m_builderOngoing.setContentTitle("Cwtch"); + m_builderOngoing.setPriority(PRIORITY_MIN); + + m_builderOngoing.setWhen(0); // Don't show the time + m_builderOngoing.setOngoing(true); + if (SDK_INT >= 21) { + m_builderOngoing.setCategory(CATEGORY_SERVICE); + //m_builder.setVisibility(VISIBILITY_SECRET); + } + + } + + m_builderOngoing.setContentText(s); + m_notificationManager.notify(ONGOING_NOTIFICATION_ID, m_builderOngoing.build()); + } + + private static void createNotificationChannel() { + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + if (SDK_INT >= 26) { + String description = "Cwtch Ongoing Notification Channel"; + int importance = NotificationManager.IMPORTANCE_LOW; + NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, ONGOING_NOTIFICATION_ID_NAME, importance); + channel.setDescription(description); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + m_notificationManager.createNotificationChannel(channel); + + description = "Cwtch Content Notification Channel"; + importance = NotificationManager.IMPORTANCE_DEFAULT; + channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, CONTENT_NOTIFICATION_ID_NAME, importance); + channel.setDescription(description); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + m_notificationManager.createNotificationChannel(channel); + + } + } +} diff --git a/go/gothings/androidCwtchActivity.go b/go/gothings/androidCwtchActivity.go new file mode 100644 index 00000000..72e41fa8 --- /dev/null +++ b/go/gothings/androidCwtchActivity.go @@ -0,0 +1,50 @@ +package gothings + +import ( + "github.com/therecipe/qt/androidextras" + "github.com/therecipe/qt/core" +) + +type AndroidCwtchActivity struct { + core.QObject + + _ func() `constructor:"init"` + + _ string `property:"notification"` + + _ func(string) `slot:"updateAndroidNotification"` +} + +func (c *AndroidCwtchActivity) init() { + + c.createOngoingNotification() + c.ConnectNotificationChanged(c.updateAndroidNotification) +} + +func (c *AndroidCwtchActivity) updateAndroidNotification(n string) { + + var err = androidextras.QAndroidJniObject_CallStaticMethodVoid2Caught( + "ca/openprivacy/cwtch/ui/CwtchActivity", + "notify", + "(Ljava/lang/String;)V", + n, + ) + + if err != nil { + println(err.Error()) + } +} + +func (c *AndroidCwtchActivity) createOngoingNotification() { + + var err = androidextras.QAndroidJniObject_CallStaticMethodVoid2Caught( + "ca/openprivacy/cwtch/ui/CwtchActivity", + "ongoingNotify", + "(Ljava/lang/String;)V", + "Cwtch is running", + ) + + if err != nil { + println(err.Error()) + } +} diff --git a/go/the/globals.go b/go/the/globals.go index 0b82bca7..06b40a69 100644 --- a/go/the/globals.go +++ b/go/the/globals.go @@ -3,15 +3,17 @@ package the import ( "cwtch.im/cwtch/app" libPeer "cwtch.im/cwtch/peer" + "git.openprivacy.ca/openprivacy/libricochet-go/connectivity" ) var CwtchApp app.Application +var ACN connectivity.ACN var Peer libPeer.CwtchPeer var CwtchDir string type AckId struct { - ID string - Ack bool + ID string + Ack bool Error bool } diff --git a/main.go b/main.go index eeb163ea..cf0e1980 100644 --- a/main.go +++ b/main.go @@ -111,8 +111,21 @@ func main() { gcd.SetThemeScale(1.0) } engine.RootContext().SetContextProperty("gcd", gcd) - engine.Load(qmlSource) + var androidCwtchActivity = gothings.NewAndroidCwtchActivity(nil) + engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity) + + engine.Load(qmlSource) + the.ACN = nil + go loadNetworkingAndFiles(gcd) + app.Exec() + + if the.ACN != nil { + the.ACN.Close() + } +} + +func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) { if os.Getenv("CWTCH_FOLDER") != "" { the.CwtchDir = os.Getenv("CWTCH_FOLDER") } else if runtime.GOOS == "android" { @@ -145,17 +158,17 @@ func main() { torpath = path.Join(dir, "tor") } } - - acn, err := connectivity.StartTor(the.CwtchDir, torpath) + var err error + the.ACN, err = connectivity.StartTor(the.CwtchDir, torpath) if err != nil { log.Errorf("Could not start Tor: %v", err) os.Exit(1) } // these are long-lived pollers/listeners for incoming messages and status changes - loadCwtchData(gcd, acn) + loadCwtchData(gcd, the.ACN) go characters.IncomingListener(gcd.UIState.AddMessage, gcd.UIState.AddSendMessageError) - go characters.TorStatusPoller(gcd.TorStatus, acn) + go characters.TorStatusPoller(gcd.TorStatus, the.ACN) go characters.PresencePoller(gcd.UIState.GetContact, gcd.UIState.AddContact, gcd.UIState.UpdateContact) go characters.GroupPoller(gcd.UIState.GetContact, gcd.UIState.UpdateContact) @@ -165,9 +178,6 @@ func main() { if exists { gcd.SetLocale_helper(locale) } - - app.Exec() - acn.Close() } // this is mostly going to get factored out when we add profile support diff --git a/qml/overlays/ChatOverlay.qml b/qml/overlays/ChatOverlay.qml index 3b90577f..ac2986f4 100644 --- a/qml/overlays/ChatOverlay.qml +++ b/qml/overlays/ChatOverlay.qml @@ -77,6 +77,9 @@ ColumnLayout { // If the window is out of focus, alert the user (makes taskbar light up) windowItem.alert(0) + if (gcd.os == "android" && windowItem.activeFocusItem == null) { + androidCwtchActivity.notification = "New Content" + } } onPrependMessage: function(handle, from, displayName, message, image, mid, fromMe, ts, ackd, error) {