Merge heads

This commit is contained in:
youtaol
2013-06-08 13:12:39 +08:00
parent 7a09e89041
commit d1055ef5ee
48 changed files with 374 additions and 411 deletions
+2 -2
View File
@@ -16,8 +16,8 @@ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
android:versionCode="66"
android:versionName="2.0.4"
android:versionCode="67"
android:versionName="2.0.5"
package="com.google.android.maps.mytracks" >
<!-- Permission to initialize services -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 361 B

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2013 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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/list_selector_background_mytracks" android:state_activated="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
+2 -2
View File
@@ -65,10 +65,10 @@ limitations under the License.
android:id="@+id/export_external_storage_options"
style="@style/ExportRadioGroup" >
<RadioButton
android:id="@+id/export_external_storage_gpx"
android:id="@+id/export_external_storage_kml"
style="@style/TextMedium" />
<RadioButton
android:id="@+id/export_external_storage_kml"
android:id="@+id/export_external_storage_gpx"
style="@style/TextMedium" />
<RadioButton
android:id="@+id/export_external_storage_csv"
@@ -20,15 +20,31 @@ limitations under the License.
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
android:padding="8dp" >
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="8dp" >
<CheckBox
android:id="@+id/share_track_public"
android:layout_gravity="center_vertical"
android:text="@string/share_track_public"
style="@style/TextMedium" />
<CheckBox
android:id="@+id/share_track_invite"
android:layout_gravity="center_vertical"
android:layout_marginTop="16dp"
android:text="@string/share_track_invite"
style="@style/TextMedium" />
<MultiAutoCompleteTextView
android:hint="@string/share_track_add_emails_hint"
android:completionThreshold="1"
android:id="@+id/add_emails"
android:hint="@string/share_track_emails_hint"
android:id="@+id/share_track_emails"
android:imeOptions="actionDone"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_width="match_parent"
android:singleLine="false" >
android:singleLine="false"
android:visibility="gone" >
</MultiAutoCompleteTextView>
</LinearLayout>
</ScrollView>
+13 -13
View File
@@ -27,32 +27,32 @@ limitations under the License.
android:showAsAction="ifRoom"
android:title="@string/menu_start_gps"/>
<item
android:icon="@drawable/menu_import"
android:id="@+id/track_list_import_all"
android:title="@string/menu_import_all">
</item>
android:icon="@drawable/menu_sync_now"
android:id="@+id/track_list_sync_now"
android:title="@string/menu_sync_now"/>
<item
android:icon="@drawable/menu_aggregated_statistics"
android:id="@+id/track_list_aggregated_statistics"
android:title="@string/menu_aggregated_statistics"/>
<item
android:icon="@drawable/menu_export"
android:id="@+id/track_list_export_all"
android:title="@string/menu_export_all">
</item>
<item
android:icon="@drawable/menu_import"
android:id="@+id/track_list_import_all"
android:title="@string/menu_import_all">
</item>
<item
android:icon="@drawable/menu_delete"
android:id="@+id/track_list_delete_all"
android:title="@string/menu_delete_all"/>
<item
android:icon="@drawable/menu_aggregated_statistics"
android:id="@+id/track_list_aggregated_statistics"
android:title="@string/menu_aggregated_statistics"/>
<item
android:icon="@drawable/menu_sync_now"
android:id="@+id/track_list_sync_now"
android:title="@string/menu_sync_now"/>
<item
android:icon="@drawable/menu_settings"
android:id="@+id/track_list_settings"
android:title="@string/menu_settings"/>
<item
<item
android:icon="@drawable/menu_feedback"
android:id="@+id/track_list_feedback"
android:title="@string/menu_feedback"/>
Binary file not shown.
+1 -1
View File
@@ -34,7 +34,7 @@ limitations under the License.
<item name="android:measureWithLargestChild">true</item>
</style>
<style name="ListItem">
<item name="android:background">@drawable/activated_background_mytracks</item>
<item name="android:background">?android:attr/activatedBackgroundIndicator</item>
</style>
<style name="ThemeSelector" parent="android:Theme.Holo">
<item name="android:actionBarStyle">@style/ActionBarStyle.MyTracks</item>
@@ -93,8 +93,8 @@ limitations under the License.
<item>-1</item>
</string-array>
<string-array name="file_types">
<item>GPX</item>
<item>KML</item>
<item>GPX</item>
<item>CSV</item>
<item>TCX</item>
</string-array>
+2
View File
@@ -37,6 +37,8 @@ limitations under the License.
<string name="min_required_accuracy_key">minRequiredAccuracy</string>
<string name="report_speed_key">reportSpeed</string>
<string name="sensor_type_key">sensorType</string>
<string name="share_track_invite_key">shareTrackInvite</string>
<string name="share_track_public_key">shareTrackPublic</string>
<string name="split_frequency_key">splitFrequency</string>
<string name="stats_show_coordinate_key">statsShowCoordinate</string>
<string name="stats_show_grade_elevation_key">statsShowGradeElevation</string>
+80 -61
View File
@@ -613,17 +613,50 @@ limitations under the License.
</string>
<!-- Export -->
<string name="export_all_option"
translation_description="When exporting all tracks to the external storage, the option to export
as a certain file format.
%1$s: file format. 'KML', 'GPX', 'CSV', or 'TCX'.">
Export all as %1$s
</string>
<string name="export_all_title"
translation_description="The dialog title to export all tracks to the external storage.">
Export to external storage
</string>
<string name="export_external_storage"
translation_description="When exporting a track, the option to export to external storage.">
translation_description="When exporting a track, the option to export to the external storage.">
External storage
</string>
<string name="export_external_storage_option"
translation_description="When exporting a track to external storage, the option to export as a
certain file format.
<string name="export_external_storage_error"
translation_description="When exporting tracks to the external storage, the error message
indicating that only some of the tracks are exported.
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.">
%1$d the number of tracks successfully exported. E.g., '1'.
%1$s the number of tracks to export. E.g., '2 tracks'.
%2$s the directory. E.g., '/storage/sdcard0/MyTracks/kml/'.">
Exported %1$d of %2$s to %3$s.
</string>
<string name="export_external_storage_option"
translation_description="When exporting a track to the external storage, the option to export as
a certain file format.
%1$s: file format. 'KML', 'GPX', 'CSV', or 'TCX'.">
as %1$s file
</string>
<string name="export_external_storage_progress_message"
translation_description="When exporting tracks to the external storage, the progress message.
%1$s: the directory. E.g., '/storage/sdcard0/MyTracks/kml/'.">
Exporting to %1$s&#8230;
</string>
<string name="export_external_storage_success"
translation_description="When exporting tracks to the external storage, the success message.
%1$s the number of tracks. E.g., '2 tracks'.
%2$s the directory. E.g., '/storage/sdcard0/MyTracks/kml/'.">
Exported %1$s to %2$s.
</string>
<string name="export_google_drive"
translation_description="When exporting a track, the option to export to Google Drive.">
Google Drive
@@ -638,7 +671,7 @@ limitations under the License.
as new private table
</string>
<string name="export_google_fusion_tables_public"
translation_description="When exporting a trck to Google Fusion Tables, the option to export as
translation_description="When exporting a track to Google Fusion Tables, the option to export as
a new public table as opposed to a new private table.">
as new public table
</string>
@@ -652,7 +685,7 @@ limitations under the License.
as new public map
</string>
<string name="export_google_maps_unlisted"
translation_description="When sending a track to Google Maps, the option to export as a new
translation_description="When exporting a track to Google Maps, the option to export as a new
unlisted map as opposed to a new public map.">
as new unlisted map
</string>
@@ -660,7 +693,7 @@ limitations under the License.
translation_description="When exporting a track, the option to export to Google Spreadsheets.">
Google Spreadsheets
</string>
<string name="export_dialog_title"
<string name="export_title"
translation_description="The dialog title when exporting a track.">
Export to&#8230;
</string>
@@ -885,27 +918,27 @@ limitations under the License.
%1$d the number of files successfully imported. E.g., '2'.
%2$s the number of files in the directory. E.g., '2 files'.
%3$s the directory. E.g., '/storage/sdcard0/MyTracks/gpx/'.">
%3$s the directory. E.g., '/storage/sdcard0/MyTracks/kml/'.">
Imported %1$d of %2$s from %3$s.
</string>
<string name="import_no_directory"
translation_description="When importing from the external storage, the error message when the
directory doesn't exist.
%1$s: the directory. E.g., '/storage/sdcard0/MyTracks/gpx/'.">
%1$s: the directory. E.g., '/storage/sdcard0/MyTracks/kml/'.">
%1$s does not exist.
</string>
<string name="import_progress_message"
translation_description="When importing from the external storage, the progress message.
%1$s: the directory. E.g., '/storage/sdcard0/MyTracks/gpx/'.">
%1$s: the directory. E.g., '/storage/sdcard0/MyTracks/kml/'.">
Importing from %1$s&#8230;
</string>
<string name="import_selection_option"
translation_description="When importing from external storage, the option to import all the
files of a certain file format.
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.">
%1$s: file format. 'KML', 'GPX', 'CSV', or 'TCX'.">
Import all %1$s
</string>
<string name="import_selection_title"
@@ -916,7 +949,7 @@ limitations under the License.
translation_description="When importing from the external storage, the success message.
%1$s the number of files. E.g., '2 files'.
%2$s the directory. E.g., '/storage/sdcard0/MyTracks/gpx/'.">
%2$s the directory. E.g., '/storage/sdcard0/MyTracks/kml/'.">
Imported %1$s from %2$s.
</string>
@@ -926,7 +959,7 @@ limitations under the License.
Deselect all
</string>
<string name="list_item_selected"
translation_description="Title indictating the number of items selected in a list.
translation_description="Title indicating the number of items selected in a list.
%1$d: an integer value. E.g., '2'.">
%1$d selected
</string>
@@ -1247,41 +1280,6 @@ limitations under the License.
write data to Google My Tracks and start/stop Google My Tracks recording
</string>
<!-- Save -->
<string name="save_all_selection_option"
translation_description="When saving to external storage, the option to save all the tracks as a
certain file format.
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.">
Save all as %1$s
</string>
<string name="save_error"
translation_description="When saving to the external storage, the error message indicating that
only some of the tracks are saved.
%1$d the number of tracks successfully saved. E.g., '1'.
%1$s the number of tracks to save. E.g., '2 tracks'.
%2$s the directory. E.g., '/storage/sdcard0/MyTracks/gpx/'.">
Saved %1$d of %2$s to %3$s.
</string>
<string name="save_progress_message"
translation_description="When saving to the external storage, the progress message.
%1$s: the directory. E.g., '/storage/sdcard0/MyTracks/gpx/'.">
Saving to %1$s&#8230;
</string>
<string name="save_selection_title"
translation_description="The dialog title to save to external storage.">
Save to external storage
</string>
<string name="save_success"
translation_description="When saving to the external storage, the success message.
%1$s the number of tracks. E.g., '2 tracks'.
%2$s the directory. E.g., '/storage/sdcard0/MyTracks/gpx/'.">
Saved %1$s to %2$s.
</string>
<!-- Search -->
<string name="search_global_description"
translation_description="Description of what is searched in My Tracks, to be displayed in the
@@ -2000,26 +1998,38 @@ limitations under the License.
</string>
<!-- Share Track -->
<string name="share_track_add_emails_title"
translation_description="The dialog title for entering email addresses for sharing a track
with.">
Share track with
</string>
<string name="share_track_add_emails_hint"
translation_description="The hint in the auto complete text box for entering email addresses.">
Enter email addresses
</string>
<string name="share_track_drive_confirm_message"
<string name="share_track_confirm_message"
translation_description="The confirmation message when sharing a track via Google Drive with
friends.">
This will upload your track to Google Drive so you can share the file with friends. The file
will be private and only those you have shared with will have access.
This will upload your track to Google Drive so you can share the file with friends.
</string>
<string name="share_track_emails_hint"
translation_description="The hint for the auto complete text box for entering email addresses.">
Email addresses
</string>
<string name="share_track_invite"
translation_description="The checkbox to invite people to view a track.">
Invite people to view
</string>
<string name="share_track_no_emails"
translation_description="When sharing a track, error message indicating that no email addresses
is entered.">
No email addresses entered.
</string>
<string name="share_track_no_selection"
translation_description="When sharing a track, error message indicating that no option is
selected.">
No option selected.
</string>
<string name="share_track_picker_title"
translation_description="When sharing a track with friends, the title on the picker to ask the
user to select an application.">
Select an application
</string>
<string name="share_track_public"
translation_description="The checkbox to make a track public and share its url.">
Make public &amp; share URL
</string>
<string name="share_track_share_file"
translation_description="After saving a track to the external storage, the button on the result
dialog to share the saved track file with friends.">
@@ -2046,10 +2056,19 @@ limitations under the License.
%2$s: track description.">
I think you might be interested in this track:\n\n%1$s\n\n%2$s
</string>
<string name="share_track_share_url_title"
translation_description="The dialog title asking the user to select an application for sharing
an URL.">
Share URL using:
</string>
<string name="share_track_subject"
translation_description="When sharing a track with friends, the subject line.">
I would like to share a track with you
</string>
<string name="share_track_title"
translation_description="The dialog title to share a track.">
Share track
</string>
<!-- Stats -->
<string name="stats_average_moving_pace"
+2 -1
View File
@@ -75,7 +75,8 @@ limitations under the License.
<!-- export radio group -->
<style name="ExportRadioGroup">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginLeft">16dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:layout_marginLeft">20dp</item>
<item name="android:layout_width">match_parent</item>
</style>
<!-- help answer -->
@@ -16,16 +16,15 @@
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.fragments.AddEmailsDialogFragment;
import com.google.android.apps.mytracks.fragments.AddEmailsDialogFragment.AddEmailsCaller;
import com.google.android.apps.mytracks.fragments.CheckPermissionFragment;
import com.google.android.apps.mytracks.fragments.CheckPermissionFragment.CheckPermissionCaller;
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment;
import com.google.android.apps.mytracks.fragments.ChooseAccountDialogFragment.ChooseAccountCaller;
import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment;
import com.google.android.apps.mytracks.fragments.ConfirmDialogFragment;
import com.google.android.apps.mytracks.fragments.ConfirmDialogFragment.ConfirmCaller;
import com.google.android.apps.mytracks.fragments.InstallEarthDialogFragment;
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment;
import com.google.android.apps.mytracks.fragments.ShareTrackDialogFragment.ShareTrackCaller;
import com.google.android.apps.mytracks.io.drive.SendDriveActivity;
import com.google.android.apps.mytracks.io.file.SaveActivity;
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
@@ -66,7 +65,7 @@ import java.io.IOException;
* @author Jimmy Shih
*/
public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActivity implements
ChooseAccountCaller, CheckPermissionCaller, AddEmailsCaller, ConfirmCaller {
ChooseAccountCaller, CheckPermissionCaller, ShareTrackCaller, ConfirmCaller {
private static final String TAG = AbstractMyTracksActivity.class.getSimpleName();
private static final String SEND_REQUEST_KEY = "send_request_key";
@@ -182,13 +181,12 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
}
@Override
public void onAddEmailsDone(String emails) {
if (emails != null && !emails.equals("")) {
sendRequest.setDriveShareEmails(emails);
Intent intent = IntentUtils.newIntent(this, SendDriveActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
startActivity(intent);
}
public void onShareTrackDone(String emails, boolean makePublic) {
sendRequest.setDriveShareEmails(emails);
sendRequest.setDriveSharePublic(makePublic);
Intent intent = IntentUtils.newIntent(this, SendDriveActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
startActivity(intent);
}
private void onDrivePermissionSuccess() {
@@ -260,15 +258,11 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
* <p>
* isSendDrive and isDriveEnableSync -> enable sync
* <p>
* isSendDrive and isDriveShare -> show {@link AddEmailsDialogFragment}
* isSendDrive and isDriveShare -> show {@link ShareTrackDialogFragment}
* <p>
* isSendDrive -> start {@link SendDriveActivity}
* <p>
* isSendMaps and isMapShare -> show {@link ChooseActivityDialogFragment}
* <p>
* isSendMaps and isMapsExistingMap -> start {@link ChooseMapActivity}
* <p>
* isSendMaps and !isMapsExistingMap -> {@link SendMapsActivity}
* isSendMaps -> start {@link SendMapsActivity}
* <p>
* isSendFusionTables -> start {@link SendFusionTablesActivity}
* <p>
@@ -292,8 +286,8 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
SyncUtils.enableSync(sendRequest.getAccount());
return;
} else if (sendRequest.isDriveShare()) {
AddEmailsDialogFragment.newInstance(sendRequest.getTrackId())
.show(getSupportFragmentManager(), AddEmailsDialogFragment.ADD_EMAILS_DIALOG_TAG);
ShareTrackDialogFragment.newInstance(sendRequest.getTrackId())
.show(getSupportFragmentManager(), ShareTrackDialogFragment.SHARE_TRACK_DIALOG_TAG);
return;
} else {
next = SendDriveActivity.class;
@@ -344,7 +338,7 @@ public abstract class AbstractSendToGoogleActivity extends AbstractMyTracksActiv
protected void confirmShare(long trackId) {
ConfirmDialogFragment.newInstance(R.string.confirm_share_drive_key,
PreferencesUtils.CONFIRM_SHARE_DRIVE_DEFAULT,
getString(R.string.share_track_drive_confirm_message), new long[] { trackId })
getString(R.string.share_track_confirm_message), new long[] { trackId })
.show(getSupportFragmentManager(), ConfirmDialogFragment.CONFIRM_DIALOG_TAG);
}
@@ -527,7 +527,7 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
return true;
case R.id.track_list_export_all:
FileTypeDialogFragment.newInstance(R.id.track_list_export_all,
R.string.save_selection_title, R.string.save_all_selection_option, 4)
R.string.export_all_title, R.string.export_all_option, 4)
.show(getSupportFragmentManager(), FileTypeDialogFragment.FILE_TYPE_DIALOG_TAG);
return true;
case R.id.track_list_delete_all:
@@ -124,7 +124,7 @@ public class ChooseActivityDialogFragment extends DialogFragment {
caller.onChooseActivityDone(
activityInfo.applicationInfo.packageName, activityInfo.name);
}
}).setTitle(R.string.share_track_picker_title).create();
}).setTitle(R.string.share_track_share_url_title).create();
}
@Override
@@ -120,10 +120,10 @@ public class ExportDialogFragment extends DialogFragment {
exportGoogleFusionTablesPublic ? R.id.export_google_fusion_tables_public
: R.id.export_google_fusion_tables_private);
setExternalStorageOption(
(RadioButton) view.findViewById(R.id.export_external_storage_gpx), TrackFileFormat.GPX);
setExternalStorageOption(
(RadioButton) view.findViewById(R.id.export_external_storage_kml), TrackFileFormat.KML);
setExternalStorageOption(
(RadioButton) view.findViewById(R.id.export_external_storage_gpx), TrackFileFormat.GPX);
setExternalStorageOption(
(RadioButton) view.findViewById(R.id.export_external_storage_csv), TrackFileFormat.CSV);
setExternalStorageOption(
@@ -159,7 +159,7 @@ public class ExportDialogFragment extends DialogFragment {
}
caller.onExportDone(type, format);
}
}).setTitle(R.string.export_dialog_title).setView(view).create();
}).setTitle(R.string.export_title).setView(view).create();
}
/**
@@ -179,10 +179,10 @@ public class ExportDialogFragment extends DialogFragment {
*/
private int getExternalStorageFormatId(TrackFileFormat trackFileFormat) {
switch (trackFileFormat) {
case GPX:
return R.id.export_external_storage_gpx;
case KML:
return R.id.export_external_storage_kml;
case GPX:
return R.id.export_external_storage_gpx;
case CSV:
return R.id.export_external_storage_csv;
default:
@@ -197,10 +197,10 @@ public class ExportDialogFragment extends DialogFragment {
*/
private TrackFileFormat getTrackFileFormat(int externalStorageFormatId) {
switch (externalStorageFormatId) {
case R.id.export_external_storage_gpx:
return TrackFileFormat.GPX;
case R.id.export_external_storage_kml:
return TrackFileFormat.KML;
case R.id.export_external_storage_gpx:
return TrackFileFormat.GPX;
case R.id.export_external_storage_csv:
return TrackFileFormat.CSV;
default:
@@ -62,7 +62,9 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -146,6 +148,15 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
RelativeLayout mapContainer = (RelativeLayout) layout.findViewById(R.id.map_container);
mapContainer.addView(mapView, 0);
/*
* For Froyo (2.2) and Gingerbread (2.3), need a transparent FrameLayout on
* top for view pager to work correctly.
*/
FrameLayout frameLayout = new FrameLayout(getActivity());
frameLayout.setBackgroundColor(getResources().getColor(android.R.color.transparent));
mapContainer.addView(frameLayout,
new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
myLocationImageButton = (ImageButton) layout.findViewById(R.id.map_my_location);
myLocationImageButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -16,6 +16,7 @@
package com.google.android.apps.mytracks.fragments;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
@@ -30,64 +31,73 @@ import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FilterQueryProvider;
import android.widget.MultiAutoCompleteTextView;
import android.widget.Toast;
/**
* A DialogFragment to add emails.
* A DialogFragment to share a track.
*
* @author Jimmy Shih
*/
public class AddEmailsDialogFragment extends DialogFragment {
public class ShareTrackDialogFragment extends DialogFragment {
/**
* Interface for caller of this dialog fragment.
*
* @author Jimmy Shih
*/
public interface AddEmailsCaller {
public interface ShareTrackCaller {
/**
* Called when add emails is done.
* Called when share track is done.
*
* @param emails the added emails
* @param makePublic true to make the track public
*/
public void onAddEmailsDone(String emails);
public void onShareTrackDone(String emails, boolean makePublic);
}
public static final String ADD_EMAILS_DIALOG_TAG = "addEmailsDialog";
public static final String SHARE_TRACK_DIALOG_TAG = "shareTrackDialog";
private static final String KEY_TRACK_ID = "trackId";
public static AddEmailsDialogFragment newInstance(long trackId) {
public static ShareTrackDialogFragment newInstance(long trackId) {
Bundle bundle = new Bundle();
bundle.putLong(KEY_TRACK_ID, trackId);
AddEmailsDialogFragment addPeopleDialogFragment = new AddEmailsDialogFragment();
addPeopleDialogFragment.setArguments(bundle);
return addPeopleDialogFragment;
ShareTrackDialogFragment shareleTrackDialogFragment = new ShareTrackDialogFragment();
shareleTrackDialogFragment.setArguments(bundle);
return shareleTrackDialogFragment;
}
private AddEmailsCaller caller;
private ShareTrackCaller caller;
private FragmentActivity fragmentActivity;
private MultiAutoCompleteTextView multiAutoCompleteTextView;
private CheckBox publicCheckBox;
private CheckBox inviteCheckBox;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
caller = (AddEmailsCaller) activity;
caller = (ShareTrackCaller) activity;
} catch (ClassCastException e) {
throw new ClassCastException(
activity.toString() + " must implement " + AddEmailsCaller.class.getSimpleName());
activity.toString() + " must implement " + ShareTrackCaller.class.getSimpleName());
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
fragmentActivity = getActivity();
View view = fragmentActivity.getLayoutInflater().inflate(R.layout.add_emails, null);
multiAutoCompleteTextView = (MultiAutoCompleteTextView) view.findViewById(R.id.add_emails);
View view = fragmentActivity.getLayoutInflater().inflate(R.layout.share_track, null);
multiAutoCompleteTextView = (MultiAutoCompleteTextView) view.findViewById(
R.id.share_track_emails);
multiAutoCompleteTextView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
SimpleCursorAdapter adapter = new SimpleCursorAdapter(fragmentActivity,
@@ -109,15 +119,45 @@ public class AddEmailsDialogFragment extends DialogFragment {
});
multiAutoCompleteTextView.setAdapter(adapter);
publicCheckBox = (CheckBox) view.findViewById(R.id.share_track_public);
publicCheckBox.setChecked(PreferencesUtils.getBoolean(
fragmentActivity, R.string.share_track_public_key,
PreferencesUtils.SHARE_TRACK_PUBLIC_DEFAULT));
inviteCheckBox = (CheckBox) view.findViewById(R.id.share_track_invite);
inviteCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
multiAutoCompleteTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
});
inviteCheckBox.setChecked(PreferencesUtils.getBoolean(
fragmentActivity, R.string.share_track_invite_key,
PreferencesUtils.SHARE_TRACK_INVITE_DEFAULT));
return new AlertDialog.Builder(fragmentActivity).setNegativeButton(
R.string.generic_cancel, null)
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String acl = multiAutoCompleteTextView.getText().toString();
caller.onAddEmailsDone(acl);
if (!publicCheckBox.isChecked() && !inviteCheckBox.isChecked()) {
Toast.makeText(fragmentActivity, R.string.share_track_no_selection, Toast.LENGTH_LONG)
.show();
return;
}
String acl = multiAutoCompleteTextView.getText().toString().trim();
if (!publicCheckBox.isChecked() && acl.equals("")) {
Toast.makeText(fragmentActivity, R.string.share_track_no_emails, Toast.LENGTH_LONG)
.show();
return;
}
PreferencesUtils.setBoolean(
fragmentActivity, R.string.share_track_public_key, publicCheckBox.isChecked());
PreferencesUtils.setBoolean(
fragmentActivity, R.string.share_track_invite_key, inviteCheckBox.isChecked());
caller.onShareTrackDone(acl, publicCheckBox.isChecked());
}
}).setTitle(R.string.share_track_add_emails_title).setView(view).create();
}).setTitle(R.string.share_track_title).setView(view).create();
}
/**
@@ -37,8 +37,8 @@ public class SendDriveActivity extends AbstractSendActivity {
@Override
protected AbstractSendAsyncTask createAsyncTask() {
return new SendDriveAsyncTask(
this, sendRequest.getTrackId(), sendRequest.getAccount(), sendRequest.getDriveShareEmails());
return new SendDriveAsyncTask(this, sendRequest.getTrackId(), sendRequest.getAccount(),
sendRequest.getDriveShareEmails(), sendRequest.isDriveSharePublic());
}
@Override
@@ -28,6 +28,7 @@ import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecovera
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.Permission;
import com.google.api.services.drive.model.PermissionList;
import android.accounts.Account;
import android.content.Context;
@@ -44,10 +45,12 @@ public class SendDriveAsyncTask extends AbstractSendAsyncTask {
private final long trackId;
private final Account account;
private final String[] acl;
private final boolean isPublic;
private final Context context;
private final MyTracksProviderUtils myTracksProviderUtils;
public SendDriveAsyncTask(SendDriveActivity activity, long trackId, Account account, String acl) {
public SendDriveAsyncTask(
SendDriveActivity activity, long trackId, Account account, String acl, boolean isPublic) {
super(activity);
this.trackId = trackId;
this.account = account;
@@ -56,7 +59,8 @@ public class SendDriveAsyncTask extends AbstractSendAsyncTask {
} else {
this.acl = null;
}
this.isPublic = isPublic;
context = activity.getApplicationContext();
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
}
@@ -64,9 +68,6 @@ public class SendDriveAsyncTask extends AbstractSendAsyncTask {
@Override
protected void closeConnection() {}
@Override
protected void saveResult() {}
@Override
protected boolean performTask() {
try {
@@ -91,18 +92,18 @@ public class SendDriveAsyncTask extends AbstractSendAsyncTask {
File driveFile = drive.files().get(driveId).execute();
if (SyncUtils.isValid(driveFile, folderId) && SyncUtils.updateDriveFile(
drive, driveFile, context, myTracksProviderUtils, track, false)) {
addPermission(drive, driveId);
addPermission(drive, driveFile);
return true;
}
SyncUtils.updateTrackWithDriveFileInfo(myTracksProviderUtils, track, null);
}
String id = SyncUtils.insertDriveFile(
File file = SyncUtils.insertDriveFile(
drive, folderId, context, myTracksProviderUtils, track, false);
if (id == null) {
if (file == null) {
return false;
}
addPermission(drive, id);
addPermission(drive, file);
return true;
} catch (UserRecoverableAuthException e) {
SendToGoogleUtils.sendNotification(
@@ -126,18 +127,40 @@ public class SendDriveAsyncTask extends AbstractSendAsyncTask {
* Adds permission.
*
* @param drive the drive
* @param driveId the drive id
* @param file the drive file
*/
private void addPermission(Drive drive, String driveId) throws IOException {
private void addPermission(Drive drive, File file) throws IOException {
if (isPublic) {
boolean hasPublic = false;
PermissionList permissionList = drive.permissions().list(file.getId()).execute();
for (Permission permission : permissionList.getItems()) {
String role = permission.getRole();
if (role.equals("reader") || role.equals("writer")) {
if (permission.getType().equals("anyone")) {
hasPublic = true;
break;
}
}
}
if (!hasPublic) {
Permission permission = new Permission();
permission.setRole("reader");
permission.setType("anyone");
permission.setValue("");
drive.permissions().insert(file.getId(), permission).execute();
}
shareUrl = file.getAlternateLink();
}
if (acl != null) {
for (String email : acl) {
email = email.trim();
if (!email.equals("")) {
Permission permission = new Permission();
permission.setValue(email);
permission.setType("user");
permission.setRole("reader");
drive.permissions().insert(driveId, permission).execute();
permission.setType("user");
permission.setValue(email);
drive.permissions().insert(file.getId(), permission).execute();
}
}
}
@@ -111,8 +111,9 @@ public class SaveActivity extends Activity {
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_PROGRESS_ID:
progressDialog = DialogUtils.createHorizontalProgressDialog(
this, R.string.save_progress_message, new DialogInterface.OnCancelListener() {
progressDialog = DialogUtils.createHorizontalProgressDialog(this,
R.string.export_external_storage_progress_message,
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
saveAsyncTask.cancel(true);
@@ -128,10 +129,11 @@ public class SaveActivity extends Activity {
.getQuantityString(R.plurals.tracks, totalCount, totalCount);
if (successCount == totalCount && totalCount > 0) {
success = true;
message = getString(R.string.save_success, totalTracks, directoryName);
message = getString(R.string.export_external_storage_success, totalTracks, directoryName);
} else {
success = false;
message = getString(R.string.save_error, successCount, totalTracks, directoryName);
message = getString(
R.string.export_external_storage_error, successCount, totalTracks, directoryName);
}
AlertDialog.Builder builder = new AlertDialog.Builder(this).setCancelable(true).setIcon(
success ? android.R.drawable.ic_dialog_info : android.R.drawable.ic_dialog_alert)
@@ -10,18 +10,18 @@ import java.util.Locale;
* Definition of all possible track formats.
*/
public enum TrackFileFormat implements Parcelable {
GPX {
@Override
TrackFormatWriter newFormatWriter(Context context) {
return new GpxTrackWriter(context);
}
},
KML {
@Override
TrackFormatWriter newFormatWriter(Context context) {
return new KmlTrackWriter(context);
}
},
GPX {
@Override
TrackFormatWriter newFormatWriter(Context context) {
return new GpxTrackWriter(context);
}
},
CSV {
@Override
public TrackFormatWriter newFormatWriter(Context context) {
@@ -88,9 +88,6 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
@Override
protected void closeConnection() {}
@Override
protected void saveResult() {}
@Override
protected boolean performTask() {
try {
@@ -121,7 +118,7 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
publishProgress(PROGRESS_SET_STYLE);
setStyle(fusiontables, tableId);
setTemplate(fusiontables, tableId);
if (!setPermission(tableId)) {
if (!setPermission(track, tableId)) {
Log.d(TAG, "Cannot set permission for table " + tableId);
return false;
}
@@ -138,9 +135,6 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
return false;
}
track.setTableId(tableId);
myTracksProviderUtils.updateTrack(track);
publishProgress(PROGRESS_COMPLETE);
return true;
@@ -200,7 +194,7 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
fusiontables.template().insert(tableId, template).execute();
}
private boolean setPermission(String tableId) throws IOException, GoogleAuthException {
private boolean setPermission(Track track, String tableId) throws IOException, GoogleAuthException {
boolean defaultTablePublic = PreferencesUtils.getBoolean(context,
R.string.export_google_fusion_tables_public_key,
PreferencesUtils.EXPORT_GOOGLE_FUSION_TABLES_PUBLIC_DEFAULT);
@@ -214,9 +208,12 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
}
Drive drive = SyncUtils.getDriveService(driveCredential);
Permission permission = new Permission();
permission.setType("anyone");
permission.setRole("reader");
permission.setType("anyone");
permission.setValue("");
drive.permissions().insert(tableId, permission).execute();
shareUrl = SendFusionTablesUtils.getMapUrl(track, tableId);
return true;
}
@@ -42,13 +42,11 @@ public class SendFusionTablesUtils {
* Gets the url to visualize a fusion table on a map.
*
* @param track the track
* @param tableId the table id
* @return the url.
*/
public static String getMapUrl(Track track) {
if (track == null
|| track.getTripStatistics() == null
|| track.getTableId() == null
|| track.getTableId().length() == 0) {
public static String getMapUrl(Track track, String tableId) {
if (track == null || track.getTripStatistics() == null) {
Log.e(TAG, "Invalid track");
return null;
}
@@ -57,7 +55,7 @@ public class SendFusionTablesUtils {
int z;
if (track.getNumberOfPoints() < 2) {
// Use Google's latitude and longitude
latE6 = 37.423 * 1.E6;
latE6 = 37.423 * 1.E6;
lonE6 = -122.084 * 1.E6;
z = 2;
} else {
@@ -69,8 +67,7 @@ public class SendFusionTablesUtils {
// We explicitly format with Locale.US because we need the latitude and
// longitude to be formatted in a locale-independent manner. Specifically,
// we need the decimal separator to be a period rather than a comma.
return String.format(
Locale.US, MAP_URL, track.getTableId(), latE6 / 1.E6, lonE6 / 1.E6, z);
return String.format(Locale.US, MAP_URL, tableId, latE6 / 1.E6, lonE6 / 1.E6, z);
}
/**
@@ -123,17 +123,6 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
}
}
@Override
protected void saveResult() {
Track track = myTracksProviderUtils.getTrack(trackId);
if (track == null) {
Log.d(TAG, "No track for " + trackId);
return;
}
track.setMapId(mapId);
myTracksProviderUtils.updateTrack(track);
}
@Override
protected boolean performTask() {
// Reset the per upload states
@@ -222,6 +211,7 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
+ context.getString(R.string.send_google_by_my_tracks, "", "");
mapId = SendMapsUtils.createNewMap(
track.getName(), description, defaultMapPublic, mapsClient, authToken);
shareUrl = MapsClient.buildMapUrl(mapId);
} catch (ParseException e) {
Log.d(TAG, "Unable to create a new map", e);
return false;
@@ -15,7 +15,6 @@
*/
package com.google.android.apps.mytracks.io.maps;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.gdata.maps.MapsClient;
import com.google.android.apps.mytracks.io.gdata.maps.MapsFeature;
@@ -46,22 +45,6 @@ public class SendMapsUtils {
private SendMapsUtils() {}
/**
* Gets the Google Maps url for a track.
*
* @param track the track
* @return the url if available.
*/
public static String getMapUrl(Track track) {
if (track == null
|| track.getMapId() == null
|| track.getMapId().length() == 0) {
Log.e(TAG, "Invalid track");
return null;
}
return MapsClient.buildMapUrl(track.getMapId());
}
/**
* Creates a new Google Map.
*
@@ -90,7 +90,8 @@ public abstract class AbstractSendActivity extends Activity {
*
* @param success true if the AsyncTask is successful
*/
public void onAsyncTaskCompleted(boolean success) {
public void onAsyncTaskCompleted(boolean success, String shareUrl) {
sendRequest.setShareUrl(shareUrl);
startNextActivity(success, false);
}
@@ -20,7 +20,7 @@ import android.os.AsyncTask;
/**
* The abstract class for AsyncTasks sending a track to Google.
*
*
* @author Jimmy Shih
*/
public abstract class AbstractSendAsyncTask extends AsyncTask<Void, Integer, Boolean> {
@@ -35,6 +35,11 @@ public abstract class AbstractSendAsyncTask extends AsyncTask<Void, Integer, Boo
*/
private boolean success;
/**
* The share url from the AsyncTask.
*/
protected String shareUrl;
/**
* True if the AsyncTask has completed.
*/
@@ -47,25 +52,26 @@ public abstract class AbstractSendAsyncTask extends AsyncTask<Void, Integer, Boo
/**
* Creates an AsyncTask.
*
*
* @param activity the activity currently associated with this AsyncTask
*/
public AbstractSendAsyncTask(AbstractSendActivity activity) {
this.activity = activity;
success = false;
shareUrl = null;
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);
activity.onAsyncTaskCompleted(success, shareUrl);
}
}
@@ -94,18 +100,15 @@ public abstract class AbstractSendAsyncTask extends AsyncTask<Void, Integer, Boo
protected void onPostExecute(Boolean result) {
success = result;
completed = true;
if (success) {
saveResult();
}
if (activity != null) {
activity.onAsyncTaskCompleted(success);
activity.onAsyncTaskCompleted(success, shareUrl);
}
}
/**
* 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() {
@@ -126,14 +129,9 @@ public abstract class AbstractSendAsyncTask extends AsyncTask<Void, Integer, Boo
*/
protected abstract void closeConnection();
/**
* Saves any AsyncTask result.
*/
protected abstract void saveResult();
/**
* Performs the AsyncTask.
*
*
* @return true if success
*/
protected abstract boolean performTask();
@@ -36,9 +36,10 @@ public class SendRequest implements Parcelable {
private boolean sendFusionTables = false;
private boolean sendSpreadsheets = false;
private boolean driveEnableSync = false;
private boolean driveShare = false;
private String driveShareEmails = null;
private boolean driveEnableSync = false; // to enable Drive sync
private boolean driveShare = false; // to enable Drive share
private String driveShareEmails = null; // share with emails
private boolean driveSharePublic = false; // share as public
private Account account = null;
@@ -46,6 +47,7 @@ public class SendRequest implements Parcelable {
private boolean mapsSuccess = false;
private boolean spreadsheetsSuccess = false;
private boolean fusionTablesSuccess = false;
private String shareUrl = null;
/**
* Creates a new send request.
@@ -116,6 +118,14 @@ public class SendRequest implements Parcelable {
this.driveShareEmails = driveShareEmails;
}
public boolean isDriveSharePublic() {
return driveSharePublic;
}
public void setDriveSharePublic(boolean driveSharePublic) {
this.driveSharePublic = driveSharePublic;
}
public Account getAccount() {
return account;
}
@@ -156,6 +166,14 @@ public class SendRequest implements Parcelable {
this.spreadsheetsSuccess = spreadsheetsSuccess;
}
public String getShareUrl() {
return shareUrl;
}
public void setShareUrl(String shareUrl) {
this.shareUrl = shareUrl;
}
private SendRequest(Parcel in) {
trackId = in.readLong();
sendDrive = in.readByte() == 1;
@@ -165,11 +183,13 @@ public class SendRequest implements Parcelable {
driveEnableSync = in.readByte() == 1;
driveShare = in.readByte() == 1;
driveShareEmails = in.readString();
driveSharePublic = in.readByte() == 1;
account = in.readParcelable(null);
driveSuccess = in.readByte() == 1;
mapsSuccess = in.readByte() == 1;
fusionTablesSuccess = in.readByte() == 1;
spreadsheetsSuccess = in.readByte() == 1;
shareUrl = in.readString();
}
@Override
@@ -184,14 +204,16 @@ public class SendRequest implements Parcelable {
out.writeByte((byte) (sendMaps ? 1 : 0));
out.writeByte((byte) (sendFusionTables ? 1 : 0));
out.writeByte((byte) (sendSpreadsheets ? 1 : 0));
out.writeByte((byte) (driveEnableSync ? 1 : 0));
out.writeByte((byte) (driveEnableSync ? 1 : 0));
out.writeByte((byte) (driveShare ? 1 : 0));
out.writeString(driveShareEmails);
out.writeByte((byte) (driveSharePublic ? 1 : 0));
out.writeParcelable(account, 0);
out.writeByte((byte) (driveSuccess ? 1 : 0));
out.writeByte((byte) (mapsSuccess ? 1 : 0));
out.writeByte((byte) (fusionTablesSuccess ? 1 : 0));
out.writeByte((byte) (spreadsheetsSuccess ? 1 : 0));
out.writeString(shareUrl);
}
public static final Parcelable.Creator<SendRequest>
@@ -20,10 +20,7 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment;
import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment.ChooseActivityCaller;
import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesUtils;
import com.google.android.apps.mytracks.io.maps.SendMapsUtils;
import com.google.android.apps.mytracks.util.IntentUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import com.google.common.annotations.VisibleForTesting;
@@ -60,7 +57,7 @@ public class UploadResultActivity extends FragmentActivity implements ChooseActi
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY);
shareUrl = null;
shareUrl = sendRequest.getShareUrl();
Track track = MyTracksProviderUtils.Factory.get(this).getTrack(sendRequest.getTrackId());
if (track == null) {
@@ -69,17 +66,10 @@ public class UploadResultActivity extends FragmentActivity implements ChooseActi
return;
}
if (sendRequest.isSendMaps() && sendRequest.isMapsSuccess()) {
shareUrl = SendMapsUtils.getMapUrl(track);
}
if (shareUrl == null && sendRequest.isSendFusionTables()
&& sendRequest.isFusionTablesSuccess()) {
boolean defaultTablePublic = PreferencesUtils.getBoolean(this,
R.string.export_google_fusion_tables_public_key,
PreferencesUtils.EXPORT_GOOGLE_FUSION_TABLES_PUBLIC_DEFAULT);
if (defaultTablePublic) {
shareUrl = SendFusionTablesUtils.getMapUrl(track);
}
if (sendRequest.isDriveSuccess() && shareUrl != null) {
new ChooseActivityDialogFragment().show(
getSupportFragmentManager(), ChooseActivityDialogFragment.CHOOSE_ACTIVITY_DIALOG_TAG);
return;
}
showDialog(DIALOG_RESULT_ID);
}
@@ -171,7 +161,7 @@ public class UploadResultActivity extends FragmentActivity implements ChooseActi
.setView(view);
// Add a Share URL button if shareUrl exists
if (shareUrl != null) {
if (!hasError && shareUrl != null) {
builder.setNegativeButton(
R.string.share_track_share_url, new DialogInterface.OnClickListener() {
@Override
@@ -18,8 +18,6 @@ package com.google.android.apps.mytracks.io.spreadsheets;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesUtils;
import com.google.android.apps.mytracks.io.maps.SendMapsUtils;
import com.google.android.apps.mytracks.io.sendtogoogle.AbstractSendAsyncTask;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.apps.mytracks.io.sync.SyncUtils;
@@ -97,9 +95,6 @@ public class SendSpreadsheetsAsyncTask extends AbstractSendAsyncTask {
@Override
protected void closeConnection() {}
@Override
protected void saveResult() {}
@Override
protected boolean performTask() {
try {
@@ -281,19 +276,7 @@ public class SendSpreadsheetsAsyncTask extends AbstractSendAsyncTask {
row.getCustomElements().setValueLocal(
"maxelevation", SendSpreadsheetsUtils.getElevation(tripStatistics.getMaxElevation(), metricUnits));
row.getCustomElements().setValueLocal("elevationunit", elevationUnit);
String map = SendMapsUtils.getMapUrl(track);
if (map == null) {
map = context.getString(R.string.value_unknown);
}
row.getCustomElements().setValueLocal("map", map);
String fusionTable = SendFusionTablesUtils.getMapUrl(track);
if (fusionTable == null) {
fusionTable = context.getString(R.string.value_unknown);
}
row.getCustomElements().setValueLocal("fusiontable", fusionTable);
ListEntry result = spreadsheetService.insert(worksheetUrl, row);
return result != null;
}
@@ -262,9 +262,9 @@ public class SyncUtils {
* @param myTracksProviderUtils the myTracksProviderUtils
* @param track the track
* @param canRetry true if can retry
* @return the added drive file id or null.
* @return the added drive file or null.
*/
public static String insertDriveFile(Drive drive, String folderId, Context context,
public static File insertDriveFile(Drive drive, String folderId, Context context,
MyTracksProviderUtils myTracksProviderUtils, Track track, boolean canRetry)
throws IOException {
java.io.File file = getFile(context, myTracksProviderUtils, track);
@@ -281,7 +281,7 @@ public class SyncUtils {
return null;
}
SyncUtils.updateTrackWithDriveFileInfo(myTracksProviderUtils, track, uploadedFile);
return uploadedFile.getId();
return uploadedFile;
} finally {
file.delete();
}
@@ -77,8 +77,8 @@ public class RemoveTempFilesService extends Service {
// Can't do anything
return null;
}
cleanTempDirectory(TrackFileFormat.GPX.getExtension());
cleanTempDirectory(TrackFileFormat.KML.getExtension());
cleanTempDirectory(TrackFileFormat.GPX.getExtension());
cleanTempDirectory(TrackFileFormat.CSV.getExtension());
cleanTempDirectory(TrackFileFormat.TCX.getExtension());
return null;
@@ -48,6 +48,7 @@ public class PreferencesUtils {
public static final int AUTO_RESUME_TRACK_TIMEOUT_NEVER = 0;
public static final String BLUETOOTH_SENSOR_DEFAULT = "";
public static final boolean CHART_BY_DISTANCE_DEFAULT = true;
public static final boolean CHART_SHOW_CADENCE_DEFAULT = true;
public static final boolean CHART_SHOW_ELEVATION_DEFAULT = true;
@@ -59,6 +60,7 @@ public class PreferencesUtils {
public static final boolean CONFIRM_SHARE_DRIVE_DEFAULT = true;
public static final String DEFAULT_ACTIVITY_DEFAULT = "";
public static final String DRIVE_DELETED_LIST_DEFAULT = "";
public static final long DRIVE_LARGEST_CHANGE_ID_DEFAULT = -1L;
public static final boolean DRIVE_SYNC_DEFAULT = false;
@@ -72,9 +74,7 @@ public class PreferencesUtils {
public static final int FREQUENCY_OFF = 0;
public static final String GOOGLE_ACCOUNT_DEFAULT = "";
public static final int MAP_TYPE_DEFAUlT = 1;
public static final int MAX_RECORDING_DISTANCE_DEFAULT = 200;
public static final boolean METRIC_UNITS_DEFAULT = true;
public static final int MIN_RECORDING_DISTANCE_DEFAULT = 5;
@@ -93,16 +93,27 @@ public class PreferencesUtils {
public static final boolean RECORDING_TRACK_PAUSED_DEFAULT = true;
public static final boolean REPORT_SPEED_DEFAULT = true;
public static final long SELECTED_TRACK_ID_DEFAULT = -1L;
public static final String SENSOR_TYPE_DEFAULT = "NONE";
// Share track
public static final boolean SHARE_TRACK_INVITE_DEFAULT = false;
public static final boolean SHARE_TRACK_PUBLIC_DEFAULT = false;
public static final int SPLIT_FREQUENCY_DEFAULT = 0;
// Stats
public static final boolean STATS_SHOW_COORDINATE_DEFAULT = false;
public static final boolean STATS_SHOW_GRADE_ELEVATION_DEFAULT = false;
// Track color
public static final String TRACK_COLOR_MODE_DEFAULT = "SINGLE";
public static final int TRACK_COLOR_MODE_MEDIUM_DEFAULT = 15;
public static final int TRACK_COLOR_MODE_PERCENTAGE_DEFAULT = 25;
public static final int TRACK_COLOR_MODE_SLOW_DEFAULT = 9;
public static final String TRACK_NAME_DEFAULT = "LOCATION";
// Track widget
public static final int TRACK_WIDGET_ITEM1_DEFAULT = 3; // moving time
public static final int TRACK_WIDGET_ITEM2_DEFAULT = 0; // distance
public static final int TRACK_WIDGET_ITEM3_DEFAULT = 1; // total time
@@ -82,8 +82,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
int elevationGainIndex = cursor.getColumnIndexOrThrow(TracksColumns.ELEVATIONGAIN);
int minGradeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MINGRADE);
int maxGradeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAXGRADE);
int mapIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAPID);
int tableIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.TABLEID);
int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON);
int driveIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.DRIVEID);
int modifiedTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MODIFIEDTIME);
@@ -154,12 +152,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
if (!cursor.isNull(maxGradeIndex)) {
tripStatistics.setMaxGrade(cursor.getFloat(maxGradeIndex));
}
if (!cursor.isNull(mapIdIndex)) {
track.setMapId(cursor.getString(mapIdIndex));
}
if (!cursor.isNull(tableIdIndex)) {
track.setTableId(cursor.getString(tableIdIndex));
}
if (!cursor.isNull(iconIndex)) {
track.setIcon(cursor.getString(iconIndex));
}
@@ -319,8 +311,6 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
values.put(TracksColumns.ELEVATIONGAIN, tripStatistics.getTotalElevationGain());
values.put(TracksColumns.MINGRADE, tripStatistics.getMinGrade());
values.put(TracksColumns.MAXGRADE, tripStatistics.getMaxGrade());
values.put(TracksColumns.MAPID, track.getMapId());
values.put(TracksColumns.TABLEID, track.getTableId());
values.put(TracksColumns.ICON, track.getIcon());
values.put(TracksColumns.DRIVEID, track.getDriveId());
values.put(TracksColumns.MODIFIEDTIME, track.getModifiedTime());
@@ -44,8 +44,6 @@ public class Track implements Parcelable {
* not loaded)
*/
private int numberOfPoints = 0;
private String mapId = "";
private String tableId = "";
private String icon = "";
private String driveId = "";
private long modifiedTime = -1L;
@@ -67,8 +65,6 @@ public class Track implements Parcelable {
startId = in.readLong();
stopId = in.readLong();
numberOfPoints = in.readInt();
mapId = in.readString();
tableId = in.readString();
icon = in.readString();
driveId = in.readString();
modifiedTime = in.readLong();
@@ -98,8 +94,6 @@ public class Track implements Parcelable {
dest.writeLong(startId);
dest.writeLong(stopId);
dest.writeInt(numberOfPoints);
dest.writeString(mapId);
dest.writeString(tableId);
dest.writeString(icon);
dest.writeString(driveId);
dest.writeLong(modifiedTime);
@@ -180,22 +174,6 @@ public class Track implements Parcelable {
this.numberOfPoints = numberOfPoints;
}
public String getMapId() {
return mapId;
}
public void setMapId(String mapId) {
this.mapId = mapId;
}
public String getTableId() {
return tableId;
}
public void setTableId(String tableId) {
this.tableId = tableId;
}
public String getIcon() {
return icon;
}
@@ -32,36 +32,23 @@ import junit.framework.TestCase;
public class SendFusionTablesUtilsTest extends TestCase {
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with null track.
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null track.
*/
public void testGetMapUrl_null_track() {
assertEquals(null, SendFusionTablesUtils.getMapUrl(null));
assertEquals(null, SendFusionTablesUtils.getMapUrl(null, "123"));
}
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with null table id.
*/
public void testGetMapUrl_null_table_id() {
Track track = new Track();
TripStatistics stats = new TripStatistics();
stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6);
track.setTripStatistics(stats);
track.setTableId(null);
assertEquals(null, SendFusionTablesUtils.getMapUrl(track));
}
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with null stats.
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null stats.
*/
public void testGetMapUrl_null_stats() {
Track track = new Track();
track.setTripStatistics(null);
track.setTableId("123");
assertEquals(null, SendFusionTablesUtils.getMapUrl(track));
assertEquals(null, SendFusionTablesUtils.getMapUrl(track, "123"));
}
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with a valid track.
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with a valid track.
*/
public void testGetMapUrl_valid_track() {
Track track = new Track();
@@ -69,11 +56,10 @@ public class SendFusionTablesUtilsTest extends TestCase {
TripStatistics stats = new TripStatistics();
stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6);
track.setTripStatistics(stats);
track.setTableId("123");
assertEquals(
"https://www.google.com/fusiontables/embedviz?"
+ "viz=MAP&q=select+col0,+col1,+col2,+col3+from+123+&h=false&lat=7.500000&lng=75.000000"
+ "&z=15&t=1&l=col2", SendFusionTablesUtils.getMapUrl(track));
+ "&z=15&t=1&l=col2", SendFusionTablesUtils.getMapUrl(track, "123"));
}
/**
@@ -89,23 +89,6 @@ public class SendMapsAsyncTaskTest extends AndroidTestCase {
AndroidMock.expect(sendMapsActivityMock.getApplicationContext()).andReturn(getContext());
}
/**
* Tests the method {@link SendMapsAsyncTask#saveResult()}and makes sure the
* track is updated.
*/
public void testSaveResult() {
Track track = TrackStubUtils.createTrack(1);
track.setMapId(null);
AndroidMock.expect(myTracksProviderUtilsMock.getTrack(TRACK_ID)).andReturn(track);
myTracksProviderUtilsMock.updateTrack(track);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
sendMapsAsyncTask.saveResult();
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
}
/**
* Tests {@link SendMapsAsyncTask#fetchSendMapId(Track)} when chooseMapId is
* null and makes sure it returns false.
@@ -15,7 +15,6 @@
*/
package com.google.android.apps.mytracks.io.maps;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.gdata.maps.MapsFeature;
import android.location.Location;
@@ -31,31 +30,6 @@ import junit.framework.TestCase;
*/
public class SendMapsUtilsTest extends TestCase {
/**
* Tests {@link SendMapsUtils#getMapUrl(Track)} with null track.
*/
public void testGetMapUrl_null_track() {
assertEquals(null, SendMapsUtils.getMapUrl(null));
}
/**
* Tests {@link SendMapsUtils#getMapUrl(Track)} with null map id.
*/
public void testGetMapUrl_null_map_id() {
Track track = new Track();
track.setMapId(null);
assertEquals(null, SendMapsUtils.getMapUrl(track));
}
/**
* Tests {@link SendMapsUtils#getMapUrl(Track)} with a valid track.
*/
public void testGetMapUrl_valid_track() {
Track track = new Track();
track.setMapId("123");
assertEquals("https://maps.google.com/maps/ms?msa=0&msid=123", SendMapsUtils.getMapUrl(track));
}
/**
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
* Location)} with a title.
@@ -32,6 +32,7 @@ public class SendRequestTest extends AndroidTestCase {
private final static String ACCOUNTNAME = "testAccount1";
private final static String ACCOUNTYPE = "testType1";
private final static String DRIVE_SHARE_EMAILS = "foo@foo.com";
private final static String SHARE_URL = "url@url.com";
@Override
protected void setUp() throws Exception {
@@ -128,12 +129,14 @@ public class SendRequestTest extends AndroidTestCase {
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeString(DRIVE_SHARE_EMAILS);
parcel.writeByte((byte) 1);
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
parcel.writeParcelable(account, 0);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeString(SHARE_URL);
parcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
assertEquals(2, sendRequest.getTrackId());
@@ -144,11 +147,13 @@ public class SendRequestTest extends AndroidTestCase {
assertTrue(sendRequest.isDriveEnableSync());
assertTrue(sendRequest.isDriveShare());
assertEquals(DRIVE_SHARE_EMAILS, sendRequest.getDriveShareEmails());
assertTrue(sendRequest.isDriveSharePublic());
assertEquals(account, sendRequest.getAccount());
assertTrue(sendRequest.isDriveSuccess());
assertTrue(sendRequest.isMapsSuccess());
assertTrue(sendRequest.isFusionTablesSuccess());
assertTrue(sendRequest.isSpreadsheetsSuccess());
assertEquals(SHARE_URL, sendRequest.getShareUrl());
}
/**
@@ -165,12 +170,14 @@ public class SendRequestTest extends AndroidTestCase {
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeString(null);
parcel.writeByte((byte) 0);
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
parcel.writeParcelable(account, 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeString(null);
parcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
assertEquals(4, sendRequest.getTrackId());
@@ -181,11 +188,13 @@ public class SendRequestTest extends AndroidTestCase {
assertFalse(sendRequest.isDriveEnableSync());
assertFalse(sendRequest.isDriveShare());
assertNull(sendRequest.getDriveShareEmails());
assertFalse(sendRequest.isDriveSharePublic());
assertEquals(account, sendRequest.getAccount());
assertFalse(sendRequest.isDriveSuccess());
assertFalse(sendRequest.isMapsSuccess());
assertFalse(sendRequest.isFusionTablesSuccess());
assertFalse(sendRequest.isSpreadsheetsSuccess());
assertNull(sendRequest.getShareUrl());
}
/**
@@ -202,14 +211,16 @@ public class SendRequestTest extends AndroidTestCase {
boolean sendMaps = parcel.readByte() == 1;
boolean sendFusionTables = parcel.readByte() == 1;
boolean sendSpreadsheets = parcel.readByte() == 1;
boolean driveEnableSync = parcel.readByte() == 1;
boolean driveEnableSync = parcel.readByte() == 1;
boolean driveShare = parcel.readByte() == 1;
String dirveShareEmails = parcel.readString();
boolean driveSharePublic = parcel.readByte() == 1;
Parcelable account = parcel.readParcelable(null);
boolean driveSuccess = parcel.readByte() == 1;
boolean mapsSuccess = parcel.readByte() == 1;
boolean fusionTablesSuccess = parcel.readByte() == 1;
boolean spreadsheetsSuccess = parcel.readByte() == 1;
String shareUrl = parcel.readString();
assertEquals(1, trackId);
assertFalse(sendDrive);
assertFalse(sendMaps);
@@ -218,11 +229,13 @@ public class SendRequestTest extends AndroidTestCase {
assertFalse(driveEnableSync);
assertFalse(driveShare);
assertNull(dirveShareEmails);
assertFalse(driveSharePublic);
assertNull(account);
assertFalse(driveSuccess);
assertFalse(mapsSuccess);
assertFalse(fusionTablesSuccess);
assertFalse(spreadsheetsSuccess);
assertNull(shareUrl);
}
/**
@@ -237,12 +250,14 @@ public class SendRequestTest extends AndroidTestCase {
sendRequest.setDriveEnableSync(true);
sendRequest.setDriveShare(true);
sendRequest.setDriveShareEmails(DRIVE_SHARE_EMAILS);
sendRequest.setDriveSharePublic(true);
Account accountNew = new Account(ACCOUNTNAME + "2", ACCOUNTYPE + "2");
sendRequest.setAccount(accountNew);
sendRequest.setMapsSuccess(true);
sendRequest.setDriveSuccess(true);
sendRequest.setFusionTablesSuccess(true);
sendRequest.setSpreadsheetsSuccess(true);
sendRequest.setShareUrl(SHARE_URL);
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
sendRequest.writeToParcel(parcel, 1);
@@ -255,11 +270,13 @@ public class SendRequestTest extends AndroidTestCase {
boolean driveEnableSync = parcel.readByte() == 1;
boolean driveShare = parcel.readByte() == 1;
String driveShareEmails = parcel.readString();
boolean driveSharePublic = parcel.readByte() == 1;
Parcelable account = parcel.readParcelable(null);
boolean driveSuccess = parcel.readByte() == 1;
boolean mapsSuccess = parcel.readByte() == 1;
boolean fusionTablesSuccess = parcel.readByte() == 1;
boolean spreadsheetsSuccess = parcel.readByte() == 1;
String shareUrl = parcel.readString();
assertEquals(4, trackId);
assertTrue(sendDrive);
assertTrue(sendMaps);
@@ -268,10 +285,12 @@ public class SendRequestTest extends AndroidTestCase {
assertTrue(driveEnableSync);
assertTrue(driveShare);
assertEquals(DRIVE_SHARE_EMAILS, driveShareEmails);
assertTrue(driveSharePublic);
assertEquals(accountNew, account);
assertTrue(driveSuccess);
assertTrue(mapsSuccess);
assertTrue(fusionTablesSuccess);
assertTrue(spreadsheetsSuccess);
assertEquals(SHARE_URL, shareUrl);
}
}
@@ -73,13 +73,14 @@ public class DeleteTest extends ActivityInstrumentationTestCase2<TrackListActivi
// Export when there is no track.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_export_all), true);
EndToEndTestUtils.SOLO.clickOnText(String.format(
activityMyTracks.getString(R.string.save_all_selection_option),
activityMyTracks.getString(R.string.export_external_storage_option),
EndToEndTestUtils.GPX.toUpperCase()));
EndToEndTestUtils.getButtonOnScreen(
EndToEndTestUtils.activityMytracks.getString(R.string.generic_ok), true, true);
String totalTracks = activityMyTracks.getResources().getQuantityString(R.plurals.tracks, 0, 0);
String directoryName = FileUtils.buildExternalDirectoryPath(EndToEndTestUtils.GPX);
String message = activityMyTracks.getString(R.string.save_error, 0, totalTracks, directoryName);
String message = activityMyTracks.getString(
R.string.export_external_storage_error, 0, totalTracks, directoryName);
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.external_storage_not_available), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)
@@ -22,9 +22,6 @@ import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import android.view.View;
import java.util.ArrayList;
/**
* Tests some menu items of MyTracks.
@@ -35,7 +32,6 @@ public class MenuItemsTest extends ActivityInstrumentationTestCase2<TrackListAct
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
private final static String SHARE_ITEM_PARENT_VIEW_NAME = "RecycleListView";
public MenuItemsTest() {
super(TrackListActivity.class);
@@ -110,30 +106,6 @@ public class MenuItemsTest extends ActivityInstrumentationTestCase2<TrackListAct
return activityMyTracks.findViewById(R.id.track_controler_container).isShown();
}
/**
* Gets the view to click the share item by item index.
*
* @param index of a share item
* @return null when no such item
*/
private View findShareItem(int index) {
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_share), true);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_yes));
ArrayList<View> views = EndToEndTestUtils.SOLO.getViews();
int i = 0;
for (View view : views) {
String name = view.getParent().getClass().getName();
// Each share item is a child of a "RecycleListView"
if (name.indexOf(SHARE_ITEM_PARENT_VIEW_NAME) > 0) {
if (index == i) {
return view;
}
i++;
}
}
return null;
}
/**
* Checks the voice frequency and split frequency menus during recording. When
* recording, they should be in both the menu and the recording settings. When
@@ -133,7 +133,7 @@ public class SendToGoogleTest extends ActivityInstrumentationTestCase2<TrackList
*/
private boolean sendToGoogle() {
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_export), true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.export_dialog_title));
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.export_title));
instrumentation.waitForIdleSync();
ArrayList<CheckBox> checkBoxs = EndToEndTestUtils.SOLO.getCurrentCheckBoxes();
for (int i = 0; i < checkBoxs.size(); i++) {