Merge heads

This commit is contained in:
youtaol
2012-05-17 10:42:09 +08:00
parent 2fe97f55dd
commit 164ba7a16b
78 changed files with 1490 additions and 1666 deletions
-2
View File
@@ -165,7 +165,6 @@ limitations under the License.
android:name="android.app.default_searchable"
android:value="com.google.android.apps.mytracks.SearchListActivity" />
</activity>
<activity android:name="com.google.android.apps.mytracks.SaveAllActivity" />
<activity
android:launchMode="singleTop"
android:name="com.google.android.apps.mytracks.SearchListActivity" >
@@ -206,7 +205,6 @@ limitations under the License.
<activity android:name="com.google.android.apps.mytracks.io.maps.SendMapsActivity" />
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.AccountChooserActivity" />
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity" />
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.UploadServiceChooserActivity" />
<activity android:name="com.google.android.apps.mytracks.settings.BackupSettingsActivity" />
<activity android:name="com.google.android.apps.mytracks.settings.ChartSettingsActivity" />
<activity android:name="com.google.android.apps.mytracks.settings.MapSettingsActivity" />
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2012 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp" >
<ImageView
android:contentDescription="@string/icon_application"
android:id="@+id/choose_activity_list_item_icon"
android:layout_height="@android:dimen/app_icon_size"
android:layout_width="@android:dimen/app_icon_size"
android:scaleType="fitCenter" />
<LinearLayout
android:gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/choose_activity_list_item_text1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="2"
android:paddingLeft="16dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall" />
<TextView
android:id="@+id/choose_activity_list_item_text2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="2"
android:paddingLeft="16dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</LinearLayout>
@@ -21,51 +21,51 @@ limitations under the License.
android:layout_width="fill_parent"
android:padding="8dp"
android:stretchColumns="1" >
<TableRow android:id="@+id/send_google_maps_row" >
<TableRow>
<ImageView
android:contentDescription="@string/send_google_maps"
android:src="@drawable/google_maps_icon"
style="@style/UploadServiceChooserImageView" />
style="@style/ChooseUploadServiceImageView" />
<CheckBox
android:id="@+id/send_google_maps"
android:id="@+id/choose_upload_service_maps"
android:text="@string/send_google_maps"
style="@style/UploadServiceChooserCheckBox" />
style="@style/ChooseUploadServiceCheckBox" />
</TableRow>
<TableRow android:id="@+id/send_google_maps_option_row" >
<TableRow android:id="@+id/choose_upload_service_maps_options" >
<RadioGroup
android:layout_column="1"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_width="0dp" >
<RadioButton
android:id="@+id/send_google_new_map"
android:id="@+id/choose_upload_service_new_map"
android:text="@string/send_google_new_map"
style="@style/TextMedium" />
<RadioButton
android:id="@+id/send_google_existing_map"
android:id="@+id/choose_upload_service_existing_map"
android:text="@string/send_google_existing_map"
style="@style/TextMedium" />
</RadioGroup>
</TableRow>
<TableRow android:id="@+id/send_google_fusion_tables_row" >
<TableRow>
<ImageView
android:contentDescription="@string/send_google_fusion_tables"
android:src="@drawable/google_fusion_tables_icon"
style="@style/UploadServiceChooserImageView" />
style="@style/ChooseUploadServiceImageView" />
<CheckBox
android:id="@+id/send_google_fusion_tables"
android:id="@+id/choose_upload_service_fusion_tables"
android:text="@string/send_google_fusion_tables"
style="@style/UploadServiceChooserCheckBox" />
style="@style/ChooseUploadServiceCheckBox" />
</TableRow>
<TableRow android:id="@+id/send_google_docs_row" >
<TableRow>
<ImageView
android:contentDescription="@string/send_google_docs"
android:src="@drawable/google_docs_icon"
style="@style/UploadServiceChooserImageView" />
style="@style/ChooseUploadServiceImageView" />
<CheckBox
android:id="@+id/send_google_docs"
android:id="@+id/choose_upload_service_docs"
android:text="@string/send_google_docs"
style="@style/UploadServiceChooserCheckBox" />
style="@style/ChooseUploadServiceCheckBox" />
</TableRow>
</TableLayout>
</ScrollView>
+4 -4
View File
@@ -91,16 +91,16 @@ limitations under the License.
android:text="@string/help_saved_files_answer"
style="@style/HelpAnswer" />
<TextView
android:text="@string/help_waypoint_marker_question"
android:text="@string/help_marker_question"
style="@style/HelpQuestion" />
<TextView
android:text="@string/help_waypoint_marker_answer"
android:text="@string/help_marker_answer"
style="@style/HelpAnswer" />
<TextView
android:text="@string/help_statistics_marker_question"
android:text="@string/help_split_marker_question"
style="@style/HelpQuestion" />
<TextView
android:text="@string/help_statistics_marker_answer"
android:text="@string/help_split_marker_answer"
style="@style/HelpAnswer" />
<TextView
android:text="@string/help_delete_tracks_question"
+10 -10
View File
@@ -26,16 +26,6 @@ limitations under the License.
android:id="@+id/map_view"
android:layout_height="fill_parent"
android:layout_width="fill_parent" />
<ImageButton
android:background="@drawable/my_location"
android:contentDescription="@string/icon_my_location"
android:id="@+id/map_my_location"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_width="wrap_content" />
<TextView
android:background="@color/warning_background"
android:drawableLeft="@android:drawable/ic_dialog_alert"
@@ -47,4 +37,14 @@ limitations under the License.
android:textColor="@android:color/primary_text_dark"
android:visibility="gone"
style="@style/TextMedium.WithIcon" />
<ImageButton
android:background="@drawable/my_location"
android:contentDescription="@string/icon_my_location"
android:id="@+id/map_my_location"
android:layout_below="@id/map_message"
android:layout_alignParentRight="true"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_width="wrap_content" />
</RelativeLayout>
+17 -19
View File
@@ -39,18 +39,6 @@ limitations under the License.
android:orderInCategory="4"
android:showAsAction="ifRoom"
android:title="@string/menu_share">
<menu>
<item
android:id="@+id/track_detail_share_map_url"
android:title="@string/menu_share_map_url"/>
<item
android:id="@+id/track_detail_share_fusion_table_url"
android:title="@string/menu_share_fusion_table_url"/>
<item android:id="@+id/track_detail_share_gpx"/>
<item android:id="@+id/track_detail_share_kml"/>
<item android:id="@+id/track_detail_share_csv"/>
<item android:id="@+id/track_detail_share_tcx"/>
</menu>
</item>
<item
android:icon="@drawable/menu_markers"
@@ -59,15 +47,25 @@ limitations under the License.
android:showAsAction="ifRoom"
android:title="@string/menu_markers"/>
<!-- android:orderInCategory="6" is in map.xml -->
<item
android:icon="@drawable/menu_voice_frequency"
android:id="@+id/track_detail_voice_frequency"
android:orderInCategory="7"
android:title="@string/menu_voice_frequency"/>
<item
android:icon="@drawable/menu_split_frequency"
android:id="@+id/track_detail_split_frequency"
android:orderInCategory="8"
android:title="@string/menu_split_frequency"/>
<item
android:icon="@drawable/menu_send_google"
android:id="@+id/track_detail_send_google"
android:orderInCategory="7"
android:orderInCategory="9"
android:title="@string/menu_send_google"/>
<item
android:icon="@drawable/menu_save"
android:id="@+id/track_detail_save"
android:orderInCategory="8"
android:orderInCategory="10"
android:title="@string/menu_save">
<menu>
<item android:id="@+id/track_detail_save_gpx"/>
@@ -79,26 +77,26 @@ limitations under the License.
<item
android:icon="@drawable/menu_edit"
android:id="@+id/track_detail_edit"
android:orderInCategory="9"
android:orderInCategory="11"
android:title="@string/menu_edit"/>
<item
android:icon="@drawable/menu_delete"
android:id="@+id/track_detail_delete"
android:orderInCategory="10"
android:orderInCategory="12"
android:title="@string/menu_delete"/>
<item
android:icon="@drawable/menu_sensor_state"
android:id="@+id/track_detail_sensor_state"
android:orderInCategory="11"
android:orderInCategory="13"
android:title="@string/menu_sensor_state"/>
<item
android:icon="@drawable/menu_settings"
android:id="@+id/track_detail_settings"
android:orderInCategory="12"
android:orderInCategory="14"
android:title="@string/menu_settings"/>
<item
android:icon="@drawable/menu_help"
android:id="@+id/track_detail_help"
android:orderInCategory="13"
android:orderInCategory="15"
android:title="@string/menu_help"/>
</menu>
+16 -16
View File
@@ -96,6 +96,22 @@ limitations under the License.
<item>CSV</item>
<item>TCX</item>
</string-array>
<string-array name="frequency_values">
<item>0</item>
<item>1</item>
<item>2</item>
<item>5</item>
<item>10</item>
<item>15</item>
<item>30</item>
<item>60</item>
<item>-1</item>
<item>-5</item>
<item>-10</item>
<item>-25</item>
<item>-50</item>
<item>-100</item>
</string-array>
<string-array name="max_recording_distance_values">
<item>50</item>
<item>100</item>
@@ -142,22 +158,6 @@ limitations under the License.
<item>2000</item>
<item>5000</item>
</string-array>
<string-array name="periodic_task_values">
<item>0</item>
<item>1</item>
<item>2</item>
<item>5</item>
<item>10</item>
<item>15</item>
<item>30</item>
<item>60</item>
<item>-1</item>
<item>-5</item>
<item>-10</item>
<item>-25</item>
<item>-50</item>
<item>-100</item>
</string-array>
<string-array name="sensor_type_all_options">
<item>@string/settings_sensor_type_none</item>
<item>@string/settings_sensor_type_ant</item>
+1 -2
View File
@@ -39,7 +39,6 @@ limitations under the License.
<string name="min_recording_interval_key">minRecordingInterval</string>
<string name="min_required_accuracy_key">minRequiredAccuracy</string>
<string name="pick_existing_map_key">pickExistingMap</string>
<string name="preferred_account_key">preferredAccount</string>
<string name="recording_track_id_key">recordingTrackId</string>
<string name="report_speed_key">reportSpeed</string>
<string name="selected_track_id_key">selectedTrackId</string>
@@ -47,7 +46,7 @@ limitations under the License.
<string name="send_to_fusion_tables_key">sendToFusionTables</string>
<string name="send_to_maps_key">sendToMaps</string>
<string name="sensor_type_key">sensorType</string>
<string name="share_url_only_key">shareUrlOnly</string>
<string name="sharing_account_key">sharingAccount</string>
<string name="show_check_units_dialog_key">showCheckUnitsDialog</string>
<string name="show_welcome_dialog_key">showWelcomeDialog</string>
<string name="split_frequency_key">splitFrequency</string>
+178 -221
View File
@@ -377,8 +377,8 @@ limitations under the License.
Use My Tracks while you run, bike, hike, or do anything else outdoors, and it will use the GPS
sensor in your phone to record the path you took. It will also gather useful statistics such as
time, speed, distance, and elevation. You can review all of this data live, or you can save it
for use later. While you\'re out, you can mark relevant waypoints, and can ask to hear automatic
voice announcements about your progress.\n
for use later. While you\'re out, you can insert markers, have split markers inserted
automatically, and can ask to hear periodic voice announcements of your progress.\n
\n
My Tracks can record data from external sensors:\n
- Zephyr Technology Consumer HxM Bluetooth heart rate monitor\n
@@ -630,6 +630,12 @@ limitations under the License.
translation_description="The text label for entering a description.">
Description
</string>
<string name="generic_description_line"
translation_description="A line containing a description.
%1$s description. E.g., 'At the top'.">
Description: %1$s
</string>
<string name="generic_error_title"
translation_description="The title on an alert dialog indicating error.">
Error
@@ -638,6 +644,12 @@ limitations under the License.
translation_description="The text label for entering a name.">
Name
</string>
<string name="generic_name_line"
translation_description="A line containing a name.
%1$s name. E.g., 'Track 1'.">
Name: %1$s
</string>
<string name="generic_ok"
translation_description="The text on a button to say ok.">
OK
@@ -654,7 +666,7 @@ limitations under the License.
translation_description="The title on an alert dialog indicating success.">
Success
</string>
<!-- GPS -->
<string name="gps_need_to_enable"
translation_description="In the main view, the message on the top asking the user to enable
@@ -755,6 +767,14 @@ limitations under the License.
translation_description="In the 'Help' page, the question on location precision.">
How precise are the recorded tracks?
</string>
<string name="help_marker_answer"
translation_description="In the 'Help' page, the answer on markers.">
Markers are used to annotate a location.
</string>
<string name="help_marker_question"
translation_description="In the 'Help' page, the question on markers.">
What are markers?
</string>
<string name="help_my_tracks_answer"
translation_description="In the 'Help' page, the answer on what is My Tracks.">
My Tracks allows you to record GPS tracks and visualize your hiking, running, biking or any
@@ -793,6 +813,15 @@ limitations under the License.
translation_description="In the 'Help' page, the question on share visibility.">
Who can see the tracks I send to Google Maps and Google Fusion Tables?
</string>
<string name="help_split_marker_answer"
translation_description="In the 'Help' page, the answer on split markers.">
The split markers are used to segment a track to calculate statistics for each segment. Split
markers are inserted by setting the split frequency in the menu.
</string>
<string name="help_split_marker_question"
translation_description="In the 'Help' page, the question on split markers.">
What are split markers?
</string>
<string name="help_split_track_answer"
translation_description="In the 'Help' page, the answer on splitting long tracks.">
Tracks on Google Maps and Google Fusion Tables are limited to certain sizes.
@@ -802,26 +831,14 @@ limitations under the License.
Why do very long tracks split into multiple segments upon sending them to Google Maps and
Google Fusion Tables?
</string>
<string name="help_statistics_marker_answer"
translation_description="In the 'Help' page, the answer on statistics markers.">
Statistics markers are used to segment a track to calculate statistics for each segment. For
example, let\'s say you are recording a bike ride up a hill, you can insert a statistics marker
at the bottom of the hill and another at the top.
</string>
<string name="help_statistics_marker_question"
translation_description="In the 'Help' page, the question on statistics markers.">
What are statistics markers?
</string>
<string name="help_waypoint_marker_answer"
translation_description="In the 'Help' page, the answer on waypoint markers.">
Waypoint markers are used to annotate a location.
</string>
<string name="help_waypoint_marker_question"
translation_description="In the 'Help' page, the question on waypoint markers.">
What are waypoint markers?
</string>
<!-- Icon -->
<string name="icon_application"
translation_description="When sharing a track, we display a list of Android applications on the
phone that can be used. In the list, we display an application icon for each application. This
is the accessibility description for the icon.">
Application
</string>
<string name="icon_marker"
translation_description="The accessibility description for the 'Marker' icon.">
Marker
@@ -839,14 +856,7 @@ limitations under the License.
Track
</string>
<!-- Import -->
<string name="import_error"
translation_description="When importing all the tracks, a toast message indicating import error
for one of the tracks.
%1$s: the track's file path on the SD card. E.g., '/mnt/sdcard/MyTacks/gpx/1.gpx'.">
Import error for file %1$s.
</string>
<!-- Import GPX Files -->
<string name="import_gpx_files_few"
translation_description="When importing all the tracks, phrase for 'few' GPX files.
@@ -878,27 +888,6 @@ limitations under the License.
translation_description="When importing all the tracks, phrase for 0 GPX files.">
0 GPX files
</string>
<string name="import_no_file"
translation_description="After importing all the tracks from the SD card, the alert message
indicating that no track is imported.
%1$s: the SD card directory path. E.g., '/mnt/sdcard/MyTracks/gpx/'.">
No GPX file found in %1$s. The SD card may be unreadable or the directory may not contain any
GPX file.
</string>
<string name="import_progress_message"
translation_description="When importing all the tracks from the SD card, the progress message.">
Importing all tracks...
</string>
<string name="import_success"
translation_description="After importing all the tracks from the SD card, the alert message
indicating success.
%1$d the number of successfully imported tracks. E.g., '1'.
%2$s the number of GPX files in the SD card. E.g., '1 GPX file' or '2 GPX files'.
%3$s the SD card directory path. E.g., '/mnt/sdcard/MyTracks/gpx/'.">
My Tracks: Imported %1$d of %2$s from %3$s.
</string>
<!-- Maps List -->
<string name="maps_list_error"
@@ -947,39 +936,27 @@ limitations under the License.
user that the marker will be permanently deleted from the phone.">
The marker will be permanently deleted from the phone.
</string>
<string name="marker_detail_name"
translation_description="In the marker detail page, the label for the marker name.
%1$s marker name. E.g., 'Marker 1'.">
Name: %1$s
</string>
<string name="marker_detail_description"
translation_description="In the marker detail page, the label for the description.
%1$s marker description. E.g., 'At the top'.">
Description: %1$s
</string>
<string name="marker_detail_marker_type"
translation_description="In the marker detail page, the label for the marker type.
%1$s marker type. E.g., 'building'.">
Marker type: %1$s
</string>
</string>
<string name="marker_detail_statistics_title"
translation_description="In the marker detail page, the title for the statistics section
indicating that the data below are since the last Statistics marker.">
Since last Statistics marker:
</string>
indicating that the data below are since the last split marker.">
Since last split marker:
</string>
<string name="marker_edit_marker_type"
translation_description="In the marker edit page, the label for the marker type, including some
exmaples.">
examples.">
Marker type (e.g. building, pothole...)
</string>
<string name="marker_edit_marker_type_hint"
translation_description="In the marker edit page, the hint in the marker type text field when it
is empty.">
Marker type
</string>
</string>
<string name="marker_label_end"
translation_description="When inserting a marker to indicate the end of a track, the marker's
name. E.g., 'track_name (End)'.
@@ -998,20 +975,19 @@ limitations under the License.
translation_description="The message when the marker list is empty.">
You don\'t have any markers.
</string>
<string name="marker_statistics_name_format"
translation_description="When adding a statistics marker, the string format for the default
name.
%1$d: number. E.g., '1'.">
Statistics %1$d
</string>
<string name="marker_name_format"
translation_description="When adding a marker, the string format for the default name.
%1$d: number. E.g., '1'.">
Marker %1$d
</string>
<string name="marker_split_name_format"
translation_description="When adding a split marker, the string format for the default name.
%1$d: number. E.g., '1'.">
Split %1$d
</string>
<!-- Menu Items -->
<string name="menu_aggregated_statistics"
translation_description="In the menu, to go to the aggregated statistics page.">
@@ -1098,32 +1074,24 @@ limitations under the License.
translation_description="In the menu, to share a track.">
Share
</string>
<string name="menu_share_file"
translation_description="Under the 'Share' menu option, the option to share a track as a
certain file format.
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.">
%1$s file
</string>
<string name="menu_share_fusion_table_url"
translation_description="Under the 'Share' menu option, the option to save a track to Google
Fusion Tables and share the Fusion Table URL with friends. 'Fusion Table URL' in this context
means a Google Fusion Table URL.">
Fusion Table URL
</string>
<string name="menu_share_map_url"
translation_description="Under the 'Share' menu option, the option to save a track to Google
Maps and share the Map URL with friends. 'Map URL' in this context means a Google Map URL.">
Map URL
</string>
<string name="menu_show_on_map"
translation_description="In the menu, to show a marker on map.">
translation_description="In the menu, to show a track or a marker on the map.">
Show on map
</string>
<string name="menu_split_frequency"
translation_description="In the menu, to configure the split frequency, how frequent to insert
a split marker.">
Split frequency
</string>
<string name="menu_stop_recording"
translation_description="In the menu, to stop recording a track.">
Stop recording
</string>
<string name="menu_voice_frequency"
translation_description="In the menu, to configure the voice frequency, how frequent to announce
status.">
Voice frequency
</string>
<!-- My Location -->
<string name="my_location_approximate_location"
@@ -1183,63 +1151,69 @@ limitations under the License.
write data to My Tracks and start/stop My Tracks recording
</string>
<!-- Save All -->
<string name="save_all_error"
translation_description="When saving all the tracks to the SD card, a toast message indicating
error.">
Unable to save.
</string>
<string name="save_all_progress_message"
translation_description="When saving all the tracks to the SD card, the progress message.">
Saving all tracks...
</string>
<string name="save_all_success"
translation_description="When saving all the tracks to the SD card, a toast message indicating
success.">
Save finished.
</string>
<!-- SD Card -->
<string name="sd_card_canceled"
translation_description="When exporting a track to the SD card, a message indicating that the
export operation was canceled.">
translation_description="When importing/saving to the SD card, the message indicating that the
operation was canceled.">
The operation was canceled.
</string>
<string name="sd_card_error_create_dir"
translation_description="When writing to the SD card, the error message when not able to create
a directory on the SD card.">
Unable to create a directory on the SD card.
</string>
<string name="sd_card_error_no_storage"
translation_description="When writing to the SD card, the error message when the SD card is not
found.">
No external storage was found. Make sure that a SD card is inserted and that your phone is not
mounted to a computer.
translation_description="When importing/saving to the SD card, the error message indicating that
no SD card is found.">
No SD card is found.
</string>
<string name="sd_card_error_read_file"
translation_description="When reading from the SD card, the error message when not able to read
a file.">
Unable to read from a file.
<string name="sd_card_import_error"
translation_description="When importing from the SD card, the error message indicating not able
to import.">
Unable to import from SD card.
</string>
<string name="sd_card_error_write_file"
translation_description="When writing to the SD card, the error message when not able to write a
file.">
Unable to write to a file.
<string name="sd_card_import_error_no_file"
translation_description="When importing from the SD card, the error message indicating that no
file is found on a SD card directory.
%1$s: the SD card directory. E.g., '/mnt/sdcard/MyTracks/gpx/'.">
No file found in %1$s.
</string>
<string name="sd_card_import_progress_message"
translation_description="When importing from the SD card, the progress message.">
Importing from SD card...
</string>
<string name="sd_card_progress_message"
translation_description="When saving a track to the SD card, the progress message.">
Saving to the SD card...
<string name="sd_card_import_success"
translation_description="When importing from the SD card, the success message.">
Finished importing from SD card.
</string>
<string name="sd_card_success_read_file"
translation_description="When reading from the SD card, the success message when finish reading
from the SD card.">
Finished reading from the SD card.
<string name="sd_card_import_success_count"
translation_description="When importing from the SD card, the success message with a count of
the imported files.
%1$d the number of successfully imported tracks. E.g., '1'.
%2$s the number of files in the SD card. E.g., '1 GPX file' or '2 GPX files'.
%3$s the SD card directory. E.g., '/mnt/sdcard/MyTracks/gpx/'.">
Imported %1$d of %2$s from %3$s.
</string>
<string name="sd_card_success_write_file"
translation_description="When writing to the SD card, the success message when finish writing to
the SD card.">
Finished writing to the SD card.
<string name="sd_card_save_error"
translation_description="When saving to the SD card, the error message indicating not able to
save.">
Unable to save to SD card.
</string>
<string name="sd_card_save_error_create_dir"
translation_description="When saving to the SD card, the error message indicating not able to
create a directory on the SD card.">
Unable to create a directory on SD card.
</string>
<string name="sd_card_save_error_no_track"
translation_description="When saving to the SD card, the error message indicating that no track
is available.">
You have no track to save to SD card.
</string>
<string name="sd_card_save_progress_message"
translation_description="When saving to the SD card, the progress message.">
Saving to SD card...
</string>
<string name="sd_card_save_success"
translation_description="When saving to the SD card, the success message">
Finished saving to SD card.
</string>
<!-- Search -->
<string name="search_global_description"
@@ -1334,11 +1308,6 @@ limitations under the License.
%1$s: service name. 'Google Maps', 'Google Fusion Tables', or 'Google Docs'.">
Sending to %1$s...
</string>
<string name="send_google_result_share_url"
translation_description="When sending a track to Google, in the result dialog, the button on
the bottom to share with friends the URL of the uploaded track.">
Share track URL
</string>
<string name="send_google_send_now"
translation_description="When sending a track to Google, under the 'Send to...' dialog, the
button on the bottom to send the track to the selected Google services.">
@@ -1500,13 +1469,13 @@ limitations under the License.
translation_description="In the 'Chart' settings, the option to display the x axis by
distance.">
By distance
</string>
</string>
<string name="settings_chart_by_time"
translation_description="In the 'Chart' settings, the option to display the x axis by time.">
By time
</string>
<string name="settings_chart_x_axis"
translation_description="In the 'Chart' setttings, the option to change the x axis display,
translation_description="In the 'Chart' settings, the option to change the x axis display,
either by distance or by time.">
X axis
</string>
@@ -1573,7 +1542,7 @@ limitations under the License.
track recording.">
Not available while recording a track.
</string>
<!-- Settings Recording -->
<string name="settings_recording"
translation_description="In the 'Settings' page, the option to change the track recording
@@ -1647,19 +1616,6 @@ limitations under the License.
recordings of your position.">
Smallest time interval between two recordings of your position.
</string>
<string name="settings_recording_marker"
translation_description="In the 'Recording' settings, the dropdown option to configure the time
or distance a new marker will be inserted.
Character limit: ~23 (1 line)">
Marker
</string>
<string name="settings_recording_marker_summary"
translation_description="In the 'Recording' settings, the summary for the 'Marker'
dropdown option explaining that it configures the time or distance after which a new marker
will be inserted.">
Time/distance after which a new marker will be inserted.
</string>
<string name="settings_recording_track_distance"
translation_description="In the 'Recording' settings, the dropdown option to configure the
distance between two tracks.
@@ -1707,20 +1663,7 @@ limitations under the License.
list explaining that it chooses the default track name format.">
Default track name
</string>
<string name="settings_recording_voice"
translation_description="In the 'Recording' settings, the dropdown option to configure the voice
announcement frequency.
Character limit: ~23 (1 line)">
Voice
</string>
<string name="settings_recording_voice_summary"
translation_description="In the 'Recording' settings, the summary for the 'Voice'
dropdown option explaining that it configures the time or distance between two voice
announcements.">
Time/distance between two voice announcements.
</string>
<!-- Settings Reset -->
<string name="settings_reset"
translation_description="In the 'Settings' page, the option to reset everything to the defaults.
@@ -1745,7 +1688,7 @@ limitations under the License.
explaining reverting all the settings to the default values.">
Revert all your settings to the default values.
</string>
<!-- Settings Sensor -->
<string name="settings_sensor"
translation_description="In the 'Settings' page, the option to change the sensor related
@@ -1870,7 +1813,7 @@ limitations under the License.
Character limit: ~26 (1 line)">
Unpair SRM ANT+ bridge
</string>
<!-- Settings Sharing -->
<string name="settings_sharing"
translation_description="In the 'Settings' page, the option to change the track sharing related
@@ -1879,6 +1822,14 @@ limitations under the License.
Character limit: ~26 (1 line)">
Sharing
</string>
<string name="settings_sharing_account"
translation_description="In the 'Sharing' settings, the option to switch account.">
Switch account
</string>
<string name="settings_sharing_account_summary"
translation_description="In the 'Sharing' settings, the summary for 'Switch account'.">
Switch account used when sending a track to Google.
</string>
<string name="settings_sharing_allow_access"
translation_description="In the 'Sharing' settings, the checkbox option to allow third party
apps access to the My Tracks data.
@@ -1925,24 +1876,11 @@ limitations under the License.
be public, as opposed to unlisted.">
Make new maps created in Google Maps public.
</string>
<string name="settings_sharing_url_only"
translation_description="In the 'Sharing' settings, the checkbox option to share only the URL,
without any descriptive text, when sharing a URL with friends.
Character limit: ~23 (1 line)">
Share only URL
</string>
<string name="settings_sharing_url_only_summary_off"
translation_description="In the 'Sharing' settings, the summary for the 'Share only URL'
checkbox option when it is unchecked explaining that it will include descriptive text when
sharing a URL with friends.">
Include descriptive text when sharing a URL with friends.
</string>
<string name="settings_sharing_url_only_summary_on"
translation_description="In the 'Sharing' settings, the summary for the 'Share only URL'
checkbox option when it is checked explaining that it will remove any descriptive text when
sharing a URL with friends.">
Remove any descriptive text when sharing a URL with friends.
<!-- Settings Split -->
<string name="settings_split_frequency_title"
translation_description="In title of the 'Split frequency' dialog.">
Time/distance between two split markers
</string>
<!-- Settings Stats -->
@@ -1986,7 +1924,7 @@ limitations under the License.
Time measurement
</string>
<string name="settings_stats_units_imperial"
translation_description="In the 'Stats' setttings, the option to use imperial units, with
translation_description="In the 'Stats' settings, the option to use imperial units, with
examples.">
Imperial (mi, ft)
</string>
@@ -1994,34 +1932,53 @@ limitations under the License.
translation_description="In the 'Stats' settings, the option to use metric units, with
examples.">
Metric (km, m)
</string>
</string>
<string name="settings_stats_units_title"
translation_description="In the 'Stats' settings page, the option to change the preferred units,
either metric (km) or imperial (mi).">
Preferred units
</string>
<!-- Share Track -->
<string name="share_track_file_body_format"
translation_description="When sharing a track file with friends, the body of the message.">
I think you might be interested in this track.\n\nTo view this track use Google Earth or other
mapping software.
<!-- Settings Voice -->
<string name="settings_voice_frequency_title"
translation_description="The title of the 'Voice frequency' dialog.">
Time/distance between two voice announcements
</string>
<!-- Share Track -->
<string name="share_track_picker_title"
translation_description="When sharing a track URL with friends, the title on the picker to ask
the user which application he wants to use.">
Share track using:
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_share_file"
translation_description="After saving a track to the SD card, the button on the result dialog to
share the saved track file with friends.">
Share track file
</string>
<string name="share_track_share_file_body"
translation_description="When sharing a track file with friends, the body of the message.
%1$s: track description.">
I think you might be interested in this track.\n\nTo view this track, use Google Earth or other
mapping software.\n\n%1$s
</string>
<string name="share_track_share_url"
translation_description="After sending a track to Google, the button on the result dialog to
share the uploaded track URL with friends.">
Share track URL
</string>
<string name="share_track_share_url_body"
translation_description="When sharing a track URL with friends, the body of the message.
%1$s: url. E.g, 'https://maps.google.com/maps'.
%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_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_url_body_format"
translation_description="When sharing a track URL with friends, the body of the message.
%1$s: url. E.g, 'https://maps.google.com/maps'.">
I think you might be interested in this track:\n\n%1$s
</string>
<!-- Stats Page -->
<string name="stats_average_moving_pace"
@@ -2124,11 +2081,11 @@ limitations under the License.
<string name="track_detail_stats_tab"
translation_description="In the track detail page, the title of the tab showing the stats.">
Stats
</string>
</string>
<string name="track_detail_title_recording"
translation_description="In the track detail page, the title when recording.">
Recording...
</string>
</string>
<string name="track_edit_activity_type"
translation_description="In the page to edit a track, the label for the text field to edit the
activity type, including some examples of activity types.">
@@ -2361,10 +2318,10 @@ limitations under the License.
</string>
<string name="value_integer_percent"
translation_description="To display a value in percent like 2 %.
%1$d: an integer value. E.g., '2'">
%1$d %%
</string>
%1$d %%
</string>
<string name="value_integer_second"
translation_description="In a setting picker, the string format to display an integer value in
seconds (s).
@@ -2388,11 +2345,11 @@ limitations under the License.
<string name="value_coordinate_degree"
translation_description="To display a latitude or longitude coordinate in degree. E.g.,
2.2 \u00B0. \u00B0 is the unicode value for the degree symbol.
%1$s: a string value of the coordinate. E.g., '2.2'">
%1$s \u00B0
</string>
<!-- Voice -->
<string name="voice_hours_few"
translation_description="For voice announcement, to say 'few' hours.
@@ -2902,10 +2859,10 @@ limitations under the License.
<string name="welcome_message"
translation_description="The message of the welcome dialog.">
Use My Tracks while you run, bike, hike, or do anything outdoor to record your path. While
recording, you can visualize your track and watch live statistics. You can also add
markers, have markers inserted periodically, or hear automatic voice announcements of
your progress. For recorded tracks, you can play them on Google Earth, share with friends, or
upload to Google Maps, Google Fusion Tables, or Google Docs.
recording, you can visualize your track and watch live statistics. You can also add markers,
have split markers inserted periodically, or hear periodic announcements of your progress.
For recorded tracks, you can play them on Google Earth, share with friends, or upload to Google
Maps, Google Fusion Tables, or Google Docs.
</string>
<string name="welcome_title"
translation_description="The title of the welcome dialog.">
+11 -11
View File
@@ -31,6 +31,17 @@ limitations under the License.
<item name="android:layout_width">fill_parent</item>
<item name="android:orientation">horizontal</item>
</style>
<!-- The style for choose upload service check box -->
<style name="ChooseUploadServiceCheckBox" parent="@style/TextMedium">
<item name="android:layout_gravity">center_vertical</item>
<item name="android:layout_marginLeft">8dp</item>
<item name="android:layout_width">0dp</item>
</style>
<!-- The style for choose upload service image view -->
<style name="ChooseUploadServiceImageView">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
</style>
<!-- The style for the edit category -->
<style name="EditCategory" parent="@style/TextMedium">
<item name="android:layout_width">fill_parent</item>
@@ -150,15 +161,4 @@ limitations under the License.
<style name="TrackWidgetValue" parent="@style/TextSmall">
<item name="android:width">100dp</item>
</style>
<!-- The style for upload service chooser check box -->
<style name="UploadServiceChooserCheckBox" parent="@style/TextMedium">
<item name="android:layout_gravity">center_vertical</item>
<item name="android:layout_marginLeft">8dp</item>
<item name="android:layout_width">0dp</item>
</style>
<!-- The style for upload service chooser image view -->
<style name="UploadServiceChooserImageView">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
</style>
</resources>
-12
View File
@@ -16,18 +16,6 @@ limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/settings_recording" >
<com.google.android.apps.mytracks.IntegerListPreference
android:defaultValue="0"
android:entryValues="@array/periodic_task_values"
android:key="@string/announcement_frequency_key"
android:summary="@string/settings_recording_voice_summary"
android:title="@string/settings_recording_voice" />
<com.google.android.apps.mytracks.IntegerListPreference
android:defaultValue="0"
android:entryValues="@array/periodic_task_values"
android:key="@string/split_frequency_key"
android:summary="@string/settings_recording_marker_summary"
android:title="@string/settings_recording_marker" />
<ListPreference
android:defaultValue="@string/settings_recording_track_name_date_local_value"
android:entries="@array/track_name_options"
+5 -6
View File
@@ -16,18 +16,17 @@ limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/settings_sharing" >
<ListPreference
android:defaultValue=""
android:key="@string/sharing_account_key"
android:summary="@string/settings_sharing_account_summary"
android:title="@string/settings_sharing_account" />
<CheckBoxPreference
android:defaultValue="true"
android:key="@string/default_map_public_key"
android:summaryOff="@string/settings_sharing_map_public_summary_off"
android:summaryOn="@string/settings_sharing_map_public_summary_on"
android:title="@string/settings_sharing_map_public" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/share_url_only_key"
android:summaryOff="@string/settings_sharing_url_only_summary_off"
android:summaryOn="@string/settings_sharing_url_only_summary_on"
android:title="@string/settings_sharing_url_only" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/allow_access_key"
@@ -47,8 +47,7 @@ public class AntPreference extends Preference {
if (sensorId == 0) {
setSummary(R.string.settings_sensor_ant_not_paired);
} else {
setSummary(
String.format(getContext().getString(R.string.settings_sensor_ant_paired), sensorId));
setSummary(getContext().getString(R.string.settings_sensor_ant_paired, sensorId));
}
// Add actions to allow repairing.
@@ -111,7 +111,7 @@ public class ImportActivity extends Activity {
switch (id) {
case DIALOG_PROGRESS_ID:
progressDialog = DialogUtils.createHorizontalProgressDialog(
this, R.string.import_progress_message, new DialogInterface.OnCancelListener() {
this, R.string.sd_card_import_progress_message, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
importAsyncTask.cancel(true);
@@ -122,11 +122,12 @@ public class ImportActivity extends Activity {
case DIALOG_RESULT_ID:
String message;
if (successCount == 0) {
message = getString(R.string.import_no_file, path);
message = getString(R.string.sd_card_import_error_no_file, path);
} else {
String totalFiles = getResources()
.getQuantityString(R.plurals.importGpxFiles, totalCount, totalCount);
message = getString(R.string.import_success, successCount, totalFiles, path);
message = getString(
R.string.sd_card_import_success_count, successCount, totalFiles, path);
}
return new AlertDialog.Builder(this)
.setCancelable(true)
@@ -171,7 +172,8 @@ public class ImportActivity extends Activity {
if (success) {
showDialog(DIALOG_RESULT_ID);
} else {
Toast.makeText(this, getString(R.string.import_error, path), Toast.LENGTH_LONG).show();
Toast.makeText(this, getString(R.string.sd_card_import_error), Toast.LENGTH_LONG)
.show();
finish();
}
}
@@ -73,7 +73,7 @@ public class MarkerDetailActivity extends AbstractMyTracksActivity {
finish();
return;
}
name.setText(getString(R.string.marker_detail_name, waypoint.getName()));
name.setText(getString(R.string.generic_name_line, waypoint.getName()));
if (waypoint.getType() == Waypoint.TYPE_WAYPOINT) {
waypointSection.setVisibility(View.VISIBLE);
statisticsSection.setVisibility(View.GONE);
@@ -81,7 +81,7 @@ public class MarkerDetailActivity extends AbstractMyTracksActivity {
TextView markerType = (TextView) findViewById(R.id.marker_detail_waypoint_marker_type);
markerType.setText(getString(R.string.marker_detail_marker_type, waypoint.getCategory()));
TextView description = (TextView) findViewById(R.id.marker_detail_waypoint_description);
description.setText(getString(R.string.marker_detail_description, waypoint.getDescription()));
description.setText(getString(R.string.generic_description_line, waypoint.getDescription()));
} else {
waypointSection.setVisibility(View.GONE);
statisticsSection.setVisibility(View.VISIBLE);
@@ -146,8 +146,8 @@ public class MarkerListActivity extends AbstractMyTracksActivity {
}
};
listView.setAdapter(resourceCursorAdapter);
ApiAdapterFactory.getApiAdapter().configureListViewContextualMenu(this, listView,
R.menu.list_context_menu, R.id.list_item_name, contextualActionModeCallback);
ApiAdapterFactory.getApiAdapter()
.configureListViewContextualMenu(this, listView, contextualActionModeCallback);
final long firstWaypointId = MyTracksProviderUtils.Factory.get(this)
.getFirstWaypointId(trackId);
@@ -1,115 +0,0 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.DialogUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
/**
* An activity to save all the tracks to the SD card.
*
* @author Sandor Dornbush
*/
public class SaveAllActivity extends Activity {
public static final String EXTRA_TRACK_FILE_FORMAT = "track_file_format";
private static final int DIALOG_PROGRESS_ID = 0;
private SaveAllAsyncTask saveAllAsyncTask;
private ProgressDialog progressDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Object retained = getLastNonConfigurationInstance();
if (retained instanceof SaveAllAsyncTask) {
saveAllAsyncTask = (SaveAllAsyncTask) retained;
saveAllAsyncTask.setActivity(this);
} else {
Intent intent = getIntent();
TrackFileFormat trackFileFormat = intent.getParcelableExtra(EXTRA_TRACK_FILE_FORMAT);
saveAllAsyncTask = new SaveAllAsyncTask(this, trackFileFormat);
saveAllAsyncTask.execute();
}
}
@Override
public Object onRetainNonConfigurationInstance() {
saveAllAsyncTask.setActivity(null);
return saveAllAsyncTask;
}
@Override
protected Dialog onCreateDialog(int id) {
if (id != DIALOG_PROGRESS_ID) {
return null;
}
progressDialog = DialogUtils.createHorizontalProgressDialog(
this, R.string.save_all_progress_message, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
saveAllAsyncTask.cancel(true);
finish();
}
});
return progressDialog;
}
/**
* Invokes when the associated AsyncTask completes.
*
* @param success true if the AsyncTask is successful
* @param messageId message id to display to user
*/
public void onAsyncTaskCompleted(boolean success, int messageId) {
removeDialog(DIALOG_PROGRESS_ID);
Toast.makeText(this, messageId, success ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show();
finish();
}
/**
* Shows the progress dialog.
*/
public void showProgressDialog() {
showDialog(DIALOG_PROGRESS_ID);
}
/**
* Sets the progress dialog value.
*
* @param number the number of tracks saved
* @param max the maximum number of tracks
*/
public void setProgressDialogValue(int number, int max) {
if (progressDialog != null) {
progressDialog.setIndeterminate(false);
progressDialog.setMax(max);
progressDialog.setProgress(Math.min(number, max));
}
}
}
@@ -1,162 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.TracksColumns;
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.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.PowerManager.WakeLock;
/**
* AsyncTask to save all the tracks to the SD card.
*
* @author Jimmy Shih
*/
public class SaveAllAsyncTask extends AsyncTask<Void, Integer, Boolean> {
private SaveAllActivity saveAllActivity;
private final TrackFileFormat trackFileFormat;
private final Context context;
private final MyTracksProviderUtils myTracksProviderUtils;
private WakeLock wakeLock;
private TrackWriter trackWriter;
// true if the AsyncTask result is success
private boolean success;
// true if the AsyncTask has completed
private boolean completed;
// message id to return to the activity
private int messageId;
/**
* Creates an AsyncTask.
*
* @param saveAllActivity the activity currently associated with this AsyncTask
* @param trackFileFormat the track file format
*/
public SaveAllAsyncTask(SaveAllActivity saveAllActivity, TrackFileFormat trackFileFormat) {
this.saveAllActivity = saveAllActivity;
this.trackFileFormat = trackFileFormat;
context = saveAllActivity.getApplicationContext();
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(saveAllActivity);
// Get the wake lock if not recording
if (PreferencesUtils.getLong(saveAllActivity, R.string.recording_track_id_key)
== PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
wakeLock = SystemUtils.acquireWakeLock(saveAllActivity, wakeLock);
}
success = false;
completed = false;
messageId = R.string.save_all_error;
}
/**
* Sets the current {@link SaveAllActivity} associated with this AyncTask.
*
* @param saveAllActivity the current {@link SaveAllActivity}, can be null
*/
public void setActivity(SaveAllActivity saveAllActivity) {
this.saveAllActivity = saveAllActivity;
if (completed && saveAllActivity != null) {
saveAllActivity.onAsyncTaskCompleted(success, messageId);
}
}
@Override
protected void onPreExecute() {
if (saveAllActivity != null) {
saveAllActivity.showProgressDialog();
}
}
@Override
protected Boolean doInBackground(Void... params) {
Cursor cursor = null;
try {
cursor = myTracksProviderUtils.getTracksCursor(null, null, TracksColumns._ID);
if (cursor == null) {
messageId = R.string.save_all_success;
return true;
}
int count = cursor.getCount();
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
for (int i = 0; i < count; i++) {
if (isCancelled()) {
return false;
}
cursor.moveToPosition(i);
long id = cursor.getLong(idIndex);
trackWriter = TrackWriterFactory.newWriter(
context, myTracksProviderUtils, id, trackFileFormat);
if (trackWriter == null) {
return false;
}
trackWriter.writeTrack();
if (!trackWriter.wasSuccess()) {
messageId = trackWriter.getErrorMessage();
return false;
}
publishProgress(i + 1, count);
}
messageId = R.string.save_all_success;
return true;
} finally {
if (cursor != null) {
cursor.close();
}
// Release the wake lock if obtained
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
}
}
}
@Override
protected void onProgressUpdate(Integer... values) {
if (saveAllActivity != null) {
saveAllActivity.setProgressDialogValue(values[0], values[1]);
}
}
@Override
protected void onPostExecute(Boolean result) {
success = result;
completed = true;
if (saveAllActivity != null) {
saveAllActivity.onAsyncTaskCompleted(success, messageId);
}
}
@Override
protected void onCancelled() {
if (trackWriter != null) {
trackWriter.stopWriteTrack();
}
}
}
@@ -187,8 +187,8 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
}
};
listView.setAdapter(arrayAdapter);
ApiAdapterFactory.getApiAdapter().configureListViewContextualMenu(this, listView,
R.menu.list_context_menu, R.id.list_item_name, contextualActionModeCallback);
ApiAdapterFactory.getApiAdapter()
.configureListViewContextualMenu(this, listView, contextualActionModeCallback);
handleIntent(getIntent());
}
@@ -233,8 +233,7 @@ public class SensorStateActivity extends AbstractMyTracksActivity {
String value;
if (sensorDataSet.hasPower() && sensorDataSet.getPower().hasValue()
&& sensorDataSet.getPower().getState() == Sensor.SensorState.SENDING) {
String format = getString(R.string.sensor_state_power_value);
value = String.format(format, sensorDataSet.getPower().getValue());
value = getString(R.string.sensor_state_power_value, sensorDataSet.getPower().getValue());
} else {
value = SensorUtils.getStateAsString(
sensorDataSet.hasPower() ? sensorDataSet.getPower().getState() : Sensor.SensorState.NONE,
@@ -252,8 +251,7 @@ public class SensorStateActivity extends AbstractMyTracksActivity {
String value;
if (sensorDataSet.hasCadence() && sensorDataSet.getCadence().hasValue()
&& sensorDataSet.getCadence().getState() == Sensor.SensorState.SENDING) {
String format = getString(R.string.sensor_state_cadence_value);
value = String.format(format, sensorDataSet.getCadence().getValue());
value = getString(R.string.sensor_state_cadence_value, sensorDataSet.getCadence().getValue());
} else {
value = SensorUtils.getStateAsString(
sensorDataSet.hasCadence() ? sensorDataSet.getCadence().getState()
@@ -271,8 +269,8 @@ public class SensorStateActivity extends AbstractMyTracksActivity {
String value;
if (sensorDataSet.hasHeartRate() && sensorDataSet.getHeartRate().hasValue()
&& sensorDataSet.getHeartRate().getState() == Sensor.SensorState.SENDING) {
String format = getString(R.string.sensor_state_heart_rate_value);
value = String.format(format, sensorDataSet.getHeartRate().getValue());
value = getString(
R.string.sensor_state_heart_rate_value, sensorDataSet.getHeartRate().getValue());
} else {
value = SensorUtils.getStateAsString(
sensorDataSet.hasHeartRate() ? sensorDataSet.getHeartRate().getState()
@@ -22,15 +22,17 @@ import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.fragments.ChartFragment;
import com.google.android.apps.mytracks.fragments.ChooseActivityDialogFragment;
import com.google.android.apps.mytracks.fragments.ChooseUploadServiceDialogFragment;
import com.google.android.apps.mytracks.fragments.DeleteOneTrackDialogFragment;
import com.google.android.apps.mytracks.fragments.DeleteOneTrackDialogFragment.DeleteOneTrackCaller;
import com.google.android.apps.mytracks.fragments.FrequencyDialogFragment;
import com.google.android.apps.mytracks.fragments.InstallEarthDialogFragment;
import com.google.android.apps.mytracks.fragments.MapFragment;
import com.google.android.apps.mytracks.fragments.StatsFragment;
import com.google.android.apps.mytracks.io.file.SaveActivity;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
import com.google.android.apps.mytracks.io.sendtogoogle.UploadServiceChooserActivity;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
import com.google.android.apps.mytracks.settings.SettingsActivity;
import com.google.android.apps.mytracks.util.AnalyticsUtils;
@@ -83,6 +85,8 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
private MenuItem insertMarkerMenuItem;
private MenuItem playMenuItem;
private MenuItem shareMenuItem;
private MenuItem voiceFrequencyMenuItem;
private MenuItem splitFrequencyMenuItem;
private MenuItem sendGoogleMenuItem;
private MenuItem saveMenuItem;
@@ -209,19 +213,12 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
menu.findItem(R.id.track_detail_save_tcx)
.setTitle(getString(R.string.menu_save_format, fileTypes[3]));
menu.findItem(R.id.track_detail_share_gpx)
.setTitle(getString(R.string.menu_share_file, fileTypes[0]));
menu.findItem(R.id.track_detail_share_kml)
.setTitle(getString(R.string.menu_share_file, fileTypes[1]));
menu.findItem(R.id.track_detail_share_csv)
.setTitle(getString(R.string.menu_share_file, fileTypes[2]));
menu.findItem(R.id.track_detail_share_tcx)
.setTitle(getString(R.string.menu_share_file, fileTypes[3]));
stopRecordingMenuItem = menu.findItem(R.id.track_detail_stop_recording);
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
playMenuItem = menu.findItem(R.id.track_detail_play);
shareMenuItem = menu.findItem(R.id.track_detail_share);
voiceFrequencyMenuItem = menu.findItem(R.id.track_detail_voice_frequency);
splitFrequencyMenuItem = menu.findItem(R.id.track_detail_split_frequency);
sendGoogleMenuItem = menu.findItem(R.id.track_detail_send_google);
saveMenuItem = menu.findItem(R.id.track_detail_save);
@@ -271,49 +268,42 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
getSupportFragmentManager(), InstallEarthDialogFragment.INSTALL_EARTH_DIALOG_TAG);
}
return true;
case R.id.track_detail_share_map_url:
intent = IntentUtils.newIntent(this, UploadServiceChooserActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, true, false, false));
startActivity(intent);
return true;
case R.id.track_detail_share_fusion_table_url:
intent = IntentUtils.newIntent(this, UploadServiceChooserActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, false, true, false));
startActivity(intent);
return true;
case R.id.track_detail_share_gpx:
startSaveActivity(TrackFileFormat.GPX, true);
return true;
case R.id.track_detail_share_kml:
startSaveActivity(TrackFileFormat.KML, true);
return true;
case R.id.track_detail_share_csv:
startSaveActivity(TrackFileFormat.CSV, true);
return true;
case R.id.track_detail_share_tcx:
startSaveActivity(TrackFileFormat.TCX, true);
case R.id.track_detail_share:
ChooseActivityDialogFragment.newInstance(trackId, null).show(
getSupportFragmentManager(), ChooseActivityDialogFragment.CHOOSE_ACTIVITY_DIALOG_TAG);
return true;
case R.id.track_detail_markers:
intent = IntentUtils.newIntent(this, MarkerListActivity.class)
.putExtra(MarkerListActivity.EXTRA_TRACK_ID, trackId);
startActivity(intent);
return true;
case R.id.track_detail_voice_frequency:
FrequencyDialogFragment.newInstance(R.string.announcement_frequency_key,
PreferencesUtils.ANNOUNCEMENT_FREQUENCY_DEFAULT,
R.string.settings_voice_frequency_title)
.show(getSupportFragmentManager(), FrequencyDialogFragment.FREQUENCY_DIALOG_TAG);
return true;
case R.id.track_detail_split_frequency:
FrequencyDialogFragment.newInstance(R.string.split_frequency_key,
PreferencesUtils.SPLIT_FREQUENCY_DEFAULT, R.string.settings_split_frequency_title)
.show(getSupportFragmentManager(), FrequencyDialogFragment.FREQUENCY_DIALOG_TAG);
return true;
case R.id.track_detail_send_google:
intent = IntentUtils.newIntent(this, UploadServiceChooserActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, true, true, true));
startActivity(intent);
ChooseUploadServiceDialogFragment.newInstance(new SendRequest(trackId)).show(
getSupportFragmentManager(),
ChooseUploadServiceDialogFragment.CHOOSE_UPLOAD_SERVICE_DIALOG_TAG);
return true;
case R.id.track_detail_save_gpx:
startSaveActivity(TrackFileFormat.GPX, false);
startSaveActivity(TrackFileFormat.GPX);
return true;
case R.id.track_detail_save_kml:
startSaveActivity(TrackFileFormat.KML, false);
startSaveActivity(TrackFileFormat.KML);
return true;
case R.id.track_detail_save_csv:
startSaveActivity(TrackFileFormat.CSV, false);
startSaveActivity(TrackFileFormat.CSV);
return true;
case R.id.track_detail_save_tcx:
startSaveActivity(TrackFileFormat.TCX, false);
startSaveActivity(TrackFileFormat.TCX);
return true;
case R.id.track_detail_edit:
intent = IntentUtils.newIntent(this, TrackEditActivity.class)
@@ -446,6 +436,12 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
if (shareMenuItem != null) {
shareMenuItem.setVisible(!isRecording);
}
if (voiceFrequencyMenuItem != null) {
voiceFrequencyMenuItem.setVisible(isRecording);
}
if (splitFrequencyMenuItem != null) {
splitFrequencyMenuItem.setVisible(isRecording);
}
if (sendGoogleMenuItem != null) {
sendGoogleMenuItem.setVisible(!isRecording);
}
@@ -458,13 +454,11 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
* Starts the {@link SaveActivity} to save a track.
*
* @param trackFileFormat the track file format
* @param shareTrack true to share the track after saving
*/
private void startSaveActivity(TrackFileFormat trackFileFormat, boolean shareTrack) {
private void startSaveActivity(TrackFileFormat trackFileFormat) {
Intent intent = IntentUtils.newIntent(this, SaveActivity.class)
.putExtra(SaveActivity.EXTRA_TRACK_ID, trackId)
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat)
.putExtra(SaveActivity.EXTRA_SHARE_TRACK, shareTrack);
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat);
startActivity(intent);
}
@@ -64,7 +64,7 @@ public class TrackEditActivity extends AbstractMyTracksActivity {
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(this);
track = myTracksProviderUtils.getTrack(trackId);
if (track == null) {
Log.e(TAG, "no track");
Log.e(TAG, "No track for " + trackId);
finish();
return;
}
@@ -23,6 +23,7 @@ import com.google.android.apps.mytracks.fragments.DeleteOneTrackDialogFragment;
import com.google.android.apps.mytracks.fragments.DeleteOneTrackDialogFragment.DeleteOneTrackCaller;
import com.google.android.apps.mytracks.fragments.EulaDialogFragment;
import com.google.android.apps.mytracks.fragments.WelcomeDialogFragment;
import com.google.android.apps.mytracks.io.file.SaveActivity;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
@@ -240,9 +241,8 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
}
};
listView.setAdapter(resourceCursorAdapter);
ApiAdapterFactory.getApiAdapter().configureListViewContextualMenu(
this, listView, R.menu.list_context_menu, R.id.list_item_name,
contextualActionModeCallback);
ApiAdapterFactory.getApiAdapter()
.configureListViewContextualMenu(this, listView, contextualActionModeCallback);
getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<Cursor>() {
@Override
@@ -399,24 +399,16 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
startActivity(intent);
return true;
case R.id.track_list_save_all_gpx:
intent = IntentUtils.newIntent(this, SaveAllActivity.class)
.putExtra(SaveAllActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) TrackFileFormat.GPX);
startActivity(intent);
startSaveActivity(TrackFileFormat.GPX);
return true;
case R.id.track_list_save_all_kml:
intent = IntentUtils.newIntent(this, SaveAllActivity.class)
.putExtra(SaveAllActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) TrackFileFormat.KML);
startActivity(intent);
startSaveActivity(TrackFileFormat.KML);
return true;
case R.id.track_list_save_all_csv:
intent = IntentUtils.newIntent(this, SaveAllActivity.class)
.putExtra(SaveAllActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) TrackFileFormat.CSV);
startActivity(intent);
startSaveActivity(TrackFileFormat.CSV);
return true;
case R.id.track_list_save_all_tcx:
intent = IntentUtils.newIntent(this, SaveAllActivity.class)
.putExtra(SaveAllActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) TrackFileFormat.TCX);
startActivity(intent);
startSaveActivity(TrackFileFormat.TCX);
return true;
case R.id.track_list_delete_all:
new DeleteAllTrackDialogFragment().show(
@@ -439,6 +431,17 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
}
}
/**
* Starts the {@link SaveActivity} to save all tracks.
*
* @param trackFileFormat the track file format
*/
private void startSaveActivity(TrackFileFormat trackFileFormat) {
Intent intent = IntentUtils.newIntent(this, SaveActivity.class)
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat);
startActivity(intent);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
@@ -36,7 +36,9 @@ import java.util.Vector;
public class DescriptionGeneratorImpl implements DescriptionGenerator {
private static final String HTML_LINE_BREAK = "<br>";
private static final String HTML_PARAGRAPH_SEPARATOR = "<p>";
private static final String TEXT_LINE_BREAK = "\n";
private static final String TEXT_PARAGRAPH_SEPARATOR = "\n\n";
private Context context;
@@ -46,26 +48,26 @@ public class DescriptionGeneratorImpl implements DescriptionGenerator {
@Override
public String generateTrackDescription(
Track track, Vector<Double> distances, Vector<Double> elevations) {
Track track, Vector<Double> distances, Vector<Double> elevations, boolean html) {
String paragraphSeparator = html ? HTML_PARAGRAPH_SEPARATOR : TEXT_PARAGRAPH_SEPARATOR;
String lineBreak = html ? HTML_LINE_BREAK : TEXT_LINE_BREAK;
StringBuilder builder = new StringBuilder();
// Created by
String url = context.getString(R.string.my_tracks_web_url);
builder.append(context.getString(
R.string.send_google_by_my_tracks, "<a href='http://" + url + "'>", "</a>"));
builder.append("<p>");
String beginAnchor = html
? "<a href='http://" + context.getString(R.string.my_tracks_web_url) + "'>"
: "";
String endAnchor = html ? "</a>" : "";
builder.append(context.getString(R.string.send_google_by_my_tracks, beginAnchor, endAnchor));
builder.append(paragraphSeparator);
builder.append(generateTripStatisticsDescription(track.getStatistics(), true));
// Activity type
String trackCategory = track.getCategory();
String category = trackCategory != null && trackCategory.length() > 0 ? trackCategory
: context.getString(R.string.value_unknown);
builder.append(context.getString(R.string.description_activity_type, category));
builder.append(HTML_LINE_BREAK);
writeString(track.getName(), builder, R.string.generic_name_line, lineBreak);
writeString(track.getCategory(), builder, R.string.description_activity_type, lineBreak);
writeString(track.getDescription(), builder, R.string.generic_description_line, lineBreak);
builder.append(generateTripStatisticsDescription(track.getStatistics(), html));
// Elevation chart
if (distances != null && elevations != null) {
if (html && distances != null && elevations != null) {
builder.append("<img border=\"0\" src=\""
+ ChartURLGenerator.getChartUrl(distances, elevations, track, context) + "\"/>");
builder.append(HTML_LINE_BREAK);
@@ -78,6 +80,22 @@ public class DescriptionGeneratorImpl implements DescriptionGenerator {
return generateTripStatisticsDescription(waypoint.getStatistics(), false);
}
/**
* Writes a string to a string builder.
*
* @param text the string
* @param builder the string builder
* @param resId the resource id containing one string placeholder
* @param lineBreak the line break
*/
private void writeString(String text, StringBuilder builder, int resId, String lineBreak) {
if (text == null || text.length() == 0) {
text = context.getString(R.string.value_unknown);
}
builder.append(context.getString(resId, text));
builder.append(lineBreak);
}
/**
* Generates a description for a {@link TripStatistics}.
*
@@ -132,11 +132,11 @@ public class ChartFragment extends Fragment implements TrackDataListener {
return view;
}
@SuppressWarnings("deprecation")
@Override
public void onStart() {
super.onStart();
ViewGroup layout = (ViewGroup) getActivity().findViewById(R.id.chart_view_layout);
@SuppressWarnings("deprecation")
LayoutParams layoutParams = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
layout.addView(chartView, layoutParams);
@@ -0,0 +1,260 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.fragments;
import com.google.android.apps.mytracks.io.sendtogoogle.AccountChooserActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
import com.google.android.apps.mytracks.util.IntentUtils;
import com.google.android.maps.mytracks.R;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.ShareCompat;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
/**
* A DialogFragment to choose an activity.
*
* @author Jimmy Shih
*/
public class ChooseActivityDialogFragment extends DialogFragment {
public static final String CHOOSE_ACTIVITY_DIALOG_TAG = "chooseActivityDialog";
private static final String KEY_TRACK_ID = "trackId";
private static final String KEY_TRACK_URL = "trackUrl";
private PackageManager packageManager;
public static ChooseActivityDialogFragment newInstance(long trackId, String trackUrl) {
Bundle bundle = new Bundle();
bundle.putLong(KEY_TRACK_ID, trackId);
bundle.putString(KEY_TRACK_URL, trackUrl);
ChooseActivityDialogFragment chooseActivityDialogFragment = new ChooseActivityDialogFragment();
chooseActivityDialogFragment.setArguments(bundle);
return chooseActivityDialogFragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
packageManager = getActivity().getPackageManager();
List<DisplayInfo> displayInfos = getDisplayInfos();
ArrayAdapter<DisplayInfo> arrayAdapter = new ArrayAdapter<DisplayInfo>(getActivity(),
R.layout.choose_activity_list_item, R.id.choose_activity_list_item_text1, displayInfos) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = getActivity()
.getLayoutInflater().inflate(R.layout.choose_activity_list_item, parent, false);
} else {
view = convertView;
}
DisplayInfo displayInfo = getItem(position);
TextView text1 = (TextView) view.findViewById(R.id.choose_activity_list_item_text1);
TextView text2 = (TextView) view.findViewById(R.id.choose_activity_list_item_text2);
ImageView icon = (ImageView) view.findViewById(R.id.choose_activity_list_item_icon);
text1.setText(displayInfo.primaryLabel);
if (displayInfo.secondaryLabel != null) {
text2.setVisibility(View.VISIBLE);
text2.setText(displayInfo.secondaryLabel);
} else {
text2.setVisibility(View.GONE);
}
icon.setImageDrawable(displayInfo.icon);
return view;
}
};
return new AlertDialog.Builder(getActivity())
.setSingleChoiceItems(arrayAdapter, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
AlertDialog alertDialog = (AlertDialog) dialog;
DisplayInfo displayInfo = (DisplayInfo) alertDialog.getListView()
.getItemAtPosition(which);
ActivityInfo activityInfo = displayInfo.resolveInfo.activityInfo;
String packageName = activityInfo.applicationInfo.packageName;
String className = activityInfo.name;
long trackId = getArguments().getLong(KEY_TRACK_ID);
String trackUrl = getArguments().getString(KEY_TRACK_URL);
if (trackUrl == null) {
SendRequest sendRequest = new SendRequest(trackId);
sendRequest.setSendMaps(true);
sendRequest.setNewMap(true);
sendRequest.setSharingAppPackageName(packageName);
sendRequest.setSharingAppClassName(className);
Intent intent = IntentUtils.newIntent(getActivity(), AccountChooserActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
startActivity(intent);
dismiss();
} else {
Intent intent = IntentUtils.newShareUrlIntent(
getActivity(), trackId, trackUrl, packageName, className);
startActivity(intent);
getActivity().finish();
}
}
})
.setTitle(R.string.share_track_picker_title)
.create();
}
/**
* Gets the display info.
*/
private List<DisplayInfo> getDisplayInfos() {
List<DisplayInfo> displayInfos = new ArrayList<DisplayInfo>();
Intent intent = ShareCompat.IntentBuilder.from(getActivity())
.setType(IntentUtils.TEXT_PLAIN_TYPE).getIntent();
List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(
intent, PackageManager.MATCH_DEFAULT_ONLY);
if (resolveInfos != null && resolveInfos.size() > 0) {
int size = resolveInfos.size();
ResolveInfo firstResolveInfo = resolveInfos.get(0);
for (int i = 1; i < size; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
if (firstResolveInfo.priority != resolveInfo.priority
|| firstResolveInfo.isDefault != resolveInfo.isDefault) {
while (i < size) {
resolveInfos.remove(i);
size--;
}
}
}
if (size > 1) {
ResolveInfo.DisplayNameComparator displayNameComparator = new ResolveInfo.DisplayNameComparator(
packageManager);
Collections.sort(resolveInfos, displayNameComparator);
}
firstResolveInfo = resolveInfos.get(0);
int start = 0;
CharSequence firstLabel = firstResolveInfo.loadLabel(packageManager);
for (int i = 1; i < size; i++) {
if (firstLabel == null) {
firstLabel = firstResolveInfo.activityInfo.packageName;
}
ResolveInfo resolveInfo = resolveInfos.get(i);
CharSequence label = resolveInfo.loadLabel(packageManager);
if (label == null) {
label = resolveInfo.activityInfo.packageName;
}
if (label.equals(firstLabel)) {
continue;
}
processGroup(resolveInfos, displayInfos, start, i - 1);
firstResolveInfo = resolveInfo;
firstLabel = label;
start = i;
}
// Process last group
processGroup(resolveInfos, displayInfos, start, size - 1);
}
return displayInfos;
}
/**
* Contains display info.
*
* @author Jimmy Shih
*/
private final class DisplayInfo {
private ResolveInfo resolveInfo;
private CharSequence primaryLabel;
private CharSequence secondaryLabel;
private Drawable icon;
public DisplayInfo(ResolveInfo resolveInfo, CharSequence primaryLabel,
CharSequence secondaryLabel, Drawable icon) {
this.resolveInfo = resolveInfo;
this.primaryLabel = primaryLabel;
this.secondaryLabel = secondaryLabel;
this.icon = icon;
}
}
/**
* Processes a group of items with the same label.
*
* @param resolveInfos list of resolve infos
* @param displayInfos list of display infos
* @param start start index
* @param end end index
*/
private void processGroup(
List<ResolveInfo> resolveInfos, List<DisplayInfo> displayInfos, int start, int end) {
ResolveInfo startResolveInfo = resolveInfos.get(start);
CharSequence primaryLabel = startResolveInfo.loadLabel(packageManager);
Drawable icon = startResolveInfo.loadIcon(packageManager);
int num = end - start + 1;
if (num == 1) {
// Only one, set the secondary label to null
displayInfos.add(new DisplayInfo(startResolveInfo, primaryLabel, null, icon));
} else {
// Decide package name or application name for the secondary label
boolean usePackageName = false;
CharSequence appName = startResolveInfo.activityInfo.applicationInfo.loadLabel(
packageManager);
if (appName == null) {
usePackageName = true;
} else {
// Use HashSet to track duplicates
HashSet<CharSequence> duplicates = new HashSet<CharSequence>();
duplicates.add(appName);
for (int i = start + 1; i <= end; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
CharSequence name = resolveInfo.activityInfo.applicationInfo.loadLabel(packageManager);
if ((name == null) || (duplicates.contains(name))) {
usePackageName = true;
break;
} else {
duplicates.add(name);
}
}
// Clear HashSet for later use
duplicates.clear();
}
for (int i = start; i <= end; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
CharSequence secondaryLabel = usePackageName ? resolveInfo.activityInfo.packageName
: resolveInfo.activityInfo.applicationInfo.loadLabel(packageManager);
displayInfos.add(new DisplayInfo(resolveInfo, primaryLabel, secondaryLabel, icon));
}
}
}
}
@@ -0,0 +1,172 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.fragments;
import com.google.android.apps.mytracks.io.sendtogoogle.AccountChooserActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
import com.google.android.apps.mytracks.util.AnalyticsUtils;
import com.google.android.apps.mytracks.util.IntentUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.TableRow;
import android.widget.Toast;
import java.util.ArrayList;
/**
* A DialogFragment to choose upload service.
*
* @author Jimmy Shih
*/
public class ChooseUploadServiceDialogFragment extends DialogFragment {
public static final String CHOOSE_UPLOAD_SERVICE_DIALOG_TAG = "chooseUploadService";
private static final String KEY_SEND_REQUEST = "sendRequest";
public static ChooseUploadServiceDialogFragment newInstance(SendRequest sendRequest) {
Bundle bundle = new Bundle();
bundle.putParcelable(KEY_SEND_REQUEST, sendRequest);
ChooseUploadServiceDialogFragment chooseUploadServiceDialogFragment =
new ChooseUploadServiceDialogFragment();
chooseUploadServiceDialogFragment.setArguments(bundle);
return chooseUploadServiceDialogFragment;
}
private SendRequest sendRequest;
private CheckBox mapsCheckBox;
private CheckBox fusionTablesCheckBox;
private CheckBox docsCheckBox;
private TableRow mapsOptionTableRow;
private RadioButton existingMapRadioButton;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
sendRequest = getArguments().getParcelable(KEY_SEND_REQUEST);
View view = getActivity().getLayoutInflater().inflate(R.layout.choose_upload_service, null);
mapsCheckBox = (CheckBox) view.findViewById(R.id.choose_upload_service_maps);
fusionTablesCheckBox = (CheckBox) view.findViewById(R.id.choose_upload_service_fusion_tables);
docsCheckBox = (CheckBox) view.findViewById(R.id.choose_upload_service_docs);
mapsCheckBox.setChecked(PreferencesUtils.getBoolean(
getActivity(), R.string.send_to_maps_key, PreferencesUtils.SEND_TO_MAPS_DEFAULT));
fusionTablesCheckBox.setChecked(PreferencesUtils.getBoolean(
getActivity(), R.string.send_to_fusion_tables_key,
PreferencesUtils.SEND_TO_FUSION_TABLES_DEFAULT));
docsCheckBox.setChecked(PreferencesUtils.getBoolean(
getActivity(), R.string.send_to_docs_key, PreferencesUtils.SEND_TO_DOCS_DEFAULT));
mapsCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton button, boolean checked) {
updateMapsOption();
}
});
mapsOptionTableRow = (TableRow) view.findViewById(R.id.choose_upload_service_maps_options);
RadioButton newMapRadioButton = (RadioButton) view.findViewById(
R.id.choose_upload_service_new_map);
existingMapRadioButton = (RadioButton) view.findViewById(
R.id.choose_upload_service_existing_map);
updateMapsOption();
if (PreferencesUtils.getBoolean(getActivity(), R.string.pick_existing_map_key,
PreferencesUtils.PICK_EXISTING_MAP_DEFAULT)) {
existingMapRadioButton.setChecked(true);
} else {
newMapRadioButton.setChecked(true);
}
return new AlertDialog.Builder(getActivity()).setNegativeButton(R.string.generic_cancel, null)
.setPositiveButton(R.string.send_google_send_now, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
PreferencesUtils.setBoolean(
getActivity(), R.string.pick_existing_map_key, existingMapRadioButton.isChecked());
PreferencesUtils.setBoolean(
getActivity(), R.string.send_to_maps_key, mapsCheckBox.isChecked());
PreferencesUtils.setBoolean(getActivity(), R.string.send_to_fusion_tables_key,
fusionTablesCheckBox.isChecked());
PreferencesUtils.setBoolean(
getActivity(), R.string.send_to_docs_key, docsCheckBox.isChecked());
if (mapsCheckBox.isChecked() || fusionTablesCheckBox.isChecked()
|| docsCheckBox.isChecked()) {
startNextActivity();
} else {
Toast.makeText(
getActivity(), R.string.send_google_no_service_selected, Toast.LENGTH_LONG)
.show();
}
}
})
.setTitle(R.string.send_google_title)
.setView(view)
.create();
}
/**
* Updates map option.
*/
private void updateMapsOption() {
mapsOptionTableRow.setVisibility(mapsCheckBox.isChecked() ? View.VISIBLE : View.GONE);
}
/**
* Starts the next activity, {@link AccountChooserActivity}.
*/
private void startNextActivity() {
sendStats();
sendRequest.setSendMaps(mapsCheckBox.isChecked());
sendRequest.setSendFusionTables(fusionTablesCheckBox.isChecked());
sendRequest.setSendDocs(docsCheckBox.isChecked());
sendRequest.setNewMap(!existingMapRadioButton.isChecked());
Intent intent = IntentUtils.newIntent(getActivity(), AccountChooserActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
startActivity(intent);
}
/**
* Sends stats to Google Analytics.
*/
private void sendStats() {
ArrayList<String> pages = new ArrayList<String>();
if (sendRequest.isSendMaps()) {
pages.add("/send/maps");
}
if (sendRequest.isSendFusionTables()) {
pages.add("/send/fusion_tables");
}
if (sendRequest.isSendDocs()) {
pages.add("/send/docs");
}
AnalyticsUtils.sendPageViews(getActivity(), pages.toArray(new String[pages.size()]));
}
}
@@ -0,0 +1,118 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.fragments;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
/**
* A DialogFragment to configure frequency.
*
* @author Jimmy Shih
*/
public class FrequencyDialogFragment extends DialogFragment {
public static final String FREQUENCY_DIALOG_TAG = "frequencyDialog";
private static final String KEY_PREFERENCE_ID = "preferenceId";
private static final String KEY_DEFAULT_VALUE = "defaultValue";
private static final String KEY_TITLE_ID = "titleId";
public static FrequencyDialogFragment newInstance(
int preferenceId, int defaultValue, int titleId) {
Bundle bundle = new Bundle();
bundle.putInt(KEY_PREFERENCE_ID, preferenceId);
bundle.putInt(KEY_DEFAULT_VALUE, defaultValue);
bundle.putInt(KEY_TITLE_ID, titleId);
FrequencyDialogFragment frequencyDialogFragment = new FrequencyDialogFragment();
frequencyDialogFragment.setArguments(bundle);
return frequencyDialogFragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final int preferenceId = getArguments().getInt(KEY_PREFERENCE_ID);
int defaultValue = getArguments().getInt(KEY_DEFAULT_VALUE);
int titleId = getArguments().getInt(KEY_TITLE_ID);
int frequencyValue = PreferencesUtils.getInt(getActivity(), preferenceId, defaultValue);
return new AlertDialog.Builder(getActivity())
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int listIndex = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
PreferencesUtils.setInt(getActivity(), preferenceId, getFrequencyValue(listIndex));
}
})
.setSingleChoiceItems(getFrequencyDisplayOptions(), getListIndex(frequencyValue), null)
.setTitle(titleId)
.create();
}
/**
* Gets the frequency display options.
*/
private String[] getFrequencyDisplayOptions() {
boolean metricUnits = PreferencesUtils.getBoolean(
getActivity(), R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
String[] values = getResources().getStringArray(R.array.frequency_values);
String[] options = new String[values.length];
for (int i = 0; i < values.length; i++) {
int value = Integer.parseInt(values[i]);
if (value == PreferencesUtils.FREQUENCY_OFF) {
options[i] = getString(R.string.value_off);
} else if (value < 0) {
options[i] = getString(metricUnits ? R.string.value_integer_kilometer
: R.string.value_integer_mile, Math.abs(value));
} else {
options[i] = getString(R.string.value_integer_minute, value);
}
}
return options;
}
/**
* Gets the list index for a frequency value. Returns 0 if the value is not on
* the list.
*/
private int getListIndex(int frequencyValue) {
String[] values = getResources().getStringArray(R.array.frequency_values);
for (int i = 0; i < values.length; i++) {
if (frequencyValue == Integer.parseInt(values[i])) {
return i;
}
}
return 0;
}
/**
* Gets the frequency value from a list index.
*
* @param listIndex the list index
*/
private int getFrequencyValue(int listIndex) {
String[] values = getResources().getStringArray(R.array.frequency_values);
return Integer.parseInt(values[listIndex]);
}
}
@@ -56,7 +56,7 @@ public class BackupAsyncTask extends AsyncTask<Void, Integer, Boolean> {
this.externalFileBackup = new ExternalFileBackup(backupActivity);
success = false;
completed = false;
messageId = R.string.sd_card_error_write_file;
messageId = R.string.sd_card_save_error;
}
/**
@@ -86,13 +86,13 @@ public class BackupAsyncTask extends AsyncTask<Void, Integer, Boolean> {
}
if (!externalFileBackup.isBackupsDirectoryAvailable(true)) {
messageId = R.string.sd_card_error_create_dir;
messageId = R.string.sd_card_save_error_create_dir;
return false;
}
try {
externalFileBackup.writeToDefaultFile();
messageId = R.string.sd_card_success_write_file;
messageId = R.string.sd_card_save_success;
return true;
} catch (IOException e) {
Log.d(TAG, "IO exception", e);
@@ -23,6 +23,7 @@ import android.net.Uri;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Locale;
/**
* Database importer which reads values written by {@link DatabaseDumper}.
@@ -179,7 +180,7 @@ public class DatabaseImporter {
byte[] blob = new byte[blobLength];
int readBytes = reader.read(blob, 0, blobLength);
if (readBytes != blobLength) {
throw new IOException(String.format(
throw new IOException(String.format(Locale.US,
"Short read on column %s; expected %d bytes, read %d",
name, blobLength, readBytes));
}
@@ -59,7 +59,7 @@ public class RestoreAsyncTask extends AsyncTask<Void, Integer, Boolean> {
this.externalFileBackup = new ExternalFileBackup(restoreActivity);
success = false;
completed = false;
messageId = R.string.sd_card_error_read_file;
messageId = R.string.sd_card_import_error;
}
/**
@@ -85,7 +85,7 @@ public class RestoreAsyncTask extends AsyncTask<Void, Integer, Boolean> {
protected Boolean doInBackground(Void... params) {
try {
externalFileBackup.restoreFromDate(date);
messageId = R.string.sd_card_success_read_file;
messageId = R.string.sd_card_import_success;
return true;
} catch (IOException e) {
Log.d(TAG, "IO exception", e);
@@ -119,7 +119,7 @@ public class SendDocsAsyncTask extends AbstractSendAsyncTask {
Track track = myTracksProviderUtils.getTrack(trackId);
if (track == null) {
Log.d(TAG, "Track is null");
Log.d(TAG, "No track for " + trackId);
return false;
}
@@ -106,7 +106,7 @@ public class SendDocsUtils {
throws IOException, ParseException, HttpException {
GDataParser gDataParser = null;
try {
String uri = String.format(GET_SPREADSHEET_BY_TITLE_URI, URLEncoder.encode(title));
String uri = String.format(Locale.US, GET_SPREADSHEET_BY_TITLE_URI, URLEncoder.encode(title));
gDataParser = documentsClient.getParserForFeed(Entry.class, uri, authToken);
gDataParser.init();
@@ -222,7 +222,7 @@ public class SendDocsUtils {
throws IOException, AuthenticationException, ParseException {
GDataParser gDataParser = null;
try {
String uri = String.format(GET_WORKSHEETS_URI, spreadsheetId);
String uri = String.format(Locale.US, GET_WORKSHEETS_URI, spreadsheetId);
gDataParser = spreadsheetClient.getParserForWorksheetsFeed(uri, authToken);
gDataParser.init();
if (!gDataParser.hasMoreData()) {
@@ -269,7 +269,7 @@ public class SendDocsUtils {
public static void addTrackInfo(
Track track, String spreadsheetId, String worksheetId, String authToken, Context context)
throws IOException {
String worksheetUri = String.format(GET_WORKSHEET_URI, spreadsheetId, worksheetId);
String worksheetUri = String.format(Locale.US, GET_WORKSHEET_URI, spreadsheetId, worksheetId);
boolean metricUnits = PreferencesUtils.getBoolean(
context, R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
addRow(worksheetUri, getRowContent(track, metricUnits, context), authToken);
@@ -312,8 +312,8 @@ public class SendDocsUtils {
appendTag(builder, "elevationunit", elevationUnit);
if (track.getMapId().length() > 0) {
appendTag(builder, "map",
String.format("%s?msa=0&msid=%s", Constants.MAPSHOP_BASE_URL, track.getMapId()));
appendTag(builder, "map", String.format(
Locale.US, "%s?msa=0&msid=%s", Constants.MAPSHOP_BASE_URL, track.getMapId()));
}
builder.append("</entry>");
@@ -197,7 +197,7 @@ public class KmlTrackWriter implements TrackFormatWriter {
printWriter.println("</gx:MultiTrack>");
printWriter.println("</Placemark>");
String name = context.getString(R.string.marker_label_end, track.getName());
String description = descriptionGenerator.generateTrackDescription(track, null, null);
String description = descriptionGenerator.generateTrackDescription(track, null, null, false);
writePlacemark(name, description, END_STYLE, lastLocation);
}
}
@@ -16,10 +16,9 @@
package com.google.android.apps.mytracks.io.file;
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.DialogUtils;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.IntentUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
@@ -30,21 +29,19 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import java.io.File;
/**
* Activity for saving a track to the SD card, and optionally share or play the
* track.
*
* An activity for saving tracks to the SD card. If saving a specific track,
* option to save it to a temp directory and play the track afterward.
*
* @author Rodrigo Damazio
*/
public class SaveActivity extends Activity {
public static final String EXTRA_TRACK_ID = "track_id";
public static final String EXTRA_TRACK_FILE_FORMAT = "track_file_format";
public static final String EXTRA_SHARE_TRACK = "share_track";
public static final String EXTRA_TRACK_ID = "track_id";
public static final String EXTRA_PLAY_TRACK = "play_track";
public static final String GOOGLE_EARTH_KML_MIME_TYPE = "application/vnd.google-earth.kml+xml";
@@ -55,14 +52,11 @@ public class SaveActivity extends Activity {
GOOGLE_EARTH_TOUR_FEATURE_ID = "com.google.earth.EXTRA.tour_feature_id";
private static final String GOOGLE_EARTH_CLASS = "com.google.earth.EarthActivity";
private static final String TAG = SaveActivity.class.getSimpleName();
private static final int DIALOG_PROGRESS_ID = 0;
private static final int DIALOG_RESULT_ID = 1;
private long trackId;
private TrackFileFormat trackFileFormat;
private boolean shareTrack;
private long trackId;
private boolean playTrack;
private SaveAsyncTask saveAsyncTask;
@@ -74,23 +68,16 @@ public class SaveActivity extends Activity {
// message id from the AsyncTask
private int messageId;
// path of the saved file
private String filePath;
// saved file path from the AsyncTask
private String savedPath;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
if (trackId < 0) {
Log.d(TAG, "Invalid track id");
finish();
return;
}
trackFileFormat = intent.getParcelableExtra(EXTRA_TRACK_FILE_FORMAT);
shareTrack = intent.getBooleanExtra(EXTRA_SHARE_TRACK, false);
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
playTrack = intent.getBooleanExtra(EXTRA_PLAY_TRACK, false);
Object retained = getLastNonConfigurationInstance();
@@ -98,20 +85,7 @@ public class SaveActivity extends Activity {
saveAsyncTask = (SaveAsyncTask) retained;
saveAsyncTask.setActivity(this);
} else {
TrackWriter trackWriter = TrackWriterFactory.newWriter(
this, MyTracksProviderUtils.Factory.get(this), trackId, trackFileFormat);
if (trackWriter == null) {
Log.e(TAG, "Track writer is null");
finish();
return;
}
if (shareTrack || playTrack) {
// Save to the temp directory
String dirName = FileUtils.buildExternalDirectoryPath(
trackFileFormat.getExtension(), "tmp");
trackWriter.setDirectory(new File(dirName));
}
saveAsyncTask = new SaveAsyncTask(this, trackWriter);
saveAsyncTask = new SaveAsyncTask(this, trackFileFormat, trackId, playTrack);
saveAsyncTask.execute();
}
}
@@ -127,7 +101,7 @@ public class SaveActivity extends Activity {
switch (id) {
case DIALOG_PROGRESS_ID:
progressDialog = DialogUtils.createHorizontalProgressDialog(
this, R.string.sd_card_progress_message, new DialogInterface.OnCancelListener() {
this, R.string.sd_card_save_progress_message, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
saveAsyncTask.cancel(true);
@@ -136,7 +110,7 @@ public class SaveActivity extends Activity {
});
return progressDialog;
case DIALOG_RESULT_ID:
return new AlertDialog.Builder(this)
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setCancelable(true)
.setIcon(success
? android.R.drawable.ic_dialog_info : android.R.drawable.ic_dialog_alert)
@@ -155,8 +129,22 @@ public class SaveActivity extends Activity {
onPostResultDialog();
}
})
.setTitle(success ? R.string.generic_success_title : R.string.generic_error_title)
.create();
.setTitle(success ? R.string.generic_success_title : R.string.generic_error_title);
if (success && trackId != -1L && !playTrack) {
builder.setNegativeButton(
R.string.share_track_share_file, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = IntentUtils.newShareFileIntent(
SaveActivity.this, trackId, savedPath, trackFileFormat);
startActivity(
Intent.createChooser(intent, getString(R.string.share_track_picker_title)));
finish();
}
});
}
return builder.create();
default:
return null;
}
@@ -167,12 +155,12 @@ public class SaveActivity extends Activity {
*
* @param isSuccess true if the AsyncTask is successful
* @param aMessageId the id of the AsyncTask message
* @param aPath the path of the saved file
* @param aSavedPath the path of the saved file
*/
public void onAsyncTaskCompleted(boolean isSuccess, int aMessageId, String aPath) {
public void onAsyncTaskCompleted(boolean isSuccess, int aMessageId, String aSavedPath) {
this.success = isSuccess;
this.messageId = aMessageId;
this.filePath = aPath;
this.savedPath = aSavedPath;
removeDialog(DIALOG_PROGRESS_ID);
showDialog(DIALOG_RESULT_ID);
}
@@ -202,23 +190,13 @@ public class SaveActivity extends Activity {
* To be invoked after showing the result dialog.
*/
private void onPostResultDialog() {
if (success) {
if (shareTrack) {
Intent intent = new Intent(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filePath)))
.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_track_subject))
.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_track_file_body_format))
.putExtra(getString(R.string.track_id_broadcast_extra), trackId)
.setType(trackFileFormat.getMimeType());
startActivity(Intent.createChooser(intent, getString(R.string.share_track_picker_title)));
} else if (playTrack) {
Intent intent = new Intent()
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(GOOGLE_EARTH_TOUR_FEATURE_ID, KmlTrackWriter.TOUR_FEATURE_ID)
.setClassName(GOOGLE_EARTH_PACKAGE, GOOGLE_EARTH_CLASS)
.setDataAndType(Uri.fromFile(new File(filePath)), GOOGLE_EARTH_KML_MIME_TYPE);
startActivity(intent);
}
if (success && playTrack) {
Intent intent = new Intent()
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(GOOGLE_EARTH_TOUR_FEATURE_ID, KmlTrackWriter.TOUR_FEATURE_ID)
.setClassName(GOOGLE_EARTH_PACKAGE, GOOGLE_EARTH_CLASS)
.setDataAndType(Uri.fromFile(new File(savedPath)), GOOGLE_EARTH_KML_MIME_TYPE);
startActivity(intent);
}
finish();
}
@@ -16,48 +16,93 @@
package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import java.io.File;
/**
* Async Task to save a track to the SD card.
*
* Async Task to save tracks to the SD card.
*
* @author Jimmy Shih
*/
public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
private static final String TAG = SaveAsyncTask.class.getSimpleName();
private SaveActivity saveActivity;
private final TrackWriter trackWriter;
private final TrackFileFormat trackFileFormat;
private final long trackId;
private final boolean useTempDir;
private final Context context;
private final MyTracksProviderUtils myTracksProviderUtils;
private WakeLock wakeLock;
private TrackWriter trackWriter;
// true if the AsyncTask result is success
private boolean success;
// true if the AsyncTask has completed
private boolean completed;
// message id to return to the activity
private int messageId;
// saved file path to return to the activity
private String savedPath;
/**
* Creates an AsyncTask.
*
* @param saveActivity the {@link SaveActivity} currently associated with this
* AsyncTask
* @param trackWriter the track writer
*
* @param saveActivity the activity currently associated with this task.
* @param trackFileFormat the track format
* @param trackId the track id
* @param useTempDir true to use the temp directory
*/
public SaveAsyncTask(SaveActivity saveActivity, TrackWriter trackWriter) {
public SaveAsyncTask(SaveActivity saveActivity, TrackFileFormat trackFileFormat, long trackId,
boolean useTempDir) {
this.saveActivity = saveActivity;
this.trackWriter = trackWriter;
this.trackFileFormat = trackFileFormat;
this.trackId = trackId;
this.useTempDir = useTempDir;
context = saveActivity.getApplicationContext();
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(saveActivity);
// Get the wake lock if not recording
if (PreferencesUtils.getLong(saveActivity, R.string.recording_track_id_key)
== PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
wakeLock = SystemUtils.acquireWakeLock(saveActivity, wakeLock);
}
trackWriter = null;
success = false;
completed = false;
messageId = R.string.sd_card_save_error;
savedPath = null;
}
/**
* Sets the current {@link SaveActivity} associated with this AyncTask.
*
* @param saveActivity the current {@link SaveActivity}, can be null
* Sets the current activity associated with this AyncTask.
*
* @param saveActivity the current activity, can be null
*/
public void setActivity(SaveActivity saveActivity) {
this.saveActivity = saveActivity;
if (completed && saveActivity != null) {
saveActivity.onAsyncTaskCompleted(
success, trackWriter.getErrorMessage(), trackWriter.getAbsolutePath());
saveActivity.onAsyncTaskCompleted(success, messageId, savedPath);
}
}
@@ -69,20 +114,85 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
}
@Override
protected Boolean doInBackground(Void... params) {
protected Boolean doInBackground(Void... params) {
try {
if (trackId != -1L) {
return saveOneTrack(trackId, true);
} else {
return saveAllTracks();
}
} finally {
// Release the wake lock if obtained
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
}
}
}
/**
* Saves one track.
*
* @param id the track id
* @param updateSavingProgress true to update the saving progress
*/
private Boolean saveOneTrack(long id, final boolean updateSavingProgress) {
trackWriter = TrackWriterFactory.newWriter(
context, myTracksProviderUtils, id, trackFileFormat);
if (trackWriter == null) {
Log.e(TAG, "Track writer is null");
return false;
}
if (useTempDir) {
String dirName = FileUtils.buildExternalDirectoryPath(trackFileFormat.getExtension(), "tmp");
trackWriter.setDirectory(new File(dirName));
}
trackWriter.setOnWriteListener(new TrackWriter.OnWriteListener() {
@Override
@Override
public void onWrite(int number, int max) {
// Update the progress dialog once every 500 points
if (number % 500 == 0) {
if (updateSavingProgress && number % 500 == 0) {
publishProgress(number, max);
}
}
});
trackWriter.writeTrack();
messageId = trackWriter.getErrorMessage();
savedPath = trackWriter.getAbsolutePath();
return trackWriter.wasSuccess();
}
/**
* Saves all the tracks.
*/
private Boolean saveAllTracks() {
Cursor cursor = null;
try {
cursor = myTracksProviderUtils.getTracksCursor(null, null, TracksColumns._ID);
if (cursor == null) {
messageId = R.string.sd_card_save_error_no_track;
return false;
}
int count = cursor.getCount();
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
for (int i = 0; i < count; i++) {
if (isCancelled()) {
return false;
}
cursor.moveToPosition(i);
long id = cursor.getLong(idIndex);
if (!saveOneTrack(id, false)) {
return false;
}
publishProgress(i + 1, count);
}
messageId = R.string.sd_card_save_success;
return true;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
@Override
protected void onProgressUpdate(Integer... values) {
if (saveActivity != null) {
@@ -95,13 +205,14 @@ public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
success = result;
completed = true;
if (saveActivity != null) {
saveActivity.onAsyncTaskCompleted(
success, trackWriter.getErrorMessage(), trackWriter.getAbsolutePath());
saveActivity.onAsyncTaskCompleted(success, messageId, savedPath);
}
}
@Override
protected void onCancelled() {
trackWriter.stopWriteTrack();
if (trackWriter != null) {
trackWriter.stopWriteTrack();
}
}
}
@@ -118,7 +118,7 @@ public class TrackWriterFactory {
long trackId, TrackFileFormat format) {
Track track = providerUtils.getTrack(trackId);
if (track == null) {
Log.w(TAG, "Trying to create a writer for an invalid track, id=" + trackId);
Log.d(TAG, "No track for " + trackId);
return null;
}
@@ -53,7 +53,7 @@ class TrackWriterImpl implements TrackWriter {
private final Track track;
private final TrackFormatWriter writer;
private boolean success = false;
private int errorMessage = -1;
private int errorMessage = R.string.sd_card_save_error;
private File directory = null;
private File file = null;
private OnWriteListener onWriteListener;
@@ -105,7 +105,7 @@ class TrackWriterImpl implements TrackWriter {
private void doWriteTrack() {
// Open the input and output
success = false;
errorMessage = R.string.sd_card_error_write_file;
errorMessage = R.string.sd_card_save_error;
if (track != null) {
if (openFile()) {
try {
@@ -186,7 +186,7 @@ class TrackWriterImpl implements TrackWriter {
writer.prepare(track, newOutputStream(fileName));
} catch (FileNotFoundException e) {
Log.e(Constants.TAG, "Failed to open output file.", e);
errorMessage = R.string.sd_card_error_write_file;
errorMessage = R.string.sd_card_save_error;
return false;
}
return true;
@@ -209,7 +209,7 @@ class TrackWriterImpl implements TrackWriter {
}
if (!FileUtils.ensureDirectoryExists(directory)) {
Log.i(Constants.TAG, "Could not create export directory.");
errorMessage = R.string.sd_card_error_create_dir;
errorMessage = R.string.sd_card_save_error_create_dir;
return false;
}
@@ -283,7 +283,7 @@ class TrackWriterImpl implements TrackWriter {
writer.close();
success = true;
Log.d(Constants.TAG, "Done writing track.");
errorMessage = R.string.sd_card_success_write_file;
errorMessage = R.string.sd_card_save_success;
}
private void writeLocations() throws InterruptedException {
@@ -105,12 +105,12 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
@Override
protected void saveResult() {
Track track = myTracksProviderUtils.getTrack(trackId);
if (track != null) {
track.setTableId(tableId);
myTracksProviderUtils.updateTrack(track);
} else {
Log.d(TAG, "No track");
if (track == null) {
Log.d(TAG, "No track for " + trackId);
return;
}
track.setTableId(tableId);
myTracksProviderUtils.updateTrack(track);
}
@Override
@@ -136,7 +136,7 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
Track track = myTracksProviderUtils.getTrack(trackId);
if (track == null) {
Log.d(TAG, "Track is null");
Log.d(TAG, "No track for " + trackId);
return false;
}
@@ -277,7 +277,8 @@ public class SendFusionTablesAsyncTask extends AbstractSendAsyncTask {
elevations.add(elevationBuffer.getAverage());
DescriptionGenerator descriptionGenerator = new DescriptionGeneratorImpl(context);
track.setDescription("<p>" + track.getDescription() + "</p><p>"
+ descriptionGenerator.generateTrackDescription(track, distances, elevations) + "</p>");
+ descriptionGenerator.generateTrackDescription(track, distances, elevations, true)
+ "</p>");
String name = context.getString(R.string.marker_label_end, track.getName());
if (!createNewPoint(name, track.getDescription(), lastLocation, MARKER_TYPE_END)) {
Log.d(TAG, "Unable to create the end marker");
@@ -7,6 +7,8 @@ import com.google.wireless.gdata.client.GDataServiceClient;
import android.util.Log;
import java.util.Locale;
/**
* Client to talk to Google Maps via GData.
*/
@@ -93,9 +95,8 @@ public class MapsClient extends GDataServiceClient {
public static String getVersionFeed(String versionUserId,
String versionClient, String currentVersion) {
return String.format(MAPS_VERSION_FEED_PATH_FORMAT,
MAPS_BASE_FEED_URL, versionUserId,
versionClient, currentVersion);
return String.format(Locale.US, MAPS_VERSION_FEED_PATH_FORMAT, MAPS_BASE_FEED_URL,
versionUserId, versionClient, currentVersion);
}
}
@@ -131,14 +131,14 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
@Override
protected void saveResult() {
Track track = myTracksProviderUtils.getTrack(trackId);
if (track != null) {
track.setMapId(mapId);
myTracksProviderUtils.updateTrack(track);
} else {
Log.d(TAG, "No track");
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
@@ -173,7 +173,7 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
// Get the track
Track track = myTracksProviderUtils.getTrack(trackId);
if (track == null) {
Log.d(TAG, "Track is null");
Log.d(TAG, "No track for " + trackId);
return false;
}
@@ -353,7 +353,8 @@ public class SendMapsAsyncTask extends AbstractSendAsyncTask {
String getTrackDescription(Track track, Vector<Double> distances, Vector<Double> elevations) {
DescriptionGenerator descriptionGenerator = new DescriptionGeneratorImpl(context);
return "<p>" + track.getDescription() + "</p><p>"
+ descriptionGenerator.generateTrackDescription(track, distances, elevations) + "</p>";
+ descriptionGenerator.generateTrackDescription(track, distances, elevations, true)
+ "</p>";
}
/**
@@ -80,9 +80,6 @@ public abstract class AbstractSendAsyncTask extends AsyncTask<Void, Integer, Boo
return performTask();
} finally {
closeConnection();
if (success) {
saveResult();
}
}
}
@@ -97,6 +94,9 @@ 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);
}
@@ -76,7 +76,6 @@ public class AccountChooserActivity extends Activity {
private SendRequest sendRequest;
private Account[] accounts;
private int selectedAccountIndex;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -84,32 +83,28 @@ public class AccountChooserActivity extends Activity {
sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY);
accounts = AccountManager.get(this).getAccountsByType(Constants.ACCOUNT_TYPE);
if (accounts.length == 0) {
showDialog(DIALOG_NO_ACCOUNT_ID);
return;
}
if (accounts.length == 1) {
sendRequest.setAccount(accounts[0]);
PreferencesUtils.setString(this, R.string.sharing_account_key, accounts[0].name);
getPermission(MapsConstants.SERVICE_NAME, sendRequest.isSendMaps(), mapsCallback);
return;
}
String preferredAccount = PreferencesUtils.getString(this, R.string.preferred_account_key,
PreferencesUtils.PREFERRED_ACCOUNT_DEFAULT);
selectedAccountIndex = 0;
String sharingAccount = PreferencesUtils.getString(this, R.string.sharing_account_key,
PreferencesUtils.SHARING_ACCOUNT_DEFAULT);
for (int i = 0; i < accounts.length; i++) {
if (accounts[i].name.equals(preferredAccount)) {
selectedAccountIndex = i;
break;
if (accounts[i].name.equals(sharingAccount)) {
sendRequest.setAccount(accounts[i]);
getPermission(MapsConstants.SERVICE_NAME, sendRequest.isSendMaps(), mapsCallback);
return;
}
}
}
@Override
protected void onResume() {
super.onResume();
if (accounts.length == 0) {
showDialog(DIALOG_NO_ACCOUNT_ID);
} else if (accounts.length > 1 ) {
showDialog(DIALOG_CHOOSER_ID);
}
showDialog(DIALOG_CHOOSER_ID);
}
@Override
@@ -162,20 +157,15 @@ public class AccountChooserActivity extends Activity {
})
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Account account = accounts[selectedAccountIndex];
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
Account account = accounts[position];
PreferencesUtils.setString(
AccountChooserActivity.this, R.string.preferred_account_key, account.name);
AccountChooserActivity.this, R.string.sharing_account_key, account.name);
sendRequest.setAccount(account);
getPermission(MapsConstants.SERVICE_NAME, sendRequest.isSendMaps(), mapsCallback);
}
})
.setSingleChoiceItems(
choices, selectedAccountIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
selectedAccountIndex = which;
}
})
.setSingleChoiceItems(choices, 0, null)
.setTitle(R.string.send_google_choose_account_title)
.create();
}
@@ -31,9 +31,8 @@ public class SendRequest implements Parcelable {
public static final String SEND_REQUEST_KEY = "sendRequest";
private long trackId = -1L;
private boolean showMaps = false;
private boolean showFusionTables = false;
private boolean showDocs = false;
private String sharingAppPackageName = null;
private String sharingAppClassName = null;
private boolean sendMaps = false;
private boolean sendFusionTables = false;
private boolean sendDocs = false;
@@ -48,15 +47,9 @@ public class SendRequest implements Parcelable {
* Creates a new send request.
*
* @param trackId the track id
* @param showMaps true to show the Google Maps option
* @param showFusionTables true to show the Google Fusion Tables option
* @param showDocs true to show the Google Docs option
*/
public SendRequest(long trackId, boolean showMaps, boolean showFusionTables, boolean showDocs) {
public SendRequest(long trackId) {
this.trackId = trackId;
this.showMaps = showMaps;
this.showFusionTables = showFusionTables;
this.showDocs = showDocs;
}
/**
@@ -67,31 +60,35 @@ public class SendRequest implements Parcelable {
}
/**
* True if showing the send to Google Maps option.
* Gets the sharing app package name.
*/
public boolean isShowMaps() {
return showMaps;
public String getSharingAppPackageName() {
return sharingAppPackageName;
}
/**
* True if showing the send to Google Fusion Tables option.
* Sets the sharing app package name.
*
* @param sharingAppPackageName the sharing app package name
*/
public boolean isShowFusionTables() {
return showFusionTables;
public void setSharingAppPackageName(String sharingAppPackageName) {
this.sharingAppPackageName = sharingAppPackageName;
}
/**
* True if showing the send to Google Docs option.
* Gets the sharing app class name.
*/
public boolean isShowDocs() {
return showDocs;
public String getSharingAppClassName() {
return sharingAppClassName;
}
/**
* True if showing all the send options.
* Sets the sharing app class name.
*
* @param sharingAppClassName the sharing app class name
*/
public boolean isShowAll() {
return showMaps && showFusionTables && showDocs;
public void setSharingAppClassName(String sharingAppClassName) {
this.sharingAppClassName = sharingAppClassName;
}
/**
@@ -245,9 +242,8 @@ public class SendRequest implements Parcelable {
private SendRequest(Parcel in) {
trackId = in.readLong();
showMaps = in.readByte() == 1;
showFusionTables = in.readByte() == 1;
showDocs = in.readByte() == 1;
sharingAppPackageName = in.readString();
sharingAppClassName = in.readString();
sendMaps = in.readByte() == 1;
sendFusionTables = in.readByte() == 1;
sendDocs = in.readByte() == 1;
@@ -267,9 +263,8 @@ public class SendRequest implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeLong(trackId);
out.writeByte((byte) (showMaps ? 1 : 0));
out.writeByte((byte) (showFusionTables ? 1 : 0));
out.writeByte((byte) (showDocs ? 1 : 0));
out.writeString(sharingAppPackageName);
out.writeString(sharingAppClassName);
out.writeByte((byte) (sendMaps ? 1 : 0));
out.writeByte((byte) (sendFusionTables ? 1 : 0));
out.writeByte((byte) (sendDocs ? 1 : 0));
@@ -17,18 +17,20 @@ package com.google.android.apps.mytracks.io.sendtogoogle;
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.io.fusiontables.SendFusionTablesUtils;
import com.google.android.apps.mytracks.io.maps.SendMapsUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.apps.mytracks.util.IntentUtils;
import com.google.android.maps.mytracks.R;
import com.google.common.annotations.VisibleForTesting;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -36,45 +38,45 @@ import android.widget.TextView;
/**
* A dialog to show the result of uploading to Google services.
*
*
* @author Jimmy Shih
*/
public class UploadResultActivity extends Activity {
public class UploadResultActivity extends FragmentActivity {
private static final String TEXT_PLAIN_TYPE = "text/plain";
private static final String TAG = UploadResultActivity.class.getSimpleName();
private static final int DIALOG_RESULT_ID = 0;
private SendRequest sendRequest;
private Track track;
private String shareUrl;
private Dialog resultDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY);
track = null;
shareUrl = null;
Track track = MyTracksProviderUtils.Factory.get(this).getTrack(sendRequest.getTrackId());
if (track == null) {
Log.d(TAG, "No track for " + sendRequest.getTrackId());
finish();
return;
}
if (sendRequest.isSendMaps() && sendRequest.isMapsSuccess()) {
shareUrl = SendMapsUtils.getMapUrl(getTrack());
shareUrl = SendMapsUtils.getMapUrl(track);
if (sendRequest.getSharingAppPackageName() != null) {
Intent intent = IntentUtils.newShareUrlIntent(this, sendRequest.getTrackId(), shareUrl,
sendRequest.getSharingAppPackageName(), sendRequest.getSharingAppClassName());
startActivity(intent);
finish();
return;
}
}
if (shareUrl == null && sendRequest.isSendFusionTables()
&& sendRequest.isFusionTablesSuccess()) {
shareUrl = SendFusionTablesUtils.getMapUrl(getTrack());
shareUrl = SendFusionTablesUtils.getMapUrl(track);
}
}
private Track getTrack() {
if (track == null) {
track = MyTracksProviderUtils.Factory.get(this).getTrack(sendRequest.getTrackId());
}
return track;
}
@Override
protected void onResume() {
super.onResume();
showDialog(DIALOG_RESULT_ID);
}
@@ -82,7 +84,7 @@ public class UploadResultActivity extends Activity {
protected Dialog onCreateDialog(int id) {
if (id != DIALOG_RESULT_ID) {
return null;
}
}
View view = getLayoutInflater().inflate(R.layout.upload_result, null);
LinearLayout mapsResult = (LinearLayout) view.findViewById(R.id.upload_result_maps_result);
@@ -139,31 +141,29 @@ public class UploadResultActivity extends Activity {
.setCancelable(true)
.setIcon(hasError ? android.R.drawable.ic_dialog_alert : android.R.drawable.ic_dialog_info)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
})
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
@Override
public void onClick(DialogInterface dialog, int which) {
if (!sendRequest.isShowAll() && shareUrl != null) {
startShareUrlActivity(shareUrl);
}
finish();
}
})
.setTitle(hasError ? R.string.generic_error_title : R.string.generic_success_title)
.setView(view);
// Add a Share URL button if showing all the options and a shareUrl exists
if (sendRequest.isShowAll() && shareUrl != null) {
// Add a Share URL button if shareUrl exists
if (shareUrl != null) {
builder.setNegativeButton(
R.string.send_google_result_share_url, new DialogInterface.OnClickListener() {
@Override
R.string.share_track_share_url, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startShareUrlActivity(shareUrl);
finish();
ChooseActivityDialogFragment.newInstance(sendRequest.getTrackId(), shareUrl).show(
getSupportFragmentManager(),
ChooseActivityDialogFragment.CHOOSE_ACTIVITY_DIALOG_TAG);
}
});
}
@@ -171,22 +171,6 @@ public class UploadResultActivity extends Activity {
return resultDialog;
}
/**
* Starts an activity to share the url.
*
* @param url the url
*/
private void startShareUrlActivity(String url) {
boolean shareUrlOnly = PreferencesUtils.getBoolean(
this, R.string.share_url_only_key, PreferencesUtils.SHARE_URL_ONLY_DEFAULT);
Intent intent = new Intent(Intent.ACTION_SEND)
.setType(TEXT_PLAIN_TYPE)
.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_track_subject))
.putExtra(Intent.EXTRA_TEXT,
shareUrlOnly ? url : getString(R.string.share_track_url_body_format, url));
startActivity(Intent.createChooser(intent, getString(R.string.share_track_picker_title)));
}
@VisibleForTesting
Dialog getDialog() {
return resultDialog;
@@ -1,268 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.io.sendtogoogle;
import com.google.android.apps.mytracks.util.AnalyticsUtils;
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;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.TableRow;
import android.widget.Toast;
import java.util.ArrayList;
/**
* A chooser to select the Google services to upload a track to.
*
* @author Jimmy Shih
*/
public class UploadServiceChooserActivity extends Activity {
private static final int DIALOG_CHOOSER_ID = 0;
private SendRequest sendRequest;
private AlertDialog alertDialog;
private TableRow mapsTableRow;
private TableRow fusionTablesTableRow;
private TableRow docsTableRow;
private CheckBox mapsCheckBox;
private CheckBox fusionTablesCheckBox;
private CheckBox docsCheckBox;
private TableRow mapsOptionTableRow;
private RadioButton newMapRadioButton;
private RadioButton existingMapRadioButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sendRequest = getIntent().getParcelableExtra(SendRequest.SEND_REQUEST_KEY);
}
@Override
protected void onResume() {
super.onResume();
showDialog(DIALOG_CHOOSER_ID);
}
@Override
protected Dialog onCreateDialog(int id) {
if (id != DIALOG_CHOOSER_ID) {
return null;
}
View view = getLayoutInflater().inflate(R.layout.upload_service_chooser, null);
mapsTableRow = (TableRow) view.findViewById(R.id.send_google_maps_row);
fusionTablesTableRow = (TableRow) view.findViewById(R.id.send_google_fusion_tables_row);
docsTableRow = (TableRow) view.findViewById(R.id.send_google_docs_row);
mapsCheckBox = (CheckBox) view.findViewById(R.id.send_google_maps);
fusionTablesCheckBox = (CheckBox) view.findViewById(R.id.send_google_fusion_tables);
docsCheckBox = (CheckBox) view.findViewById(R.id.send_google_docs);
mapsOptionTableRow = (TableRow) view.findViewById(R.id.send_google_maps_option_row);
newMapRadioButton = (RadioButton) view.findViewById(R.id.send_google_new_map);
existingMapRadioButton = (RadioButton) view.findViewById(R.id.send_google_existing_map);
// Setup checkboxes
OnCheckedChangeListener checkBoxListener = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton button, boolean checked) {
updateStateBySelection();
}
};
mapsCheckBox.setOnCheckedChangeListener(checkBoxListener);
fusionTablesCheckBox.setOnCheckedChangeListener(checkBoxListener);
docsCheckBox.setOnCheckedChangeListener(checkBoxListener);
// Setup initial state
initState();
// Update state based on sendRequest
updateStateBySendRequest();
// Update state based on current selection
updateStateBySelection();
alertDialog = new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.generic_cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface d) {
finish();
}
})
.setPositiveButton(R.string.send_google_send_now, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
saveState();
if (sendMaps() || sendFusionTables() || sendDocs()) {
startNextActivity();
} else {
Toast.makeText(UploadServiceChooserActivity.this,
R.string.send_google_no_service_selected, Toast.LENGTH_LONG).show();
finish();
}
}
})
.setTitle(R.string.send_google_title)
.setView(view)
.create();
return alertDialog;
}
/**
* Initializes the UI state based on the shared preferences.
*/
@VisibleForTesting
void initState() {
boolean pickExistingMap = PreferencesUtils.getBoolean(
this, R.string.pick_existing_map_key, PreferencesUtils.PICK_EXISTING_MAP_DEFAULT);
newMapRadioButton.setChecked(!pickExistingMap);
existingMapRadioButton.setChecked(pickExistingMap);
mapsCheckBox.setChecked(PreferencesUtils.getBoolean(
this, R.string.send_to_maps_key, PreferencesUtils.SEND_TO_MAPS_DEFAULT));
fusionTablesCheckBox.setChecked(PreferencesUtils.getBoolean(
this, R.string.send_to_fusion_tables_key, PreferencesUtils.SEND_TO_FUSION_TABLES_DEFAULT));
docsCheckBox.setChecked(PreferencesUtils.getBoolean(
this, R.string.send_to_docs_key, PreferencesUtils.SEND_TO_DOCS_DEFAULT));
}
/**
* Updates the UI state based on sendRequest.
*/
private void updateStateBySendRequest() {
if (!sendRequest.isShowAll()) {
if (sendRequest.isShowMaps()) {
mapsCheckBox.setChecked(true);
} else if (sendRequest.isShowFusionTables()) {
fusionTablesCheckBox.setChecked(true);
} else if (sendRequest.isShowDocs()) {
docsCheckBox.setChecked(true);
}
}
mapsTableRow.setVisibility(sendRequest.isShowMaps() ? View.VISIBLE : View.GONE);
fusionTablesTableRow.setVisibility(sendRequest.isShowFusionTables() ? View.VISIBLE : View.GONE);
docsTableRow.setVisibility(sendRequest.isShowDocs() ? View.VISIBLE : View.GONE);
}
/**
* Updates the UI state based on the current selection.
*/
private void updateStateBySelection() {
mapsOptionTableRow.setVisibility(sendMaps() ? View.VISIBLE : View.GONE);
}
/**
* Saves the UI state to the shared preferences.
*/
@VisibleForTesting
void saveState() {
PreferencesUtils.setBoolean(
this, R.string.pick_existing_map_key, existingMapRadioButton.isChecked());
if (sendRequest.isShowAll()) {
PreferencesUtils.setBoolean(this, R.string.send_to_maps_key, sendMaps());
PreferencesUtils.setBoolean(this, R.string.send_to_fusion_tables_key, sendFusionTables());
PreferencesUtils.setBoolean(this, R.string.send_to_docs_key, sendDocs());
}
}
/**
* Returns true to send to Google Maps.
*/
private boolean sendMaps() {
return sendRequest.isShowMaps() && mapsCheckBox.isChecked();
}
/**
* Returns true to send to Google Fusion Tables.
*/
private boolean sendFusionTables() {
return sendRequest.isShowFusionTables() && fusionTablesCheckBox.isChecked();
}
/**
* Returns true to send to Google Docs.
*/
private boolean sendDocs() {
return sendRequest.isShowDocs() && docsCheckBox.isChecked();
}
/**
* Starts the next activity, {@link AccountChooserActivity}.
*/
@VisibleForTesting
protected void startNextActivity() {
sendStats();
sendRequest.setSendMaps(sendMaps());
sendRequest.setSendFusionTables(sendFusionTables());
sendRequest.setSendDocs(sendDocs());
sendRequest.setNewMap(!existingMapRadioButton.isChecked());
Intent intent = IntentUtils.newIntent(this, AccountChooserActivity.class)
.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
startActivity(intent);
finish();
}
/**
* Sends stats to Google Analytics.
*/
private void sendStats() {
ArrayList<String> pages = new ArrayList<String>();
if (sendRequest.isSendMaps()) {
pages.add("/send/maps");
}
if (sendRequest.isSendFusionTables()) {
pages.add("/send/fusion_tables");
}
if (sendRequest.isSendDocs()) {
pages.add("/send/docs");
}
AnalyticsUtils.sendPageViews(this, pages.toArray(new String[pages.size()]));
}
@VisibleForTesting
AlertDialog getAlertDialog() {
return alertDialog;
}
@VisibleForTesting
SendRequest getSendRequest() {
return sendRequest;
}
}
@@ -93,6 +93,10 @@ public class DynamicSpeedTrackPathDescriptor implements TrackPathDescriptor,
return false;
}
Track track = MyTracksProviderUtils.Factory.get(context).getTrack(selectedTrackId);
if (track == null) {
Log.d(TAG, "No track for " + selectedTrackId);
return false;
}
TripStatistics stats = track.getStatistics();
double newAverageMovingSpeed = (int) Math.floor(
stats.getAverageMovingSpeed() * UnitConversions.MS_TO_KMH);
@@ -51,7 +51,7 @@ public class SingleColorTrackPathPainter implements TrackPathPainter {
@Override
public void updatePath(Projection projection, Rect viewRect, int startLocationIdx,
Boolean alwaysVisible, List<CachedLocation> points) {
path = new Path();
path = newPath();
updatePath(projection, viewRect, startLocationIdx, alwaysVisible, points, path);
}
@@ -66,6 +66,7 @@ import android.os.PowerManager.WakeLock;
import android.os.Process;
import android.util.Log;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
@@ -777,9 +778,9 @@ public class TrackRecordingService extends Service {
return;
}
} else {
Log.d(TAG, String.format(
"Not recording. Distance to last recorded point (%f m) is less than"
+ " %d m.", distanceToLastRecorded, minRecordingDistance));
Log.d(TAG, String.format(Locale.US,
"Not recording. Distance to last recorded point (%f m) is less than %d m.",
distanceToLastRecorded, minRecordingDistance));
// Return here so that the location is NOT recorded as the last location.
return;
}
@@ -997,7 +998,7 @@ public class TrackRecordingService extends Service {
} else {
int nextMarkerNumber = providerUtils.getNextMarkerNumber(recordingTrackId, true);
name = nextMarkerNumber == -1 ? getString(R.string.marker_type_statistics)
: getString(R.string.marker_statistics_name_format, nextMarkerNumber);
: getString(R.string.marker_split_name_format, nextMarkerNumber);
}
waypoint.setName(name);
waypoint.setStatistics(waypointStatsBuilder.getStatistics());
@@ -33,6 +33,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import java.util.Locale;
/**
* This is the common superclass for ANT-based sensors. It handles tasks which
* apply to the ANT framework as a whole, such as framework initialization and
@@ -279,7 +281,7 @@ public abstract class AntSensorManager extends SensorManager {
*/
protected boolean handleMessage(byte messageId, byte[] messageData) {
if (messageId == AntMesg.MESG_STARTUP_MESG_ID) {
Log.d(TAG, String.format(
Log.d(TAG, String.format(Locale.US,
"Received startup message (reason %02x); initializing channel",
new AntStartupMessage(messageData).getMessage()));
setupAntSensorChannels();
@@ -376,7 +378,7 @@ public abstract class AntSensorManager extends SensorManager {
private String messageToString(byte[] message) {
StringBuilder out = new StringBuilder();
for (byte b : message) {
out.append(String.format("%s%02x", (out.length() == 0 ? "" : " "), b));
out.append(String.format(Locale.US, "%s%02x", (out.length() == 0 ? "" : " "), b));
}
return out.toString();
}
@@ -35,7 +35,7 @@ public class PeriodicTaskExecutor {
* A value greater than zero is a frequency in time.
* A value less than zero is considered a frequency in distance.
*/
private int taskFrequency = PreferencesUtils.PERIODIC_TASK_OFF;
private int taskFrequency = PreferencesUtils.FREQUENCY_OFF;
/**
* The next distance when the task should execute.
@@ -75,7 +75,7 @@ public class PeriodicTaskExecutor {
timerExecutor = null;
}
}
if (taskFrequency == PreferencesUtils.PERIODIC_TASK_OFF) {
if (taskFrequency == PreferencesUtils.FREQUENCY_OFF) {
return;
}
@@ -182,7 +182,7 @@ public class StatusAnnouncerTask implements PeriodicTask {
speed = context.getResources().getQuantityString(speedId, getQuantityCount(s), s);
} else {
int paceId = metricUnits ? R.string.voice_pace_per_kilometer : R.string.voice_pace_per_mile;
speed = String.format(context.getString(paceId), getAnnounceTime((long) s));
speed = context.getString(paceId, getAnnounceTime((long) s));
}
int totalDistanceId = metricUnits ? R.plurals.voiceTotalDistanceKilometers
@@ -36,13 +36,13 @@ public class AbstractSettingsActivity extends PreferenceActivity {
private BackupPreferencesListener backupPreferencesListener;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
ApiAdapterFactory.getApiAdapter().configureActionBarHomeAsUp(this);
@SuppressWarnings("deprecation")
PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setSharedPreferencesName(Constants.SETTINGS_NAME);
preferenceManager.setSharedPreferencesMode(Context.MODE_PRIVATE);
@@ -63,10 +63,10 @@ public class AbstractSettingsActivity extends PreferenceActivity {
return true;
}
@SuppressWarnings("deprecation")
@Override
protected void onDestroy() {
super.onDestroy();
@SuppressWarnings("deprecation")
PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(backupPreferencesListener);
@@ -39,14 +39,6 @@ public class RecordingSettingsActivity extends AbstractSettingsActivity {
boolean metricUnits = PreferencesUtils.getBoolean(
this, R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
ListPreference announcementFrequencyListPreference = (ListPreference) findPreference(
getString(R.string.announcement_frequency_key));
announcementFrequencyListPreference.setEntries(getPeriodicTaskDisplayOptions(metricUnits));
ListPreference splitFrequencyListPreference = (ListPreference) findPreference(
getString(R.string.split_frequency_key));
splitFrequencyListPreference.setEntries(getPeriodicTaskDisplayOptions(metricUnits));
ListPreference minRecordingIntervalListPreference = (ListPreference) findPreference(
getString(R.string.min_recording_interval_key));
minRecordingIntervalListPreference.setEntries(getMinRecordingIntervalDisplayOptions());
@@ -70,28 +62,6 @@ public class RecordingSettingsActivity extends AbstractSettingsActivity {
autoResumeTrackTimeoutListPreference.setEntries(getAutoResumeTrackTimeoutDisplayOptions());
}
/**
* Gets the periodic task display options.
*
* @param metricUnits true to display metric units
*/
private String[] getPeriodicTaskDisplayOptions(boolean metricUnits) {
String[] values = getResources().getStringArray(R.array.periodic_task_values);
String[] options = new String[values.length];
for (int i = 0; i < values.length; i++) {
int value = Integer.parseInt(values[i]);
if (value == PreferencesUtils.PERIODIC_TASK_OFF) {
options[i] = getString(R.string.value_off);
} else if (value < 0) {
options[i] = getString(metricUnits ? R.string.value_integer_kilometer
: R.string.value_integer_mile, Math.abs(value));
} else {
options[i] = getString(R.string.value_integer_minute, value);
}
}
return options;
}
/**
* Gets the min recording interval display options.
*/
@@ -120,8 +120,8 @@ public class SensorSettingsActivity extends AbstractSettingsActivity {
/**
* Updates the bluetooth sensor list preference.
*/
@SuppressWarnings("deprecation")
private void updateBluetoothSensorListPreference() {
@SuppressWarnings("deprecation")
ListPreference bluetoothSensorListPreference = (ListPreference) findPreference(
getString(R.string.bluetooth_sensor_key));
List<String> entries = new ArrayList<String>();
@@ -16,16 +16,23 @@
package com.google.android.apps.mytracks.settings;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.util.DialogUtils;
import com.google.android.maps.mytracks.R;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import java.util.ArrayList;
import java.util.List;
/**
* An activity for accessing the sharing settings.
*
@@ -56,6 +63,21 @@ public class SharingSettingsActivity extends AbstractSettingsActivity {
}
}
});
ListPreference sharingAccountListPreference = (ListPreference) findPreference(
getString(R.string.sharing_account_key));
List<String> entries = new ArrayList<String>();
Account[] accounts = AccountManager.get(this).getAccountsByType(Constants.ACCOUNT_TYPE);
for (Account account : accounts) {
entries.add(account.name);
}
sharingAccountListPreference.setEntries(entries.toArray(new CharSequence[entries.size()]));
sharingAccountListPreference.setEntryValues(entries.toArray(
new CharSequence[entries.size()]));
if (entries.size() == 1) {
sharingAccountListPreference.setValueIndex(0);
}
}
@Override
@@ -17,6 +17,7 @@
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.ContextualActionModeCallback;
import com.google.android.maps.mytracks.R;
import android.annotation.TargetApi;
import android.app.Activity;
@@ -55,7 +56,6 @@ public class Api11Adapter extends Api10Adapter {
@Override
public void configureListViewContextualMenu(final Activity activity, ListView listView,
final int menuId, final int actionModeTitleId,
final ContextualActionModeCallback contextualActionModeCallback) {
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
ActionMode actionMode;
@@ -68,7 +68,7 @@ public class Api11Adapter extends Api10Adapter {
actionMode = activity.startActionMode(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(menuId, menu);
mode.getMenuInflater().inflate(R.menu.list_context_menu, menu);
return true;
}
@Override
@@ -86,7 +86,7 @@ public class Api11Adapter extends Api10Adapter {
return contextualActionModeCallback.onClick(item.getItemId(), position, id);
}
});
TextView textView = (TextView) view.findViewById(actionModeTitleId);
TextView textView = (TextView) view.findViewById(R.id.list_item_name);
if (textView != null) {
actionMode.setTitle(textView.getText());
}
@@ -118,8 +118,8 @@ public class Api7Adapter implements ApiAdapter {
}
@Override
public void configureListViewContextualMenu(Activity activity, ListView listView, int menuId,
int actionModeTitleId, ContextualActionModeCallback contextualActionModeCallback) {
public void configureListViewContextualMenu(Activity activity, ListView listView,
ContextualActionModeCallback contextualActionModeCallback) {
activity.registerForContextMenu(listView);
}
@@ -134,14 +134,11 @@ public interface ApiAdapter {
*
* @param activity the activity
* @param listView the list view
* @param menuId the menu resource id
* @param actionModeTitleId the id of the list view item TextView to be used
* as the action mode title
* @param contextualActionModeCallback the callback when an item is selected
* in the contextual action mode
*/
public void configureListViewContextualMenu(Activity activity, ListView listView, int menuId,
int actionModeTitleId, ContextualActionModeCallback contextualActionModeCallback);
public void configureListViewContextualMenu(Activity activity, ListView listView,
ContextualActionModeCallback contextualActionModeCallback);
/**
* Configures the search widget.
@@ -16,8 +16,18 @@
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.maps.mytracks.R;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import java.io.File;
/**
* Utilities for creating intents.
@@ -26,6 +36,9 @@ import android.content.Intent;
*/
public class IntentUtils {
public static final String TEXT_PLAIN_TYPE = "text/plain";
private static final String TWITTER_PACKAGE_NAME = "com.twitter.android";
private IntentUtils() {}
/**
@@ -39,4 +52,52 @@ public class IntentUtils {
return new Intent(context, cls).addFlags(
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
}
/**
* Creates an intent to share a track url with an app.
*
* @param context the context
* @param trackId the track id
* @param trackUrl the track url
* @param packageName the sharing app package name
* @param className the sharing app class name
*/
public static final Intent newShareUrlIntent(
Context context, long trackId, String trackUrl, String packageName, String className) {
Track track = MyTracksProviderUtils.Factory.get(context).getTrack(trackId);
String trackDescription = track == null ? ""
: new DescriptionGeneratorImpl(context).generateTrackDescription(track, null, null, false);
return new Intent(Intent.ACTION_SEND)
.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.share_track_subject))
.putExtra(Intent.EXTRA_TEXT, TWITTER_PACKAGE_NAME.equals(packageName)
? trackUrl
: context.getString(R.string.share_track_share_url_body, trackUrl, trackDescription))
.setComponent(new ComponentName(packageName, className))
.setType(TEXT_PLAIN_TYPE);
}
/**
* Creates an intent to share a track file with an app.
*
* @param context the context
* @param trackId the track id
* @param filePath the file path
* @param trackFileFormat the track file format
*/
public static final Intent newShareFileIntent(
Context context, long trackId, String filePath, TrackFileFormat trackFileFormat) {
Track track = MyTracksProviderUtils.Factory.get(context).getTrack(trackId);
String trackDescription = track == null ? ""
: new DescriptionGeneratorImpl(context).generateTrackDescription(track, null, null, false);
return new Intent(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filePath)))
.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.share_track_subject))
.putExtra(Intent.EXTRA_TEXT,
context.getString(R.string.share_track_share_file_body, trackDescription))
.putExtra(context.getString(R.string.track_id_broadcast_extra), trackId)
.setType(trackFileFormat.getMimeType());
}
}
@@ -52,6 +52,7 @@ public class PreferencesUtils {
public static final String DEFAULT_ACTIVITY_DEFAULT = "";
public static final boolean DEFAULT_MAP_PUBLIC_DEFAULT = true;
public static final int FREQUENCY_OFF = 0;
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;
@@ -64,16 +65,14 @@ public class PreferencesUtils {
public static final int MIN_REQUIRED_ACCURACY_EXCELLENT = 10;
public static final int MIN_REQUIRED_ACCURACY_POOR = 5000;
public static final int PERIODIC_TASK_OFF = 0;
public static final boolean PICK_EXISTING_MAP_DEFAULT = false;
public static final String PREFERRED_ACCOUNT_DEFAULT = "";
public static final long RECORDING_TRACK_ID_DEFAULT = -1L;
public static final boolean REPORT_SPEED_DEFAULT = true;
public static final long SELECTED_TRACK_ID_DEFAULT = -1L;
public static final boolean SEND_TO_DOCS_DEFAULT = true;
public static final boolean SEND_TO_FUSION_TABLES_DEFAULT = true;
public static final boolean SEND_TO_MAPS_DEFAULT = true;
public static final boolean SHARE_URL_ONLY_DEFAULT = false;
public static final String SHARING_ACCOUNT_DEFAULT = "";
public static final boolean SHOW_CHECK_UNITS_DIALOG_DEFAULT = true;
public static final boolean SHOW_WELCOME_DIALOG_DEFAULT = true;
public static final int SPLIT_FREQUENCY_DEFAULT = 0;
@@ -31,9 +31,10 @@ public interface DescriptionGenerator {
* @param track the track
* @param distances a vector of distances to generate the elevation chart
* @param elevations a vector of elevations to generate the elevation chart
* @param html true to output html, false to output plain text
*/
public String generateTrackDescription(
Track track, Vector<Double> distances, Vector<Double> elevations);
Track track, Vector<Double> distances, Vector<Double> elevations, boolean html);
/**
* Generate a waypoint description.
@@ -911,15 +911,13 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
String selection;
String[] selectionArgs;
if (minWaypointId > 0) {
selection = String.format("%s = ? AND %s >= ?",
WaypointsColumns.TRACKID,
WaypointsColumns._ID);
selection = WaypointsColumns.TRACKID + "=? AND " + WaypointsColumns._ID + ">=?";
selectionArgs = new String[] {
Long.toString(trackId),
Long.toString(minWaypointId)
};
} else {
selection = String.format("%s=?", WaypointsColumns.TRACKID);
selection = WaypointsColumns.TRACKID + "=?";
selectionArgs = new String[] { Long.toString(trackId) };
}
@@ -40,7 +40,7 @@ public class DescriptionGeneratorImplTest extends AndroidTestCase {
/**
* Tests {@link DescriptionGeneratorImpl#generateTrackDescription(Track,
* java.util.Vector, java.util.Vector)}.
* java.util.Vector, java.util.Vector, boolean)}.
*/
public void testGenerateTrackDescription() {
Track track = new Track();
@@ -59,6 +59,9 @@ public class DescriptionGeneratorImplTest extends AndroidTestCase {
track.setCategory("hiking");
String expected = "Created by"
+ " <a href='http://www.google.com/mobile/mytracks'>My Tracks</a> on Android.<p>"
+ "Name: -<br>"
+ "Activity type: hiking<br>"
+ "Description: -<br>"
+ "Total distance: 20.00 km (12.4 mi)<br>"
+ "Total time: 10:00<br>"
+ "Moving time: 05:00<br>"
@@ -73,9 +76,8 @@ public class DescriptionGeneratorImplTest extends AndroidTestCase {
+ "Elevation gain: 6000 m (19685 ft)<br>"
+ "Max grade: 42 %<br>"
+ "Min grade: 11 %<br>"
+ "Recorded: " + StringUtils.formatDateTime(getContext(), START_TIME) + "<br>"
+ "Activity type: hiking<br>";
assertEquals(expected, descriptionGenerator.generateTrackDescription(track, null, null));
+ "Recorded: " + StringUtils.formatDateTime(getContext(), START_TIME) + "<br>";
assertEquals(expected, descriptionGenerator.generateTrackDescription(track, null, null, true));
}
/**
@@ -43,7 +43,7 @@ public class KmlTrackWriterTest extends TrackFormatWriterTest {
private class FakeDescriptionGenerator implements DescriptionGenerator {
@Override
public String generateTrackDescription(
Track aTrack, Vector<Double> distances, Vector<Double> elevations) {
Track aTrack, Vector<Double> distances, Vector<Double> elevations, boolean html) {
return FULL_TRACK_DESCRIPTION;
}
@@ -34,7 +34,7 @@ public class SendFusionTablesActivityTest extends AndroidTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
sendRequest = new SendRequest(1L, true, false, true);
sendRequest = new SendRequest(1L);
sendFusionTablesActivity = new SendFusionTablesActivity();
}
@@ -35,7 +35,7 @@ public class SendMapsActivityTest extends AndroidTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
sendRequest = new SendRequest(1L, true, false, true);
sendRequest = new SendRequest(1L);
sendMapsActivity = new SendMapsActivity();
}
@@ -86,7 +86,7 @@ public class SendMapsAsyncTaskTest extends AndroidTestCase {
prepareAndUploadPointsCounter = 0;
sendMapsActivityMock = AndroidMock.createMock(SendMapsActivity.class);
myTracksProviderUtilsMock = AndroidMock.createMock(MyTracksProviderUtils.class);
sendRequest = new SendRequest(TRACK_ID, false, true, false);
sendRequest = new SendRequest(TRACK_ID);
AndroidMock.expect(sendMapsActivityMock.getApplicationContext()).andReturn(getContext());
}
@@ -35,7 +35,7 @@ public class SendRequestTest extends AndroidTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
sendRequest = new SendRequest(1, true, true, true);
sendRequest = new SendRequest(1);
}
/**
@@ -46,44 +46,6 @@ public class SendRequestTest extends AndroidTestCase {
assertEquals(1, sendRequest.getTrackId());
}
/**
* Tests the method {@link SendRequest#isShowMaps()}. The value should be set
* to true when it is initialed in setup method.
*/
public void testIsShowMaps() {
assertEquals(true, sendRequest.isShowMaps());
}
/**
* Tests the method {@link SendRequest#isShowFusionTables()}. The value should
* be set to true when it is initialed in setup method.
*/
public void testIsShowFusionTables() {
assertEquals(true, sendRequest.isShowFusionTables());
}
/**
* Tests the method {@link SendRequest#isShowDocs()}. The value should be set
* to true when it is initialed in setup method.
*/
public void testIsShowDocs() {
assertEquals(true, sendRequest.isShowDocs());
}
public void testIsShowAll() {
assertEquals(true, sendRequest.isShowAll());
sendRequest = new SendRequest(1, false, true, true);
assertEquals(false, sendRequest.isShowAll());
sendRequest = new SendRequest(1, true, false, true);
assertEquals(false, sendRequest.isShowAll());
sendRequest = new SendRequest(1, true, true, false);
assertEquals(false, sendRequest.isShowAll());
sendRequest = new SendRequest(1, false, true, false);
assertEquals(false, sendRequest.isShowAll());
sendRequest = new SendRequest(1, false, false, false);
assertEquals(false, sendRequest.isShowAll());
}
public void testIsSendMaps() {
assertEquals(false, sendRequest.isSendMaps());
sendRequest.setSendMaps(true);
@@ -174,120 +136,114 @@ public class SendRequestTest extends AndroidTestCase {
* Tests SendRequest.CREATOR.createFromParcel when all values are true.
*/
public void testCreateFromParcel_true() {
Parcel sourceParcel = Parcel.obtain();
sourceParcel.setDataPosition(0);
sourceParcel.writeLong(2);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
parcel.writeLong(2);
parcel.writeString("");
parcel.writeString("");
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
sourceParcel.writeParcelable(account, 0);
sourceParcel.writeString(MAPID);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
sourceParcel.writeByte((byte) 1);
sourceParcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(sourceParcel);
parcel.writeParcelable(account, 0);
parcel.writeString(MAPID);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
assertEquals(2, sendRequest.getTrackId());
assertEquals(true, sendRequest.isShowMaps());
assertEquals(true, sendRequest.isShowFusionTables());
assertEquals(true, sendRequest.isShowDocs());
assertEquals(true, sendRequest.isSendMaps());
assertEquals(true, sendRequest.isSendFusionTables());
assertEquals(true, sendRequest.isSendDocs());
assertEquals(true, sendRequest.isNewMap());
assertEquals("", sendRequest.getSharingAppPackageName());
assertEquals("", sendRequest.getSharingAppClassName());
assertTrue(sendRequest.isSendMaps());
assertTrue(sendRequest.isSendFusionTables());
assertTrue(sendRequest.isSendDocs());
assertTrue(sendRequest.isNewMap());
assertEquals(account, sendRequest.getAccount());
assertEquals(MAPID, sendRequest.getMapId());
assertEquals(true, sendRequest.isMapsSuccess());
assertEquals(true, sendRequest.isFusionTablesSuccess());
assertEquals(true, sendRequest.isDocsSuccess());
assertTrue(sendRequest.isMapsSuccess());
assertTrue(sendRequest.isFusionTablesSuccess());
assertTrue(sendRequest.isDocsSuccess());
}
/**
* Tests SendRequest.CREATOR.createFromParcel when all values are false.
*/
public void testCreateFromParcel_false() {
Parcel sourceParcel = Parcel.obtain();
sourceParcel.setDataPosition(0);
sourceParcel.writeLong(4);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
parcel.writeLong(4);
parcel.writeString(null);
parcel.writeString(null);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
sourceParcel.writeParcelable(account, 0);
sourceParcel.writeString(MAPID);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
sourceParcel.writeByte((byte) 0);
sourceParcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(sourceParcel);
parcel.writeParcelable(account, 0);
parcel.writeString(MAPID);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
assertEquals(4, sendRequest.getTrackId());
assertEquals(false, sendRequest.isShowMaps());
assertEquals(false, sendRequest.isShowFusionTables());
assertEquals(false, sendRequest.isShowDocs());
assertEquals(false, sendRequest.isSendMaps());
assertEquals(false, sendRequest.isSendFusionTables());
assertEquals(false, sendRequest.isSendDocs());
assertEquals(false, sendRequest.isNewMap());
assertNull(sendRequest.getSharingAppPackageName());
assertNull(sendRequest.getSharingAppClassName());
assertFalse(sendRequest.isSendMaps());
assertFalse(sendRequest.isSendFusionTables());
assertFalse(sendRequest.isSendDocs());
assertFalse(sendRequest.isNewMap());
assertEquals(account, sendRequest.getAccount());
assertEquals(MAPID, sendRequest.getMapId());
assertEquals(false, sendRequest.isMapsSuccess());
assertEquals(false, sendRequest.isFusionTablesSuccess());
assertEquals(false, sendRequest.isDocsSuccess());
assertFalse(sendRequest.isMapsSuccess());
assertFalse(sendRequest.isFusionTablesSuccess());
assertFalse(sendRequest.isDocsSuccess());
}
/**
* Tests {@link SendRequest#writeToParcel(Parcel, int)} when all input values
* are true or affirmative.
* Tests {@link SendRequest#writeToParcel(Parcel, int)} with default values.
*/
public void testWriteToParcel_allTrue() {
sendRequest = new SendRequest(1, false, false, false);
Parcel parcelWrite1st = Parcel.obtain();
parcelWrite1st.setDataPosition(0);
sendRequest.writeToParcel(parcelWrite1st, 1);
parcelWrite1st.setDataPosition(0);
long trackId = parcelWrite1st.readLong();
boolean showMaps = parcelWrite1st.readByte() == 1;
boolean showFusionTables = parcelWrite1st.readByte() == 1;
boolean showDocs = parcelWrite1st.readByte() == 1;
boolean sendMaps = parcelWrite1st.readByte() == 1;
boolean sendFusionTables = parcelWrite1st.readByte() == 1;
boolean sendDocs = parcelWrite1st.readByte() == 1;
boolean newMap = parcelWrite1st.readByte() == 1;
Parcelable account = parcelWrite1st.readParcelable(null);
String mapId = parcelWrite1st.readString();
boolean mapsSuccess = parcelWrite1st.readByte() == 1;
boolean fusionTablesSuccess = parcelWrite1st.readByte() == 1;
boolean docsSuccess = parcelWrite1st.readByte() == 1;
public void testWriteToParcel_default() {
sendRequest = new SendRequest(1);
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
sendRequest.writeToParcel(parcel, 1);
parcel.setDataPosition(0);
long trackId = parcel.readLong();
String sharingAppPackageName = parcel.readString();
String sharingAppClassName = parcel.readString();
boolean sendMaps = parcel.readByte() == 1;
boolean sendFusionTables = parcel.readByte() == 1;
boolean sendDocs = parcel.readByte() == 1;
boolean newMap = parcel.readByte() == 1;
Parcelable account = parcel.readParcelable(null);
String mapId = parcel.readString();
boolean mapsSuccess = parcel.readByte() == 1;
boolean fusionTablesSuccess = parcel.readByte() == 1;
boolean docsSuccess = parcel.readByte() == 1;
assertEquals(1, trackId);
assertEquals(false, showMaps);
assertEquals(false, showFusionTables);
assertEquals(false, showDocs);
assertEquals(false, sendMaps);
assertEquals(false, sendFusionTables);
assertEquals(false, sendDocs);
assertEquals(false, newMap);
assertEquals(null, account);
assertEquals(null, mapId);
assertEquals(false, mapsSuccess);
assertEquals(false, fusionTablesSuccess);
assertEquals(false, docsSuccess);
assertNull(sharingAppPackageName);
assertNull(sharingAppClassName);
assertFalse(sendMaps);
assertFalse(sendFusionTables);
assertFalse(sendDocs);
assertFalse(newMap);
assertNull(account);
assertNull(mapId);
assertFalse(mapsSuccess);
assertFalse(fusionTablesSuccess);
assertFalse(docsSuccess);
}
/**
* Tests {@link SendRequest#writeToParcel(Parcel, int)} when all input values
* are false or negative.
* Tests {@link SendRequest#writeToParcel(Parcel, int)}.
*/
public void testWriteToParcel_allFalse() {
sendRequest = new SendRequest(4, true, true, true);
public void testWriteToParcel() {
sendRequest = new SendRequest(4);
sendRequest.setSharingAppPackageName("package");
sendRequest.setSharingAppClassName("class");
sendRequest.setSendMaps(true);
sendRequest.setSendFusionTables(true);
sendRequest.setSendDocs(true);
@@ -298,36 +254,33 @@ public class SendRequestTest extends AndroidTestCase {
sendRequest.setMapsSuccess(true);
sendRequest.setFusionTablesSuccess(true);
sendRequest.setDocsSuccess(true);
Parcel parcelWrite2nd = Parcel.obtain();
parcelWrite2nd.setDataPosition(0);
sendRequest.writeToParcel(parcelWrite2nd, 1);
parcelWrite2nd.setDataPosition(0);
long trackId = parcelWrite2nd.readLong();
boolean showMaps = parcelWrite2nd.readByte() == 1;
boolean showFusionTables = parcelWrite2nd.readByte() == 1;
boolean showDocs = parcelWrite2nd.readByte() == 1;
boolean sendMaps = parcelWrite2nd.readByte() == 1;
boolean sendFusionTables = parcelWrite2nd.readByte() == 1;
boolean sendDocs = parcelWrite2nd.readByte() == 1;
boolean newMap = parcelWrite2nd.readByte() == 1;
Parcelable account = parcelWrite2nd.readParcelable(null);
String mapId = parcelWrite2nd.readString();
boolean mapsSuccess = parcelWrite2nd.readByte() == 1;
boolean fusionTablesSuccess = parcelWrite2nd.readByte() == 1;
boolean docsSuccess = parcelWrite2nd.readByte() == 1;
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
sendRequest.writeToParcel(parcel, 1);
parcel.setDataPosition(0);
long trackId = parcel.readLong();
String sharingAppPackageName = parcel.readString();
String sharingAppClassName = parcel.readString();
boolean sendMaps = parcel.readByte() == 1;
boolean sendFusionTables = parcel.readByte() == 1;
boolean sendDocs = parcel.readByte() == 1;
boolean newMap = parcel.readByte() == 1;
Parcelable account = parcel.readParcelable(null);
String mapId = parcel.readString();
boolean mapsSuccess = parcel.readByte() == 1;
boolean fusionTablesSuccess = parcel.readByte() == 1;
boolean docsSuccess = parcel.readByte() == 1;
assertEquals(4, trackId);
assertEquals(true, showMaps);
assertEquals(true, showFusionTables);
assertEquals(true, showDocs);
assertEquals(true, sendMaps);
assertEquals(true, sendFusionTables);
assertEquals(true, sendDocs);
assertEquals(true, newMap);
assertEquals("package", sharingAppPackageName);
assertEquals("class", sharingAppClassName);
assertTrue(sendMaps);
assertTrue(sendFusionTables);
assertTrue(sendDocs);
assertTrue(newMap);
assertEquals(accountNew, account);
assertEquals(MAPID, mapId);
assertEquals(true, mapsSuccess);
assertEquals(true, fusionTablesSuccess);
assertEquals(true, docsSuccess);
assertTrue(mapsSuccess);
assertTrue(fusionTablesSuccess);
assertTrue(docsSuccess);
}
}
@@ -97,7 +97,7 @@ public class UploadResultActivityTest
private void initialActivity(boolean isSendMaps, boolean isSendFusionTables, boolean isSendDocs,
boolean isMapsSuccess, boolean isFusionTablesSuccess, boolean isDocsSuccess) {
Intent intent = new Intent();
SendRequest sendRequest = new SendRequest(1L, true, true, true);
SendRequest sendRequest = new SendRequest(1L);
sendRequest.setSendMaps(isSendMaps);
sendRequest.setSendFusionTables(isSendFusionTables);
sendRequest.setSendDocs(isSendDocs);
@@ -1,257 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.io.sendtogoogle;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.CheckBox;
import android.widget.RadioButton;
/**
* Tests the {@link UploadServiceChooserActivity}.
*
* @author Youtao Liu
*/
public class UploadServiceChooserActivityTest extends
ActivityInstrumentationTestCase2<UploadServiceChooserActivity> {
private Instrumentation instrumentation;
private UploadServiceChooserActivity uploadServiceChooserActivity;
public UploadServiceChooserActivityTest() {
super(UploadServiceChooserActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
}
/**
* Tests the logic to display all options.
*/
public void testOnCreateDialog_displayAll() {
// Initials activity to display all send items.
initialActivity(true, true, true);
instrumentation.waitForIdleSync();
assertTrue(getMapsCheckBox().isShown());
assertTrue(getFusionTablesCheckBox().isShown());
assertTrue(getDocsCheckBox().isShown());
// Clicks to disable all send items.
uploadServiceChooserActivity.runOnUiThread(new Runnable() {
public void run() {
if (getMapsCheckBox().isChecked()) {
getMapsCheckBox().performClick();
}
if (getFusionTablesCheckBox().isChecked()) {
getFusionTablesCheckBox().performClick();
}
if (getDocsCheckBox().isChecked()) {
getDocsCheckBox().performClick();
}
}
});
instrumentation.waitForIdleSync();
assertTrue(getMapsCheckBox().isShown());
assertTrue(getFusionTablesCheckBox().isShown());
assertTrue(getDocsCheckBox().isShown());
assertFalse(getNewMapRadioButton().isShown());
assertFalse(getExistingMapRadioButton().isShown());
}
/**
* Tests the logic to display only the "Send to Google Maps" option.
*/
public void testOnCreateDialog_displayOne() {
// Initials activity to display all send items.
initialActivity(true, false, false);
instrumentation.waitForIdleSync();
assertTrue(getMapsCheckBox().isShown());
// Clicks to enable this items.
uploadServiceChooserActivity.runOnUiThread(new Runnable() {
public void run() {
if (!getMapsCheckBox().isChecked()) {
getMapsCheckBox().performClick();
}
}
});
instrumentation.waitForIdleSync();
assertTrue(getMapsCheckBox().isShown());
assertTrue(getNewMapRadioButton().isShown());
assertTrue(getExistingMapRadioButton().isShown());
}
/**
* Tests the logic to display no option.
*/
public void testOnCreateDialog_displayNone() {
initialActivity(false, false, false);
assertFalse(getMapsCheckBox().isShown());
assertFalse(getFusionTablesCheckBox().isShown());
assertFalse(getDocsCheckBox().isShown());
}
/**
* Tests the logic to initial state of check box to unchecked. This test cover
* code in method {@link UploadServiceChooserActivity#onCreateDialog(int)},
* {@link UploadServiceChooserActivity#initState()}.
*/
public void testOnCreateDialog_initStateUnchecked() {
initialActivity(true, true, true);
// Initial all values to false in SharedPreferences.
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_maps_key, false);
PreferencesUtils.setBoolean(
uploadServiceChooserActivity, R.string.send_to_fusion_tables_key, false);
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_docs_key, false);
uploadServiceChooserActivity.runOnUiThread(new Runnable() {
public void run() {
uploadServiceChooserActivity.initState();
}
});
instrumentation.waitForIdleSync();
assertFalse(getMapsCheckBox().isChecked());
assertFalse(getFusionTablesCheckBox().isChecked());
assertFalse(getDocsCheckBox().isChecked());
}
/**
* Tests the logic to initial state of check box to checked. This test cover
* code in method {@link UploadServiceChooserActivity#onCreateDialog(int)},
* {@link UploadServiceChooserActivity#initState()}.
*/
public void testOnCreateDialog_initStateChecked() {
initialActivity(true, true, true);
// Initial all values to true in SharedPreferences.
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.pick_existing_map_key, true);
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_maps_key, true);
PreferencesUtils.setBoolean(
uploadServiceChooserActivity, R.string.send_to_fusion_tables_key, true);
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_docs_key, true);
uploadServiceChooserActivity.runOnUiThread(new Runnable() {
public void run() {
uploadServiceChooserActivity.initState();
}
});
instrumentation.waitForIdleSync();
assertTrue(getMapsCheckBox().isChecked());
assertTrue(getFusionTablesCheckBox().isChecked());
assertTrue(getDocsCheckBox().isChecked());
assertTrue(getExistingMapRadioButton().isChecked());
assertFalse(getNewMapRadioButton().isChecked());
}
/**
* Tests the logic of saveState when click send button. This test cover code
* in method {@link UploadServiceChooserActivity#initState()} and
* {@link UploadServiceChooserActivity#saveState()},
*/
public void testOnCreateDialog_saveState() {
initialActivity(true, true, true);
// Initial all values to true in SharedPreferences.
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_maps_key, true);
PreferencesUtils.setBoolean(
uploadServiceChooserActivity, R.string.send_to_fusion_tables_key, true);
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_docs_key, true);
uploadServiceChooserActivity.runOnUiThread(new Runnable() {
public void run() {
uploadServiceChooserActivity.initState();
}
});
instrumentation.waitForIdleSync();
uploadServiceChooserActivity.saveState();
// All values in SharedPreferences must be changed.
assertTrue(PreferencesUtils.getBoolean(uploadServiceChooserActivity, R.string.send_to_maps_key,
PreferencesUtils.SEND_TO_MAPS_DEFAULT));
assertTrue(PreferencesUtils.getBoolean(
uploadServiceChooserActivity, R.string.send_to_fusion_tables_key,
PreferencesUtils.SEND_TO_FUSION_TABLES_DEFAULT));
assertTrue(PreferencesUtils.getBoolean(uploadServiceChooserActivity, R.string.send_to_docs_key,
PreferencesUtils.SEND_TO_DOCS_DEFAULT));
}
/**
* Tests the logic of startNextActivity when click send button. This test
* cover code in method {@link UploadServiceChooserActivity#initState()} and
* {@link UploadServiceChooserActivity#startNextActivity()}.
*/
public void testOnCreateDialog_startNextActivity() {
initialActivity(true, true, true);
// Initial all values to true or false in SharedPreferences.
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_maps_key, true);
PreferencesUtils.setBoolean(uploadServiceChooserActivity, R.string.send_to_docs_key, true);
PreferencesUtils.setBoolean(
uploadServiceChooserActivity, R.string.send_to_fusion_tables_key, false);
uploadServiceChooserActivity.runOnUiThread(new Runnable() {
public void run() {
uploadServiceChooserActivity.initState();
}
});
instrumentation.waitForIdleSync();
uploadServiceChooserActivity.startNextActivity();
// All values in SendRequest must be same as set above.
assertTrue(uploadServiceChooserActivity.getSendRequest().isSendMaps());
assertTrue(uploadServiceChooserActivity.getSendRequest().isSendDocs());
assertFalse(uploadServiceChooserActivity.getSendRequest().isSendFusionTables());
}
/**
* Initials a activity to be tested.
*
* @param showMaps
* @param showFusionTables
* @param showDocs
*/
private void initialActivity(boolean showMaps, boolean showFusionTables, boolean showDocs) {
Intent intent = new Intent();
intent.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(1L, showMaps, showFusionTables,
showDocs));
setActivityIntent(intent);
uploadServiceChooserActivity = this.getActivity();
}
private CheckBox getMapsCheckBox() {
return (CheckBox) uploadServiceChooserActivity.getAlertDialog().findViewById(R.id.send_google_maps);
}
private CheckBox getFusionTablesCheckBox() {
return (CheckBox) uploadServiceChooserActivity.getAlertDialog().findViewById(
R.id.send_google_fusion_tables);
}
private CheckBox getDocsCheckBox() {
return (CheckBox) uploadServiceChooserActivity.getAlertDialog().findViewById(R.id.send_google_docs);
}
private RadioButton getNewMapRadioButton() {
return (RadioButton) uploadServiceChooserActivity.getAlertDialog().findViewById(
R.id.send_google_new_map);
}
private RadioButton getExistingMapRadioButton() {
return (RadioButton) uploadServiceChooserActivity.getAlertDialog().findViewById(
R.id.send_google_existing_map);
}
}
@@ -502,7 +502,7 @@ public class TrackRecordingServiceTest extends ServiceTestCase<TestRecordingServ
Waypoint wpt = providerUtils.getWaypoint(2);
assertEquals(getContext().getString(R.string.marker_statistics_icon_url), wpt.getIcon());
assertEquals(getContext().getString(R.string.marker_statistics_name_format, 1), wpt.getName());
assertEquals(getContext().getString(R.string.marker_split_name_format, 1), wpt.getName());
assertEquals(Waypoint.TYPE_STATISTICS, wpt.getType());
assertEquals(123L, wpt.getTrackId());
assertEquals(0.0, wpt.getLength());