nl.dobots.imbusy.ImBusyApp.java Source code

Java tutorial

Introduction

Here is the source code for nl.dobots.imbusy.ImBusyApp.java

Source

package nl.dobots.imbusy;

import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.provider.ContactsContract;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import org.jivesoftware.smack.packet.Presence;

import java.util.HashSet;
import java.util.Set;

import nl.dobots.bluenet.ble.extended.BleExt;
import nl.dobots.bluenet.ble.extended.structs.BleDevice;
import nl.dobots.bluenet.ble.extended.structs.BleDeviceMap;

/**
 * Copyright (c) 2015 Bart van Vliet <bart@dobots.nl>. All rights reserved.
 * <p/>
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 3, as
 * published by the Free Software Foundation.
 * <p/>
 * This code 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
 * version 3 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * <p/>
 * Created on 24-7-15
 *
 * @author Bart van Vliet
 */

// TODO: bind to services to send stuff to services
// TODO: use event listeners instead of calling ImBusyApp.function() from services.
// TODO: use local broadcasts to send stuff to UI? <-- listener is fine too (but synchronous)

public class ImBusyApp extends Application {
    private static final String TAG = ImBusyApp.class.getCanonicalName();
    private static ImBusyApp _instance;
    private Context _context;
    private static final String DATABASE_NAME = "ImBusyDataBase";
    private static final int DATABASE_VERSION = 1;
    private static final String PREFERENCES_FILE = "ImBusyPreferences";
    public static final String PREFERENCE_PHONE_NUMBER = "phoneNumber";
    public static final String PREFERENCE_PASSWORD = "password";
    public static final int IMBUSY_NOTIFICATION_ID_FRIEND_REQUEST = 1;

    private NotificationManager _notificationManager;
    private NotificationCompat.Builder _notificationBuilder;

