Removing singleton usage: moving all send and save logic out of the MyTracks class.

This is a non-trivial step: I decentralized dialog creation (since it made no sense to have a single place creating a lot of completely unrelated dialogs), made invisible activities just for sending/saving, and changed menu handling a bit, all to decentralize those functions from MyTracks.

There's still a TODO to handle GET_LOGIN more nicely instead of returning from the depths of auth management into the current activity.
This commit is contained in:
Rodrigo Damazio
2011-05-25 04:50:21 -03:00
parent 16b0d4eb24
commit eeaa50ddcb
16 changed files with 978 additions and 863 deletions
+7
View File
@@ -90,6 +90,13 @@ limitations under the License.
android:label="@string/elevation_label"
android:exported="false" />
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.SendActivity"
android:label="@string/sendtogoogle_title"
android:theme="@android:style/Theme.Translucent" />
<activity android:name="com.google.android.apps.mytracks.io.file.SaveActivity"
android:label="@string/tracklist_write_to_sd"
android:theme="@android:style/Theme.Translucent" />
<activity android:name="com.google.android.apps.mytracks.WelcomeActivity"
android:label="@string/welcome"
android:exported="false" />
@@ -29,7 +29,7 @@ import android.util.Log;
* @author Sandor Dornbush
*/
public class AccountChooser {
/**
* The last selected account.
*/
@@ -68,13 +68,13 @@ public class AccountChooser {
handler.handleAccountSelected(accounts[0]);
return;
}
// TODO This should be read out of a preference.
if (selectedAccount != null) {
handler.handleAccountSelected(selectedAccount);
return;
}
// Let the user choose.
Log.e(Constants.TAG, "Multiple matching accounts found.");
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
@@ -50,7 +50,7 @@ public abstract class Constants {
public static final int AUTHENTICATE_TO_DOCLIST = 10;
public static final int AUTHENTICATE_TO_TRIX = 11;
public static final int DELETE_TRACK = 13;
public static final int SEND_TO_GOOGLE_DIALOG = 14;
public static final int SEND_TO_GOOGLE = 14;
public static final int SHARE_LINK = 15;
public static final int SHARE_GPX_FILE = 16;
public static final int SHARE_KML_FILE = 17;
@@ -190,7 +190,7 @@ public abstract class Constants {
public static int getActionFromMenuId(int menuId) {
switch (menuId) {
case Constants.MENU_SEND_TO_GOOGLE:
return Constants.SEND_TO_GOOGLE_DIALOG;
return Constants.SEND_TO_GOOGLE;
case Constants.MENU_EDIT:
return Constants.EDIT_DETAILS;
case Constants.MENU_DELETE:
@@ -24,6 +24,8 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager.BadTokenException;
@@ -37,7 +39,6 @@ public class DialogManager {
public static final int DIALOG_IMPORT_PROGRESS = 2;
public static final int DIALOG_PROGRESS = 3;
public static final int DIALOG_SEND_TO_GOOGLE = 4;
private ProgressDialog progressDialog;
private ProgressDialog importProgressDialog;
@@ -69,21 +70,10 @@ public class DialogManager {
progressDialog.setMax(100);
progressDialog.setProgress(10);
return progressDialog;
case DIALOG_SEND_TO_GOOGLE:
sendToGoogleDialog = new SendDialog(activity);
return sendToGoogleDialog;
}
return null;
}
protected void onPrepareDialog(int id, Dialog dialog) {
switch (id) {
case DIALOG_SEND_TO_GOOGLE:
activity.resetSendToGoogleStatus();
break;
}
}
public void setProgressMessage(final String message) {
activity.runOnUiThread(new Runnable() {
public void run() {
@@ -126,19 +116,24 @@ public class DialogManager {
public void showMessageDialog(final int message, final boolean success) {
activity.runOnUiThread(new Runnable() {
public void run() {
AlertDialog dialog = null;
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(message));
builder.setNegativeButton(activity.getString(R.string.ok), null);
builder.setIcon(success ? android.R.drawable.ic_dialog_info :
android.R.drawable.ic_dialog_alert);
builder.setTitle(success ? R.string.success : R.string.error);
dialog = builder.create();
dialog.show();
showMessageDialog(activity, message, success, null);
}
});
}
public static void showMessageDialog(
Context ctx, int message, boolean success, DialogInterface.OnClickListener okListener) {
AlertDialog dialog = null;
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setMessage(message);
builder.setNeutralButton(R.string.ok, okListener);
builder.setIcon(success ? android.R.drawable.ic_dialog_info :
android.R.drawable.ic_dialog_alert);
builder.setTitle(success ? R.string.success : R.string.error);
dialog = builder.create();
dialog.show();
}
/**
* Just like showDialog, but will catch a {@link BadTokenException} that
* sometimes (very rarely) gets thrown. This might happen if the user hits
@@ -23,6 +23,8 @@ import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
import com.google.android.apps.mytracks.content.TrackDataListener;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.SaveActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendActivity;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ApiFeatures;
@@ -391,13 +393,27 @@ public class MapActivity extends com.google.android.maps.MapActivity
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (!super.onMenuItemSelected(featureId, item)) {
MyTracks.getInstance().onActivityResult(
Constants.getActionFromMenuId(item.getItemId()), RESULT_OK,
new Intent());
return true;
switch (item.getItemId()) {
case Constants.MENU_SEND_TO_GOOGLE:
SendActivity.sendToGoogle(this, dataHub.getSelectedTrackId(), false);
return true;
case Constants.MENU_SHARE_LINK:
SendActivity.sendToGoogle(this, dataHub.getSelectedTrackId(), true);
return true;
case Constants.MENU_SAVE_GPX_FILE:
case Constants.MENU_SAVE_KML_FILE:
case Constants.MENU_SAVE_CSV_FILE:
case Constants.MENU_SAVE_TCX_FILE:
case Constants.MENU_SHARE_GPX_FILE:
case Constants.MENU_SHARE_KML_FILE:
case Constants.MENU_SHARE_CSV_FILE:
case Constants.MENU_SHARE_TCX_FILE:
SaveActivity.handleExportTrackAction(this, dataHub.getSelectedTrackId(),
Constants.getActionFromMenuId(item.getItemId()));
return true;
default:
return super.onMenuItemSelected(featureId, item);
}
return false;
}
@Override
@@ -25,11 +25,7 @@ import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
@@ -42,29 +38,12 @@ import android.widget.TextView;
* @author Rodrigo Damazio
*/
public class MyMapsList extends Activity implements MapsFacade.MapsListCallback {
private static final int MENU_OPEN = 0;
private static final int MENU_SHARE = 2;
private static final int GET_LOGIN = 1;
private MapsFacade mapsClient;
private AuthManager auth;
private MyMapsListAdapter listAdapter;
private int contextPosition;
private final OnCreateContextMenuListener contextMenuListener =
new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) menuInfo;
contextPosition = info.position;
menu.add(0, MENU_OPEN, 0, R.string.open_map);
menu.add(0, MENU_SHARE, 0, R.string.share_map);
}
};
private final OnItemClickListener clickListener =
new OnItemClickListener() {
@Override
@@ -91,7 +70,6 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
ListView list = (ListView) findViewById(R.id.maplist);
list.setOnItemClickListener(clickListener);
list.setOnCreateContextMenuListener(contextMenuListener);
list.setAdapter(listAdapter);
startLogin();
@@ -101,7 +79,8 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
// Starts in the UI thread.
// TODO fix this for non-froyo devices.
if (AuthManagerFactory.useModernAuthManager()) {
MyTracks.getInstance().getAccountChooser().chooseAccount(
AccountChooser accountChooser = new AccountChooser();
accountChooser.chooseAccount(
MyMapsList.this,
new AccountChooser.AccountHandler() {
@Override
@@ -183,27 +162,4 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case MENU_OPEN:
clickListener.onItemClick(null, null, contextPosition, 0);
return true;
case MENU_SHARE:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
getText(R.string.share_map_subject));
String[] listItem = (String[]) listAdapter.getMapListingArray(contextPosition);
shareIntent.putExtra(Intent.EXTRA_TEXT, String.format(
getText(R.string.share_map_body_format).toString(),
listItem[1],
MapsFacade.buildMapUrl(listItem[0])));
startActivity(Intent.createChooser(shareIntent,
getText(R.string.share_map).toString()));
return true;
}
return false;
}
}
@@ -17,36 +17,16 @@ package com.google.android.apps.mytracks;
import static com.google.android.apps.mytracks.Constants.TAG;
import static com.google.android.apps.mytracks.DialogManager.DIALOG_IMPORT_PROGRESS;
import static com.google.android.apps.mytracks.DialogManager.DIALOG_PROGRESS;
import static com.google.android.apps.mytracks.DialogManager.DIALOG_SEND_TO_GOOGLE;
import com.google.android.accounts.Account;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.SendToDocs;
import com.google.android.apps.mytracks.io.SendToFusionTables;
import com.google.android.apps.mytracks.io.SendToFusionTables.OnSendCompletedListener;
import com.google.android.apps.mytracks.io.SendToMyMaps;
import com.google.android.apps.mytracks.io.file.GpxImporter;
import com.google.android.apps.mytracks.io.file.TempFileCleaner;
import com.google.android.apps.mytracks.io.file.TrackWriter;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
import com.google.android.apps.mytracks.io.sendtogoogle.ResultDialogFactory;
import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog;
import com.google.android.apps.mytracks.io.sendtogoogle.SendResult;
import com.google.android.apps.mytracks.io.sendtogoogle.SendType;
import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.TrackRecordingService;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R;
@@ -60,13 +40,9 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -79,13 +55,9 @@ import android.widget.RelativeLayout;
import android.widget.TabHost;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
@@ -98,21 +70,7 @@ import org.xml.sax.SAXException;
*/
public class MyTracks extends TabActivity implements OnTouchListener,
ProgressIndicator {
/**
* Singleton instance
*/
private static MyTracks instance;
private TrackDataHub dataHub;
private ChartActivity chartActivity;
/*
* Authentication
*/
private AuthManager auth;
private final HashMap<String, AuthManager> authMap =
new HashMap<String, AuthManager>();
private final AccountChooser accountChooser = new AccountChooser();
/*
* Dialogs manager.
@@ -124,21 +82,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
*/
private MenuManager menuManager;
/*
* Information on upload success to MyMaps/Docs.
* Used by SendToGoogleResultDialog.
*/
public long sendToTrackId = -1;
public boolean sendToMyMapsSuccess = false;
public boolean sendToFusionTablesSuccess = false;
public boolean sendToDocsSuccess = false;
public String sendToMyMapsMapId;
public String sendToMyMapsMessage = "";
public String sendToFusionTablesTableId;
public String sendToFusionTablesMessage = "";
public String sendToDocsMessage = "";
/**
* True if a new track should be created after the track recording service
* binds.
@@ -147,11 +90,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
private ITrackRecordingService trackRecordingService;
/**
* Does the user want to share the current track.
*/
private boolean shareRequested = false;
/**
* Utilities to deal with the database.
*/
@@ -205,10 +143,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
};
public static MyTracks getInstance() {
return instance;
}
/**
* Checks whether we have a track recording session in progress.
* In some cases, when the service has crashed or has been restarted
@@ -318,6 +252,53 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
}
private void importGpxFile(final String fileName) {
dialogManager.showDialogSafely(DIALOG_IMPORT_PROGRESS);
Thread t = new Thread() {
@Override
public void run() {
int message = R.string.success;
long[] trackIdsImported = null;
try {
try {
InputStream is = new FileInputStream(fileName);
trackIdsImported = GpxImporter.importGPXFile(is, providerUtils);
} catch (SAXException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_generic;
} catch (ParserConfigurationException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_generic;
} catch (IOException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_unable_to_read_file;
} catch (NullPointerException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_invalid_gpx_format;
} catch (OutOfMemoryError e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_out_of_memory;
}
if (trackIdsImported != null && trackIdsImported.length > 0) {
// select last track from import file
dataHub.loadTrack(trackIdsImported[trackIdsImported.length - 1]);
} else {
dialogManager.showMessageDialog(message, false/* success */);
}
} finally {
runOnUiThread(new Runnable() {
public void run() {
dismissDialog(DIALOG_IMPORT_PROGRESS);
}
});
}
}
};
t.start();
}
@Override
protected void onDestroy() {
Log.d(TAG, "MyTracks.onDestroy");
@@ -410,12 +391,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
return dialogManager.onCreateDialog(id, null);
}
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
dialogManager.onPrepareDialog(id, dialog);
}
/*
* Key events:
* ===========
@@ -442,19 +417,12 @@ public class MyTracks extends TabActivity implements OnTouchListener,
public void onActivityResult(int requestCode, int resultCode,
final Intent results) {
Log.d(TAG, "MyTracks.onActivityResult");
TrackFileFormat exportFormat = null;
long trackId = dataHub.getSelectedTrackId();
if (results != null) {
trackId = results.getLongExtra("trackid", trackId);
}
switch (requestCode) {
case Constants.GET_LOGIN: {
if (resultCode != RESULT_OK || auth == null || !auth.authResult(resultCode, results)) {
dialogManager.dismissDialogSafely(DIALOG_PROGRESS);
}
break;
}
case Constants.SHOW_TRACK: {
if (results != null) {
if (trackId >= 0) {
@@ -497,118 +465,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
break;
}
case Constants.SEND_TO_GOOGLE_DIALOG: {
shareRequested = false;
dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE);
break;
}
case Constants.GET_MAP: {
// User picked a map to upload to
if (resultCode == RESULT_OK) {
results.putExtra("trackid", dataHub.getSelectedTrackId());
if (results.hasExtra("mapid")) {
sendToMyMapsMapId = results.getStringExtra("mapid");
}
authenticateToGoogleMaps(results);
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_MY_MAPS: {
// Authenticated with Google My Maps
if (results != null && resultCode == RESULT_OK) {
final String mapId;
if (results.hasExtra("mapid")) {
mapId = results.getStringExtra("mapid");
} else {
mapId = "new";
}
sendToGoogleMaps(trackId, mapId);
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_FUSION_TABLES: {
// Authenticated with Google Fusion Tables
if (results != null && resultCode == RESULT_OK) {
sendToFusionTables(trackId);
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_DOCLIST: {
// Authenticated with Google Docs
if (resultCode == RESULT_OK) {
authenticateToGoogleTrix();
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_TRIX: {
// Authenticated with Trix
if (resultCode == RESULT_OK) {
sendToGoogleDocs(trackId);
} else {
onSendToGoogleDone();
}
break;
}
case Constants.SAVE_GPX_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; }
//$FALL-THROUGH$
case Constants.SAVE_KML_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.KML; }
//$FALL-THROUGH$
case Constants.SAVE_CSV_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; }
//$FALL-THROUGH$
case Constants.SAVE_TCX_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) {
if (trackId >= 0) {
saveTrack(trackId, exportFormat);
}
}
break;
case Constants.SHARE_LINK: {
Track selectedTrack = providerUtils.getTrack(dataHub.getSelectedTrackId());
if (selectedTrack != null) {
if (!TextUtils.isEmpty(selectedTrack.getMapId())) {
shareLinkToMap(MapsFacade.buildMapUrl(selectedTrack.getMapId()));
} else if (!TextUtils.isEmpty(selectedTrack.getTableId())) {
shareLinkToMap(getFusionTablesUrl(dataHub.getSelectedTrackId()));
} else {
shareRequested = true;
dialogManager.showDialogSafely(DIALOG_SEND_TO_GOOGLE);
}
}
break;
}
case Constants.SHARE_GPX_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.GPX; }
//$FALL-THROUGH$
case Constants.SHARE_KML_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.KML; }
//$FALL-THROUGH$
case Constants.SHARE_CSV_FILE:
if (exportFormat == null) { exportFormat = TrackFileFormat.CSV; }
//$FALL-THROUGH$
case Constants.SHARE_TCX_FILE: {
if (exportFormat == null) { exportFormat = TrackFileFormat.TCX; }
if (results != null && resultCode == Activity.RESULT_OK) {
if (trackId >= 0) {
sendTrack(trackId, exportFormat);
}
}
break;
}
case Constants.CLEAR_MAP: {
dataHub.unloadCurrentTrack();
break;
@@ -631,68 +487,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
return false;
}
/**
* Resets status information for sending to MyMaps/Docs.
*/
public void resetSendToGoogleStatus() {
sendToMyMapsMapId = null;
sendToMyMapsMessage = "";
sendToMyMapsSuccess = true;
sendToFusionTablesMessage = "";
sendToFusionTablesSuccess = true;
sendToDocsMessage = "";
sendToDocsSuccess = true;
sendToFusionTablesTableId = null;
}
private void importGpxFile(final String fileName) {
dialogManager.showDialogSafely(DIALOG_IMPORT_PROGRESS);
Thread t = new Thread() {
@Override
public void run() {
int message = R.string.success;
long[] trackIdsImported = null;
try {
try {
InputStream is = new FileInputStream(fileName);
trackIdsImported = GpxImporter.importGPXFile(is, providerUtils);
} catch (SAXException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_generic;
} catch (ParserConfigurationException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_generic;
} catch (IOException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_unable_to_read_file;
} catch (NullPointerException e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_invalid_gpx_format;
} catch (OutOfMemoryError e) {
Log.e(TAG, "Caught an unexpected exception.", e);
message = R.string.error_out_of_memory;
}
if (trackIdsImported != null && trackIdsImported.length > 0) {
// select last track from import file
dataHub.loadTrack(trackIdsImported[trackIdsImported.length - 1]);
} else {
dialogManager.showMessageDialog(message, false/* success */);
}
} finally {
runOnUiThread(new Runnable() {
public void run() {
dismissDialog(DIALOG_IMPORT_PROGRESS);
}
});
}
}
};
t.start();
}
// ProgressIndicator implementation
@Override
@@ -710,29 +504,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
dialogManager.setProgressValue(percent);
}
/**
* Shares a link to a My Map or Fusion Table via external app (email, gmail, ...)
* A chooser with apps that support text/plain will be shown to the user.
*/
public void shareLinkToMap(String url) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
getResources().getText(R.string.share_map_subject).toString());
boolean shareUrlOnly = true;
if (sharedPreferences != null) {
shareUrlOnly = sharedPreferences.getBoolean(
getString(R.string.share_url_only_key), false);
}
String msg = shareUrlOnly ? url : String.format(
getResources().getText(R.string.share_map_body_format).toString(), url);
shareIntent.putExtra(Intent.EXTRA_TEXT, msg);
startActivity(Intent.createChooser(shareIntent,
getResources().getText(R.string.share_map).toString()));
}
/**
* Deletes the track with the given id.
* Prompts the user if he want to really delete the track first.
@@ -787,54 +558,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
}
/**
* Initializes the authentication manager which obtains an authentication
* token, prompting the user for a login and password if needed.
*/
private void authenticate(final Intent results, final int requestCode,
final String service) {
auth = authMap.get(service);
if (auth == null) {
Log.i(TAG, "Creating a new authentication for service: " + service);
auth = AuthManagerFactory.getAuthManager(this,
Constants.GET_LOGIN,
null,
true,
service);
authMap.put(service, auth);
}
Log.d(TAG, "Logging in to " + service + "...");
if (AuthManagerFactory.useModernAuthManager()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
accountChooser.chooseAccount(MyTracks.this,
new AccountChooser.AccountHandler() {
@Override
public void handleAccountSelected(Account account) {
if (account == null) {
dialogManager.dismissDialogSafely(DIALOG_PROGRESS);
return;
}
doLogin(results, requestCode, service, account);
}
});
}
});
} else {
doLogin(results, requestCode, service, null);
}
}
private void doLogin(final Intent results, final int requestCode,
final String service, final Account account) {
auth.doLogin(new Runnable() {
public void run() {
Log.d(TAG, "Loggin success for " + service + "!");
onActivityResult(requestCode, RESULT_OK, results);
}
}, account);
}
private void startRecordingNewTrack(
ITrackRecordingService trackRecordingService) {
@@ -900,290 +623,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
trackRecordingService = null;
}
/**
* Initiates the process to send tracks to google.
* This is called once the user has selected sending options via the
* SendToGoogleDialog.
*
* TODO: Change this whole flow to an actual state machine.
*/
public void sendToGoogle() {
SendDialog sendToGoogleDialog =
dialogManager.getSendToGoogleDialog();
if (sendToGoogleDialog == null) {
return;
}
setProgressValue(0);
clearProgressMessage();
dialogManager.showDialogSafely(DIALOG_PROGRESS);
if (sendToGoogleDialog.getSendToMyMaps()) {
sendToGoogleMapsOrPickMap(sendToGoogleDialog);
} else if (sendToGoogleDialog.getSendToFusionTables()) {
authenticateToFusionTables(null);
} else if (sendToGoogleDialog.getSendToDocs()) {
authenticateToGoogleDocs();
} else {
Log.w(TAG, "Nowhere to upload to");
onSendToGoogleDone();
}
}
private void sendToGoogleMapsOrPickMap(SendDialog sendToGoogleDialog) {
if (!sendToGoogleDialog.getCreateNewMap()) {
// Ask the user to choose a map to upload into
Intent listIntent = new Intent(this, MyMapsList.class);
startActivityForResult(listIntent, Constants.GET_MAP);
// The callback for GET_MAP calls authenticateToGoogleMaps
} else {
authenticateToGoogleMaps(null);
}
}
private void authenticateToGoogleMaps(Intent results) {
if (results == null) { results = new Intent(); }
setProgressValue(0);
setProgressMessage(
R.string.progress_message_authenticating_mymaps);
authenticate(results, Constants.AUTHENTICATE_TO_MY_MAPS,
MyMapsConstants.SERVICE_NAME);
// AUTHENTICATE_TO_MY_MAPS callback calls sendToGoogleMaps
}
private void sendToGoogleMaps(final long trackId, String mapId) {
SendToMyMaps.OnSendCompletedListener onCompletion = new SendToMyMaps.OnSendCompletedListener() {
@Override
public void onSendCompleted(String mapId, boolean success, int statusMessage) {
sendToMyMapsMessage = getString(statusMessage);
sendToMyMapsSuccess = success;
if (sendToMyMapsSuccess) {
sendToMyMapsMapId = mapId;
// Update the map id for this track:
try {
Track track = providerUtils.getTrack(trackId);
track.setMapId(mapId);
providerUtils.updateTrack(track);
} catch (RuntimeException e) {
// If that fails whatever reasons we'll just log an error, but
// continue.
Log.w(TAG, "Updating map id failed.", e);
}
}
onSendToGoogleMapsDone();
}
};
final SendToMyMaps sender = new SendToMyMaps(this, mapId, auth,
trackId, this /*progressIndicator*/, onCompletion);
HandlerThread handlerThread = new HandlerThread("SendToMyMaps");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(sender);
}
private void onSendToGoogleMapsDone() {
SendDialog sendToGoogleDialog = dialogManager.getSendToGoogleDialog();
if (sendToGoogleDialog.getSendToFusionTables()) {
authenticateToFusionTables(null);
} else if (sendToGoogleDialog.getSendToDocs()) {
authenticateToGoogleDocs();
} else {
onSendToGoogleDone();
}
}
private void authenticateToFusionTables(Intent results) {
if (results == null) { results = new Intent(); }
setProgressValue(0);
setProgressMessage(R.string.progress_message_authenticating_fusiontables);
authenticate(results, Constants.AUTHENTICATE_TO_FUSION_TABLES,
SendToFusionTables.SERVICE_ID);
// AUTHENTICATE_TO_FUSION_TABLES callback calls sendToFusionTables
}
private void sendToFusionTables(final long trackId) {
OnSendCompletedListener onCompletion = new OnSendCompletedListener() {
@Override
public void onSendCompleted(String tableId, boolean success,
int statusMessage) {
sendToFusionTablesMessage = getString(statusMessage);
sendToFusionTablesSuccess = success;
if (sendToFusionTablesSuccess) {
sendToFusionTablesTableId = tableId;
// Update the table id for this track:
try {
Track track = providerUtils.getTrack(trackId);
track.setTableId(tableId);
providerUtils.updateTrack(track);
} catch (RuntimeException e) {
// If that fails whatever reasons we'll just log an error, but
// continue.
Log.w(TAG, "Updating table id failed.", e);
}
}
onSendToFusionTablesDone();
}
};
sendToTrackId = trackId;
final SendToFusionTables sender = new SendToFusionTables(this, auth,
trackId, this/*progressIndicator*/, onCompletion);
HandlerThread handlerThread = new HandlerThread("SendToFusionTables");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(sender);
}
private void onSendToFusionTablesDone() {
SendDialog sendToGoogleDialog = dialogManager.getSendToGoogleDialog();
if (sendToGoogleDialog.getSendToDocs()) {
authenticateToGoogleDocs();
} else {
onSendToGoogleDone();
}
}
private void authenticateToGoogleDocs() {
setProgressValue(0);
setProgressMessage(
R.string.progress_message_authenticating_docs);
authenticate(new Intent(),
Constants.AUTHENTICATE_TO_DOCLIST,
SendToDocs.GDATA_SERVICE_NAME_DOCLIST);
// AUTHENTICATE_TO_DOCLIST callback calls authenticateToGoogleTrix
}
private void authenticateToGoogleTrix() {
setProgressValue(30);
setProgressMessage(
R.string.progress_message_authenticating_docs);
authenticate(new Intent(),
Constants.AUTHENTICATE_TO_TRIX,
SendToDocs.GDATA_SERVICE_NAME_TRIX);
// AUTHENTICATE_TO_TRIX callback calls sendToGoogleDocs
}
private void sendToGoogleDocs(final long trackId) {
Log.d(TAG, "Sending to Docs....");
setProgressValue(50);
setProgressMessage(R.string.progress_message_sending_docs);
final SendToDocs sender = new SendToDocs(this,
authMap.get(SendToDocs.GDATA_SERVICE_NAME_TRIX),
authMap.get(SendToDocs.GDATA_SERVICE_NAME_DOCLIST), trackId);
sendToTrackId = trackId;
Runnable onCompletion = new Runnable() {
public void run() {
setProgressValue(100);
dialogManager.dismissDialogSafely(DIALOG_PROGRESS);
sendToDocsMessage = sender.getStatusMessage();
sendToDocsSuccess = sender.wasSuccess();
onSendToGoogleDocsDone();
}
};
sender.setOnCompletion(onCompletion);
sender.run();
}
private void onSendToGoogleDocsDone() {
onSendToGoogleDone();
}
private void onSendToGoogleDone() {
SendDialog sendToGoogleDialog = dialogManager.getSendToGoogleDialog();
final boolean sentToMyMaps = sendToGoogleDialog.getSendToMyMaps();
final boolean sentToFusionTables = sendToGoogleDialog.getSendToFusionTables();
dialogManager.dismissDialogSafely(DIALOG_PROGRESS);
// We've finished sending the track to the user-selected services. Now
// we tell them the results of the upload, and optionally share the track.
// There are a few different paths through this code:
//
// 1. The user pre-requested a share (shareRequested == true). We're going
// to display the result dialog *without* the share button (the share
// listener will be null). The OK button listener will initiate the
// share.
//
// 2. The user did not pre-request a share, and the set of services to
// which we succeeded in uploading the track are compatible with
// sharing. We'll display a share button (the share listener will be
// non-null), and will share the link if the user clicks it.
//
// 3. The user did not pre-request a share, and the set of services to
// which we succeeded in uploading the track are incompatible with
// sharing. We won't display a share button.
final boolean canShare = getSendToFusionTablesTableId() != null
|| getSendToMyMapsMapId() != null;
DialogInterface.OnClickListener doShareListener = null;
if (canShare) {
doShareListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
shareLinkToMap(sentToMyMaps, sentToFusionTables);
}
};
}
DialogInterface.OnClickListener onOkListener = (canShare && shareRequested)
? doShareListener : null;
DialogInterface.OnClickListener onShareListener = (canShare && !shareRequested)
? doShareListener : null;
AlertDialog sendToGoogleResultDialog = ResultDialogFactory.makeDialog(this,
makeSendToGoogleResults(sendToGoogleDialog), onOkListener, onShareListener);
DialogManager.showDialogSafely(this, sendToGoogleResultDialog);
}
boolean shareLinkToMap(boolean sentToMyMaps, boolean sentToFusionTables) {
String url = null;
if (sentToMyMaps && sendToMyMapsSuccess) {
// Prefer a link to My Maps
url = MapsFacade.buildMapUrl(sendToMyMapsMapId);
} else if (sentToFusionTables && sendToFusionTablesSuccess) {
// Otherwise try using the link to fusion tables
url = getFusionTablesUrl(sendToTrackId);
}
if (url != null) {
shareLinkToMap(url);
return true;
}
return false;
}
protected String getFusionTablesUrl(long trackId) {
Track track = providerUtils.getTrack(trackId);
return track == null ? "" : SendToFusionTables.getMapVisualizationUrl(track);
}
/**
* Creates a list of {@link SendResult} instances based on the set of
* services selected in {@link SendDialog} and the results as known to
* this class.
*/
private List<SendResult> makeSendToGoogleResults(SendDialog dialog) {
List<SendResult> results = new ArrayList<SendResult>();
if (dialog.getSendToMyMaps()) {
results.add(new SendResult(SendType.MYMAPS, sendToMyMapsSuccess));
}
if (dialog.getSendToFusionTables()) {
results.add(new SendResult(SendType.FUSION_TABLES, sendToFusionTablesSuccess));
}
if (dialog.getSendToDocs()) {
results.add(new SendResult(SendType.DOCS, sendToDocsSuccess));
}
return results;
}
void clearSelectedTrack() {
dataHub.unloadCurrentTrack();
}
@@ -1221,94 +660,10 @@ public class MyTracks extends TabActivity implements OnTouchListener,
}
}
/**
* Saves the track with the given id to the SD card.
*
* @param trackId The id of the track to be sent
*/
public void saveTrack(long trackId, TrackFileFormat format) {
TrackWriter writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format);
WriteProgressController controller = new WriteProgressController(this, writer);
controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() {
@Override
public void onComplete(TrackWriter writer) {
dialogManager.showMessageDialog(writer.getErrorMessage(), writer.wasSuccess());
}
});
controller.startWrite();
}
/**
* Sends the requested track as an email attachment.
* This will leave the gpx file on the SD card for at least one hour.
* Temporary gpx files will be deleted in onStop.
*
* @param trackId The id of the track to be sent
*/
public void sendTrack(long trackId, final TrackFileFormat format) {
TrackWriter writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format);
FileUtils fileUtils = new FileUtils();
String extension = format.getExtension();
String dirName = fileUtils.buildExternalDirectoryPath(extension, "tmp");
File dir = new File(dirName);
writer.setDirectory(dir);
WriteProgressController controller = new WriteProgressController(this, writer);
controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() {
@Override
public void onComplete(TrackWriter writer) {
if (!writer.wasSuccess()) {
dialogManager.showMessageDialog(writer.getErrorMessage(), writer.wasSuccess());
return;
}
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
getResources().getText(R.string.send_track_subject).toString());
shareIntent.putExtra(Intent.EXTRA_TEXT,
getResources().getText(R.string.send_track_body_format)
.toString());
shareIntent.setType(format.getMimeType());
Uri u = Uri.fromFile(new File(writer.getAbsolutePath()));
shareIntent.putExtra(Intent.EXTRA_STREAM, u);
startActivity(Intent.createChooser(shareIntent,
getResources().getText(R.string.share_track).toString()));
}
});
controller.startWrite();
}
public AccountChooser getAccountChooser() {
return accountChooser;
}
public ChartActivity getChartActivity() {
return chartActivity;
}
public void setChartActivity(ChartActivity chartActivity) {
this.chartActivity = chartActivity;
}
public DialogManager getDialogManager() {
return dialogManager;
}
public String getSendToMyMapsMapId() {
return sendToMyMapsMapId;
}
public String getSendToFusionTablesTableId() {
return sendToFusionTablesTableId;
}
public boolean getSendToGoogleSuccess() {
return sendToFusionTablesSuccess && sendToDocsSuccess;
}
// @VisibleForTesting
long getRecordingTrackId() {
return sharedPreferences.getLong(getString(R.string.recording_track_key), -1);
@@ -1319,11 +674,6 @@ public class MyTracks extends TabActivity implements OnTouchListener,
return sharedPreferences;
}
// @VisibleForTesting
static void clearInstance() {
instance = null;
}
// @VisibleForTesting
ITrackRecordingService getTrackRecordingService() {
return trackRecordingService;
@@ -1332,4 +682,15 @@ public class MyTracks extends TabActivity implements OnTouchListener,
public TrackDataHub getDataHub() {
return dataHub;
}
// TODO: Remove very soon
private static MyTracks instance;
public static MyTracks getInstance() {
return instance;
}
public static void clearInstance() {
instance = null;
}
}
@@ -16,6 +16,8 @@
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.io.file.SaveActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendActivity;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
@@ -138,32 +140,46 @@ public class TrackList extends ListActivity
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (!super.onMenuItemSelected(featureId, item)) {
switch (item.getItemId()) {
case Constants.MENU_SHOW: {
onListItemClick(null, null, 0, trackId);
return true;
}
case Constants.MENU_EDIT: {
Intent intent = new Intent(this, TrackDetails.class);
intent.putExtra("trackid", trackId);
startActivity(intent);
return true;
}
case Constants.MENU_SHARE:
case Constants.MENU_WRITE_TO_SD_CARD:
return false;
default: {
Intent result = new Intent();
result.putExtra("trackid", trackId);
setResult(
Constants.getActionFromMenuId(item.getItemId()), result);
finish();
return true;
}
switch (item.getItemId()) {
case Constants.MENU_SHOW: {
onListItemClick(null, null, 0, trackId);
return true;
}
case Constants.MENU_EDIT: {
Intent intent = new Intent(this, TrackDetails.class);
intent.putExtra("trackid", trackId);
startActivity(intent);
return true;
}
case Constants.MENU_SHARE:
case Constants.MENU_WRITE_TO_SD_CARD:
return false;
case Constants.MENU_SEND_TO_GOOGLE:
SendActivity.sendToGoogle(this, trackId, false);
return true;
case Constants.MENU_SHARE_LINK:
SendActivity.sendToGoogle(this, trackId, true);
return true;
case Constants.MENU_SAVE_GPX_FILE:
case Constants.MENU_SAVE_KML_FILE:
case Constants.MENU_SAVE_CSV_FILE:
case Constants.MENU_SAVE_TCX_FILE:
case Constants.MENU_SHARE_GPX_FILE:
case Constants.MENU_SHARE_KML_FILE:
case Constants.MENU_SHARE_CSV_FILE:
case Constants.MENU_SHARE_TCX_FILE:
SaveActivity.handleExportTrackAction(this, trackId,
Constants.getActionFromMenuId(item.getItemId()));
return true;
default: {
Intent result = new Intent();
result.putExtra("trackid", trackId);
setResult(
Constants.getActionFromMenuId(item.getItemId()), result);
finish();
return true;
}
}
return false;
}
@Override
@@ -22,7 +22,6 @@ import com.google.android.accounts.AccountManagerFuture;
import com.google.android.accounts.AuthenticatorException;
import com.google.android.accounts.OperationCanceledException;
import com.google.android.apps.mytracks.AccountChooser;
import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.Constants;
import android.app.Activity;
@@ -183,7 +182,9 @@ public class ModernAuthManager implements AuthManager {
public void run() {
accountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE,
authToken);
MyTracks.getInstance().getAccountChooser().chooseAccount(activity,
AccountChooser accountChooser = new AccountChooser();
accountChooser.chooseAccount(activity,
new AccountChooser.AccountHandler() {
@Override
public void handleAccountSelected(Account account) {
@@ -15,8 +15,8 @@
*/
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.docs.DocsHelper;
@@ -25,10 +25,10 @@ import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
import com.google.android.common.gdata.AndroidXmlParserFactory;
import com.google.android.maps.mytracks.R;
import com.google.wireless.gdata.client.GDataClient;
import com.google.wireless.gdata.client.GDataServiceClient;
import com.google.wireless.gdata.docs.DocumentsClient;
import com.google.wireless.gdata.docs.SpreadsheetsClient;
import com.google.wireless.gdata.docs.XmlDocsGDataParserFactory;
import com.google.wireless.gdata.client.GDataServiceClient;
import android.app.Activity;
import android.content.SharedPreferences;
@@ -49,11 +49,11 @@ public class SendToDocs {
/** The GData service name for the Google Docs Document List */
public static final String GDATA_SERVICE_NAME_DOCLIST = "writely";
private final Activity activity;
private final AuthManager trixAuth;
private final AuthManager docListAuth;
private final long trackId;
private final ProgressIndicator progressIndicator;
private final boolean metricUnits;
private final HandlerThread handlerThread;
private final Handler handler;
@@ -64,12 +64,13 @@ public class SendToDocs {
private String statusMessage = "";
private Runnable onCompletion = null;
public SendToDocs(Activity activity, AuthManager trixAuth,
AuthManager docListAuth, long trackId) {
AuthManager docListAuth, ProgressIndicator progressIndicator) {
this.activity = activity;
this.trixAuth = trixAuth;
this.docListAuth = docListAuth;
this.trackId = trackId;
this.progressIndicator = progressIndicator;
SharedPreferences preferences = activity.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
@@ -81,23 +82,23 @@ public class SendToDocs {
metricUnits = true;
}
Log.d(Constants.TAG,
"Sending to Google Docs: trackId = " + trackId);
handlerThread = new HandlerThread("SendToGoogleDocs");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
public void run() {
public void sendToDocs(final long trackId) {
Log.d(Constants.TAG,
"Sending to Google Docs: trackId = " + trackId);
handler.post(new Runnable() {
@Override
public void run() {
doUpload();
doUpload(trackId);
}
});
}
private void doUpload() {
private void doUpload(long trackId) {
// TODO
statusMessage = activity.getString(R.string.error_sending_to_fusiontables);
success = false;
@@ -198,7 +199,7 @@ public class SendToDocs {
}
if (spreadsheetId == null) {
MyTracks.getInstance().setProgressValue(65);
progressIndicator.setProgressValue(65);
// Waiting a few seconds and trying again. Maybe the server just had a
// hickup (unfortunately that happens quite a lot...).
try {
@@ -217,7 +218,7 @@ public class SendToDocs {
}
// We were unable to find an existing spreadsheet, so create a new one.
MyTracks.getInstance().setProgressValue(70);
progressIndicator.setProgressValue(70);
if (spreadsheetId == null) {
Log.i(Constants.TAG, "Creating new spreadsheet: " + sheetTitle);
@@ -229,11 +230,11 @@ public class SendToDocs {
+ sheetTitle, e);
return false;
}
MyTracks.getInstance().setProgressValue(80);
progressIndicator.setProgressValue(80);
createdNewSpreadSheet = true;
if (spreadsheetId == null) {
MyTracks.getInstance().setProgressValue(85);
progressIndicator.setProgressValue(85);
// The previous creation might have succeeded even though GData
// reported an error. Seems to be a know bug,
// see http://code.google.com/p/gdata-issues/issues/detail?id=929
@@ -255,7 +256,7 @@ public class SendToDocs {
}
if (spreadsheetId == null) {
MyTracks.getInstance().setProgressValue(87);
progressIndicator.setProgressValue(87);
// Re-try
try {
Thread.sleep(5000);
@@ -290,7 +291,7 @@ public class SendToDocs {
return false;
}
MyTracks.getInstance().setProgressValue(90);
progressIndicator.setProgressValue(90);
docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId,
track, metricUnits);
@@ -0,0 +1,152 @@
package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.DialogManager;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import java.io.File;
public class SaveActivity extends Activity {
public static final String EXTRA_TRACK_ID = "track_id";
public static final String EXTRA_SHARE_FILE = "share_file";
public static final String EXTRA_FILE_FORMAT = "file_format";
private MyTracksProviderUtils providerUtils;
private long trackId;
private TrackWriter writer;
private boolean shareFile;
private TrackFileFormat format;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
providerUtils = MyTracksProviderUtils.Factory.get(this);
}
@Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1);
int formatIdx = intent.getIntExtra(EXTRA_FILE_FORMAT, -1);
format = TrackFileFormat.values()[formatIdx];
shareFile = intent.getBooleanExtra(EXTRA_SHARE_FILE, false);
writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format);
if (shareFile) {
// If the file is for sending, save it to a temporary location instead.
FileUtils fileUtils = new FileUtils();
String extension = format.getExtension();
String dirName = fileUtils.buildExternalDirectoryPath(extension, "tmp");
File dir = new File(dirName);
writer.setDirectory(dir);
}
WriteProgressController controller = new WriteProgressController(this, writer);
controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() {
@Override
public void onComplete() {
onWriteComplete();
}
});
controller.startWrite();
}
private void onWriteComplete() {
if (shareFile) {
shareWrittenFile();
} else {
showResultDialog();
}
}
private void shareWrittenFile() {
if (!writer.wasSuccess()) {
showResultDialog();
return;
}
// Share the file.
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
getResources().getText(R.string.send_track_subject).toString());
shareIntent.putExtra(Intent.EXTRA_TEXT,
getResources().getText(R.string.send_track_body_format)
.toString());
shareIntent.setType(format.getMimeType());
Uri u = Uri.fromFile(new File(writer.getAbsolutePath()));
shareIntent.putExtra(Intent.EXTRA_STREAM, u);
startActivity(Intent.createChooser(shareIntent,
getResources().getText(R.string.share_track).toString()));
}
private void showResultDialog() {
DialogManager.showMessageDialog(this, writer.getErrorMessage(), writer.wasSuccess(),
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss();
finish();
}
});
}
public static void handleExportTrackAction(Context ctx, long trackId, int actionCode) {
if (trackId < 0) {
return;
}
TrackFileFormat exportFormat = null;
switch (actionCode) {
case Constants.SAVE_GPX_FILE:
case Constants.SHARE_GPX_FILE:
exportFormat = TrackFileFormat.GPX;
break;
case Constants.SAVE_KML_FILE:
case Constants.SHARE_KML_FILE:
exportFormat = TrackFileFormat.KML;
break;
case Constants.SAVE_CSV_FILE:
case Constants.SHARE_CSV_FILE:
exportFormat = TrackFileFormat.CSV;
break;
case Constants.SAVE_TCX_FILE:
case Constants.SHARE_TCX_FILE:
exportFormat = TrackFileFormat.TCX;
break;
default:
throw new IllegalArgumentException("Warning unhandled action code: " + actionCode);
}
boolean shareFile = false;
switch (actionCode) {
case Constants.SHARE_GPX_FILE:
case Constants.SHARE_KML_FILE:
case Constants.SHARE_CSV_FILE:
case Constants.SHARE_TCX_FILE:
shareFile = true;
}
Intent intent = new Intent(ctx, SaveActivity.class);
intent.putExtra(EXTRA_TRACK_ID, trackId);
intent.putExtra(EXTRA_FILE_FORMAT, exportFormat.ordinal());
intent.putExtra(EXTRA_SHARE_FILE, shareFile);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
ctx.startActivity(intent);
}
}
@@ -13,9 +13,9 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.io.file.TrackWriter;
import com.google.android.apps.mytracks.DialogManager;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
@@ -41,7 +41,7 @@ class WriteProgressController {
* dialog has been dismissed. Whether the write succeeded can be
* determined by examining the {@link TrackWriter}.
*/
public void onComplete(TrackWriter writer);
public void onComplete();
}
private final Activity activity;
@@ -104,7 +104,7 @@ class WriteProgressController {
DialogManager.dismissDialogSafely(activity, dialog);
if (onCompletionListener != null) {
onCompletionListener.onComplete(writer);
onCompletionListener.onComplete();
}
}
};
@@ -0,0 +1,619 @@
package com.google.android.apps.mytracks.io.sendtogoogle;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.accounts.Account;
import com.google.android.apps.mytracks.AccountChooser;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.DialogManager;
import com.google.android.apps.mytracks.MyMapsList;
import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.SendToDocs;
import com.google.android.apps.mytracks.io.SendToFusionTables;
import com.google.android.apps.mytracks.io.SendToFusionTables.OnSendCompletedListener;
import com.google.android.apps.mytracks.io.SendToMyMaps;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Helper for managing the sending of tracks to Google services.
*
* @author Rodrigo Damazio
*/
public class SendActivity extends Activity implements ProgressIndicator {
public static final String EXTRA_SHARE_LINK = "share_link";
public static final String EXTRA_TRACK_ID = "track_id";
// Services
private MyTracksProviderUtils providerUtils;
private SharedPreferences sharedPreferences;
// Authentication
private AuthManager lastAuth;
private final HashMap<String, AuthManager> authMap =
new HashMap<String, AuthManager>();
private final AccountChooser accountChooser = new AccountChooser();
// Send request information.
private boolean shareRequested = false;
private long sendTrackId;
// Send result information, used by SendToGoogleResultDialog.
private boolean sendToMyMapsSuccess = false;
private boolean sendToFusionTablesSuccess = false;
private boolean sendToDocsSuccess = false;
private String sendToMyMapsMapId;
private String sendToFusionTablesTableId;
// TODO: Make these be used for showing results
@SuppressWarnings("unused")
private String sendToMyMapsMessage;
@SuppressWarnings("unused")
private String sendToFusionTablesMessage;
@SuppressWarnings("unused")
private String sendToDocsMessage;
// State used while sending.
private SendDialog sendDialog;
private ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
providerUtils = MyTracksProviderUtils.Factory.get(this);
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
}
@Override
protected void onStart() {
super.onStart();
resetState();
sendTrackId = getIntent().getLongExtra(EXTRA_TRACK_ID, -1);
sendDialog = new SendDialog(this);
sendDialog.setOwnerActivity(this);
sendDialog.setOnClickListener(new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int which) {
if (which != DialogInterface.BUTTON_POSITIVE) {
finish();
return;
}
doSend();
}
});
sendDialog.show();
}
/**
* Initiates the process to send tracks to google.
* This is called once the user has selected sending options via the
* SendToGoogleDialog.
*
* TODO: Change this whole flow to an actual state machine.
*/
private void doSend() {
progressDialog = new ProgressDialog(this);
progressDialog.setIcon(android.R.drawable.ic_dialog_info);
progressDialog.setTitle(R.string.progress_title);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("");
progressDialog.setMax(100);
progressDialog.setProgress(0);
progressDialog.show();
if (sendDialog.getSendToMyMaps()) {
sendToGoogleMapsOrPickMap();
} else if (sendDialog.getSendToFusionTables()) {
authenticateToFusionTables(null);
} else if (sendDialog.getSendToDocs()) {
authenticateToGoogleDocs();
} else {
Log.w(TAG, "Nowhere to upload to");
onSendToGoogleDone();
}
}
private void sendToGoogleMapsOrPickMap() {
if (!sendDialog.getCreateNewMap()) {
// Ask the user to choose a map to upload into
Intent listIntent = new Intent(this, MyMapsList.class);
startActivityForResult(listIntent, Constants.GET_MAP);
// The callback for GET_MAP calls authenticateToGoogleMaps
} else {
authenticateToGoogleMaps(null);
}
}
private void authenticateToGoogleMaps(Intent results) {
if (results == null) { results = new Intent(); }
progressDialog.setProgress(0);
progressDialog.setMessage(getString(
R.string.progress_message_authenticating_mymaps));
authenticate(results, Constants.AUTHENTICATE_TO_MY_MAPS,
MyMapsConstants.SERVICE_NAME);
// AUTHENTICATE_TO_MY_MAPS callback calls sendToGoogleMaps
}
private void sendToGoogleMaps(String mapId) {
SendToMyMaps.OnSendCompletedListener onCompletion = new SendToMyMaps.OnSendCompletedListener() {
@Override
public void onSendCompleted(String mapId, boolean success, int statusMessage) {
// TODO: Use this message
sendToMyMapsMessage = getString(statusMessage);
sendToMyMapsSuccess = success;
if (sendToMyMapsSuccess) {
sendToMyMapsMapId = mapId;
// Update the map id for this track:
try {
Track track = providerUtils.getTrack(sendTrackId);
track.setMapId(mapId);
providerUtils.updateTrack(track);
} catch (RuntimeException e) {
// If that fails whatever reasons we'll just log an error, but
// continue.
Log.w(TAG, "Updating map id failed.", e);
}
}
onSendToGoogleMapsDone();
}
};
final SendToMyMaps sender = new SendToMyMaps(this, mapId, lastAuth,
sendTrackId, this /*progressIndicator*/, onCompletion);
HandlerThread handlerThread = new HandlerThread("SendToMyMaps");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(sender);
}
private void onSendToGoogleMapsDone() {
if (sendDialog.getSendToFusionTables()) {
authenticateToFusionTables(null);
} else if (sendDialog.getSendToDocs()) {
authenticateToGoogleDocs();
} else {
onSendToGoogleDone();
}
}
private void authenticateToFusionTables(Intent results) {
if (results == null) { results = new Intent(); }
progressDialog.setProgress(0);
progressDialog.setMessage(getString(
R.string.progress_message_authenticating_fusiontables));
authenticate(results, Constants.AUTHENTICATE_TO_FUSION_TABLES,
SendToFusionTables.SERVICE_ID);
// AUTHENTICATE_TO_FUSION_TABLES callback calls sendToFusionTables
}
private void sendToFusionTables() {
OnSendCompletedListener onCompletion = new OnSendCompletedListener() {
@Override
public void onSendCompleted(String tableId, boolean success,
int statusMessage) {
// TODO: Use this message
sendToFusionTablesMessage = getString(statusMessage);
sendToFusionTablesSuccess = success;
if (sendToFusionTablesSuccess) {
sendToFusionTablesTableId = tableId;
// Update the table id for this track:
try {
Track track = providerUtils.getTrack(sendTrackId);
track.setTableId(tableId);
providerUtils.updateTrack(track);
} catch (RuntimeException e) {
// If that fails whatever reasons we'll just log an error, but
// continue.
Log.w(TAG, "Updating table id failed.", e);
}
}
onSendToFusionTablesDone();
}
};
final SendToFusionTables sender = new SendToFusionTables(this, lastAuth,
sendTrackId, this/*progressIndicator*/, onCompletion);
HandlerThread handlerThread = new HandlerThread("SendToFusionTables");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(sender);
}
private void onSendToFusionTablesDone() {
if (sendDialog.getSendToDocs()) {
authenticateToGoogleDocs();
} else {
onSendToGoogleDone();
}
}
private void authenticateToGoogleDocs() {
setProgressValue(0);
setProgressMessage(
R.string.progress_message_authenticating_docs);
authenticate(new Intent(),
Constants.AUTHENTICATE_TO_DOCLIST,
SendToDocs.GDATA_SERVICE_NAME_DOCLIST);
// AUTHENTICATE_TO_DOCLIST callback calls authenticateToGoogleTrix
}
private void authenticateToGoogleTrix() {
setProgressValue(30);
setProgressMessage(
R.string.progress_message_authenticating_docs);
authenticate(new Intent(),
Constants.AUTHENTICATE_TO_TRIX,
SendToDocs.GDATA_SERVICE_NAME_TRIX);
// AUTHENTICATE_TO_TRIX callback calls sendToGoogleDocs
}
private void sendToGoogleDocs() {
Log.d(TAG, "Sending to Docs....");
setProgressValue(50);
setProgressMessage(R.string.progress_message_sending_docs);
final SendToDocs sender = new SendToDocs(this,
authMap.get(SendToDocs.GDATA_SERVICE_NAME_TRIX),
authMap.get(SendToDocs.GDATA_SERVICE_NAME_DOCLIST),
this);
Runnable onCompletion = new Runnable() {
public void run() {
setProgressValue(100);
// TODO: Use this message
sendToDocsMessage = sender.getStatusMessage();
sendToDocsSuccess = sender.wasSuccess();
onSendToGoogleDocsDone();
}
};
sender.setOnCompletion(onCompletion);
sender.sendToDocs(sendTrackId);
}
private void onSendToGoogleDocsDone() {
onSendToGoogleDone();
}
private void onSendToGoogleDone() {
final boolean sentToMyMaps = sendDialog.getSendToMyMaps();
final boolean sentToFusionTables = sendDialog.getSendToFusionTables();
List<SendResult> results = makeSendToGoogleResults();
runOnUiThread(new Runnable() {
@Override
public void run() {
progressDialog.dismiss();
progressDialog = null;
sendDialog = null;
}
});
// We've finished sending the track to the user-selected services. Now
// we tell them the results of the upload, and optionally share the track.
// There are a few different paths through this code:
//
// 1. The user pre-requested a share (shareRequested == true). We're going
// to display the result dialog *without* the share button (the share
// listener will be null). The OK button listener will initiate the
// share.
//
// 2. The user did not pre-request a share, and the set of services to
// which we succeeded in uploading the track are compatible with
// sharing. We'll display a share button (the share listener will be
// non-null), and will share the link if the user clicks it.
//
// 3. The user did not pre-request a share, and the set of services to
// which we succeeded in uploading the track are incompatible with
// sharing. We won't display a share button.
final boolean canShare = sendToFusionTablesTableId != null
|| sendToMyMapsMapId != null;
DialogInterface.OnClickListener doShareListener = null;
if (canShare) {
doShareListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
shareLinkToMap(sentToMyMaps, sentToFusionTables);
}
};
}
DialogInterface.OnClickListener onOkListener = (canShare && shareRequested)
? doShareListener : null;
DialogInterface.OnClickListener onShareListener = (canShare && !shareRequested)
? doShareListener : null;
AlertDialog sendToGoogleResultDialog = ResultDialogFactory.makeDialog(this,
results, onOkListener, onShareListener);
DialogManager.showDialogSafely(this, sendToGoogleResultDialog);
}
boolean shareLinkToMap(boolean sentToMyMaps, boolean sentToFusionTables) {
String url = null;
if (sentToMyMaps && sendToMyMapsSuccess) {
// Prefer a link to My Maps
url = MapsFacade.buildMapUrl(sendToMyMapsMapId);
} else if (sentToFusionTables && sendToFusionTablesSuccess) {
// Otherwise try using the link to fusion tables
url = getFusionTablesUrl(sendTrackId);
}
if (url != null) {
shareLinkToMap(url);
return true;
}
return false;
}
/**
* Shares a link to a My Map or Fusion Table via external app (email, gmail, ...)
* A chooser with apps that support text/plain will be shown to the user.
*/
private void shareLinkToMap(String url) {
boolean shareUrlOnly = sharedPreferences.getBoolean(
getString(R.string.share_url_only_key), false);
String msg = shareUrlOnly ? url : String.format(
getResources().getText(R.string.share_map_body_format).toString(), url);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
getResources().getText(R.string.share_map_subject).toString());
shareIntent.putExtra(Intent.EXTRA_TEXT, msg);
startActivity(Intent.createChooser(shareIntent,
getResources().getText(R.string.share_map).toString()));
}
protected String getFusionTablesUrl(long trackId) {
Track track = providerUtils.getTrack(trackId);
return track == null ? "" : SendToFusionTables.getMapVisualizationUrl(track);
}
/**
* Creates a list of {@link SendResult} instances based on the set of
* services selected in {@link SendDialog} and the results as known to
* this class.
*/
private List<SendResult> makeSendToGoogleResults() {
List<SendResult> results = new ArrayList<SendResult>();
if (sendDialog.getSendToMyMaps()) {
results.add(new SendResult(SendType.MYMAPS, sendToMyMapsSuccess));
}
if (sendDialog.getSendToFusionTables()) {
results.add(new SendResult(SendType.FUSION_TABLES, sendToFusionTablesSuccess));
}
if (sendDialog.getSendToDocs()) {
results.add(new SendResult(SendType.DOCS, sendToDocsSuccess));
}
return results;
}
/**
* Initializes the authentication manager which obtains an authentication
* token, prompting the user for a login and password if needed.
*/
private void authenticate(final Intent results, final int requestCode,
final String service) {
lastAuth = authMap.get(service);
if (lastAuth == null) {
Log.i(TAG, "Creating a new authentication for service: " + service);
lastAuth = AuthManagerFactory.getAuthManager(this,
Constants.GET_LOGIN,
null,
true,
service);
authMap.put(service, lastAuth);
}
Log.d(TAG, "Logging in to " + service + "...");
if (AuthManagerFactory.useModernAuthManager()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
chooseAccount(results, requestCode, service);
}
});
} else {
doLogin(results, requestCode, service, null);
}
}
private void chooseAccount(final Intent results, final int requestCode,
final String service) {
accountChooser.chooseAccount(SendActivity.this,
new AccountChooser.AccountHandler() {
@Override
public void handleAccountSelected(Account account) {
if (account == null) {
progressDialog.dismiss();
return;
}
doLogin(results, requestCode, service, account);
}
});
}
private void doLogin(final Intent results, final int requestCode,
final String service, final Account account) {
lastAuth.doLogin(new Runnable() {
public void run() {
Log.i(TAG, "Loggin success for " + service + "!");
onActivityResult(requestCode, RESULT_OK, results);
}
}, account);
}
@Override
public void onActivityResult(int requestCode, int resultCode,
final Intent results) {
switch (requestCode) {
case Constants.GET_LOGIN: {
// TODO: This is a result from inside the auth manager,
// make this return path explicit.
if (resultCode != RESULT_OK || lastAuth == null ||
!lastAuth.authResult(resultCode, results)) {
progressDialog.dismiss();
}
break;
}
case Constants.GET_MAP: {
// User picked a map to upload to
if (resultCode == RESULT_OK) {
results.putExtra("trackid", sendTrackId);
if (results.hasExtra("mapid")) {
sendToMyMapsMapId = results.getStringExtra("mapid");
}
authenticateToGoogleMaps(results);
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_MY_MAPS: {
// Authenticated with Google My Maps
if (results != null && resultCode == RESULT_OK) {
final String mapId;
if (results.hasExtra("mapid")) {
mapId = results.getStringExtra("mapid");
} else {
mapId = "new";
}
sendToGoogleMaps(mapId);
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_FUSION_TABLES: {
// Authenticated with Google Fusion Tables
if (results != null && resultCode == RESULT_OK) {
sendToFusionTables();
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_DOCLIST: {
// Authenticated with Google Docs
if (resultCode == RESULT_OK) {
authenticateToGoogleTrix();
} else {
onSendToGoogleDone();
}
break;
}
case Constants.AUTHENTICATE_TO_TRIX: {
// Authenticated with Trix
if (resultCode == RESULT_OK) {
sendToGoogleDocs();
} else {
onSendToGoogleDone();
}
break;
}
case Constants.SHARE_LINK: {
Track selectedTrack = providerUtils.getTrack(sendTrackId);
if (selectedTrack != null) {
if (!TextUtils.isEmpty(selectedTrack.getMapId())) {
shareLinkToMap(MapsFacade.buildMapUrl(selectedTrack.getMapId()));
} else if (!TextUtils.isEmpty(selectedTrack.getTableId())) {
shareLinkToMap(getFusionTablesUrl(sendTrackId));
} else {
shareRequested = true;
sendDialog.dismiss();
}
}
break;
}
default: {
Log.w(TAG, "Warning unhandled request code: " + requestCode);
}
}
}
/**
* Resets status information for sending to MyMaps/Docs.
*/
private void resetState() {
sendToMyMapsMapId = null;
sendToMyMapsMessage = "";
sendToMyMapsSuccess = true;
sendToFusionTablesMessage = "";
sendToFusionTablesSuccess = true;
sendToDocsMessage = "";
sendToDocsSuccess = true;
sendToFusionTablesTableId = null;
}
@Override
public void setProgressMessage(final int resId) {
runOnUiThread(new Runnable() {
public void run() {
if (progressDialog != null) {
progressDialog.setMessage(getString(resId));
}
}
});
}
@Override
public void setProgressValue(final int percent) {
runOnUiThread(new Runnable() {
public void run() {
if (progressDialog != null) {
progressDialog.setProgress(percent);
}
}
});
}
@Override
public void clearProgressMessage() {
progressDialog.setMessage("");
}
public static void sendToGoogle(Context ctx, long trackId, boolean shareLink) {
Intent intent = new Intent(ctx, SendActivity.class);
intent.putExtra(SendActivity.EXTRA_TRACK_ID, trackId);
intent.putExtra(SendActivity.EXTRA_SHARE_LINK, shareLink);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
ctx.startActivity(intent);
}
}
@@ -16,8 +16,6 @@
package com.google.android.apps.mytracks.io.sendtogoogle;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.DialogManager;
import com.google.android.apps.mytracks.MyTracks;
import com.google.android.maps.mytracks.R;
import android.app.Dialog;
@@ -42,15 +40,13 @@ import android.widget.RadioGroup;
*/
public class SendDialog extends Dialog {
private RadioGroup groupMyMaps;
private RadioButton createNewMapRadioButton;
private RadioButton pickMapRadioButton;
private CheckBox sendToMyMapsCheckBox;
private CheckBox sendToFusionTablesCheckBox;
private CheckBox sendToDocsCheckBox;
private RadioButton sendStatsRadioButton;
private RadioButton sendStatsAndPointsRadioButton;
private Button sendButton;
private OnClickListener clickListener;
public SendDialog(Context context) {
super(context);
@@ -62,18 +58,38 @@ public class SendDialog extends Dialog {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.mytracks_send_to_google);
final Button sendButton = (Button) findViewById(R.id.sendtogoogle_send_now);
final RadioGroup groupMyMaps = (RadioGroup) findViewById(R.id.sendtogoogle_group_mymaps);
sendToMyMapsCheckBox =
(CheckBox) findViewById(R.id.sendtogoogle_google_mymaps);
sendToFusionTablesCheckBox =
(CheckBox) findViewById(R.id.sendtogoogle_google_fusiontables);
sendToDocsCheckBox = (CheckBox) findViewById(R.id.sendtogoogle_google_docs);
createNewMapRadioButton =
(RadioButton) findViewById(R.id.sendtogoogle_create_new_map);
pickMapRadioButton =
(RadioButton) findViewById(R.id.sendtogoogle_pick_existing_map);
RadioButton sendStatsRadioButton = (RadioButton) findViewById(R.id.sendtogoogle_send_stats);
sendStatsAndPointsRadioButton = (RadioButton) findViewById(
R.id.sendtogoogle_send_stats_and_points);
Button cancel = (Button) findViewById(R.id.sendtogoogle_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
MyTracks.getInstance().dismissDialog(DialogManager.DIALOG_SEND_TO_GOOGLE);
if (clickListener != null) {
clickListener.onClick(SendDialog.this, BUTTON_NEGATIVE);
}
dismiss();
}
});
Button send = (Button) findViewById(R.id.sendtogoogle_send_now);
send.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (clickListener != null) {
clickListener.onClick(SendDialog.this, BUTTON_POSITIVE);
}
dismiss();
MyTracks.getInstance().sendToGoogle();
}
});
@@ -86,25 +102,9 @@ public class SendDialog extends Dialog {
groupMyMaps.setVisibility(sendToMyMapsCheckBox.isChecked() ? View.VISIBLE : View.INVISIBLE);
}
};
sendButton = (Button) findViewById(R.id.sendtogoogle_send_now);
groupMyMaps = (RadioGroup) findViewById(R.id.sendtogoogle_group_mymaps);
sendToMyMapsCheckBox =
(CheckBox) findViewById(R.id.sendtogoogle_google_mymaps);
sendToMyMapsCheckBox.setOnCheckedChangeListener(checkBoxListener);
sendToFusionTablesCheckBox =
(CheckBox) findViewById(R.id.sendtogoogle_google_fusiontables);
sendToFusionTablesCheckBox.setOnCheckedChangeListener(checkBoxListener);
sendToDocsCheckBox = (CheckBox) findViewById(R.id.sendtogoogle_google_docs);
sendToDocsCheckBox.setOnCheckedChangeListener(checkBoxListener);
createNewMapRadioButton =
(RadioButton) findViewById(R.id.sendtogoogle_create_new_map);
pickMapRadioButton =
(RadioButton) findViewById(R.id.sendtogoogle_pick_existing_map);
sendStatsRadioButton =
(RadioButton) findViewById(R.id.sendtogoogle_send_stats);
sendStatsAndPointsRadioButton = (RadioButton) findViewById(
R.id.sendtogoogle_send_stats_and_points);
SharedPreferences prefs =
getContext().getSharedPreferences(Constants.SETTINGS_NAME, 0);
@@ -163,6 +163,10 @@ public class SendDialog extends Dialog {
super.onStop();
}
public void setOnClickListener(OnClickListener clickListener) {
this.clickListener = clickListener;
}
public boolean getSendToMyMaps() {
return sendToMyMapsCheckBox.isChecked();
}
@@ -182,4 +186,4 @@ public class SendDialog extends Dialog {
public boolean getSendStatsAndPoints() {
return sendStatsAndPointsRadioButton.isChecked();
}
}
}
@@ -38,13 +38,6 @@ public class DialogManagerTest
assertNull(MyTracks.getInstance());
}
public void test_onCreateChartSettings() {
Dialog d =
getActivity().onCreateDialog(DialogManager.DIALOG_CHART_SETTINGS, null);
assertNotNull(d);
assertTrue(d instanceof ChartSettingsDialog);
}
public void test_onCreateImportProgress() {
Dialog d =
getActivity().onCreateDialog(
@@ -62,11 +55,4 @@ public class DialogManagerTest
assertEquals(100, pd.getMax());
assertEquals(10, pd.getProgress());
}
public void test_onCreateSendToGoogle() {
Dialog d =
getActivity().onCreateDialog(DialogManager.DIALOG_SEND_TO_GOOGLE, null);
assertNotNull(d);
assertTrue(d instanceof SendDialog);
}
}
@@ -13,10 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.io.file.MockTrackWriter;
import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.io.file.TrackWriter;
import com.google.android.apps.mytracks.io.file.WriteProgressController;
import android.app.ProgressDialog;
import android.test.ActivityInstrumentationTestCase2;
@@ -60,7 +61,7 @@ public class WriteProgressControllerTest extends ActivityInstrumentationTestCase
getActivity(), mockWriter);
controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() {
@Override
public void onComplete(TrackWriter writer) {
public void onComplete() {
controllerDoneRef.set(true);
}
});