Created
May 12, 2020 20:42
-
-
Save javieranton-zz/b39d1bf7d92b452a4748778e706137fa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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