gpsalarm.app.service.PostMonitor.java Source code

Java tutorial

Introduction

Here is the source code for gpsalarm.app.service.PostMonitor.java

Source

package gpsalarm.app.service;

/*
* ****************************************************************************
*
* Copyright (C) 2013 Geosai Pty Ltd, Sydney, Australia.
* 
* Author: Kalyan Kumar Janakiraman (kalyankj @ gmail.com)
* Dated : 14th Feb 2011
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* *****************************************************************************
*/
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

import gpsalarm.app.IPostListener;
import gpsalarm.app.IPostMonitor;
import gpsalarm.app.R;
import gpsalarm.app.controller.AlarmEdit3;
import gpsalarm.app.controller.AlertList;
import gpsalarm.app.data.ReminderHelper;
import gpsalarm.app.data.TimelineHelper;
import gpsalarm.app.datatype.Alert;
import gpsalarm.app.datatype.Alerts;
import gpsalarm.app.datatype.Position;
import gpsalarm.app.datatype.Reminder;
import gpsalarm.app.datatype.Tweet;

import com.commonsware.cwac.wakeful.WakefulIntentService;

public class PostMonitor extends WakefulIntentService {
    protected static final String TAG = PostMonitor.class.getSimpleName();
    public static final int NOTIFICATION_ID = 1337;
    public static final String STATUS_UPDATE = "gpsalarm.app.service.STATUS_UPDATE";
    public static final String FRIEND = "gpsalarm.app.service.FRIEND";
    public static final String STATUS = "gpsalarm.app.service.STATUS";
    public static final String CREATED_AT = "gpsalarm.app.service.CREATED_AT";
    public static final String POLL_ACTION = "gpsalarm.app.service.POLL_ACTION";
    private static final String NOTIFY_KEYWORD = "RemindMe@";
    private static final int INITIAL_POLL_PERIOD = 60000; //60000
    private static final int POLL_PERIOD = 119907;//60000; //119907; //
    private Set<Tweet> updatedToSend = new HashSet<Tweet>();
    private Map<IPostListener, Account> accounts = new ConcurrentHashMap<IPostListener, Account>();
    private final Binder binder = new LocalBinder();
    private AtomicBoolean isBatteryLow = new AtomicBoolean(false);
    private AlarmManager alarm = null;
    private PendingIntent pi = null;
    SharedPreferences prefs = null;

    private TimelineHelper sdb;
    private ReminderHelper rdb;

    Account myAccount = null;
    String team = null;
    Position curr = null;
    Position prev = null;

    //   String urlToSendRequest = "http://192.168.0.194:8080/wsdbServiceWAR/tasks/-1/";
    String targetDomain = "211.30.144.192";
    //   String targetDomain = "kalyankj.no-ip.org";  //"10.3.1.144"; //"192.168.0.153";
    int targetPort = 9998;

