/clients/android/branches/response-codes/src/org/moca/util/BackgroundUploader.java
Java | 343 lines | 293 code | 32 blank | 18 comment | 36 complexity | a1e87ba8db85b5544f6bca09bfa5ae09 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
- package org.moca.util;
-
- import java.util.PriorityQueue;
- import java.util.Timer;
- import java.util.TimerTask;
-
- import org.moca.Constants;
- import org.moca.db.MocaDB.ProcedureSQLFormat;
- import org.moca.db.MocaDB.SavedProcedureSQLFormat;
- import org.moca.net.MDSInterface;
-
- import android.app.Service;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.Intent;
- import android.database.Cursor;
- import android.net.Uri;
- import android.net.wifi.WifiManager;
- import android.os.Binder;
- import android.os.IBinder;
- import android.os.Looper;
- import android.telephony.TelephonyManager;
- import android.util.Log;
- import android.view.Gravity;
- import android.widget.Toast;
-
- /**
- * Background service to upload pending transfers when data service is available.
- * NOTE: This is used in conjunction with DataConnectionListener which also offloads
- * pending transfers, but only on a no connection -> connection transition.
- * This class will try to offload the pending transfers at a certain interval -
- * useful because we may have given up on a transfer during an episode with virtually
- * no usable connection, but technically still within GPRS service area (so a transition
- * never occurs).
- */
- public class BackgroundUploader extends Service {
-
- private final IBinder mBinder = new LocalBinder();
- private static TelephonyManager telMan;
- private static WifiManager wifiMan;
- private Timer timer = new Timer();
- private static final long POLL_INTERVAL = Constants.DEFAULT_POLL_PERIOD * 1000;
- private static PriorityQueue<Uri> queue = new PriorityQueue<Uri>();
- private static final String TAG = BackgroundUploader.class.toString();
- private static boolean uploadFlag = false;
- private static boolean result = false;
- private static ContentResolver contentResolver;
- private static boolean isCredentialsValidated = false;
-
- private static final String[] PROJECTION = {
- SavedProcedureSQLFormat._ID,
- SavedProcedureSQLFormat.GUID,
- SavedProcedureSQLFormat.PROCEDURE_ID,
- SavedProcedureSQLFormat.UPLOAD_QUEUE };
-
- public class LocalBinder extends Binder {
- BackgroundUploader getService() {
- return BackgroundUploader.this;
- }
- }
-
- @Override
- public void onCreate() {
- //Log.i(TAG, "in oncreate()");
- try {
- super.onCreate();
- startService();
- telMan = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
- wifiMan = (WifiManager) getSystemService(WIFI_SERVICE);
- contentResolver = getContentResolver();
-
- initQueue(getBaseContext());
- }
- catch (Exception e) {
- Log.e(TAG, "Exception creating background uploading service: " + e.toString());
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- shutdownService();
- }
-
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- //Used by methods in this class, as well as in other classes,
- //such as in Settings.java before validating password.
- public static boolean checkConnection(Context c, ContentResolver cr) {
- try {
- boolean hasConnection;
- telMan = (TelephonyManager) c.getSystemService(Context.TELEPHONY_SERVICE);
- wifiMan = (WifiManager) c.getSystemService(WIFI_SERVICE);
- hasConnection = telMan.getDataState() == TelephonyManager.DATA_CONNECTED || (wifiMan.isWifiEnabled() && wifiMan.pingSupplicant());
- Log.i(TAG, "checkConnection is returning: " + hasConnection);
- if (hasConnection) {
- try {
- ContentValues cv = new ContentValues();
- Log.i(TAG, "Here is the queue right now: " + queue);
- Log.i(TAG, "Right now the value of isCredentialsValidated is: " + isCredentialsValidated);
- if (isCredentialsValidated)
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 1); // Signify procedures waiting in queue to be uploaded
- else
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 6); // Signify username/password incorrect
-
- for (Uri procedure: queue) {
- Log.i(TAG, "Updating queue status in checkConnection for procedure: " + procedure);
- cr.update(procedure, cv, null, null);
- }
- } catch (Exception e) {
- Log.e(TAG, "Exception updating upload status in database: " + e.toString());
- }
- return true;
- } else {
- try {
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 4); // Signify procedures waiting for connectivity to upload
- for (Uri procedure: queue)
- cr.update(procedure, cv, null, null);
- } catch (Exception e) {
- Log.e(TAG, "Exception updating upload status in database: " + e.toString());
- }
- return false;
- }
- }
- catch (Exception e) {
- Log.e(TAG, "Exception in checkConnection(): " + e.toString());
- return false;
- }
- }
-
- private void startService() {
- try {
- //Log.i(TAG, "Service has been started for background uploading.");
- if (checkConnection(getBaseContext(), contentResolver)) {
- isCredentialsValidated = MDSInterface.validateCredentials(getBaseContext());
- }
- timer.scheduleAtFixedRate(
- new TimerTask() {
- public void run() {
- if (checkConnection(getBaseContext(), contentResolver)) {
- Log.i(TAG, "startService is calling inituploads");
- initUploads(getBaseContext());
- }
- }
- },
- 0,
- POLL_INTERVAL);
- }
- catch (Exception e) {
- Log.e(TAG, "Exception in starting service: " + e.toString());
- }
- }
-
- private void shutdownService() {
- if (timer != null)
- timer.cancel();
- }
-
- public static boolean addProcedureToQueue(Uri procedureUri) {
- Log.i(TAG, "addProcedureToQueue" + procedureUri);
- boolean result = queue.add(procedureUri);
- Log.i(TAG, "Queue is now: " + queue.toString());
- updateQueueInDB();
- if (isCredentialsValidated) {
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 1); //Signify waiting in queue to be uploaded
- contentResolver.update(procedureUri, cv, null, null);
- } else {
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 6); // Signify procedures incorrect username/password
- contentResolver.update(procedureUri, cv, null, null);
- }
- Log.i(TAG, "Succeeded in adding procedure to upload queue? " + result);
- return result;
- }
-
- public static boolean removeFromQueue(Uri procedureUri) {
- Log.i(TAG, "removeFromQueue" + procedureUri);
- if (isInQueue(procedureUri)) {
- queue.remove(procedureUri);
- updateQueueInDB();
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_QUEUE, -1);
- contentResolver.update(procedureUri, cv, null, null); // Signify no longer in queue
- return true;
- }
- return false;
- }
-
- public static boolean isInQueue(Uri procedureUri) {
- return queue.contains(procedureUri);
- }
-
- public static int queueIndex(Uri procedureUri) {
- if (isInQueue(procedureUri)) {
- Object[] queueList = queue.toArray();
- for (int i = 0; i < queueList.length; i++) {
- Uri test = (Uri) queueList[i];
- if (test.equals(procedureUri))
- return i;
- }
- }
- return -1;
- }
-
- //Only check credentials with openMRS when username or password have changed in settings
- public static void credentialsChanged(boolean credentials, ContentResolver cr) {
- isCredentialsValidated = credentials;
- Log.i(TAG, "Queue is now: " + queue);
- if (isCredentialsValidated) {
- Log.i(TAG, "In credentialsChanged, Validate Credentials returned true");
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 1); // Signify procedures waiting in queue to be uploaded
- for (Uri procedure: queue)
- cr.update(procedure, cv, null, null);
- } else {
- Log.i(TAG, "In credentialsChanged, Validate Credentials returned false - could not validate OpenMRS username/password");
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 6); // Signify procedures incorrect username/password
- for (Uri procedure: queue)
- cr.update(procedure, cv, null, null);
- }
- }
-
- public static void initUploads(final Context c) {
- // check if there are pending transfers in the database
- // if so, then spawn a thread to upload the first one
-
- Log.i(TAG, "initUploads has been called.");
- uploadFlag = (!queue.isEmpty()) && checkConnection(c, contentResolver);
- if (uploadFlag) {
- if (!isCredentialsValidated) {
- Log.i(TAG, "OpenMRS username/password incorrect - will not attempt to upload");
- }
- else {
- Thread t = new Thread() {
- public void run() {
- Looper.prepare();
- while (uploadFlag) {
- Uri procedure = queue.element();
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 3);
- contentResolver.update(procedure, cv, null, null); // Signify procedure upload in progress
- result = MDSInterface.postProcedureToDjangoServer(procedure, c);
- if(result) uploadSuccess(c, procedure);
- else if (!result) uploadFailure(c, procedure);
- uploadFlag = !queue.isEmpty() && checkConnection(c, contentResolver);
- Log.i(TAG, "uploadFlag after a loop: " + uploadFlag);
- }
- Looper.loop();
- Looper.myLooper().quit();
- }
- };
- Log.i(TAG, "running a new thread to do the upload.");
- t.start();
- }
- }
- }
-
- private static void uploadSuccess(Context c, Uri procedure) {
- Log.i(TAG, "Upload was successfull. Now in uploadSuccess()");
- removeFromQueue(procedure); //Remove the procedure from the queue after it has been successfully uploaded
-
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 2); // Signify has been uploaded
- contentResolver.update(procedure, cv, null, null); // Signify has been uploaded
-
- Cursor cursor = c.getContentResolver().query(procedure, new String [] { SavedProcedureSQLFormat._ID, SavedProcedureSQLFormat.PROCEDURE_ID, SavedProcedureSQLFormat.PROCEDURE_STATE }, null, null, null);
- cursor.moveToFirst();
- long savedProcedureId = cursor.getLong(cursor.getColumnIndex(SavedProcedureSQLFormat._ID));
- long procedureId = cursor.getLong(cursor.getColumnIndex(SavedProcedureSQLFormat.PROCEDURE_ID));
- cursor.deactivate();
- int sizeOfQueue = queue.size();
- Uri procedureUri = ContentUris.withAppendedId(ProcedureSQLFormat.CONTENT_URI, procedureId);;
- cursor = c.getContentResolver().query(procedureUri, new String[] { ProcedureSQLFormat.TITLE }, null, null, null);
- cursor.moveToFirst();
- String procedureTitle = cursor.getString(cursor.getColumnIndex(ProcedureSQLFormat.TITLE));
- cursor.deactivate();
-
-
- //String msg = "Successfully sent " + procedureTitle + " procedure\nwith ID = " + savedProcedureId;
- String msg = "Successfully sent procedure\nwith ID = " + savedProcedureId;
- if (sizeOfQueue != 0) {
- msg += "\nThere are still " + sizeOfQueue + "\nprocedures to be uploaded.";
- }
- else {
- msg += "\nAll procedures are done uploading.";
- }
- Toast toast = Toast.makeText(c, msg, Toast.LENGTH_LONG);
- toast.setGravity(Gravity.CENTER, 0, 0);
- toast.show();
- }
-
- private static void uploadFailure(Context c, Uri procedure) {
- Log.i(TAG, "Upload failed. Now in uploadFailure()");
- removeFromQueue(procedure); //Remove the procedure from the queue so it does not keep trying to upload
- ContentValues cv = new ContentValues();
- cv.put(SavedProcedureSQLFormat.UPLOAD_STATUS, 5); // Signify did not successfully upload
- contentResolver.update(procedure, cv, null, null);
- }
-
- private static void updateQueueInDB() {
- Log.i(TAG, "Updating queue information in the database");
- Log.i(TAG, "Queue is now: " + queue.toString());
- ContentValues cv;
- for (Uri procedureUri: queue) {
- cv = new ContentValues();
- Log.i(TAG, "In updateQueueInDB, queueIndex(" + procedureUri + ") returns: " + queueIndex(procedureUri));
- cv.put(SavedProcedureSQLFormat.UPLOAD_QUEUE, queueIndex(procedureUri));
- contentResolver.update(procedureUri, cv, null, null);
- }
- }
-
- private static void initQueue(Context c) {
- try {
- //Initialize the queue from the database
- Log.i(TAG, "In initQueue - getting queue from database");
- Cursor cursor = c.getContentResolver().query(SavedProcedureSQLFormat.CONTENT_URI, PROJECTION,
- SavedProcedureSQLFormat.UPLOAD_QUEUE + " >= 0",
- null, SavedProcedureSQLFormat.QUEUE_SORT_ORDER);
- cursor.moveToFirst();
-
- while (!cursor.isAfterLast()) {
- int savedProcedureId = cursor.getInt(0);
- Log.i(TAG, "savedProcedureId is: " + savedProcedureId);
- Uri savedProcedureUri = ContentUris.withAppendedId(SavedProcedureSQLFormat.CONTENT_URI, savedProcedureId);
- Log.i(TAG, "Adding procedure with this Uri to the queue: " + savedProcedureUri);
- queue.add(savedProcedureUri);
- cursor.moveToNext();
- }
- Log.i(TAG, "Queue has been extracted from database. Here is the queue: " + queue);
- } catch (Exception e) {
- Log.e(TAG, "Exception in getting queue from database: " + e.toString());
- }
- }
- }