Skip to content

Commit

Permalink
Include final demo on site, fix long notification ids
Browse files Browse the repository at this point in the history
When we did base64 encoding for notifications tags, that ended up pushing them over the tag length limit (sometimes).
Solution? Sha1 the original notification id -> unique (ish) id but of a set length.
  • Loading branch information
C0Newb committed Apr 24, 2023
1 parent 9df64cf commit 8075c25
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
Expand All @@ -22,27 +18,23 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
import android.text.format.DateUtils;

import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.graphics.drawable.IconCompat;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.neptune.app.MainActivity;
import com.neptune.app.NotificationsActivity;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NeptuneNotification {
private final Context context;
Expand Down Expand Up @@ -80,19 +72,21 @@ public NeptuneNotification(StatusBarNotification statusBarNotification, Context
try {
PackageManager packageManager = context.getPackageManager();
this.applicationName = packageManager.getApplicationLabel(packageManager.getApplicationInfo(this.applicationPackageName, 0)).toString();
if (this.applicationName == null)
this.applicationName = "(unknown)";
} catch (Exception e) {
this.applicationName = "(unknown)";
}


if (extras.containsKey(Notification.EXTRA_TITLE)) {
this.title = extras.getCharSequence(Notification.EXTRA_TITLE).toString();
} else if (extras.containsKey(Notification.EXTRA_CONVERSATION_TITLE)) {
this.title = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE).toString();
} else if (extras.containsKey(Notification.EXTRA_TITLE_BIG)) {
this.title = extras.getCharSequence(Notification.EXTRA_TITLE_BIG).toString();
try {
if (extras.containsKey(Notification.EXTRA_TITLE)) {
this.title = extras.getCharSequence(Notification.EXTRA_TITLE).toString();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && extras.containsKey(Notification.EXTRA_CONVERSATION_TITLE)) {
this.title = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE).toString();
} else if (extras.containsKey(Notification.EXTRA_TITLE_BIG)) {
this.title = extras.getCharSequence(Notification.EXTRA_TITLE_BIG).toString();
}
} catch (Exception ignored) {
throw new Exception("Invalid notification");
}

// Get text data
Expand All @@ -109,6 +103,32 @@ else if (extras.containsKey(Notification.EXTRA_SUMMARY_TEXT)) // We're getting d
if (this.text == null)
this.text = " ";

/*try {
if (applicationPackageName.equals("com.google.android.deskclock")) {
String text = notification.getSortKey(); // get the notification text
// use regular expressions to extract the paused state, total time, and time remaining from the text
Pattern pausedPattern = Pattern.compile("\\|(PAUSED)\\|");
Matcher pausedMatcher = pausedPattern.matcher(text);
Pattern expiredPattern = Pattern.compile("\\|(EXPIRED)\\|");
Matcher expiredMatcher = expiredPattern.matcher(text);
Pattern durationPattern = Pattern.compile("Σ(\\d+:\\d+:\\d+)");
Matcher durationMatcher = durationPattern.matcher(text);
Pattern elapsedPattern = Pattern.compile("Δ(\\d+:\\d+:\\d+)");
Matcher elapsedMatcher = elapsedPattern.matcher(text);
Pattern remainingPattern = Pattern.compile("⏳(\\d+:\\d+:\\d+)");
Matcher remainingMatcher = remainingPattern.matcher(text);
boolean isPaused = pausedMatcher.find();
if (durationMatcher.find() && remainingMatcher.find()) {
String duration = durationMatcher.group(1);
String remaining = remainingMatcher.group(1);
// durations are in the format "HH:MM:SS", convert them to seconds if needed
// Do something with the timer durations, remaining time, and paused state
this.text = "Timer " + (isPaused ? "paused" : "running") + ".\n" +
"Time remaining: " + remaining + "\n\nTotal duration: " + duration;
}
}
} catch (Exception ignored) {}*/

// Sub text
if (extras.containsKey(Notification.EXTRA_SUB_TEXT)) {
CharSequence charSequence = extras.getCharSequence(Notification.EXTRA_SUB_TEXT);
Expand All @@ -135,7 +155,7 @@ else if (extras.containsKey(Notification.EXTRA_SUMMARY_TEXT)) // We're getting d
isSilent = (channel.getImportance() == android.app.NotificationManager.IMPORTANCE_LOW
|| channel.getImportance() == android.app.NotificationManager.IMPORTANCE_MIN);
} else {
isSilent = (notification.priority == Notification.PRIORITY_LOW || notification.priority == Notification.PRIORITY_LOW);
isSilent = (notification.priority == Notification.PRIORITY_LOW);
}
} else {
int flags = notification.flags;
Expand Down Expand Up @@ -228,12 +248,10 @@ public void activate(JsonObject actionParameters) {
}
} else {
// No buttonId, textContent, or comboBoxChoice, so "tap" the notification body
if (notification.contentIntent != null && !firedIntent) {
if (notification.contentIntent != null) {
notification.contentIntent.send();
}
}
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Expand Down Expand Up @@ -310,9 +328,7 @@ private JsonObject processNotificationMessage(Notification.MessagingStyle.Messag


// Extract image from Uri attachment
Uri messageUri = null;

messageUri = message.getDataUri();
Uri messageUri = message.getDataUri();
String mimeType = message.getDataMimeType();
if (messageUri != null && mimeType != null) {
if (messageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT) ||
Expand Down Expand Up @@ -386,8 +402,11 @@ public JsonObject toJson() {
try {
if (extras.containsKey(Notification.EXTRA_PICTURE ) || extras.containsKey(Notification.EXTRA_PICTURE_ICON)) {
Bitmap imageBitmap = (Bitmap) extras.get(Notification.EXTRA_PICTURE);
if (extras.containsKey(Notification.EXTRA_PICTURE_ICON) && extras.get(Notification.EXTRA_PICTURE_ICON) != null)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
&& extras.containsKey(Notification.EXTRA_PICTURE_ICON)
&& extras.get(Notification.EXTRA_PICTURE_ICON) != null) {
imageBitmap = (Bitmap) extras.get(Notification.EXTRA_PICTURE_ICON);
}

if (imageBitmap != null) {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
Expand All @@ -406,9 +425,9 @@ public JsonObject toJson() {
&& (notification.category != null && (notification.category.equals(Notification.EXTRA_SHOW_CHRONOMETER)
|| notification.category.equals(Notification.CATEGORY_STOPWATCH)))) {
jsonObject.addProperty("type", "timer");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
JsonObject timerData = new JsonObject();
boolean countingDown = countingDown = extras.getBoolean(Notification.EXTRA_CHRONOMETER_COUNT_DOWN, true);
boolean countingDown = extras.getBoolean(Notification.EXTRA_CHRONOMETER_COUNT_DOWN, true);
timerData.addProperty("countingDown", countingDown);
jsonObject.add("timerData", timerData);
}
Expand Down Expand Up @@ -453,8 +472,7 @@ public JsonObject toJson() {
if (messages != null && messages.size() > 0) {
for (Notification.MessagingStyle.Message message : messages) {
JsonObject messageObject = processNotificationMessage(message);
if (messageObject != null)
conversationDataArray.add(messageObject);
conversationDataArray.add(messageObject);
}
}
}
Expand Down Expand Up @@ -516,10 +534,8 @@ public JsonObject toJson() {

// Actions (buttons, text box)
JsonArray actionsArray = new JsonArray();
PendingIntent contentIntent = notification.contentIntent;
if (notification.actions != null) {
try {

// Loop through the Notification.Action array and extract the button data
for (int i = 0; i < notification.actions.length; i++) {
JsonObject action = new JsonObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,13 @@ public IBinder onBind(Intent intent) {
public void onNotificationPosted(StatusBarNotification notification) {
try {
Log.d("NotificationListener", "Notification from package: " + notification.getPackageName());
Bundle extras = notification.getNotification().extras;
if (extras.getCharSequence("android.title") == null) { //Some notifications are not handled correctly, so we'll just skip em
return;
}


NeptuneNotification notify = new NeptuneNotification(notification, getApplicationContext());
MainActivity.notificationManager.setNotification(notify);
new Thread(() -> {
try {
NeptuneNotification notify = new NeptuneNotification(notification, getApplicationContext());
MainActivity.notificationManager.setNotification(notify);
} catch (Exception ignored) {}
}).start();
} catch (Exception e) {
// yepirr
e.printStackTrace();
Expand Down
16 changes: 12 additions & 4 deletions Documents/Readme.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<p align="center">
<img alt="Neptune Banner" src="https://user-images.githubusercontent.com/55852895/233927319-911f77a2-7b96-46ed-a5fc-f666104ec87e.png" width="100%" ></img>
</p>

Neptune is a tool for receiving your Android device's notifications on your computer (mainly Windows).\
Neptune also supports sharing files and clipboard data between the two devices. This is useful for quickly transferring images, text and other data between devices.

No active internet connection is required, all data is sent between the devices using the local network.


_**Final demo video goes here**_

<center>
<video src="https://user-images.githubusercontent.com/55852895/233226957-ef83ceb2-306a-4269-858b-2b1586e92638.mp4" height="500px"></video>
<video src="https://user-images.githubusercontent.com/55852895/233905615-30f8dc58-839d-4338-afa4-001e24719f2d.mp4" height="500px"></video>
</center>


Expand All @@ -18,6 +20,12 @@ _**Final demo video goes here**_
[Matthew Sprinkle](https://github.com/Sprinklem)


![NotificationExamples]()

<p align="center">
<img alt="Notification Examples" src="https://user-images.githubusercontent.com/55852895/233928167-a97025eb-460b-44b7-a11a-8eac5ebee243.png" width="100%" ></img>
</p>

---


Expand Down Expand Up @@ -86,7 +94,7 @@ The devices can, however, disable file sharing or clipboard sharing for the othe

Here's a demo video:
<center>
<video controls="true" src="https://user-images.githubusercontent.com/55852895/230435879-1f880635-07e8-4623-b56b-c4fb06e0932e.mp4" height="500px"></video>
<video controls="true" src="https://user-images.githubusercontent.com/55852895/233906787-0a2fb425-9780-4f68-8ae5-7bc64373aaf0.mp4" height="500px"></video>
</center>


Expand Down
1 change: 1 addition & 0 deletions Server/NeptuneRunner/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

/NeptuneRunnerNetCore/*
/NeptuneRunnerNetCore/
/build/temp/

# User-specific files
*.rsuser
Expand Down
15 changes: 10 additions & 5 deletions Server/src/Classes/Notification.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ let { Logger } = require('./LogMan');

let EventEmitter = require("node:events");

const crypto = require("node:crypto");


/**
* Neptune
Expand Down Expand Up @@ -81,6 +83,8 @@ class Notification extends EventEmitter {
*/
data;

#neptuneRunnerId;


/**
* @typedef {Object} NotificationAction
Expand Down Expand Up @@ -176,6 +180,7 @@ class Notification extends EventEmitter {
}
}
this.#id = data.notificationId;
this.#neptuneRunnerId = crypto.createHash("sha1").update(data.notificationId).digest('hex')
}


Expand Down Expand Up @@ -291,7 +296,7 @@ class Notification extends EventEmitter {
try {
let data = {
action: this.data.action,
id: this.data.notificationId,
id: this.#neptuneRunnerId,

clientId: this.#client.clientId,
clientName: this.#client.friendlyName,
Expand Down Expand Up @@ -322,11 +327,11 @@ class Notification extends EventEmitter {

let func = this.#IPCActivation;
let actuallyThis = this;
if (global.NeptuneRunnerIPC._events['notify-client_' + this.clientId + ":" + this.data.notificationId] !== undefined)
delete global.NeptuneRunnerIPC._events['notify-client_' + this.clientId + ":" + this.data.notificationId];
if (global.NeptuneRunnerIPC._events['notify-client_' + this.clientId + ":" + this.#neptuneRunnerId] !== undefined)
delete global.NeptuneRunnerIPC._events['notify-client_' + this.clientId + ":" + this.#neptuneRunnerId];

if (global.NeptuneRunnerIPC._events['notify-client_' + this.clientId + ":" + this.data.notificationId] === undefined) {
global.NeptuneRunnerIPC.once('notify-client_' + this.clientId + ":" + this.data.notificationId, (data) => {
if (global.NeptuneRunnerIPC._events['notify-client_' + this.clientId + ":" + this.#neptuneRunnerId] === undefined) {
global.NeptuneRunnerIPC.once('notify-client_' + this.clientId + ":" + this.#neptuneRunnerId, (data) => {
func(actuallyThis, data);
});
}
Expand Down

0 comments on commit 8075c25

Please sign in to comment.