    public PostMonitor() {
        super("PostMonitor");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        sdb = new TimelineHelper(this);
        rdb = new ReminderHelper(this);

        //get user account from preference.
        prefs = PreferenceManager.getDefaultSharedPreferences(this);
        team = prefs.getString("team", "").toUpperCase();
        myAccount = new Account(prefs.getString("user", null), prefs.getString("password", ""), null);

        registerReceiver(onBatteryChanged, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(this, OnAlarmReceiver.class);
        pi = PendingIntent.getBroadcast(this, 0, i, 0);
        setAlarm(INITIAL_POLL_PERIOD);
    }

    private SharedPreferences.OnSharedPreferenceChangeListener prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {

        public void onSharedPreferenceChanged(SharedPreferences sharedPrefs, String key) {
            team = prefs.getString("team", "").toUpperCase();
            myAccount = new Account(prefs.getString("user", null), prefs.getString("password", ""), null);
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return (binder);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        alarm.cancel(pi);
        unregisterReceiver(onBatteryChanged);
    }

    @Override
    protected void doWakefulWork(Intent i) {

        if (i.getAction().equals(POLL_ACTION)) {
            myAccount = new Account(prefs.getString("user", null), prefs.getString("password", ""), null);
            if (myAccount.user != null) {
                pollForReminderUpdates(myAccount, team);
                pollStatusUpdates(myAccount);
                //            pollForReminderUpdates(myAccount, "PUBLIC");
                updateLocation(myAccount);
                pollForProximityAlerts(myAccount);
            }
        }

        setAlarm(isBatteryLow.get() ? POLL_PERIOD * 10 : POLL_PERIOD);
    }

    private void pollForProximityAlerts(Account myAccount2) {
        String baseURI = "http://" + targetDomain + ":" + targetPort + "/wsdbServiceWAR/position";
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpHost targetHost = new HttpHost(targetDomain, targetPort, "http");
        Serializer s = new Persister();

        HttpGet httpget = null;
        String urlToSendRequest = baseURI + "/get/alerts";
        httpget = new HttpGet(urlToSendRequest);
        // Make sure the server knows what kind of a response we will accept
        httpget.addHeader("Accept", "application/xml");
        // Also be sure to tell the server what kind of content we are sending
        httpget.addHeader("Content-Type", "application/xml");

        try {
            // execute is a blocking call, it's best to call this code in a thread separate from the ui's
            HttpResponse response = httpClient.execute(targetHost, httpget);

            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity en = response.getEntity();
                if (en != null) {
                    String str = convertStreamToString(en.getContent());
                    Alerts aList = s.read(Alerts.class, str);
                    List<Alert> list = aList.getProperties();
                    if (list == null)
                        return;
                    Long now = Calendar.getInstance().getTime().getTime();
                    boolean alertFlag = false;
                    for (Alert a : list) {
                        Reminder r = rdb.getReminderByGid(a.getGid().toString());
                        if (r != null && a.getUsername() != null) {
                            a.setTimestamp(now);
                            if (rdb.updateAlerts(a))
                                alertFlag = true;
                        }
                    }
                    rdb.markDeleteAlerts(now);
                    if (alertFlag)
                        showProximityNotification(
                                "there are " + rdb.getAlertsList("username").getCount() + " notifications");
                }

            }
        } catch (ClientProtocolException e) {
            Log.e(TAG, e.toString(), e);
        } catch (IllegalStateException e) {
            Log.e(TAG, e.toString(), e);
        } catch (IOException e) {
            Log.e(TAG, e.toString(), e);
        } catch (Exception e) {
            Log.e(TAG, e.toString(), e);
        } finally {
            rdb.close();
        }
    }

    private void showProximityNotification(String string) {
        final NotificationManager mgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification note = new Notification(R.drawable.status, "Friend@ notification!",
                System.currentTimeMillis());
        Intent i = new Intent(this, AlertList.class);

        //      i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
        //                      Intent.FLAG_ACTIVITY_SINGLE_TOP);
        i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
        note.setLatestEventInfo(this, "Friend@ notification", string, pi);

        mgr.notify(NOTIFICATION_ID, note);

    }

    private void updateLocation(Account myAccount2) {
        String baseURI = "http://" + targetDomain + ":" + targetPort + "/wsdbServiceWAR/position";
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpHost targetHost = new HttpHost(targetDomain, targetPort, "http");
        Serializer s = new Persister();

        try {
            curr = rdb.getPosition(myAccount2.user);
            if (curr == null)
                return;
            if ((prev == null) || (curr.distance(prev) > 20)) {
                if (curr.getUsername() == null)
                    return;
                String urlToSendRequest = baseURI + "/new";
                // Using POST here
                HttpPut httpput = new HttpPut(urlToSendRequest);
                // Make sure the server knows what kind of a response we will accept
                httpput.addHeader("Accept", "text/xml");
                // Also be sure to tell the server what kind of content we are sending
                httpput.addHeader("Content-Type", "application/xml");

                StringEntity entity = new StringEntity(curr.getXML(), "UTF-8");
                entity.setContentType("application/xml");
                httpput.setEntity(entity);

                // execute is a blocking call, it's best to call this code in a thread separate from the ui's
                httpClient.execute(targetHost, httpput);
                prev = curr;
            }

        } catch (Exception ex) {
            Log.e(TAG, ex.toString(), ex);
        } finally {
            rdb.close();
        }

        //Who is near where
    }

    private void pollForReminderUpdates(Account account, String team) {

        String baseURI = "http://" + targetDomain + ":" + targetPort + "/wsdbServiceWAR/tasks/";
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpHost targetHost = new HttpHost(targetDomain, targetPort, "http");
        Serializer s = new Persister();

        List<Reminder> rlist = new ArrayList<Reminder>();
        try {
            // INSERT in SERVER
            rlist = rdb.getReminders(" syncflag='I' and g_id is NULL ", null);
            if (rlist != null) {
                String urlToSendRequest = baseURI + "new";
                HttpPut httpput = new HttpPut(urlToSendRequest);
                httpput.addHeader("Accept", "text/xml");
                httpput.addHeader("Content-Type", "application/xml");
                for (Reminder r : rlist) {
                    if (r.getAuthor() == null)
                        continue;
                    StringEntity entity = new StringEntity(r.getXML(), "UTF-8");
                    entity.setContentType("application/xml");
                    httpput.setEntity(entity);

                    // execute is a blocking call, it's best to call this code in a thread separate from the ui's
                    HttpResponse response = httpClient.execute(targetHost, httpput);
                    if (response.getStatusLine().getStatusCode() == 201) {
                        HttpEntity en = response.getEntity();
                        if (en != null) {
                            String str = convertStreamToString(en.getContent());
                            StringTokenizer st = new StringTokenizer(str, "||");
                            if (st.hasMoreTokens()) {
                                Long g_id = Long.valueOf(st.nextToken());
                                Long g_timestamp = null;
                                if (st.hasMoreTokens())
                                    g_timestamp = Long.valueOf(st.nextToken());
                                r.setG_id(g_id);
                                r.setG_timestamp(g_timestamp);
                                r.setSyncflag("");
                                rdb.updateWithRowid(r, r.getRowid().toString());
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.toString(), ex);
        } finally {
            rdb.close();
        }
        try {
            // UPDATE SERVER
            rlist = rdb.getReminders(" syncflag='E' ", null);
            HttpPost httppost = null;
            if (rlist != null) {
                for (Reminder r : rlist) {
                    String urlToSendRequest = baseURI + r.getG_id() + "/";
                    httppost = new HttpPost(urlToSendRequest);
                    httppost.addHeader("Accept", "application/xml");
                    httppost.addHeader("Content-Type", "application/xml");
                    StringEntity entity = new StringEntity(r.getXML(), "UTF-8");
                    entity.setContentType("application/xml");
                    httppost.setEntity(entity);
                    HttpResponse response = httpClient.execute(targetHost, httppost);

                    if (response.getStatusLine().getStatusCode() == 204) {
                        r.setSyncflag("");
                        rdb.updateWithG_Id(r, r.getG_id().toString());
                    }
                }
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.toString(), ex);
        } finally {
            rdb.close();
        }

        try {
            // DELETE IN SERVER.
            // wants to remove the reminder.
            rlist = rdb.getReminders(" syncflag='D' ", null);
            HttpDelete httpdelete = null;
            if (rlist != null) {
                for (Reminder r : rlist) {
                    String urlToSendRequest = baseURI + r.getG_id() + "/";
                    httpdelete = new HttpDelete(urlToSendRequest);
                    httpdelete.addHeader("Accept", "text/xml");
                    httpdelete.addHeader("Content-Type", "application/xml");
                    HttpResponse response = httpClient.execute(targetHost, httpdelete);

                    if (response.getStatusLine().getStatusCode() == 204) {
                        rdb.delete(r.getG_id().toString()); // After marking
                        // server record
                        // with 'D' remove
                        // local record
                    }
                }
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.toString(), ex);
        } finally {
            rdb.close();
        }

        try {
            //GET FROM SERVER
            // rlist = rdb.getReminders(" syncflag='D' ", null);
            HttpGet httpget = null;
            String urlToSendRequest = baseURI + "recent?team=" + team + "&author=" + account.user;
            httpget = new HttpGet(urlToSendRequest);
            httpget.addHeader("Accept", "text/xml");
            httpget.addHeader("Content-Type", "application/xml");
            HttpResponse response = httpClient.execute(targetHost, httpget);

            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity en = response.getEntity();
                if (en != null) {
                    String str = convertStreamToString(en.getContent());
                    gpsalarm.app.datatype.Reminders rList = s.read(gpsalarm.app.datatype.Reminders.class, str);
                    List<Reminder> list = rList.getProperties();
                    if (list == null)
                        return;
                    for (Reminder r : list) {
                        String syncType = r.getSyncflag();
                        Reminder rlocal = rdb.getReminderByGid(r.getG_id().toString());
                        if (syncType.equals("I") && rlocal == null) {
                            r.setSyncflag("");
                            rdb.insert(r);
                        } else if (syncType.equals("E") && rlocal != null) {
                            if (rlocal.getG_timestamp() != r.getG_timestamp()) {
                                r.setSyncflag("");
                                rdb.updateWithG_Id(r, r.getG_id().toString());
                            }
                        } else if (syncType.equals("D") && rlocal != null) {
                            r.setSyncflag("");
                            rdb.delete(r.getG_id().toString()); // server
                            // instruction
                            // to remove
                            // record.
                            // remove.
                        }
                    }
                }

            }
        } catch (Exception ex) {
            Log.e(TAG, ex.toString(), ex);
        } finally {
            rdb.close();
        }
    }

    private void setAlarm(long period) {
        alarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + period, pi);
    }

    private void pollStatusUpdates(Account l) {
        String baseURI = "http://" + targetDomain + ":" + targetPort + "/wsdbServiceWAR/tweet/";
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpHost targetHost = new HttpHost(targetDomain, targetPort, "http");
        Serializer s = new Persister();

        //Send tweets to Server
        try {
            if (!updatedToSend.isEmpty()) {
                String urlToSendRequest = baseURI + "new";
                // Using POST here
                HttpPut httpput = new HttpPut(urlToSendRequest);
                // Make sure the server knows what kind of a response we will accept
                httpput.addHeader("Accept", "text/xml");
                // Also be sure to tell the server what kind of content we are sending
                httpput.addHeader("Content-Type", "application/xml");
                for (Tweet t : updatedToSend) {
                    StringEntity entity = new StringEntity(t.getXML(), "UTF-8");
                    entity.setContentType("application/xml");
                    httpput.setEntity(entity);

                    // execute is a blocking call, it's best to call this code in a thread separate from the ui's
                    HttpResponse response = httpClient.execute(targetHost, httpput);
                }
                updatedToSend.clear();
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.toString(), ex);
        } finally {
            rdb.close();
        }

        //receive tweets from server
        try {
            HttpGet httpget = null;
            String urlToSendRequest = baseURI + "get";
            httpget = new HttpGet(urlToSendRequest);
            httpget.addHeader("Accept", "application/xml");
            httpget.addHeader("Content-Type", "application/xml");
            HttpResponse response = httpClient.execute(targetHost, httpget);
            String gid = null;
            String msg = null;
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity en = response.getEntity();
                if (en != null) {
                    String str = convertStreamToString(en.getContent());
                    gpsalarm.app.datatype.Tweets rList = s.read(gpsalarm.app.datatype.Tweets.class, str);
                    List<Tweet> list = rList.getProperties();
                    if (list == null)
                        return;
                    boolean updatedFlag = false;
                    for (Tweet t : list) {
                        if (!sdb.contains(t.getRid().toString())) {
                            if (rdb.getReminderByGid(t.getGid()) != null) {
                                updatedFlag = true;
                                sdb.insert(t);
                                gid = t.getGid();
                                msg = t.getStatus();
                            }

                        }
                    }
                    if (updatedFlag)
                        showNotification(msg, gid);
                }
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.toString(), ex);
        } finally {
            rdb.close();
        }
    }

    private String convertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is), 8 * 1024);
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            Log.e(TAG, e.toString(), e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                Log.e(TAG, e.toString(), e);
            }
        }

        return sb.toString();

    }

    private void showNotification(String str, String gid) {
        final NotificationManager mgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification note = new Notification(R.drawable.status, "Locate@ Tweet", System.currentTimeMillis());
        Intent i = new Intent(this, AlarmEdit3.class);
        i.putExtra("user", prefs.getString("user", null));
        i.putExtra(ReminderHelper.GLOBAL_ID, gid);
        //      i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
        //                      Intent.FLAG_ACTIVITY_SINGLE_TOP);
        i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

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

        note.setLatestEventInfo(this, "Locate@ Tweet", str, pi);

        mgr.notify(NOTIFICATION_ID, note);
    }

    BroadcastReceiver onBatteryChanged = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int pct = 100 * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 1)
                    / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);

            isBatteryLow.set(pct <= 25);
        }
    };

    class Account {
        String user = null;
        String password = null;
        IPostListener callback = null;

        Account(String user, String password, IPostListener callback) {
            this.user = user;
            this.password = password;
            this.callback = callback;
        }
    }

    public class LocalBinder extends Binder implements IPostMonitor {
        public void registerAccount(String user, String password, IPostListener callback) {

            Account l = new Account(user, password, callback);
            pollStatusUpdates(l);
            accounts.put(callback, l);
        }

        public void removeAccount(IPostListener callback) {
            accounts.remove(callback);
        }

        public void updateStatus(String taskid, String author, String status) {
            Long now = Calendar.getInstance().getTime().getTime();
            Tweet p = new Tweet();
            p.setFriend(author);
            p.setGid(taskid);
            p.setStatus(status);
            p.setCreated(now);
            updatedToSend.add(p);
        }

        @Override
        public void invokeSync() {
            myAccount = new Account(prefs.getString("user", null), prefs.getString("password", ""), null);
            if (myAccount.user != null) {
                pollForReminderUpdates(myAccount, team);
                pollStatusUpdates(myAccount);
                //            pollForReminderUpdates(myAccount, "PUBLIC");
                updateLocation(myAccount);
                pollForProximityAlerts(myAccount);
            }
            Log.d("PostMonitor", "Sync Manually invoked");

        }
    }
}