    private BleExt _ble;
    private StoredBleDeviceList _storedDeviceList;
    private Handler _handler;
    Runnable _setAvailable = new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "Changed status to " + Status.AVAILABLE);
            _status = Status.AVAILABLE;
        }
    };

    private SharedPreferences _preferences;
    private Status _status;
    private XmppService.XmppStatus _xmppStatus;
    //   private String _phoneNumber;
    private PhoneContactList _contactList = new PhoneContactList();
    private Set<ImBusyListener> _listenerList = new HashSet<>();

    private XmppService _xmppService = null;
    private ServiceConnection _xmppServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            _xmppService = ((XmppService.XmppBinder) service).getService();
            _xmppService.addListener(_xmppListener);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            _xmppService = null;
        }
    };

    public static ImBusyApp getInstance() {
        return _instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        _instance = this;
        _context = this.getApplicationContext();

        _handler = new Handler();

        _notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        _preferences = getSharedPreferences(PREFERENCES_FILE, MODE_PRIVATE);
        //      _phoneNumber = _preferences.getString("phoneNumber", "");

        _storedDeviceList = new StoredBleDeviceList(_context);
        _storedDeviceList.load();

        start();
    }

    public void start() {
        _status = Status.AVAILABLE;
        if (_ble == null) {
            _ble = new BleExt();
        }
        this.startService(new Intent(this, CallStateService.class));
        this.startService(new Intent(this, BleScanService.class));
        if (_xmppService == null) {
            bindService(new Intent(this, XmppService.class), _xmppServiceConnection, Context.BIND_AUTO_CREATE);
        }
    }

    /** Stop all services
     */
    public void stop() {
        _storedDeviceList.save();
        stopService(new Intent(this, StatusPopupService.class));
        stopService(new Intent(this, CallStateService.class));
        stopService(new Intent(this, BleScanService.class));
        if (_xmppService != null) {
            _xmppService.removeListener(_xmppListener);
            unbindService(_xmppServiceConnection);
            _xmppService = null;
        }
        //      _xmppService = null;

        _ble = null;
        //      System.exit(0);
        //      android.os.Process.killProcess(android.os.Process.myPid());
    }

    public void addListener(ImBusyListener listener) {
        _listenerList.add(listener);
    }

    public void removeListener(ImBusyListener listener) {
        _listenerList.remove(listener);
    }

    public void sendToListeners(Status status) {
        for (ImBusyListener listener : _listenerList) {
            listener.onStatus(status);
        }
    }

    /** Should be called when an activity is opened */
    //   public void onActivityOpen(Activity activity) {
    public void onActivityOpen(Class activityClass) {
        _notificationManager.cancel(IMBUSY_NOTIFICATION_ID_FRIEND_REQUEST);
    }

    /** Should be called when an activity is closed */
    public void onActivityClose(Class activityClass) {

    }

    public void onOutgoingCall(String number) {
        Log.i(TAG, "---------------------------");
        Log.i(TAG, "Outgoing call to " + number);
        Log.i(TAG, "---------------------------");
        String fixedNumber = new String(number);
        fixedNumber = fixedNumber.replaceAll(" ", "");
        fixedNumber = fixedNumber.replaceAll("\\+", "00");
        if (_contactList.containsKey(fixedNumber) && _contactList.get(fixedNumber).getStatus() == Status.BUSY) {
            Log.i(TAG, fixedNumber + " is busy! Show popup");
            startService(new Intent(this, StatusPopupService.class));
        } else
            Log.d(TAG, fixedNumber + " is not a contact or is not busy");
    }

    /** Phone goes idle, remove the status popup
     */
    public void onHangUp() {
        stopService(new Intent(this, StatusPopupService.class));
    }

    public void onScannedDevice(BleDevice device) {
        if (device == null) {
            return;
        }
        Log.d(TAG, "Scanned " + device.getAddress() + " (" + device.getRssi() + ") " + device.getName());
        //      Log.d(TAG, "scanned device list size = " + _ble.getDeviceMap().size());
        if (_storedDeviceList.isClose(device.getAddress(), device.getRssi())) {
            setStatus(Status.BUSY);
        }
    }

    final XmppServiceListener _xmppListener = new XmppServiceListener() {
        @Override
        public void onConnectStatus(XmppService.XmppStatus status) {
            _xmppStatus = status;
            switch (status) {
            case AUTHENTICATED: {
                // After authentication, all numbers are added again, so we start with a clean list
                _contactList.clear();
                break;
            }
            }
        }

        @Override
        public void onError(XmppService.XmppError error) {

        }

        @Override
        public void onFriend(XmppService.XmppFriendEvent event, XmppFriend friend) {
            String number = getNumber(friend.getJid());
            switch (event) {
            case ADDED: {
                String name = getContactName(getNumber(friend.getJid()));
                //               if (friend.getNick() == null) {
                //                  String name = getContactName(getNumber(friend.getJid()));
                friend.setNick(name);
                //               }
                _contactList.add(new PhoneContact(number, name));
                break;
            }
            case REMOVED: {
                _contactList.remove(number);
                break;
            }
            case FRIEND_UPDATE: {
                _contactList.get(number).setStatus(getStatus(friend.getMode()));
                break;
            }
            case FRIEND_REQUEST: {
                String name = getContactName(number);
                String text = name + " (" + number + ") wants to see your status.";

                Intent contentIntent = new Intent(_context, MainActivity.class);
                contentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                PendingIntent piContent = PendingIntent.getActivity(_context, 0, contentIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);

                _notificationBuilder = new NotificationCompat.Builder(_context);
                _notificationBuilder.setSmallIcon(R.mipmap.ic_launcher);
                _notificationBuilder.setContentTitle("Friend request");
                _notificationBuilder.setContentText(text);
                _notificationBuilder.setContentIntent(piContent);
                _notificationBuilder.setAutoCancel(true);
                _notificationBuilder.setDefaults(Notification.DEFAULT_SOUND);
                _notificationBuilder.setLights(Color.BLUE, 500, 1000);
                _notificationManager.notify(IMBUSY_NOTIFICATION_ID_FRIEND_REQUEST, _notificationBuilder.build());
            }
            }
        }
    };

    public XmppService.XmppStatus getXmppStatus() {
        return _xmppStatus;
    }

    public void setStatus(Status status) {
        Log.d(TAG, "Changed status to " + status);
        _status = status;
        sendToListeners(status);
        _handler.removeCallbacks(_setAvailable);
        _handler.postDelayed(_setAvailable, Config.BUSY_TIMEOUT);
    }

    public StoredBleDeviceList getStoredDeviceList() {
        return _storedDeviceList;
    }

    public BleExt getBle() {
        return _ble;
    }

    public BleDeviceMap getDeviceMap() {
        if (_ble != null) {
            return _ble.getDeviceMap();
        }
        return null;
    }

    public static String getDatabaseName() {
        return DATABASE_NAME;
    }

    public static int getDatabaseVersion() {
        return DATABASE_VERSION;
    }

    public Status getStatus() {
        return _status;
    }

    public PhoneContactList getContactList() {
        return _contactList;
    }

    public static String getPreferencesFile() {
        return PREFERENCES_FILE;
    }

    //   public String getOwnNumber() { return _phoneNumber; }

    /** Helper function to convert xmpp presence mode to status */
    public static final Status getStatus(Presence.Mode mode) {
        switch (mode) {
        case away:
            return nl.dobots.imbusy.Status.BUSY;
        case xa:
            return nl.dobots.imbusy.Status.BUSY;
        case dnd:
            return nl.dobots.imbusy.Status.BUSY;
        case chat:
        case available:
        default:
            return nl.dobots.imbusy.Status.AVAILABLE;
        }
    }

    /** Helper function to convert status to xmpp presence mode */
    public static final Presence.Mode getMode(Status status) {
        switch (status) {
        case BUSY:
            return Presence.Mode.dnd;
        case AVAILABLE:
        default:
            return Presence.Mode.available;
        }
    }

    public final String getStatusText(Status status) {
        switch (status) {
        case BUSY:
            return getString(R.string.status_busy);
        case AVAILABLE:
        default:
            return getString(R.string.status_available);
        }
    }

    public static String getXmppUsername(String phoneNumber) {
        return phoneNumber;
    }

    /** Helper function to get the phone number from a jid */
    public static String getNumber(String jid) {
        return XmppThread.getUsername(jid);
    }

    /** Retrieves the name as stored in the phones address book, given a phone number */
    public String getContactName(String phoneNumber) {
        String[] projection = new String[] { ContactsContract.PhoneLookup.DISPLAY_NAME,
                ContactsContract.PhoneLookup._ID };
        Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
        String contactName = "";
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
            }
            cursor.close();
        }
        return contactName;
    }
}