gowtham.com.desknote.MyListener.java Source code

Java tutorial

Introduction

Here is the source code for gowtham.com.desknote.MyListener.java

Source

/*
Desktop Notifier
Copyright (C) 2015 Gowtham (gowthamgowtham@gmail.com)
    
This program 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.
    
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    
*/
package gowtham.com.desknote;

import android.app.AlarmManager;
import android.app.Notification;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Base64;
import android.util.Base64OutputStream;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

public class MyListener extends NotificationListenerService {

    private Collection<String> connectedDevices = Collections.synchronizedSet(new HashSet<String>());

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);

        // If user has disabled notifications, then skip
        if (!pref.getBoolean("send_notifications", false))
            return;

        // Look for our device
        Set<String> emptySet = new HashSet<String>();
        Collection<String> addresses = pref.getStringSet("desktop_address", emptySet);
        Log.i(MainActivity.TAG, "Connected devices " + connectedDevices);
        Collection<String> connectedAddresses = getConnectedAddresses(addresses, connectedDevices);

        Notification mNotification = sbn.getNotification();

        // Can't do much if we get a null!
        if (mNotification == null)
            return;

        Bundle extras = mNotification.extras;

        String packageName = sbn.getPackageName();
        String title = extras.getString(Notification.EXTRA_TITLE);
        String text = extras.getString(Notification.EXTRA_TEXT);
        String subText = extras.getString(Notification.EXTRA_SUB_TEXT);
        Integer smallIconID = extras.getInt(Notification.EXTRA_SMALL_ICON);
        String icon = "null";
        if (pref.getBoolean("include_images", false)) {
            if (extras.getParcelable(Notification.EXTRA_LARGE_ICON) != null) {
                Bitmap b = Bitmap.class.cast(extras.getParcelable(Notification.EXTRA_LARGE_ICON));
                icon = bitmap2Base64(b);
            } else {
                icon = getIcon(packageName, smallIconID);
            }
        }

        Map<String, String> extrasMap = new HashMap<String, String>();
        for (String key : extras.keySet()) {
            extrasMap.put(key, String.valueOf(extras.get(key)));
        }

        Log.e(MainActivity.TAG, "Got a new notification " + title + " " + mNotification.hashCode());

        Message msg = new Message(title, text, subText, icon, mNotification.toString(), extrasMap, packageName);
        NotificationTransmitter tx = new NotificationTransmitter();

        Log.e(MainActivity.TAG, "Sending bluetooth message");
        tx.transmit(connectedAddresses, msg);
    }

    private Collection<String> getConnectedAddresses(Collection<String> addresses,
            Collection<String> connectedDevices) {
        return addresses;

        //        Collection<String> connectedAddresses = new LinkedHashSet<String>(addresses);
        //        connectedAddresses.retainAll(connectedDevices);
        //
        //        return connectedAddresses;
    }

    private String getIcon(String packageName, Integer id) {
        String icon = "null";
        if (id != 0) {
            Context context = null;
            try {
                context = createPackageContext(packageName, CONTEXT_IGNORE_SECURITY);
                Drawable d = context.getResources().getDrawable(id);
                Bitmap b = BitmapDrawable.class.cast(d).getBitmap();
                icon = bitmap2Base64(b);
            } catch (PackageManager.NameNotFoundException e) {
                // Ignore
            }
        }

        return icon;
    }

    private String bitmap2Base64(Bitmap b) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //Bitmap gray = toGrayscale(b);
        // Windows needs atleast 48x48 image, otherwise, notification is not shown
        Bitmap smaller = b.createScaledBitmap(b, 48, 48, false);
        // PNG is lossless. So, quality setting is unused
        smaller.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] buf = baos.toByteArray();
        return new String(Base64.encode(buf, Base64.NO_WRAP));
    }

    private Bitmap toGrayscale(Bitmap bmpOriginal) {
        int width, height;
        height = bmpOriginal.getHeight();
        width = bmpOriginal.getWidth();

        Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmpGrayscale);
        Paint paint = new Paint();
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
        paint.setColorFilter(f);
        c.drawBitmap(bmpOriginal, 0, 0, paint);
        return bmpGrayscale;
    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        // No implementation needed
    }

    private final BroadcastReceiver deviceConnectionReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                Log.i(MainActivity.TAG, "Device found " + device.getAddress());
                connectedDevices.add(device.getAddress());
            }
            // ACL_DISCONNECTED is being fired even when the device is in range
            if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                //Log.i(MainActivity.TAG, "Device disconnected " + device.getAddress());
                //connectedDevices.remove(device.getAddress());
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        IntentFilter filterDeviceFound = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        //IntentFilter filterDisconnect = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);

        registerReceiver(deviceConnectionReceiver, filterDeviceFound);
        //registerReceiver(deviceConnectionReceiver, filterDisconnect);
    }
}