Java tutorial
/* * Copyright (C) 2014 TU Darmstadt, Hessen, Germany. * Department of Computer Science Databases and Distributed Systems * * 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 3 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, see <http://www.gnu.org/licenses/>. */ /** * */ package de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.IMyHealthHubRemoteService; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.MyHealthHubWithFragments; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.R; import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.commontools.JSONParser; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.AsyncTask; import android.os.BatteryManager; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.preference.CheckBoxPreference; import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; /** * Idea is that myHealthHub regularly (each 15mins!?) does a battery check and * the current GPS Location of the device and sends data to a Server. In case of * System Failure and the patient is in a critical condition, we can use those to * check for his last known location. * * @author HieuHa * */ public class SystemMonitor extends Service { private int batteryPercent = 0; private JSONParser jParser = new JSONParser(); @Override public IBinder onBind(Intent arg0) { Log.e(SystemMonitor.class.getSimpleName(), "onBind()"); return iservicestub; } private IMyHealthHubRemoteService.Stub iservicestub = new IMyHealthHubRemoteService.Stub() { @Override public int getStatus() throws RemoteException { // / Write here, code to be executed in background Log.e(SystemMonitor.class.getSimpleName(), "Hello World From Remote Service!!"); return 0; } }; private LocationResult locationResult = new LocationResult() { @Override public void gotLocation(Location location) { String t = getTimestamp() + "\n"; t += "BatteryPercent: " + batteryPercent + "\n"; t += "-----------------------------------------"; writeStringToLogFile(t); // Got the location! // publishResult(location); } }; private BroadcastReceiver batteryLvlReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); batteryPercent = (level * 100) / scale; } }; @Override public void onCreate() { super.onCreate(); // Use filter for Monitor Significant Changes in Battery Level only // Generally speaking, the impact of constantly monitoring the // battery // level has a greater impact on the battery than your app's normal // behavior, so it's good practice to only monitor significant // changes // in battery levelspecifically when the device enters or exits a // low // battery state. IntentFilter ifilter = new IntentFilter(); ifilter.addAction(Intent.ACTION_BATTERY_CHANGED); // ifilter.addAction(Intent.ACTION_BATTERY_OKAY); this.registerReceiver(batteryLvlReceiver, ifilter); // get Location MyLocation myLocation = new MyLocation(); myLocation.getLocation(this, locationResult); // scheduleNextUpdate(); // Notify user of this service // systemNotice(); this.stopSelf(); } private int systemNotice() { int t = START_STICKY; Log.e(SystemMonitor.class.getSimpleName(), "call me redundant BABY! onStartCommand service"); int myID = android.os.Process.myPid(); // The intent to launch when the user clicks the expanded notification Intent intent = new Intent(this, MyHealthHubWithFragments.class); // Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intent, 0); Notification notice = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher) .setWhen(System.currentTimeMillis()).setContentTitle(getPackageName()) .setContentText("System Monitor running").setContentIntent(pendIntent).getNotification(); notice.flags |= Notification.FLAG_AUTO_CANCEL; NotificationManager mNotificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE); mNotificationManager.notify(myID, notice); return t; } @Override public void onDestroy() { Log.e(SystemMonitor.class.getSimpleName(), "OnDestroy: /** Disconnection **/"); // stopr this service stopForeground(true); this.unregisterReceiver(batteryLvlReceiver); super.onDestroy(); } private void writeStringToLogFile(String text) { File root = Environment.getExternalStorageDirectory(); File file = new File(root, "SystemBatteryMonitor.txt"); try { if (!file.exists()) file.createNewFile(); FileWriter filewriter = new FileWriter(file, true); filewriter.append(text); filewriter.close(); } catch (IOException e) { Toast.makeText(this, "Unable to write file: " + e.toString(), Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } private void publishResult(Location loc) { String t = getTimestamp() + "\n"; t += "Longitude:" + loc.getLongitude() + "\n"; t += "Latitude:" + loc.getLatitude() + "\n"; t += "BatteryPercent: " + batteryPercent + "\n"; t += "-----------------------------------------"; SharedPreferences prefs = getApplicationContext().getSharedPreferences("personal", Context.MODE_PRIVATE); phoneNr = prefs.getString(getString(R.string.p_emcy_phone_nr), ""); // TODO: check Internet State before sending // send message to server JSONArray jsa = new JSONArray(); JSONObject jso = new JSONObject(); try { jso.put("Timestamp", getTimestamp()); jso.put("Longitude", loc.getLongitude()); jso.put("Latitude", loc.getLatitude()); jso.put("PercentBattery", batteryPercent); jsa.put(jso); sendNotification(jsa); } catch (JSONException e) { Log.e(SystemMonitor.class.getSimpleName(), e.getLocalizedMessage()); } // send message to a gmail acc new AsyncTask<String, Void, Void>() { @Override protected Void doInBackground(String... params) { // String message = params[0]; // GMailSender sender = new GMailSender( // null, // null); // try { // sender.sendMail("myHealthAssistant: SystemMonitor", // message, // null, // null); // } catch (Exception e) { // Log.e(SystemMonitor.class.getSimpleName(), e.getMessage()); // } return null; } }.execute(t, null, null); } private String phoneNr; private void sendNotification(JSONArray t) { new AsyncTask<JSONArray, Void, Void>() { @Override protected Void doInBackground(JSONArray... params) { JSONArray message = params[0]; try { // Building Parameters List<NameValuePair> pairs = new ArrayList<NameValuePair>(); pairs.add(new BasicNameValuePair("message", message.toString())); pairs.add(new BasicNameValuePair("phone", phoneNr)); JSONObject json = jParser.makeHttpRequest(getString(R.string.send_url), "POST", pairs); // check log cat for response if (json != null) { String response = json.getString("message"); Log.e(SystemMonitor.class.getSimpleName(), "Post Response: " + response); } else Log.e(SystemMonitor.class.getSimpleName(), "No Response!!"); } catch (JSONException e) { Log.e(SystemMonitor.class.getSimpleName(), "JSONException: " + e.getMessage()); } return null; } @Override protected void onPostExecute(Void v) { } }.execute(t, null, null); } /** * Returns the current time as "yyyy-MM-dd hh:mm:ss". * * @return time stamp */ private String getTimestamp() { return (String) android.text.format.DateFormat.format("yyyy-MM-dd hh:mm:ss", new java.util.Date()); } /** * First of all I check what providers are enabled. Some may be disabled on * the device, some may be disabled in application manifest. If any provider * is available I start location listeners and timeout timer. It's 20 * seconds in my example, may not be enough for GPS so you can enlarge it. * If I get update from location listener I use the provided value. I stop * listeners and timer. If I don't get any updates and timer elapses I have * to use last known values. I grab last known values from available * providers and choose the most recent of them. * * @author Fedor (stackoverflow.com) * */ private class MyLocation { private Timer timer1; private int timeout = 20000; private LocationManager lm; private LocationResult locationResult; private boolean gps_enabled = false; private boolean network_enabled = false; public boolean getLocation(Context context, LocationResult result) { // I use LocationResult callback class to pass location value from // MyLocation to user code. locationResult = result; if (lm == null) lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); // exceptions will be thrown if provider is not permitted. try { gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER); } catch (Exception ex) { } try { network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER); } catch (Exception ex) { } // don't start listeners if no provider is enabled if (!gps_enabled && !network_enabled) return false; if (gps_enabled) lm.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListenerGps, Looper.myLooper()); // lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, // locationListenerGps); if (network_enabled) lm.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListenerGps, Looper.myLooper()); // lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, // 0, locationListenerNetwork); timer1 = new Timer(); timer1.schedule(new GetLastLocation(), timeout); return true; } LocationListener locationListenerGps = new LocationListener() { public void onLocationChanged(Location location) { timer1.cancel(); locationResult.gotLocation(location); lm.removeUpdates(this); lm.removeUpdates(locationListenerNetwork); } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } }; LocationListener locationListenerNetwork = new LocationListener() { public void onLocationChanged(Location location) { timer1.cancel(); locationResult.gotLocation(location); lm.removeUpdates(this); lm.removeUpdates(locationListenerGps); } public void onProviderDisabled(String provider) { Toast.makeText(getApplicationContext(), "GPS disabled!", Toast.LENGTH_SHORT).show(); } public void onProviderEnabled(String provider) { Toast.makeText(getApplicationContext(), "GPS enabled!", Toast.LENGTH_SHORT).show(); } public void onStatusChanged(String provider, int status, Bundle extras) { Toast.makeText(getApplicationContext(), "GPS status changed!", Toast.LENGTH_SHORT).show(); } }; class GetLastLocation extends TimerTask { @Override public void run() { lm.removeUpdates(locationListenerGps); lm.removeUpdates(locationListenerNetwork); Location net_loc = null, gps_loc = null; if (gps_enabled) gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (network_enabled) net_loc = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); // if there are both values use the latest one if (gps_loc != null && net_loc != null) { if (gps_loc.getTime() > net_loc.getTime()) locationResult.gotLocation(gps_loc); else locationResult.gotLocation(net_loc); return; } if (gps_loc != null) { locationResult.gotLocation(gps_loc); return; } if (net_loc != null) { locationResult.gotLocation(net_loc); return; } locationResult.gotLocation(null); } } } public static abstract class LocationResult { public abstract void gotLocation(Location location); } }