package nz.co.android.cowseye; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Timer; import java.util.TimerTask; import nz.co.android.cowseye.database.DatabaseAdapter; import nz.co.android.cowseye.database.DatabaseConstructor; import nz.co.android.cowseye.event.Event; import nz.co.android.cowseye.event.EventHandler; import nz.co.android.cowseye.utility.Utils; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import android.app.Application; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.graphics.Bitmap; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.provider.MediaStore; import android.util.Log; public class RiverWatchApplication extends Application { /* Service paths */ public static String server_path = "http://api.riverwatch.co.nz:80/wainz"; public static String submission_path = server_path + "/submit"; public static String get_incidents_path = server_path + "/approved"; public static String get_incidents_path_start = "/start="; public static String get_incidents_path_number = "/number="; private static final long timerZeroDelay = 0; private static final long timerEventsProcessingPeriod = 300000; // 5 minutes private static final long timerEventsProcessingLargeDelay = 6000000; // 30 minutes private static final double MAX_TIMER_DELAYED_MULTIPLIER = 30; // 24 * 30 min = 720 min = 12 hours private double timerDelayedMultiplier = 1; // multiplier for the delay between event processing in the case of consecutive event fails or internet loss private static boolean eventProcessingSetup = false; public EventHandler eventHandler; private Timer updateEventsTimer; private DatabaseConstructor databaseConstructor; private DatabaseAdapter databaseAdapter; //Start of application @Override public void onCreate() { super.onCreate(); loadDatabase(); setupApplication(); } private void setupApplication() { updateEventsTimer = new Timer(); eventHandler = new EventHandler(this); } /** * Constructs and loads the database */ private void loadDatabase(){ databaseConstructor = new DatabaseConstructor(this); try { databaseConstructor.createDataBase(); } catch (IOException ioe) { Log.e(this.toString(),"Unable to create database"); } try { databaseConstructor.openDataBase(); }catch(SQLException sqle){ Log.e(this.toString(),"Unable to open database"); } databaseAdapter = new DatabaseAdapter(databaseConstructor); } // /** Adds this event to the database of events // * // * @param event - event to add // * @param type - type of the event. one of (check_in, check_out, registration) // * @param employeeId - employeedId of the employee if type is registration, otherwise null // */ // public void addNewEventToDatabase(Event event, String type, String employeeId) { // databaseAdapter.addNewEvent(event, type, employeeId); // } public DatabaseAdapter getDatabaseAdapter() { return databaseAdapter; } public EventHandler getEventHandler(){ return eventHandler; } /* Sets up and starts the timer to update events */ private void startEventProcessingTimer(final long initialDelay){ eventProcessingSetup = true; Log.i(toString(), "Starting Event Processing"); updateEventsTimer = new Timer(); /* Updates the event processing */ TimerTask processEvents = new TimerTask() { public void run() { Log.i(toString(), "processing events"); eventHandler.processEvents(); } }; updateEventsTimer.scheduleAtFixedRate(processEvents, initialDelay, timerEventsProcessingPeriod); } /** Requests the timer to update event processing if not already */ public void requestStartEventHandling(){ if(!eventProcessingSetup){ eventProcessingSetup = true; //starts timer with the normal delay of 0 milliseconds startEventProcessingTimer(timerZeroDelay); } } /** Stops the current time and starts a delayed timer * Called when the network is down, for a longer delay between trying again */ public void requestDelayedEventsTimer(){ stopTimerEventHandling(); if(timerDelayedMultiplier<1) timerDelayedMultiplier=1; else if(timerDelayedMultiplier>MAX_TIMER_DELAYED_MULTIPLIER) timerDelayedMultiplier = MAX_TIMER_DELAYED_MULTIPLIER; //start event handling with the large delay startEventProcessingTimer((long)(timerEventsProcessingLargeDelay*timerDelayedMultiplier)); //Next time an event has failed the delay will be twice as long if(timerDelayedMultiplier<MAX_TIMER_DELAYED_MULTIPLIER) timerDelayedMultiplier*=2; } /** Forces the event processing to start*/ public void forceStartEventHandling(){ //stops the current timer stopTimerEventHandling(); //starts timer again with delay of zero so instant update requestStartEventHandling(); } /** Stops the event processing timer if it is currently running */ public void stopTimerEventHandling(){ if(eventProcessingSetup){ Log.i(toString(),"stopping Timer Event Handling" ); eventProcessingSetup = false; updateEventsTimer.cancel(); } } /** Returns whether this device is currently connected to a network */ public boolean isOnline() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if(cm==null) return false; NetworkInfo networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); Boolean is3g = networkInfo==null? false : networkInfo.isConnected(); networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); Boolean isWifi= networkInfo==null? false : networkInfo.isConnected(); return is3g || isWifi; } /** Returns whether this device has GPS enabled */ public boolean isGPSEnabled(){ LocationManager mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); if(mLocationManager==null) return false; // Check if GPS enabled return mLocationManager.isProviderEnabled( LocationManager.GPS_PROVIDER ); } /** Downloads an employee image thumbnail * @param url - url to download image thumbnail from * @param e - thumbnail belongs to this employee * @param lastImageThumbPath - path where the last thumbnail for the employee is if it exists * @return the local path of the saved thumbnail */ // private String downloadEmployeeImageThumbnail(String url, String lastImageThumbPath) { // // Bitmap image = RestClient.getBitmapThroughGETRequestURL(url); // if(image!=null){ // try{ // String localImageThumbnail = saveBitmapToDisk(image); // //Delete last image if it exists // if(lastImageThumbPath!=null && !lastImageThumbPath.equals("")){ // deleteImage(lastImageThumbPath); // } // return localImageThumbnail; // } // catch(IOException f){ // Log.e(toString(), "Could not save image to disk : "+f); // } // } // return null; // } /* Saves a bitmap to disk */ public String saveBitmapToDisk(Bitmap bitmap, int incidentId, boolean isThumb) throws IOException { try{ // final long num = System.currentTimeMillis(); final String ID = getString(R.string.app_name).replace(" ", "_")+ (isThumb? "thumb" : "full") +"_"+incidentId; File dir = this.getDir("", Context.MODE_PRIVATE); String pathToDir = dir.getAbsolutePath(); final String pathName = pathToDir + File.separator+ ID; FileOutputStream out = new FileOutputStream(pathName); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); return pathName; } catch (FileNotFoundException e) { e.printStackTrace(); } throw new IOException("Could not create file or could not write to created file"); } /** Deletes an image from local storage */ public void deleteImage(String filePath) { File imageFile = new File(filePath); // Log.d(toString(), "deleteImage image exists before ? "+imageFile.exists()); //delete image if(imageFile.exists()) imageFile.delete(); // Log.d(toString(), "deleteImage image exists after ? "+imageFile.exists()); } // /* Deletes the image belonging to the current event */ // public void deleteImage(Event currentEvent) { // Log.d(toString(), "path1 : "+currentEvent.getImagePath().getPath()); // URI uri = null; // try { // uri = new URI(currentEvent.getImagePath().getPath()); // } catch (URISyntaxException e) { // Log.e(toString(), "URISyntaxException: "+e); // return ; // } // Log.d(toString(), "path1 : "+uri); // File imageFile = new File(currentEvent.getImagePath().getPath()); // Log.d(toString(), "deleteImage image exists before ? "+imageFile.exists()); // //delete image // if(imageFile.exists()) // imageFile.delete(); // Log.d(toString(), "deleteImage image exists after ? "+imageFile.exists()); // // } /** * Deals with the response from a submission event return * @param response from a submission event * @return true if succesfull submission, otherwise false */ public static boolean processEventResponse(HttpResponse response){ if(response==null) return false; StatusLine statusLine = response.getStatusLine(); if(statusLine == null) return false; int statusCode = statusLine.getStatusCode(); try{ switch(statusCode){ case Utils.HTTP_OK: Log.i("app", "statusCode : "+statusCode+", Sucessful event response!"); return true; case Utils.HTTP_LOGIC_ERROR: Log.i("app", "statusCode : "+statusCode+", Logic error: Unsucessful event response!"); return false; case Utils.HTTP_SERVER_ERROR: Log.i("app", "statusCode : "+statusCode+", Server error: Unsucessful event response!"); return false; default: Log.i("app", "statusCode : "+statusCode+", ncaught error: Unsucessful event response!"); return false; } // JSONObject jsonObject = JSONHelper.parseHttpResponseAsJSON(response); // Log.d("app", "jsonObject : "+jsonObject); } catch(Exception f){ Log.e("app", "Exception in JsonParsing : "+f); } return false; } /* Deletes the image belonging to the current event */ public void deleteImage(Event currentEvent) { File imageFile = new File(currentEvent.getImagePath().toString()); // Log.d(toString(), "deleteImage image exists before ? "+imageFile.exists()); //delete image if(imageFile.exists()) imageFile.delete(); // Log.d(toString(), "deleteImage image exists after ? "+imageFile.exists()); } public String getRealPathFromURI(Uri contentURI) { Cursor cursor = getContentResolver() .query(contentURI, null, null, null, null); cursor.moveToFirst(); int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); return cursor.getString(idx); } }