remdo.services.NotificationService.java Source code

Java tutorial

Introduction

Here is the source code for remdo.services.NotificationService.java

Source

/* ************************************************************************  
 * Copyright  2013 Maite Calpe Miravet 
 * ************************************************************************ 
 * This file is part of OpenDomo Notifier.
 *
 * OpenDomo Notifier is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License v3 
 * published by the Free Software Foundation.
 *
 * OpenDomo Notifier 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 v3 for more details.
 *
 * You should have received a copy of the GNU General Public License v3
 * along with OpenDomo Notifier. If not, see <http://www.gnu.org/licenses/>
 * ************************************************************************/

package remdo.services;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.xmlpull.v1.XmlPullParserException;

import remdo.sqlite.helper.DatabaseHelper;

import com.opendomo.notifier.Event;
import com.opendomo.notifier.EventsList;
import com.opendomo.notifier.EventsXmlParser;
import com.opendomo.utilities.AlertUtilities;
import com.opendomo.utilities.Login;
import com.opendomo.utilities.NetworkUtilities;
import com.opendomo.utilities.StringUtilities;
import com.remdo.app.AlertsCategoryActivity;
import com.remdo.app.ProjectApplication;
import com.remdo.app.R;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothClass.Device;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.widget.Toast;

/**
 * Servicio de notificacin.<p>
 * 
 * Este servicio comprobar cada x minutos, segn configuracin, 
 * si el modulo odEvents del servidor Opendomo ha registrado algn evento. 
 * Si as es, el servici crear una notificacin por cada evento ledo
 * en la barra de notificaciones.<p>
 * En cada notificacin se mostrar la descripcin del evento y
 * el elemento que lo ha originado.<p>
 * La lectura de los eventos del servidor OpenDomo se realizar
 * mediante una peticin HTTP. As pues, esta actividad requiere
 * conexin a Internet. 
 *  
 * @see <a href="http://es.opendomo.org/odevents">Gestin de eventos en servidor OpenDomo</a>  
 * @version  1.0, 30/05/2013
 * @version  2.0, 07/03/2014 - Gerard Torrents se aaden pequeas modiicaciones 
 * para trabajar con RemoteDomo
 */

public class NotificationService extends Service {

    private static String mHost;
    private static int notificationId = 1;
    DatabaseHelper dm;

    //Almacenaremos la tarea de lectura de eventos para garantizar que
    //podemos cancelarla si as lo solicitamos
    private ReadEventsTask mREventsTask = null;

    @Override
    public void onCreate() {
        //Toast.makeText(this, "NotificationService.onCreate()", Toast.LENGTH_LONG).show();

        //Establecemos el administrador de cookies por defecto
        ProjectApplication applicationContext = ((ProjectApplication) getApplicationContext());
        CookieManager cookieManager = applicationContext.getCookieManager();
        CookieHandler.setDefault(cookieManager);

        //Obtenemos las preferencias compartidas
        SharedPreferences preferencesLogin = getSharedPreferences("login", MODE_PRIVATE);
        //mHost = preferencesLogin.getString("host", null);

        dm = new DatabaseHelper(applicationContext);
        mHost = dm.getDevicebyDevType(1, 0).url;
    }

