Skip to content

Instantly share code, notes, and snippets.

@javieranton-zz
Created May 12, 2020 20:42
Show Gist options
  • Save javieranton-zz/b39d1bf7d92b452a4748778e706137fa to your computer and use it in GitHub Desktop.
Save javieranton-zz/b39d1bf7d92b452a4748778e706137fa to your computer and use it in GitHub Desktop.
import com.google.firebase.messaging.RemoteMessage;
import android.app.NotificationManager;
import android.app.Activity;
import android.content.Intent;
import android.app.PendingIntent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.app.NotificationCompat.Builder;
import android.support.v4.app.NotificationCompat;
import android.content.Context;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Vector;
/**
*
* @author user
*/
public class FirebaseServiceExtended extends com.google.firebase.messaging.FirebaseMessagingService {
String NON_CHAT_KEY = "your.namespace.someKEY";
public static int notificationNonChatGroupID = 0;
int intentQueue1 = 1;
int intentQueue2 = 0;
private static android.content.Context context() {
return com.codename1.impl.android.AndroidNativeUtil.getActivity().getApplicationContext();
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
try {
int notificationNonChatGroupChildrenIDs = 0;
final Context context = this;
String notificationsString = "Notifications";
String viewString = "View";
String dismissString = "Mark as read";
String messageType = (String) remoteMessage.getData().get("messageType");
String message = (String) remoteMessage.getData().get("message");
String notifId = (String) remoteMessage.getData().get("notifId");
String notifHasImage = (String) remoteMessage.getData().get("notifHasImage");
String senderId = (String) remoteMessage.getData().get("senderId");
if(notifId == null)
notifId = "";
if(senderId == null)
senderId = "";
if(notifHasImage == null)
notifHasImage = "false";
//ack
String body = "{<somePayload>}"; your.namespace.CN1AndroidApplication.rest("https://www.yourServer.com/endpoint","POST",body);
if (appIsRunning()) {
String[] a = message.split(";");//my msg keyValue is title;body
your.namespace.MainClass.staticMethodToGetFGPush(a[0],a[1],""); }
if (!appIsRunning()) {
appendNotification(messageType, message, notifId, senderId, notifHasImage, context);//adds msgs to file
String[] messages = getPendingPush(messageType, context);//gets msgs in the form of String[]<"type;title;body;notifId;senderId;hasImage;timeInMillis">
int numMessages = messages.length;
if (true) { Drawable myIcon = getDrawable("icon", context);
Bitmap icon = ((BitmapDrawable) myIcon).getBitmap();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
for (int i = 0; i < numMessages; i++) {
String[] messageFields = messages[i].split(";");
String title = messageFields[1];
String body = messageFields[2];
notificationNonChatGroupChildrenIDs++;
Intent openIntent = new Intent(context, your.namespace.MainClass.class);
openIntent.putExtra("pushAction", "{'action':'open','notifId':'" + messageFields[3] + "','androidNotifId':" + notificationNonChatGroupChildrenIDs + "}");
PendingIntent openPendingIntent = PendingIntent.getActivity(context, intentQueue1++, openIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent dismissIntent = new Intent(context, your.namespace.GroupsReceiver.class);
dismissIntent.putExtra("action", "markNotifAsRead");
dismissIntent.putExtra("notifId",messageFields[3]);
dismissIntent.putExtra("androidNotifId",notificationNonChatGroupChildrenIDs);
PendingIntent dismissPendingIntent = PendingIntent.getBroadcast(context, intentQueue2++, dismissIntent, 0);//PendingIntent.getActivity(context, 0, dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Builder notificationBuilder1
= new NotificationCompat.Builder(context)
.setContentIntent(openPendingIntent)
.setContentTitle(title)
.setContentText(body)
.addAction(0, viewString, openPendingIntent)
.addAction(0, dismissString, dismissPendingIntent)
.setAutoCancel(true)
.setWhen(Long.parseLong(messageFields[6]))
.setGroup(NON_CHAT_KEY);
if (messageFields[5].equals("true")) {
notificationBuilder1.setLargeIcon(getBitmapfromUrl("https://www.yourServer.com/getPicture?userId=" + messageFields[4]));
}
if (android.os.Build.VERSION.SDK_INT >= 23) {
notificationBuilder1.setSmallIcon(getDrawableResourceId("ic_stat_notify", context));
} else {
notificationBuilder1.setSmallIcon(android.R.drawable.stat_notify_chat);
}
setNotificationChannel(notificationManager, notificationBuilder1, i+1 == numMessages ? true : false);//only set last notif with high importance so we only get one alert
notificationManager.notify(notificationNonChatGroupChildrenIDs, notificationBuilder1.build());
}
String summary = numMessages + " " + notificationsString;
Intent summaryIntent = new Intent(context, your.namespace.MainClass.class);
summaryIntent.putExtra("pushAction", "{'action':'summary','notifId':'"+notifId+"','androidNotifId':"+notificationNonChatGroupID+"}");
PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, summaryIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Builder summaryBuilder =
new NotificationCompat.Builder(context)
.setContentTitle(summary)
//set content text to support devices running API level < 24
.setContentText(message.split(";")[1])
.setLargeIcon(icon)
//build summary info into InboxStyle template
.setGroup(NON_CHAT_KEY)
.setContentIntent(summaryPendingIntent)
.setGroupSummary(true)
.setStyle(new NotificationCompat.InboxStyle().setSummaryText(summary));
if(android.os.Build.VERSION.SDK_INT >= 23)
summaryBuilder.setSmallIcon(getDrawableResourceId("ic_stat_notify", context));
else
summaryBuilder.setSmallIcon(android.R.drawable.stat_notify_chat);
setNotificationChannel(notificationManager, summaryBuilder, android.os.Build.VERSION.SDK_INT < 23 ? true : false);//sets channel to yourApp-channel service
notificationManager.notify(notificationNonChatGroupID, summaryBuilder.build());
}
}
} catch (Exception e) {
your.namespace.CN1AndroidApplication.traceError("onMessage receive exception: "+e.toString());
}
}
/*
isImportant determines whether notificationshould show bubble, vibrate and make a sound
*/
public void setNotificationChannel(NotificationManager nm, NotificationCompat.Builder mNotifyBuilder, boolean isImportant) {
if (android.os.Build.VERSION.SDK_INT >= 26) {
try {
NotificationManager mNotificationManager = nm;
String id = isImportant ? "yourApp-channel" : "yourApp-bg-channel";
CharSequence name = isImportant ? "YourAppBgNotifications" : "YourAppNotifications";
String description = isImportant ? "YourApp Remote notifications" : "YourApp Remote Bg notifications";
// NotificationManager.IMPORTANCE_LOW = 2
// NotificationManager.IMPORTANCE_HIGH = 4 // <-- Minimum level to produce sound.
int importance = isImportant ? 4 : 3;
Class clsNotificationChannel = Class.forName("android.app.NotificationChannel");
//android.app.NotificationChannel mChannel = new android.app.NotificationChannel(id, name, importance);
Constructor constructor = clsNotificationChannel.getConstructor(java.lang.String.class, java.lang.CharSequence.class, int.class);
Object mChannel = constructor.newInstance(new Object[]{id, name, importance});
Method method = clsNotificationChannel.getMethod("setDescription", java.lang.String.class);
method.invoke(mChannel, new Object[]{description});
//mChannel.setDescription(description);
method = clsNotificationChannel.getMethod("enableLights", boolean.class);
method.invoke(mChannel, new Object[]{isImportant ? true : false});
//mChannel.enableLights(true);
method = clsNotificationChannel.getMethod("setLightColor", int.class);
method.invoke(mChannel, new Object[]{android.graphics.Color.RED});
//mChannel.setLightColor(android.graphics.Color.RED);
method = clsNotificationChannel.getMethod("enableVibration", boolean.class);
method.invoke(mChannel, new Object[]{isImportant ? true : false});
//mChannel.enableVibration(true);
method = clsNotificationChannel.getMethod("setVibrationPattern", long[].class);
method.invoke(mChannel, new Object[]{new long[]{ 0, 500}});
method = NotificationManager.class.getMethod("createNotificationChannel", clsNotificationChannel);
method.invoke(mNotificationManager, new Object[]{mChannel});
//mNotificationManager.createNotificationChannel(mChannel);
try {
// For some reason I can't find the app-support-v4.jar for
// API 26 that includes this method so that I can compile in netbeans.
// So we use reflection... If someone coming after can find a newer version
// that has setChannelId(), please rip out this ugly reflection hack and
// replace it with a proper call to mNotifyBuilder.setChannelId(id)
mNotifyBuilder.getClass().getMethod("setChannelId", new Class[]{String.class}).invoke(mNotifyBuilder, new Object[]{id});
} catch (Exception ex) {
your.namespace.CN1AndroidApplication.traceError("setChannelId error: "+ex.toString());
}
} catch (Exception ex) {
your.namespace.CN1AndroidApplication.traceError("setChannel error: "+ex.toString());
}
}
}
public String[] getPendingPush(String type, Context a) {
InputStream i = null;
try {
i = a.openFileInput("YourApp$AndroidPendingNotifications");
if (i == null) {
return null;
}
DataInputStream is = new DataInputStream(i);
int count = is.readByte();
Vector v = new Vector<String>();
for (int iter = 0; iter < count; iter++) {
final String messageType = is.readUTF();
final String[] titleAndBody = is.readUTF().split(";");
final String notifId = is.readUTF();
final String senderId = is.readUTF();
final String hasImage = is.readUTF();
long timeInMillis = is.readLong();
if(messageType != null && type.equals(messageType)){
v.add(messageType+";"+titleAndBody[0]+";"+titleAndBody[1]+";"+notifId+";"+senderId+";"+hasImage+";"+timeInMillis);
}
}
String [] retVal = new String[v.size()];
for (int j = 0; j < retVal.length; j++) {
retVal[j] = (String)v.get(j);
}
return retVal;
} catch (Exception ex) {
your.namespace.CN1AndroidApplication.traceError("getPendingPush err: "+ex.toString());
} finally {
try {
if(i != null){
i.close();
}
} catch (IOException ex) {
}
}
return null;
}
private void sCleanup(Object o) {
try {
if(o != null) {
if(o instanceof InputStream) {
((InputStream)o).close();
return;
}
if(o instanceof OutputStream) {
((OutputStream)o).close();
return;
}
}
} catch(Throwable t) {}
}
public void appendNotification(String type, String titleAndBody, String notifId, String senderId, String hasImage, Context a) {
try {
String[] fileList = a.fileList();
byte[] data = null;
for (int iter = 0; iter < fileList.length; iter++) {
if (fileList[iter].equals("YourApp$AndroidPendingNotifications")) {
InputStream is = a.openFileInput("YourApp$AndroidPendingNotifications");
if(is != null) {
data = readInputStream(is);
sCleanup(a);
break;
}
}
}
DataOutputStream os = new DataOutputStream(a.openFileOutput("YourApp$AndroidPendingNotifications", 0));
if(data != null) {
data[0]++;
os.write(data);
} else {
os.writeByte(1);
}
os.writeUTF(type);
os.writeUTF(titleAndBody);
os.writeUTF(notifId);
os.writeUTF(senderId);
os.writeUTF(hasImage);
os.writeLong(System.currentTimeMillis());
} catch(Exception err) {
your.namespace.CN1AndroidApplication.traceError("appendNotification err: "+err.toString());
}
}
public byte[] readInputStream(InputStream i) throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
try {
copyNoClose(i, b);
} finally {
sCleanup(b);
sCleanup(i);
}
return b.toByteArray();
}
public void copyNoClose(InputStream i, OutputStream o) throws IOException {
byte[] buffer = new byte[8192];
int size = i.read(buffer);
int total = 0;
while(size > -1) {
o.write(buffer, 0, size);
size = i.read(buffer);
}
}
private static boolean allowBackgroundPush = false;
protected boolean appIsRunning() {
return your.namespace.CN1AndroidApplication.isAppInForeground();
}
private Drawable getDrawable(String name, Context context) {
android.content.res.Resources resources = context.getResources();
final int resourceId = resources.getIdentifier(name, "drawable",
context.getPackageName());
return resources.getDrawable(resourceId);
}
private int getDrawableResourceId(String name, Context context) {
android.content.res.Resources resources = context.getResources();
final int resourceId = resources.getIdentifier(name, "drawable",
context.getPackageName());
return resourceId;
}
private android.graphics.Bitmap getBitmapfromUrl(String imageUrl) {
try {
java.net.URL url = new java.net.URL(imageUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(input);
return bitmap;
} catch (Exception e) {
// TODO Auto-generated catch block
your.namespace.CN1AndroidApplication.traceError("getBitmapfromUrl error:"+e.toString());
return null;
}
}
//unused for now
public void onNewToken(String token) {
your.namespace.network.GroupChart.androidAppRegistered("cn1-fcm-"+token);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment