diff --git a/MyTracks/src/com/google/android/apps/mytracks/MyTracksApplication.java b/MyTracks/src/com/google/android/apps/mytracks/MyTracksApplication.java index 27cf04efb..c2749fce9 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/MyTracksApplication.java +++ b/MyTracks/src/com/google/android/apps/mytracks/MyTracksApplication.java @@ -22,7 +22,7 @@ import android.app.Application; /** * MyTracksApplication for keeping global state. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class MyTracksApplication extends Application { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsActivity.java index 61467a6f2..5c00f8874 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsActivity.java @@ -15,107 +15,33 @@ */ package com.google.android.apps.mytracks.io.docs; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendActivity; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask; import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest; import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity; import com.google.android.maps.mytracks.R; -import android.app.Activity; -import android.app.Dialog; -import android.app.ProgressDialog; -import android.content.DialogInterface; import android.content.Intent; -import android.os.Bundle; /** * An activity to send a track to Google Docs. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ -public class SendDocsActivity extends Activity { - - private static final int PROGRESS_DIALOG = 1; - - private SendRequest sendRequest; - private SendDocsAsyncTask asyncTask; - private ProgressDialog progressDialog; +public class SendDocsActivity extends AbstractSendActivity { @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY); - - Object retained = getLastNonConfigurationInstance(); - if (retained instanceof SendDocsAsyncTask) { - asyncTask = (SendDocsAsyncTask) retained; - asyncTask.setActivity(this); - } else { - asyncTask = new SendDocsAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount()); - asyncTask.execute(); - } + protected AbstractSendAsyncTask createAsyncTask() { + return new SendDocsAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount()); } @Override - public Object onRetainNonConfigurationInstance() { - asyncTask.setActivity(null); - return asyncTask; + protected String getServiceName() { + return getString(R.string.send_google_docs); } @Override - protected Dialog onCreateDialog(int id) { - switch (id) { - case PROGRESS_DIALOG: - progressDialog = new ProgressDialog(this); - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - progressDialog.setIcon(android.R.drawable.ic_dialog_info); - progressDialog.setTitle(getString( - R.string.send_google_progress_title, getString(R.string.send_google_docs))); - progressDialog.setMax(100); - progressDialog.setProgress(0); - progressDialog.setCancelable(true); - progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - asyncTask.cancel(true); - startNextActivity(false); - } - }); - return progressDialog; - default: - return null; - } - } - - /** - * Invokes when the associated AsyncTask completes. - * - * @param success true if success - */ - public void onAsyncTaskCompleted(boolean success) { - startNextActivity(success); - } - - /** - * Shows the progress dialog. - */ - public void showProgressDialog() { - showDialog(PROGRESS_DIALOG); - } - - /** - * Sets the progress dialog value. - */ - public void setProgressDialogValue(int value) { - if (progressDialog != null) { - progressDialog.setProgress(value); - } - } - - /** - * Starts the next activity. - * - * @param success true if sendDocs is success - */ - private void startNextActivity(boolean success) { + protected void startNextActivity(boolean success, boolean isCancel) { sendRequest.setDocsSuccess(success); Intent intent = new Intent(this, UploadResultActivity.class) .putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsAsyncTask.java index 7b4466d01..c31164387 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsAsyncTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/docs/SendDocsAsyncTask.java @@ -21,6 +21,7 @@ import com.google.android.apps.mytracks.io.gdata.GDataClientFactory; import com.google.android.apps.mytracks.io.gdata.docs.DocumentsClient; import com.google.android.apps.mytracks.io.gdata.docs.SpreadsheetsClient; import com.google.android.apps.mytracks.io.gdata.docs.XmlDocsGDataParserFactory; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask; import com.google.android.common.gdata.AndroidXmlParserFactory; import com.google.android.maps.mytracks.R; import com.google.wireless.gdata.client.GDataClient; @@ -33,7 +34,6 @@ import android.accounts.AccountManager; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.content.Context; -import android.os.AsyncTask; import android.util.Log; import java.io.IOException; @@ -41,9 +41,9 @@ import java.io.IOException; /** * AsyncTask to send a track to Google Docs. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ -public class SendDocsAsyncTask extends AsyncTask { +public class SendDocsAsyncTask extends AbstractSendAsyncTask { private static final int PROGRESS_GET_SPREADSHEET_ID = 0; private static final int PROGRESS_CREATE_SPREADSHEET = 25; private static final int PROGRESS_GET_WORKSHEET_ID = 50; @@ -52,7 +52,6 @@ public class SendDocsAsyncTask extends AsyncTask { private static final String TAG = SendDocsAsyncTask.class.getSimpleName(); - private SendDocsActivity activity; private final long trackId; private final Account account; private final Context context; @@ -61,21 +60,6 @@ public class SendDocsAsyncTask extends AsyncTask { private final DocumentsClient documentsClient; private final SpreadsheetsClient spreadsheetsClient; - /** - * True if can retry sending to Google Docs. - */ - private boolean canRetry; - - /** - * True if the AsyncTask has completed. - */ - private boolean completed; - - /** - * True if the result is success. - */ - private boolean success; - // The following variables are for per upload states private String documentsAuthToken; private String spreadsheetsAuthToken; @@ -83,7 +67,7 @@ public class SendDocsAsyncTask extends AsyncTask { private String worksheetId; public SendDocsAsyncTask(SendDocsActivity activity, long trackId, Account account) { - this.activity = activity; + super(activity); this.trackId = trackId; this.account = account; @@ -94,68 +78,22 @@ public class SendDocsAsyncTask extends AsyncTask { gDataClient, new XmlDocsGDataParserFactory(new AndroidXmlParserFactory())); spreadsheetsClient = new SpreadsheetsClient( gDataClient, new XmlDocsGDataParserFactory(new AndroidXmlParserFactory())); - - canRetry = true; - completed = false; - success = false; - } - - /** - * Sets the activity associated with this AyncTask. - * - * @param activity the activity. - */ - public void setActivity(SendDocsActivity activity) { - this.activity = activity; - if (completed && activity != null) { - activity.onAsyncTaskCompleted(success); - } } @Override - protected void onPreExecute() { - activity.showProgressDialog(); - } - - @Override - protected Boolean doInBackground(Void... params) { - return doUpload(); - } - - @Override - protected void onProgressUpdate(Integer... values) { - if (activity != null) { - activity.setProgressDialogValue(values[0]); - } - } - - @Override - protected void onPostExecute(Boolean result) { - closeClient(); - success = result; - completed = true; - if (activity != null) { - activity.onAsyncTaskCompleted(success); - } - } - - @Override - protected void onCancelled() { - closeClient(); - } - - private void closeClient() { + protected void closeConnection() { if (gDataClient != null) { gDataClient.close(); } } - /** - * Uploads a track to Google Docs. - * - * @return true if success. - */ - private boolean doUpload() { + @Override + protected void saveResult() { + // No action for Google Docs + } + + @Override + protected boolean performTask() { // Reset the per upload states documentsAuthToken = null; spreadsheetsAuthToken = null; @@ -169,13 +107,13 @@ public class SendDocsAsyncTask extends AsyncTask { account, spreadsheetsClient.getServiceName(), false); } catch (OperationCanceledException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } catch (AuthenticatorException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } catch (IOException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } Track track = myTracksProviderUtils.getTrack(trackId); @@ -192,7 +130,7 @@ public class SendDocsAsyncTask extends AsyncTask { // Get the spreadsheet ID publishProgress(PROGRESS_GET_SPREADSHEET_ID); if (!fetchSpreadSheetId(title, false)) { - return retryUpload(); + return retryTask(); } // Create a new spreadsheet if necessary @@ -223,7 +161,7 @@ public class SendDocsAsyncTask extends AsyncTask { // Get the worksheet ID publishProgress(PROGRESS_GET_WORKSHEET_ID); if (!fetchWorksheetId()) { - return retryUpload(); + return retryTask(); } if (worksheetId == null) { Log.d(TAG, "Unable to get a worksheet ID"); @@ -241,6 +179,14 @@ public class SendDocsAsyncTask extends AsyncTask { return true; } + @Override + protected void invalidateToken() { + AccountManager.get(context).invalidateAuthToken( + documentsClient.getServiceName(), documentsAuthToken); + AccountManager.get(context).invalidateAuthToken( + spreadsheetsClient.getServiceName(), spreadsheetsAuthToken); + } + /** * Fetches the spreadsheet id. Sets the instance variable * {@link SendDocsAsyncTask#spreadsheetId}. @@ -366,24 +312,4 @@ public class SendDocsAsyncTask extends AsyncTask { } return true; } - - /** - * Retries upload. Invalidates the authToken. If can retry, invokes - * {@link SendDocsAsyncTask#doUpload()}. Returns false if cannot retry. - */ - private boolean retryUpload() { - if (isCancelled()) { - return false; - } - - AccountManager.get(context).invalidateAuthToken( - documentsClient.getServiceName(), documentsAuthToken); - AccountManager.get(context).invalidateAuthToken( - spreadsheetsClient.getServiceName(), spreadsheetsAuthToken); - if (canRetry) { - canRetry = false; - return doUpload(); - } - return false; - } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesActivity.java index 287f8e955..052561d90 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesActivity.java @@ -16,121 +16,35 @@ package com.google.android.apps.mytracks.io.fusiontables; import com.google.android.apps.mytracks.io.docs.SendDocsActivity; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendActivity; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask; import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest; import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity; import com.google.android.maps.mytracks.R; -import android.app.Activity; -import android.app.Dialog; -import android.app.ProgressDialog; -import android.content.DialogInterface; import android.content.Intent; -import android.os.Bundle; /** * An activity to send a track to Google Fusion Tables. - *

- * The activity gets recreated when the screen rotates. To support the activity - * displaying a progress dialog, we do the following: - *

    - *
  • use one instance of an AyncTask to send the track
  • - *
  • save that instance as the last non configuration instance of the activity - *
  • - *
  • when a new activity is created, pass the activity to the AsyncTask so - * that the AsyncTask can update the progress dialog of the activity
  • - *
* - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ -public class SendFusionTablesActivity extends Activity { - - private static final int PROGRESS_DIALOG = 1; - - private SendRequest sendRequest; - private SendFusionTablesAsyncTask asyncTask; - private ProgressDialog progressDialog; +public class SendFusionTablesActivity extends AbstractSendActivity { @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY); - - Object retained = getLastNonConfigurationInstance(); - if (retained instanceof SendFusionTablesAsyncTask) { - asyncTask = (SendFusionTablesAsyncTask) retained; - asyncTask.setActivity(this); - } else { - asyncTask = new SendFusionTablesAsyncTask( - this, sendRequest.getTrackId(), sendRequest.getAccount()); - asyncTask.execute(); - } + protected AbstractSendAsyncTask createAsyncTask() { + return new SendFusionTablesAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount()); } @Override - public Object onRetainNonConfigurationInstance() { - asyncTask.setActivity(null); - return asyncTask; + protected String getServiceName() { + return getString(R.string.send_google_fusion_tables); } @Override - protected Dialog onCreateDialog(int id) { - switch (id) { - case PROGRESS_DIALOG: - progressDialog = new ProgressDialog(this); - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - progressDialog.setIcon(android.R.drawable.ic_dialog_info); - progressDialog.setTitle(getString( - R.string.send_google_progress_title, getString(R.string.send_google_fusion_tables))); - progressDialog.setMax(100); - progressDialog.setProgress(0); - progressDialog.setCancelable(true); - progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - asyncTask.cancel(true); - startNextActivity(false, true); - } - }); - return progressDialog; - default: - return null; - } - } - - /** - * Invokes when the associated AsyncTask completes. - * - * @param success true if success - */ - public void onAsyncTaskCompleted(boolean success) { - startNextActivity(success, false); - } - - /** - * Shows the progress dialog. - */ - public void showProgressDialog() { - showDialog(PROGRESS_DIALOG); - } - - /** - * Sets the progress dialog value. - */ - public void setProgressDialogValue(int value) { - if (progressDialog != null) { - progressDialog.setProgress(value); - } - } - - /** - * Starts the next activity. - * - * @param success true if sendFusionTables is success - * @param isCancel true if it is a cancel request - */ - private void startNextActivity(boolean success, boolean isCancel) { + protected void startNextActivity(boolean success, boolean isCancel) { sendRequest.setFusionTablesSuccess(success); - + Class next; if (isCancel) { next = UploadResultActivity.class; @@ -141,8 +55,7 @@ public class SendFusionTablesActivity extends Activity { next = UploadResultActivity.class; } } - Intent intent = new Intent(this, next) - .putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest); + Intent intent = new Intent(this, next).putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest); startActivity(intent); finish(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesAsyncTask.java index 6d5e99f7b..33beb643b 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesAsyncTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesAsyncTask.java @@ -6,6 +6,7 @@ import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Track; import com.google.android.apps.mytracks.content.Waypoint; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask; import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils; import com.google.android.apps.mytracks.stats.DoubleBuffer; import com.google.android.apps.mytracks.util.ApiAdapterFactory; @@ -32,7 +33,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.location.Location; -import android.os.AsyncTask; import android.util.Log; import java.io.ByteArrayInputStream; @@ -46,9 +46,9 @@ import java.util.Vector; /** * AsyncTask to send a track to Google Fusion Tables. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ -public class SendFusionTablesAsyncTask extends AsyncTask { +public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask { private static final String APP_NAME_PREFIX = "Google-MyTracks-"; private static final String SQL_KEY = "sql="; @@ -73,29 +73,12 @@ public class SendFusionTablesAsyncTask extends AsyncTask private static final String TAG = SendFusionTablesAsyncTask.class.getSimpleName(); - private SendFusionTablesActivity activity; - private final Context context; private final long trackId; private final Account account; private final MyTracksProviderUtils myTracksProviderUtils; private final HttpRequestFactory httpRequestFactory; - /** - * True if can retry sending to Google Fusion Tables. - */ - private boolean canRetry; - - /** - * True if the AsyncTask has completed. - */ - private boolean completed; - - /** - * True if the result is success. - */ - private boolean success; - // The following variables are for per upload states private String authToken; private String tableId; @@ -103,7 +86,7 @@ public class SendFusionTablesAsyncTask extends AsyncTask public SendFusionTablesAsyncTask( SendFusionTablesActivity activity, long trackId, Account account) { - this.activity = activity; + super(activity); this.trackId = trackId; this.account = account; @@ -111,65 +94,26 @@ public class SendFusionTablesAsyncTask extends AsyncTask myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context); HttpTransport transport = ApiAdapterFactory.getApiAdapter().getHttpTransport(); httpRequestFactory = transport.createRequestFactory(new MethodOverride()); - - canRetry = true; - completed = false; - success = false; } - /** - * Sets the activity associated with this AyncTask. - * - * @param activity the activity. - */ - public void setActivity(SendFusionTablesActivity activity) { - this.activity = activity; - if (completed && activity != null) { - activity.onAsyncTaskCompleted(success); + @Override + protected void closeConnection() { + // No action needed for Google Fusion Tables + } + + @Override + protected void saveResult() { + Track track = myTracksProviderUtils.getTrack(trackId); + if (track != null) { + track.setTableId(tableId); + myTracksProviderUtils.updateTrack(track); + } else { + Log.d(TAG, "No track"); } } @Override - protected void onPreExecute() { - activity.showProgressDialog(); - } - - @Override - protected Boolean doInBackground(Void... params) { - return doUpload(); - } - - @Override - protected void onProgressUpdate(Integer... values) { - if (activity != null) { - activity.setProgressDialogValue(values[0]); - } - } - - @Override - protected void onPostExecute(Boolean result) { - success = result; - completed = true; - if (success) { - Track track = myTracksProviderUtils.getTrack(trackId); - if (track != null) { - track.setTableId(tableId); - myTracksProviderUtils.updateTrack(track); - } else { - Log.d(TAG, "No track"); - } - } - if (activity != null) { - activity.onAsyncTaskCompleted(success); - } - } - - /** - * Uploads a track to Google Fusion Tables. - * - * @return true if success. - */ - private boolean doUpload() { + protected boolean performTask() { // Reset the per upload states authToken = null; tableId = null; @@ -179,13 +123,13 @@ public class SendFusionTablesAsyncTask extends AsyncTask authToken = AccountManager.get(context).blockingGetAuthToken(account, SERVICE_ID, false); } catch (OperationCanceledException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } catch (AuthenticatorException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } catch (IOException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } Track track = myTracksProviderUtils.getTrack(trackId); @@ -198,7 +142,7 @@ public class SendFusionTablesAsyncTask extends AsyncTask publishProgress(PROGRESS_CREATE_TABLE); if (!createNewTable(track)) { // Retry upload in case the auth token is invalid - return retryUpload(); + return retryTask(); } // Unlist table @@ -223,22 +167,9 @@ public class SendFusionTablesAsyncTask extends AsyncTask return true; } - /** - * Retries upload. Invalidates the authToken. If can retry, invokes - * {@link SendFusionTablesAsyncTask#doUpload()}. Returns false if cannot - * retry. - */ - private boolean retryUpload() { - if (isCancelled()) { - return false; - } - + @Override + protected void invalidateToken() { AccountManager.get(context).invalidateAuthToken(SERVICE_ID, authToken); - if (canRetry) { - canRetry = false; - return doUpload(); - } - return false; } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtils.java b/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtils.java index 752efcfe2..44eb97bc6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtils.java @@ -32,7 +32,7 @@ import java.util.Locale; /** * Utilities for sending a track to Google Fusion Tables. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class SendFusionTablesUtils { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapActivity.java index 6e87f217e..cedfd06e9 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapActivity.java @@ -41,7 +41,7 @@ import java.util.ArrayList; /** * An activity to choose a Google Map. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class ChooseMapActivity extends Activity { @@ -208,7 +208,7 @@ public class ChooseMapActivity extends Activity { /** * A class containing {@link ChooseMapActivity} list item. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ private class ListItem { private String mapId; diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapAsyncTask.java index 96c0064b8..a4a957197 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapAsyncTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/maps/ChooseMapAsyncTask.java @@ -42,7 +42,7 @@ import java.util.ArrayList; /** * AsyncTask for {@link ChooseMapActivity} to get all the maps from Google Maps. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class ChooseMapAsyncTask extends AsyncTask { private static final String TAG = ChooseMapAsyncTask.class.getSimpleName(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsActivity.java index 7b3d83de9..9d54efed5 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsActivity.java @@ -17,111 +17,36 @@ package com.google.android.apps.mytracks.io.maps; import com.google.android.apps.mytracks.io.docs.SendDocsActivity; import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendActivity; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask; import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest; import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity; import com.google.android.maps.mytracks.R; -import android.app.Activity; -import android.app.Dialog; -import android.app.ProgressDialog; -import android.content.DialogInterface; import android.content.Intent; -import android.os.Bundle; /** * An activity to send a track to Google Maps. * * @author Jimmy Shih */ -public class SendMapsActivity extends Activity { - - private static final int PROGRESS_DIALOG = 1; - - private SendRequest sendRequest; - private SendMapsAsyncTask asyncTask; - private ProgressDialog progressDialog; +public class SendMapsActivity extends AbstractSendActivity { @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY); - - Object retained = getLastNonConfigurationInstance(); - if (retained instanceof SendMapsAsyncTask) { - asyncTask = (SendMapsAsyncTask) retained; - asyncTask.setActivity(this); - } else { - asyncTask = new SendMapsAsyncTask( - this, sendRequest.getTrackId(), sendRequest.getAccount(), sendRequest.getMapId()); - asyncTask.execute(); - } + protected AbstractSendAsyncTask createAsyncTask() { + return new SendMapsAsyncTask( + this, sendRequest.getTrackId(), sendRequest.getAccount(), sendRequest.getMapId()); } @Override - public Object onRetainNonConfigurationInstance() { - asyncTask.setActivity(null); - return asyncTask; + protected String getServiceName() { + return getString(R.string.send_google_maps); } @Override - protected Dialog onCreateDialog(int id) { - switch (id) { - case PROGRESS_DIALOG: - progressDialog = new ProgressDialog(this); - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - progressDialog.setIcon(android.R.drawable.ic_dialog_info); - progressDialog.setTitle( - getString(R.string.send_google_progress_title, getString(R.string.send_google_maps))); - progressDialog.setMax(100); - progressDialog.setProgress(0); - progressDialog.setCancelable(true); - progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - asyncTask.cancel(true); - startNextActivity(false, true); - } - }); - return progressDialog; - default: - return null; - } - } - - /** - * Invokes when the associated AsyncTask completes. - * - * @param success true if success - */ - public void onAsyncTaskCompleted(boolean success) { - startNextActivity(success, false); - } - - /** - * Shows the progress dialog. - */ - public void showProgressDialog() { - showDialog(PROGRESS_DIALOG); - } - - /** - * Sets the progress dialog value. - */ - public void setProgressDialogValue(int value) { - if (progressDialog != null) { - progressDialog.setProgress(value); - } - } - - /** - * Starts the next activity. - * - * @param success true if sendMaps is success - * @param isCancel true if it is a cancel request - */ - private void startNextActivity(boolean success, boolean isCancel) { + protected void startNextActivity(boolean success, boolean isCancel) { sendRequest.setMapsSuccess(success); - + Class next; if (isCancel) { next = UploadResultActivity.class; @@ -134,8 +59,7 @@ public class SendMapsActivity extends Activity { next = UploadResultActivity.class; } } - Intent intent = new Intent(this, next) - .putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest); + Intent intent = new Intent(this, next).putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest); startActivity(intent); finish(); } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsAsyncTask.java index 09b20e3f8..07cea1f91 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsAsyncTask.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsAsyncTask.java @@ -24,6 +24,7 @@ import com.google.android.apps.mytracks.io.gdata.maps.MapsClient; import com.google.android.apps.mytracks.io.gdata.maps.MapsConstants; import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter; import com.google.android.apps.mytracks.io.gdata.maps.XmlMapsGDataParserFactory; +import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask; import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils; import com.google.android.apps.mytracks.stats.DoubleBuffer; import com.google.android.apps.mytracks.util.LocationUtils; @@ -43,7 +44,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.location.Location; -import android.os.AsyncTask; import android.util.Log; import java.io.IOException; @@ -63,7 +63,7 @@ import org.xmlpull.v1.XmlPullParserException; * * @author Jimmy Shih */ -public class SendMapsAsyncTask extends AsyncTask { +public class SendMapsAsyncTask extends AbstractSendAsyncTask { private static final String START_ICON_URL = "http://maps.google.com/mapfiles/ms/micons/green-dot.png"; private static final String END_ICON_URL = @@ -78,7 +78,6 @@ public class SendMapsAsyncTask extends AsyncTask { private static final String TAG = SendMapsAsyncTask.class.getSimpleName(); - private SendMapsActivity activity; private final long trackId; private final Account account; private final String chooseMapId; @@ -87,30 +86,15 @@ public class SendMapsAsyncTask extends AsyncTask { private final GDataClient gDataClient; private final MapsClient mapsClient; - /** - * True if can retry sending to Google Maps. - */ - private boolean canRetry; - - /** - * True if the AsyncTask has completed. - */ - private boolean completed; - - /** - * True if the result is success. - */ - private boolean success; - // The following variables are for per upload states private MapsGDataConverter mapsGDataConverter; private String authToken; private String mapId; int currentSegment; - public SendMapsAsyncTask( + public SendMapsAsyncTask ( SendMapsActivity activity, long trackId, Account account, String chooseMapId) { - this.activity = activity; + super(activity); this.trackId = trackId; this.account = account; this.chooseMapId = chooseMapId; @@ -120,80 +104,28 @@ public class SendMapsAsyncTask extends AsyncTask { gDataClient = GDataClientFactory.getGDataClient(context); mapsClient = new MapsClient( gDataClient, new XmlMapsGDataParserFactory(new AndroidXmlParserFactory())); - - canRetry = true; - completed = false; - success = false; - } - - /** - * Sets the activity associated with this AyncTask. - * - * @param activity the activity. - */ - public void setActivity(SendMapsActivity activity) { - this.activity = activity; - if (completed && activity != null) { - activity.onAsyncTaskCompleted(success); - } } @Override - protected void onPreExecute() { - activity.showProgressDialog(); - } - - @Override - protected Boolean doInBackground(Void... params) { - return doUpload(); - } - - @Override - protected void onProgressUpdate(Integer... values) { - if (activity != null) { - activity.setProgressDialogValue(values[0]); - } - } - - @Override - protected void onPostExecute(Boolean result) { - closeClient(); - success = result; - completed = true; - if (success) { - Track track = myTracksProviderUtils.getTrack(trackId); - if (track != null) { - track.setMapId(mapId); - myTracksProviderUtils.updateTrack(track); - } else { - Log.d(TAG, "No track"); - } - } - if (activity != null) { - activity.onAsyncTaskCompleted(success); - } - } - - @Override - protected void onCancelled() { - closeClient(); - } - - /** - * Closes the gdata client. - */ - private void closeClient() { + protected void closeConnection() { if (gDataClient != null) { gDataClient.close(); } } - /** - * Uploads a track to Google Maps. - * - * @return true if success. - */ - private boolean doUpload() { + @Override + protected void saveResult() { + Track track = myTracksProviderUtils.getTrack(trackId); + if (track != null) { + track.setMapId(mapId); + myTracksProviderUtils.updateTrack(track); + } else { + Log.d(TAG, "No track"); + } + } + + @Override + protected boolean performTask() { // Reset the per upload states mapsGDataConverter = null; authToken = null; @@ -214,13 +146,13 @@ public class SendMapsAsyncTask extends AsyncTask { account, MapsConstants.SERVICE_NAME, false); } catch (OperationCanceledException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } catch (AuthenticatorException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } catch (IOException e) { Log.d(TAG, "Unable to get auth token", e); - return retryUpload(); + return retryTask(); } // Get the track @@ -234,14 +166,14 @@ public class SendMapsAsyncTask extends AsyncTask { publishProgress(PROGRESS_FETCH_MAP_ID); if (!fetchSendMapId(track)) { Log.d("TAG", "Unable to upload all track points"); - return retryUpload(); + return retryTask(); } // Upload all the track points plus the start and end markers publishProgress(PROGRESS_UPLOAD_DATA_MIN); if (!uploadAllTrackPoints(track)) { Log.d("TAG", "Unable to upload all track points"); - return retryUpload(); + return retryTask(); } // Upload all the waypoints @@ -255,21 +187,9 @@ public class SendMapsAsyncTask extends AsyncTask { return true; } - /** - * Retries upload. Invalidates the authToken. If can retry, invokes - * {@link SendMapsAsyncTask#doUpload()}. Returns false if cannot retry. - */ - private boolean retryUpload() { - if (isCancelled()) { - return false; - } - + @Override + protected void invalidateToken() { AccountManager.get(context).invalidateAuthToken(MapsConstants.SERVICE_NAME, authToken); - if (canRetry) { - canRetry = false; - return doUpload(); - } - return false; } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsUtils.java b/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsUtils.java index db769c366..a1ff28f36 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/maps/SendMapsUtils.java @@ -37,7 +37,7 @@ import java.util.ArrayList; /** * Utilities for sending a track to Google Maps. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class SendMapsUtils { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AbstractSendActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AbstractSendActivity.java new file mode 100644 index 000000000..7ae6a1c7e --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AbstractSendActivity.java @@ -0,0 +1,139 @@ +/* + * Copyright 2012 Google Inc. + * + * 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. + */ + +package com.google.android.apps.mytracks.io.sendtogoogle; + +import com.google.android.maps.mytracks.R; + +import android.app.Activity; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.os.Bundle; + +/** + * The abstract class for activities sending a track to Google. + *

+ * The activity gets recreated when the screen rotates. To support the activity + * displaying a progress dialog, we do the following: + *

    + *
  • use one instance of an AyncTask to send the track
  • + *
  • save that instance as the last non configuration instance of the activity + *
  • + *
  • when a new activity is created, pass the activity to the AsyncTask so + * that the AsyncTask can update the progress dialog of the activity
  • + *
+ * + * @author Jimmy Shih + */ +public abstract class AbstractSendActivity extends Activity { + + private static final int PROGRESS_DIALOG = 1; + + protected SendRequest sendRequest; + private AbstractSendAsyncTask asyncTask; + private ProgressDialog progressDialog; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY); + + Object retained = getLastNonConfigurationInstance(); + if (retained instanceof AbstractSendAsyncTask) { + asyncTask = (AbstractSendAsyncTask) retained; + asyncTask.setActivity(this); + } else { + asyncTask = createAsyncTask(); + asyncTask.execute(); + } + } + + @Override + public Object onRetainNonConfigurationInstance() { + asyncTask.setActivity(null); + return asyncTask; + } + + @Override + protected Dialog onCreateDialog(int id) { + switch (id) { + case PROGRESS_DIALOG: + progressDialog = new ProgressDialog(this); + progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + progressDialog.setIcon(android.R.drawable.ic_dialog_info); + progressDialog.setTitle(getString(R.string.send_google_progress_title, getServiceName())); + progressDialog.setMax(100); + progressDialog.setProgress(0); + progressDialog.setCancelable(true); + progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + asyncTask.cancel(true); + startNextActivity(false, true); + } + }); + return progressDialog; + default: + return null; + } + } + + /** + * Invokes when the associated AsyncTask completes. + * + * @param success true if the AsyncTask is successful + */ + public void onAsyncTaskCompleted(boolean success) { + startNextActivity(success, false); + } + + /** + * Shows the progress dialog. + */ + public void showProgressDialog() { + showDialog(PROGRESS_DIALOG); + } + + /** + * Sets the progress dialog value. + * + * @param value the dialog value + */ + public void setProgressDialogValue(int value) { + if (progressDialog != null) { + progressDialog.setProgress(value); + } + } + + /** + * Creates the AsyncTask. + */ + protected abstract AbstractSendAsyncTask createAsyncTask(); + + /** + * Gets the service name. + */ + protected abstract String getServiceName(); + + /** + * Starts the next activity. + * + * @param success true if this activity is successful + * @param isCancel true if it is a cancel request + */ + protected abstract void startNextActivity(boolean success, boolean isCancel); +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AbstractSendAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AbstractSendAsyncTask.java new file mode 100644 index 000000000..3959c5b86 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AbstractSendAsyncTask.java @@ -0,0 +1,147 @@ +/* + * Copyright 2012 Google Inc. + * + * 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. + */ + +package com.google.android.apps.mytracks.io.sendtogoogle; + +import android.os.AsyncTask; + +/** + * The abstract class for AsyncTasks sending a track to Google. + * + * @author Jimmy Shih + */ +public abstract class AbstractSendAsyncTask extends AsyncTask { + + /** + * The activity associated with this AsyncTask. + */ + private AbstractSendActivity activity; + + /** + * True if the AsyncTask result is success. + */ + private boolean success; + + /** + * True if the AsyncTask has completed. + */ + private boolean completed; + + /** + * True if can retry the AsyncTask. + */ + private boolean canRetry; + + /** + * Creates an AsyncTask. + * + * @param activity the activity currently associated with this AsyncTask + */ + public AbstractSendAsyncTask(AbstractSendActivity activity) { + this.activity = activity; + success = false; + completed = false; + canRetry = true; + } + + /** + * Sets the current activity associated with this AyncTask. + * + * @param activity the current activity, can be null + */ + public void setActivity(AbstractSendActivity activity) { + this.activity = activity; + if (completed && activity != null) { + activity.onAsyncTaskCompleted(success); + } + } + + @Override + protected void onPreExecute() { + activity.showProgressDialog(); + } + + @Override + protected Boolean doInBackground(Void... params) { + return performTask(); + } + + @Override + protected void onProgressUpdate(Integer... values) { + if (activity != null) { + activity.setProgressDialogValue(values[0]); + } + } + + @Override + protected void onPostExecute(Boolean result) { + success = result; + if (success) { + saveResult(); + } + completed = true; + closeConnection(); + if (activity != null) { + activity.onAsyncTaskCompleted(success); + } + } + + @Override + protected void onCancelled() { + closeConnection(); + } + + /** + * Retries the task. First, invalidates the auth token. If can retry, invokes + * {@link #performTask()}. Returns false if cannot retry. + * + * @return the result of the retry. + */ + protected boolean retryTask() { + if (isCancelled()) { + return false; + } + + invalidateToken(); + if (canRetry) { + canRetry = false; + return performTask(); + } + return false; + } + + /** + * Closes any AsyncTask connection. + */ + protected abstract void closeConnection(); + + /** + * Saves any AsyncTask result. + */ + protected abstract void saveResult(); + + /** + * Performs the AsyncTask. + * + * @return true if success + */ + protected abstract boolean performTask(); + + /** + * Invalidates the auth token. + */ + protected abstract void invalidateToken(); +} diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AccountChooserActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AccountChooserActivity.java index 0af149c90..67c47d6f6 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AccountChooserActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/AccountChooserActivity.java @@ -38,7 +38,7 @@ import android.os.Bundle; /** * A chooser to select an account. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class AccountChooserActivity extends Activity { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java index 1dda1c770..cd50ac18f 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadResultActivity.java @@ -38,7 +38,7 @@ import android.widget.TextView; /** * A dialog to show the result of uploading to Google services. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class UploadResultActivity extends Activity { diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java index 26d0d77ef..b2b044032 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/sendtogoogle/UploadServiceChooserActivity.java @@ -41,7 +41,7 @@ import android.widget.TableRow; /** * A chooser to select the Google services to upload a track to. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class UploadServiceChooserActivity extends Activity { diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/ControlRecordingService.java b/MyTracks/src/com/google/android/apps/mytracks/services/ControlRecordingService.java index 4232ba0d4..11e6b2a13 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/ControlRecordingService.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/ControlRecordingService.java @@ -37,7 +37,7 @@ import android.util.Log; * application delegates starting and stopping a recording to * {@link TrackRecordingService} using RPC calls. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class ControlRecordingService extends IntentService implements ServiceConnection { diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/docs/SendDocsUtilsTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/docs/SendDocsUtilsTest.java index 7823269b9..8b416dbd4 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/docs/SendDocsUtilsTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/docs/SendDocsUtilsTest.java @@ -26,7 +26,7 @@ import android.test.AndroidTestCase; /** * Tests {@link SendDocsUtils}. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class SendDocsUtilsTest extends AndroidTestCase { diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java index a75aca1a1..01590997d 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java @@ -16,7 +16,6 @@ package com.google.android.apps.mytracks.io.fusiontables; import com.google.android.apps.mytracks.content.Track; -import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesUtils; import com.google.android.apps.mytracks.stats.TripStatistics; import android.location.Location; @@ -30,7 +29,7 @@ import junit.framework.TestCase; /** * Tests {@link SendFusionTablesUtils}. * - * @author jshih@google.com (Jimmy Shih) + * @author Jimmy Shih */ public class SendFusionTablesUtilsTest extends TestCase {