    @Override
    public IBinder onBind(Intent intent) {
        //Toast.makeText(this, "NotificationService.onBind()", Toast.LENGTH_LONG).show();
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, getString(R.string.stopped_alerts_service), Toast.LENGTH_LONG).show();
    }

    @SuppressWarnings("unchecked")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        //Toast.makeText(this, "NotificationService.onStartCommand()", Toast.LENGTH_LONG).show();

        readEventsAndDisplayNotifications();
        //Devolviendo START_STICKY garantizamos que el servicio continua ejecutandose
        //hasta que explcitamente lo paremos
        return START_STICKY;
    }

    private void readEventsAndDisplayNotifications() {
        if (mREventsTask != null)
            return;

        //Ejecutamos una tarea en background que leer los eventos
        mREventsTask = new ReadEventsTask();
        mREventsTask.execute(mHost);
    }

    /**
      * Tarea asncrona de lectura de eventos del servidor OpenDomo.<p>
      * La lectura de los eventos se realizar mediante una peticin HTTP GET.<p> 
      * El XML obtenido se analizar y se convertir en una lista de obtetos Event.
      */
    public class ReadEventsTask extends AsyncTask<String, Void, String> {

        private Login LoginTask = null;

        @Override
        protected String doInBackground(String... params) {

            String host = params[0].toString();

            Boolean success = false;
            String respuesta = null;
            HttpURLConnection urlConnection = null;
            try {

                int reintentos = 2;
                do {
                    URL url = new URL(host + "/cgi-bin/od.cgi/tools/showEvents.sh?&GUI=XML");
                    urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod("GET");
                    urlConnection.setDoInput(true);
                    urlConnection.setDoOutput(true);

                    int responseCode = urlConnection.getResponseCode();
                    if ((responseCode >= 200) && (responseCode < 300)) {
                        //Si existe una cookie de respuesta llamada HTSESSID estamos logueados
                        List<String> cookies = urlConnection.getHeaderFields().get("Set-Cookie");
                        if (cookies != null) {
                            for (String cookie : cookies) {
                                String cookieNameValue = cookie.substring(0, cookie.indexOf(';'));
                                String cookieName = cookieNameValue.substring(0, cookieNameValue.indexOf('='));
                                if (cookieName.equals("HTSESSID")) {
                                    success = true;
                                    break;
                                }
                            }
                        } else {
                            dm = new DatabaseHelper(getApplicationContext());
                            remdo.sqlite.model.Device dev = dm.getDevicebyDevType(1, 0);

                            //Recopilamos los parametros
                            ArrayList<String> connParams = new ArrayList<String>();
                            connParams.add(dev.url);
                            connParams.add(dev.usr);
                            connParams.add(dev.pwd);
                            //Ejecutamos una tarea en background que realizar el intento de inicio de sesion
                            LoginTask = new Login();
                            LoginTask.execute(connParams);
                            reintentos = reintentos - 1;
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                } while (reintentos > 0 && success == false);

                if (success) {
                    InputStream is = new BufferedInputStream(urlConnection.getInputStream());
                    respuesta = StringUtilities.convertStreamToString(is);
                }
            } catch (MalformedURLException e) {
            } catch (UnsupportedEncodingException e) {
            } catch (IOException e) {
            } finally {
                if (urlConnection != null)
                    urlConnection.disconnect();
            }

            return respuesta;
        }

        @Override
        protected void onPreExecute() {
            if (!NetworkUtilities.isNetworkAvailable(NotificationService.this)) {
                //Toast.makeText(getApplicationContext(), "NotificationService. Conexin a Internet no disponible", Toast.LENGTH_LONG).show();
                cancel(true);
            }
        }

        @Override
        protected void onPostExecute(final String notificacionesXML) {
            mREventsTask = null;

            if (!TextUtils.isEmpty(notificacionesXML)) {
                try {
                    InputStream stream = new ByteArrayInputStream(notificacionesXML.getBytes("UTF-8"));
                    EventsList events = EventsXmlParser.parse(stream);
                    saveNotifications(events);
                } catch (XmlPullParserException e) {
                } catch (IOException e) {
                }
            }
        }

        @Override
        protected void onCancelled() {
            mREventsTask = null;
        }
    }

    public void saveNotifications(EventsList events) {
        try {
            dm = new DatabaseHelper(getApplicationContext());
            Iterator<Event> iter = events.getIterator();
            int notif = 0;
            while (iter.hasNext()) {
                Event event = iter.next();
                if (!dm.existsEvent(event)) {
                    dm.insertEvent(event);
                    notif++;
                }
            }
            if (notif > 0)
                displayNotification();
        } catch (Exception ex) {
            Toast.makeText(getApplicationContext(),
                    "RemDo ERROR: [" + ex.getMessage() + "][" + ex.getStackTrace() + "]", Toast.LENGTH_LONG).show();
        }
    }

    /**
    * Muestra una notificacin en la barra de notificaciones
    * 
    * @param event - Objeto de tipo Event.
    * @param identifier - Identificador de la notificacin.
    */
    public void displayNotification(Event event, int identifier) {
        NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        Intent i = new Intent(this, AlertsCategoryActivity.class);
        //i.putExtra("com.opendomo.notifier.notificationID", 1);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);

        CharSequence ticker = "Nuevos eventos OpenDomo";
        CharSequence contentTitle = "OpenDomo (" + event.getTransmitter() + ")";
        CharSequence contentText = event.getMessage();
        Notification noti = new NotificationCompat.Builder(getApplicationContext()).setContentIntent(pendingIntent)
                .setTicker(ticker).setContentTitle(contentTitle).setContentText(contentText)
                .setSmallIcon(R.drawable.ic_notificaciones_blanco)
                .addAction(R.drawable.ic_notificaciones_blanco, ticker, pendingIntent).build();
        nManager.notify(identifier, noti);
    }

    /**
    * Muestra una notificacin en la barra de notificaciones
    * 
    * @param quantity - Nmero de notificaciones nuevas
    */
    public void displayNotification() {
        NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        int quantity = dm.getUnreadAlerts();

        Intent i = new Intent(this, AlertsCategoryActivity.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);

        CharSequence ticker = quantity + " New OpenDomo events";
        CharSequence contentTitle = "RemoteDomo";
        CharSequence contentText = quantity + " New OpenDomo events.";
        Notification noti = new NotificationCompat.Builder(getApplicationContext()).setContentIntent(pendingIntent)
                .setTicker(ticker).setContentTitle(contentTitle).setContentText(contentText)
                .setSmallIcon(R.drawable.ic_notificaciones_blanco)
                .addAction(R.drawable.ic_notificaciones_blanco, ticker, pendingIntent).setAutoCancel(true).build();
        nManager.notify(1, noti);
    }

}