/*
* Copyright (C) 2015 - Holy Lobster
*
* Nuntius is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Nuntius is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Nuntius. If not, see <http://www.gnu.org/licenses/>.
*/
package org.holylobster.nuntius.connection;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.provider.Telephony;
import android.service.notification.StatusBarNotification;
import android.util.Base64;
import android.util.JsonWriter;
import android.util.Log;
import org.holylobster.nuntius.sms.SMessage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Arrays;
public class Message {
// Used for logging
private String TAG = this.getClass().getSimpleName();
private String event;
private SendType type;
private StatusBarNotification[] notifications;
private SMessage sMessage;
public Message(String event, StatusBarNotification... notifications) {
this.notifications = notifications;
this.event = event;
this.type = SendType.NOTI;
}
public Message(SMessage sMessage){
this.sMessage = sMessage;
this.event = "sms";
this.type = SendType.SMS;
}
public String toJSON(Context context) {
StringWriter out = new StringWriter();
JsonWriter writer = new JsonWriter(out);
try {
writer.beginObject();
writer.name("event").value(event);
writer.name("eventItems");
writer.beginArray();
if (type == SendType.SMS) {
toJsonSMessage(context, writer, sMessage);
} else if (type == SendType.NOTI) {
for (StatusBarNotification sbn : notifications) {
toJsonNotification(context, writer, sbn);
}
}
writer.endArray();
writer.endObject();
} catch (IOException e) {
e.printStackTrace();
}
return out.toString();
}
private void toJsonSMessage(Context context, JsonWriter writer, SMessage sMessage) throws IOException {
writer.beginObject();
writer.name("id").value("0"); // test value
writer.name("sender").value(sMessage.getSender());
writer.name("sender_num").value(sMessage.getSenderNum());
writer.name("message").value(sMessage.getMessage());
if (context != null){
final PackageManager pm = context.getPackageManager();
try {
ApplicationInfo ai = pm.getApplicationInfo(Telephony.Sms.getDefaultSmsPackage(context), 0); // require api 19 min is actually 19.
Bitmap bitmap = toBitmap(pm.getApplicationIcon(ai));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
writer.name("icon").value(new String(Base64.encode(stream.toByteArray(), Base64.DEFAULT), "UTF-8"));
} catch (final PackageManager.NameNotFoundException e) {
Log.d(TAG, "Could not get the icon and label for the default sms app");
}
}
writer.endObject();
}
private void toJsonNotification(Context context, JsonWriter writer, StatusBarNotification sbn) throws IOException {
writer.beginObject();
writer.name("id").value(sbn.getId());
writer.name("packageName").value(sbn.getPackageName());
writer.name("clearable").value(sbn.isClearable());
writer.name("ongoing").value(sbn.isOngoing());
writer.name("postTime").value(sbn.getPostTime());
String tag = sbn.getTag();
if (tag != null) {
writer.name("tag").value(tag);
}
final PackageManager pm = context.getPackageManager();
try {
ApplicationInfo ai = pm.getApplicationInfo(sbn.getPackageName(), 0);
writer.name("appName").value(pm.getApplicationLabel(ai).toString());
Bitmap bitmap = toBitmap(pm.getApplicationIcon(ai));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
writer.name("icon").value(new String(Base64.encode(stream.toByteArray(), Base64.DEFAULT), "UTF-8"));
} catch (final PackageManager.NameNotFoundException e) {
Log.d(TAG, "Could not get the icon and label for package: " + sbn.getPackageName());
}
writePropertiesLollipop(writer, sbn);
writer.name("notification");
Notification notification = sbn.getNotification();
writer.beginObject();
writer.name("priority").value(notification.priority);
writer.name("when").value(notification.when);
writer.name("defaults").value(notification.defaults);
writer.name("flags").value(notification.flags);
writer.name("number").value(notification.number);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Bundle extras = notification.extras;
CharSequence notificationTitle = extras.getCharSequence(Notification.EXTRA_TITLE);
if (notificationTitle != null) {
writer.name("title").value(notificationTitle.toString());
}
CharSequence notificationText = extras.getCharSequence(Notification.EXTRA_TEXT);
if (notificationText != null) {
writer.name("text").value(notificationText.toString());
}
CharSequence notificationSubText = extras.getCharSequence(Notification.EXTRA_SUB_TEXT);
if (notificationSubText != null) {
writer.name("subText").value(notificationSubText.toString());
}
}
CharSequence tickerText = notification.tickerText;
if (tickerText != null) {
writer.name("tickerText").value(tickerText.toString());
}
PendingIntent contentIntent = notification.contentIntent;
PendingIntent deleteIntent = notification.deleteIntent;
PendingIntent fullScreenIntent = notification.fullScreenIntent;
if (contentIntent != null) {
writer.name("contentIntent").value(contentIntent.toString());
}
if (deleteIntent != null) {
writer.name("deleteIntent").value(deleteIntent.toString());
}
if (fullScreenIntent != null) {
writer.name("fullScreenIntent").value(fullScreenIntent.toString());
}
writeNotificationLollipop(writer, notification);
writeActions(writer, notification);
writer.endObject();
writer.endObject();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void writePropertiesLollipop(JsonWriter writer, StatusBarNotification sbn) throws IOException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
writer.name("key").value(sbn.getKey());
writer.name("groupKey").value(sbn.getGroupKey());
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void writeNotificationLollipop(JsonWriter writer, Notification notification) throws IOException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
String category = notification.category;
if (category != null) {
writer.name("category").value(category);
}
writer.name("color").value(notification.color);
writer.name("visibility").value(notification.visibility);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private void writeActions(JsonWriter writer, Notification notification) throws IOException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
if (notification.actions != null) {
Log.d(TAG, "writing action");
writer.name("actions");
writer.beginArray();
for (Notification.Action a : notification.actions) {
Log.d(TAG, "writing action : " + a.title.toString());
writer.beginObject();
writer.name("title").value(a.title.toString());
writer.endObject();
}
writer.endArray();
}
}
public static Bitmap toBitmap(Drawable drawable) throws IOException {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else {
final Bitmap bitmap = Bitmap.createBitmap(
drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888
);
final Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
@Override
public String toString() {
return "Message{" +
"TAG='" + TAG + '\'' +
", event='" + event + '\'' +
", notifications=" + Arrays.toString(notifications) +
", sMessage=" + sMessage +
'}';
}
public enum SendType {
NOTI, SMS
}
}