Move the track context menu to the main menu.
Use sharedPreferenceChangeListener to listen when a new recording has started to update the view like the action items.
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
@@ -59,23 +59,4 @@ limitations under the License.
|
|||||||
android:minHeight="80dp"
|
android:minHeight="80dp"
|
||||||
android:layout_gravity="center"/>
|
android:layout_gravity="center"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:paddingTop="10dp">
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width = "wrap_content"
|
|
||||||
android:layout_height= "wrap_content"
|
|
||||||
android:layout_weight="1"/>
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/showOptions"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0"
|
|
||||||
android:visibility="visible"
|
|
||||||
android:src="@android:drawable/ic_menu_more"/>
|
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@@ -15,43 +15,74 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
<item
|
|
||||||
android:icon="@drawable/menu_record_track"
|
|
||||||
android:id="@+id/menu_record_track"
|
|
||||||
android:showAsAction="always"
|
|
||||||
android:title="@string/menu_record_track"/>
|
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/menu_stop_recording"
|
android:icon="@drawable/menu_stop_recording"
|
||||||
android:id="@+id/menu_stop_recording"
|
android:id="@+id/menu_stop_recording"
|
||||||
android:showAsAction="always"
|
android:showAsAction="always"
|
||||||
android:title="@string/menu_stop_recording"/>
|
android:title="@string/menu_stop_recording"/>
|
||||||
|
<item
|
||||||
|
android:icon="@drawable/menu_insert_marker"
|
||||||
|
android:id="@+id/menu_insert_marker"
|
||||||
|
android:showAsAction="always"
|
||||||
|
android:title="@string/menu_insert_marker"/>
|
||||||
|
<item
|
||||||
|
android:icon="@drawable/menu_play"
|
||||||
|
android:id="@+id/menu_play"
|
||||||
|
android:showAsAction="always"
|
||||||
|
android:title="@string/menu_play"/>
|
||||||
|
<item
|
||||||
|
android:icon="@drawable/menu_share"
|
||||||
|
android:id="@+id/menu_share"
|
||||||
|
android:showAsAction="always"
|
||||||
|
android:title="@string/menu_share">
|
||||||
|
<menu>
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_share_map"
|
||||||
|
android:title="@string/menu_share_map"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_share_fusion_table"
|
||||||
|
android:title="@string/menu_share_fusion_table"/>
|
||||||
|
<item android:id="@+id/menu_share_gpx"/>
|
||||||
|
<item android:id="@+id/menu_share_kml"/>
|
||||||
|
<item android:id="@+id/menu_share_csv"/>
|
||||||
|
<item android:id="@+id/menu_share_tcx"/>
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/ic_menu_waypoints"
|
android:icon="@drawable/ic_menu_waypoints"
|
||||||
android:id="@+id/menu_markers"
|
android:id="@+id/menu_markers"
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
android:title="@string/menu_markers"/>
|
android:title="@string/menu_markers"/>
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/ic_menu_chartsettings"
|
android:id="@+id/menu_send_google"
|
||||||
android:id="@+id/menu_chart_settings"
|
android:title="@string/menu_send_google"/>
|
||||||
android:showAsAction="ifRoom"
|
<item
|
||||||
android:title="@string/menu_chart_settings"
|
android:id="@+id/menu_save"
|
||||||
android:visible="false"/>
|
android:title="@string/menu_save">
|
||||||
|
<menu>
|
||||||
|
<item android:id="@+id/menu_save_gpx"/>
|
||||||
|
<item android:id="@+id/menu_save_kml"/>
|
||||||
|
<item android:id="@+id/menu_save_csv"/>
|
||||||
|
<item android:id="@+id/menu_save_tcx"/>
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_edit"
|
||||||
|
android:title="@string/menu_edit"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_delete"
|
||||||
|
android:title="@string/menu_delete"/>
|
||||||
<item
|
<item
|
||||||
android:icon="@android:drawable/ic_menu_mylocation"
|
android:icon="@android:drawable/ic_menu_mylocation"
|
||||||
android:id="@+id/menu_my_location"
|
android:id="@+id/menu_my_location"
|
||||||
android:showAsAction="ifRoom"
|
android:title="@string/menu_my_location"/>
|
||||||
android:title="@string/menu_my_location"
|
|
||||||
android:visible="false"/>
|
|
||||||
<item
|
<item
|
||||||
android:icon="@android:drawable/ic_menu_mapmode"
|
android:icon="@android:drawable/ic_menu_mapmode"
|
||||||
android:id="@+id/menu_satellite_mode"
|
android:id="@+id/menu_satellite_mode"
|
||||||
android:showAsAction="ifRoom"
|
android:title="@string/menu_satellite_mode"/>
|
||||||
android:title="@string/menu_satellite_mode"
|
|
||||||
android:visible="false"/>
|
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/menu_search"
|
android:icon="@drawable/ic_menu_chartsettings"
|
||||||
android:id="@+id/menu_search"
|
android:id="@+id/menu_chart_settings"
|
||||||
android:title="@string/menu_search"/>
|
android:title="@string/menu_chart_settings"/>
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/ic_menu_sensorstatus"
|
android:icon="@drawable/ic_menu_sensorstatus"
|
||||||
android:id="@+id/menu_sensor_state"
|
android:id="@+id/menu_sensor_state"
|
||||||
@@ -60,9 +91,6 @@ limitations under the License.
|
|||||||
android:icon="@drawable/menu_settings"
|
android:icon="@drawable/menu_settings"
|
||||||
android:id="@+id/menu_settings"
|
android:id="@+id/menu_settings"
|
||||||
android:title="@string/menu_settings"/>
|
android:title="@string/menu_settings"/>
|
||||||
<item
|
|
||||||
android:id="@+id/menu_aggregated_statistics"
|
|
||||||
android:title="@string/menu_aggregated_statistics"/>
|
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/menu_help"
|
android:icon="@drawable/menu_help"
|
||||||
android:id="@+id/menu_help"
|
android:id="@+id/menu_help"
|
||||||
|
|||||||
@@ -977,10 +977,25 @@ limitations under the License.
|
|||||||
translation_description="In the menu, to delete all the tracks.">
|
translation_description="In the menu, to delete all the tracks.">
|
||||||
Delete all
|
Delete all
|
||||||
</string>
|
</string>
|
||||||
|
<string name="menu_delete"
|
||||||
|
translation_description="In the menu, to delete a track or a marker.">
|
||||||
|
Delete
|
||||||
|
</string>
|
||||||
|
<string name="menu_edit"
|
||||||
|
translation_description="In the menu, to edit a track or a marker.">
|
||||||
|
Edit
|
||||||
|
</string>
|
||||||
<string name="menu_export_all"
|
<string name="menu_export_all"
|
||||||
translation_description="In the menu, to export all the tracks to the SD card.">
|
translation_description="In the menu, to export all the tracks to the SD card.">
|
||||||
Export all
|
Export all
|
||||||
</string>
|
</string>
|
||||||
|
<string name="menu_export_all_format"
|
||||||
|
translation_description="Under the 'Export all' menu option, the option to export all tracks as
|
||||||
|
a certain file format.
|
||||||
|
|
||||||
|
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.">
|
||||||
|
Export as %1$s
|
||||||
|
</string>
|
||||||
<string name="menu_help"
|
<string name="menu_help"
|
||||||
translation_description="In the menu, to go to the help page.">
|
translation_description="In the menu, to go to the help page.">
|
||||||
Help
|
Help
|
||||||
@@ -989,6 +1004,10 @@ limitations under the License.
|
|||||||
translation_description="In the menu, to import all the tracks from the SD card.">
|
translation_description="In the menu, to import all the tracks from the SD card.">
|
||||||
Import all
|
Import all
|
||||||
</string>
|
</string>
|
||||||
|
<string name="menu_insert_marker"
|
||||||
|
translation_description="In the menu, to insert a marker.">
|
||||||
|
Insert marker
|
||||||
|
</string>
|
||||||
<string name="menu_map_mode"
|
<string name="menu_map_mode"
|
||||||
translation_description="In the menu, to switch the display to the map mode.">
|
translation_description="In the menu, to switch the display to the map mode.">
|
||||||
Map mode
|
Map mode
|
||||||
@@ -1001,6 +1020,10 @@ limitations under the License.
|
|||||||
translation_description="In the menu, to display the user's current location.">
|
translation_description="In the menu, to display the user's current location.">
|
||||||
My location
|
My location
|
||||||
</string>
|
</string>
|
||||||
|
<string name="menu_play"
|
||||||
|
translation_description="In the menu, to play a track.">
|
||||||
|
Play
|
||||||
|
</string>
|
||||||
<string name="menu_record_track"
|
<string name="menu_record_track"
|
||||||
translation_description="In the menu, to start recording a track.">
|
translation_description="In the menu, to start recording a track.">
|
||||||
Record track
|
Record track
|
||||||
@@ -1009,10 +1032,25 @@ limitations under the License.
|
|||||||
translation_description="In the menu, to switch the display to the satellite mode.">
|
translation_description="In the menu, to switch the display to the satellite mode.">
|
||||||
Satellite mode
|
Satellite mode
|
||||||
</string>
|
</string>
|
||||||
|
<string name="menu_save"
|
||||||
|
translation_description="In the menu, to save a track to the SD card.">
|
||||||
|
Save to SD card...
|
||||||
|
</string>
|
||||||
|
<string name="menu_save_format"
|
||||||
|
translation_description="Under the 'Save to SD card...' menu option, the option to save a track
|
||||||
|
as a certain file format.
|
||||||
|
|
||||||
|
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.">
|
||||||
|
As a %1$s file
|
||||||
|
</string>
|
||||||
<string name="menu_search"
|
<string name="menu_search"
|
||||||
translation_description="In the menu, to start a textual search for tracks or waypoints.">
|
translation_description="In the menu, to start a textual search for tracks or waypoints.">
|
||||||
Search
|
Search
|
||||||
</string>
|
</string>
|
||||||
|
<string name="menu_send_google"
|
||||||
|
translation_description="In the menu, to send a track to Google.">
|
||||||
|
Send to Google...
|
||||||
|
</string>
|
||||||
<string name="menu_sensor_state"
|
<string name="menu_sensor_state"
|
||||||
translation_description="In the menu, to go to the sensor state page.">
|
translation_description="In the menu, to go to the sensor state page.">
|
||||||
Sensor state
|
Sensor state
|
||||||
@@ -1025,7 +1063,31 @@ limitations under the License.
|
|||||||
translation_description="In the menu, to stop recording a track.">
|
translation_description="In the menu, to stop recording a track.">
|
||||||
Stop recording
|
Stop recording
|
||||||
</string>
|
</string>
|
||||||
|
<string name="menu_share"
|
||||||
|
translation_description="In the menu, to share a track with friends through other
|
||||||
|
applications.">
|
||||||
|
Share with friends...
|
||||||
|
</string>
|
||||||
|
<string name="menu_share_file"
|
||||||
|
translation_description="Under the 'Share with friends...' menu option, the option to share a
|
||||||
|
track as a certain file format.
|
||||||
|
|
||||||
|
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.">
|
||||||
|
A %1$s file
|
||||||
|
</string>
|
||||||
|
<string name="menu_share_fusion_table"
|
||||||
|
translation_description="Under the 'Share with friends...' menu option, the option to save a
|
||||||
|
track to Google Fusion Tables and share the Fusion Table url with friends. 'Fusion Table' in
|
||||||
|
this context means a Google Fusion Table.">
|
||||||
|
Fusion Table
|
||||||
|
</string>
|
||||||
|
<string name="menu_share_map"
|
||||||
|
translation_description="Under the 'Share with friends...' menu option, the option to save a
|
||||||
|
track to Google Maps and share the Map url with friends. 'Map' in this context means a Google
|
||||||
|
Map.">
|
||||||
|
Map
|
||||||
|
</string>
|
||||||
|
|
||||||
<!-- My Location -->
|
<!-- My Location -->
|
||||||
<string name="my_location_approximate_location"
|
<string name="my_location_approximate_location"
|
||||||
translation_description="When displaying the user's current location, a status message
|
translation_description="When displaying the user's current location, a status message
|
||||||
@@ -1196,6 +1258,13 @@ limitations under the License.
|
|||||||
search results.">
|
search results.">
|
||||||
No tracks or waypoints matched your search.
|
No tracks or waypoints matched your search.
|
||||||
</string>
|
</string>
|
||||||
|
<string name="search_track_location"
|
||||||
|
translation_description="In the 'Search Result' page, the text field indicating the track that a
|
||||||
|
waypoint belongs to.
|
||||||
|
|
||||||
|
%1$s: track name. E.g., 'Grand Canyon trail'">
|
||||||
|
In track \'%1$s\'.
|
||||||
|
</string>
|
||||||
<string name="search_voice_prompt"
|
<string name="search_voice_prompt"
|
||||||
translation_description="Prompt shown when the user activates voice search, asking him to speak
|
translation_description="Prompt shown when the user activates voice search, asking him to speak
|
||||||
what will be searched for.">
|
what will be searched for.">
|
||||||
@@ -2233,7 +2302,22 @@ limitations under the License.
|
|||||||
Total time
|
Total time
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<!-- Track Edit -->
|
<!-- Track -->
|
||||||
|
<string name="track_detail_delete_confirm_message"
|
||||||
|
translation_description="When deleting a track, the confirmation message informing the user that
|
||||||
|
the track and its markers will be permanently deleted from the phone.">
|
||||||
|
The track and its markers will be permanently deleted from the phone.
|
||||||
|
</string>
|
||||||
|
<string name="track_detail_install_earth_message"
|
||||||
|
translation_description="When playing a track, the message informing the user that he needs
|
||||||
|
Google Earth to play the track and asking him if he wants to install Google Earth from the
|
||||||
|
Android Market.">
|
||||||
|
You need Google Earth to play the track. Do you want to install from the Market?
|
||||||
|
</string>
|
||||||
|
<string name="track_icon_description"
|
||||||
|
translation_description="The accessibility description for the track icon.">
|
||||||
|
Track
|
||||||
|
</string>
|
||||||
<string name="track_edit_activity_type"
|
<string name="track_edit_activity_type"
|
||||||
translation_description="In the page to edit a track, the title for the text field to edit the
|
translation_description="In the page to edit a track, the title for the text field to edit the
|
||||||
activity type, including some examples of activity types.">
|
activity type, including some examples of activity types.">
|
||||||
@@ -2258,165 +2342,32 @@ limitations under the License.
|
|||||||
track name.">
|
track name.">
|
||||||
Track name
|
Track name
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
<!-- Track -->
|
|
||||||
<string name="track_icon_description"
|
|
||||||
translation_description="The accessibility description for the track icon.">
|
|
||||||
Track
|
|
||||||
</string>
|
|
||||||
<string name="track_list_clear_map"
|
|
||||||
translation_description="In the context menu for a track, the menu option to clear the map of
|
|
||||||
any track.
|
|
||||||
|
|
||||||
Screenshot: track_list_context_menu.png">
|
|
||||||
Clear map
|
|
||||||
</string>
|
|
||||||
<string name="track_list_context_menu_title"
|
|
||||||
translation_description="In the context menu for a track, the title indicating that all the menu
|
|
||||||
options below are for this track.
|
|
||||||
|
|
||||||
Screenshot: track_list_context_menu.png">
|
|
||||||
This track
|
|
||||||
</string>
|
|
||||||
<string name="track_list_delete_all_confirm_message"
|
<string name="track_list_delete_all_confirm_message"
|
||||||
translation_description="In the 'Tracks' page, when pressing the 'Delete all' button, the
|
translation_description="When deleting all the tracks, the confirmation dialog message informing
|
||||||
confirmation dialog message informing the user that all tracks and markers will be permanently
|
the user that all tracks and markers will be permanently deleted from the phone.">
|
||||||
deleted from the phone.
|
|
||||||
|
|
||||||
Screenshot: track_list_delete_all_confirm_message.png">
|
|
||||||
All tracks and markers will be permanently deleted from the phone.
|
All tracks and markers will be permanently deleted from the phone.
|
||||||
</string>
|
</string>
|
||||||
<string name="track_list_delete_track"
|
<string name="track_list_record_error"
|
||||||
translation_description="In the context menu for a track, the menu option to delete the
|
translation_description="When starting a new track recording, the error message informing the
|
||||||
track from the phone.
|
user not able to record and asking the user to try again.">
|
||||||
|
Unable to start recording. No GPS location. Try again.
|
||||||
Screenshot: track_list_context_menu.png">
|
|
||||||
Delete from phone...
|
|
||||||
</string>
|
</string>
|
||||||
<string name="track_list_delete_track_confirm_message"
|
<string name="track_list_record_success"
|
||||||
translation_description="In the context menu for a track, when pressing the 'Delete from
|
translation_description="When starting a new track recording, a status message indicating
|
||||||
phone...' option, the confirmation dialog message informing the user that the track and its
|
success.">
|
||||||
markers will be permanently deleted from the phone.
|
Now recording a new track.
|
||||||
|
|
||||||
Screenshot: track_list_delete_track_confirm_message.png">
|
|
||||||
The track and its markers will be permanently deleted from the phone.
|
|
||||||
</string>
|
|
||||||
<string name="track_list_edit_track"
|
|
||||||
translation_description="In the context menu for a track, the menu option to edit the track's
|
|
||||||
metadata (e.g., name, activity type, etc.).
|
|
||||||
|
|
||||||
Screenshot: track_list_context_menu.png">
|
|
||||||
Edit
|
|
||||||
</string>
|
|
||||||
<string name="track_list_export_file"
|
|
||||||
translation_description="In the 'Tracks' page, after pressing the 'Export all' button, the menu
|
|
||||||
option to export all the tracks as a certain file format
|
|
||||||
|
|
||||||
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.
|
|
||||||
Screenshot: track_list_export_file.png">
|
|
||||||
Export as %1$s
|
|
||||||
</string>
|
|
||||||
<string name="track_list_play"
|
|
||||||
translation_description="In the context menu for a track, the menu option to play the track.">
|
|
||||||
Play
|
|
||||||
</string>
|
|
||||||
<string name="track_list_play_install_earth_message"
|
|
||||||
translation_description="After pressing the menu option to play a track, the message informing
|
|
||||||
the user that he needs Google Earth to play the track and asking him if he wants to install
|
|
||||||
Google Earth from the Android Market.">
|
|
||||||
You need Google Earth to play the track. Do you want to install from the Market?
|
|
||||||
</string>
|
|
||||||
<string name="track_list_save_file"
|
|
||||||
translation_description="In the context menu for a track, under the 'Save to SD card...'
|
|
||||||
option, the menu option to save the track as a certain file format.
|
|
||||||
|
|
||||||
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.
|
|
||||||
Screenshot: track_list_save_file.png">
|
|
||||||
As a %1$s file
|
|
||||||
</string>
|
|
||||||
<string name="track_list_save_sd"
|
|
||||||
translation_description="In the context menu for a track, the menu option to save the track to
|
|
||||||
the SD card.
|
|
||||||
|
|
||||||
Screenshot: track_list_context_menu.png">
|
|
||||||
Save to SD card...
|
|
||||||
</string>
|
|
||||||
<string name="track_list_send_google"
|
|
||||||
translation_description="In the context menu for a track, the menu option to send the track to
|
|
||||||
Google.
|
|
||||||
|
|
||||||
Screenshot: track_list_context_menu.png">
|
|
||||||
Send to Google...
|
|
||||||
</string>
|
|
||||||
<string name="track_list_share_file"
|
|
||||||
translation_description="In the context menu for a track, under the 'Share with friends...'
|
|
||||||
option, the menu option to share the track as a certain file format.
|
|
||||||
|
|
||||||
%1$s: file format. 'GPX', 'KML', 'CSV', or 'TCX'.
|
|
||||||
Screenshot: track_list_share_options.png">
|
|
||||||
A %1$s file
|
|
||||||
</string>
|
|
||||||
<string name="track_list_share_fusion_table"
|
|
||||||
translation_description="In the context menu for a track, under the 'Share with friends...'
|
|
||||||
option, the menu option to save a track to Google Fusion Tables and share the Fusion Table
|
|
||||||
with friends. 'Fusion Table' in this context means a Google Fusion Table.">
|
|
||||||
Fusion Table
|
|
||||||
</string>
|
|
||||||
<string name="track_list_share_map"
|
|
||||||
translation_description="In the context menu for a track, under the 'Share with friends...'
|
|
||||||
option, the menu option to save a track to Google Maps and share the Map with friends. 'Map'
|
|
||||||
in this context means a Google Map.">
|
|
||||||
Map
|
|
||||||
</string>
|
|
||||||
<string name="track_list_share_track"
|
|
||||||
translation_description="In the context menu for a track, the menu option to share the track
|
|
||||||
with friends through other applications.
|
|
||||||
|
|
||||||
Screenshot: track_list_context_menu.png">
|
|
||||||
Share with friends...
|
|
||||||
</string>
|
|
||||||
<string name="track_list_show_on_map"
|
|
||||||
translation_description="In the context menu for a track, the menu option to show the track on
|
|
||||||
the map.
|
|
||||||
|
|
||||||
Screenshot: track_list_show_on_map.png">
|
|
||||||
Show on map
|
|
||||||
</string>
|
|
||||||
<string name="track_list_track_name"
|
|
||||||
translation_description="In the 'Search Result' page, the text field indicating the track that a
|
|
||||||
waypoint belongs to.
|
|
||||||
|
|
||||||
%1$s: track name. E.g., 'Grand Canyon trail'">
|
|
||||||
In track \'%1$s\'.
|
|
||||||
</string>
|
</string>
|
||||||
<string name="track_name_format"
|
<string name="track_name_format"
|
||||||
translation_description="When creating a new track, the string format to name the track.
|
translation_description="When creating a new track, the string format to name the track.
|
||||||
|
|
||||||
%1$d: track number. E.g., '1'.
|
%1$d: track number. E.g., '1'.">
|
||||||
Screenshot: track_name_format.png">
|
|
||||||
Track %1$d
|
Track %1$d
|
||||||
</string>
|
</string>
|
||||||
<string name="track_record_error"
|
|
||||||
translation_description="When starting a recording, message when not able to start due to no GPS
|
|
||||||
location and asking the user to try again.
|
|
||||||
|
|
||||||
Screenshot: track_record_error.png">
|
|
||||||
Unable to start recording. No GPS location. Try again.
|
|
||||||
</string>
|
|
||||||
<string name="track_record_notification"
|
<string name="track_record_notification"
|
||||||
translation_description="When recording a track, the message on the My Tracks notification
|
translation_description="When recording a track, the message on the My Tracks notification
|
||||||
informing the user that My Tracks is actively recording his track.
|
informing the user that My Tracks is actively recording his track.">
|
||||||
|
|
||||||
Screenshot: track_record_notification.png">
|
|
||||||
Recording your track...
|
Recording your track...
|
||||||
</string>
|
</string>
|
||||||
<string name="track_record_success"
|
|
||||||
translation_description="When starting a new track recording, a status message indicating
|
|
||||||
success.
|
|
||||||
|
|
||||||
Screenshot: track_record_success.png">
|
|
||||||
Now recording a new track.
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<!-- Unit -->
|
<!-- Unit -->
|
||||||
<string name="unit_feet"
|
<string name="unit_feet"
|
||||||
|
|||||||
@@ -41,24 +41,10 @@ public abstract class Constants {
|
|||||||
/*
|
/*
|
||||||
* Context menu ids. Sorted alphabetically.
|
* Context menu ids. Sorted alphabetically.
|
||||||
*/
|
*/
|
||||||
public static final int MENU_CLEAR_MAP = 100;
|
public static final int MENU_DELETE = 100;
|
||||||
public static final int MENU_DELETE = 101;
|
public static final int MENU_EDIT = 101;
|
||||||
public static final int MENU_EDIT = 102;
|
public static final int MENU_SHOW = 102;
|
||||||
public static final int MENU_PLAY = 103;
|
|
||||||
public static final int MENU_SAVE_CSV_FILE = 104;
|
|
||||||
public static final int MENU_SAVE_GPX_FILE = 105;
|
|
||||||
public static final int MENU_SAVE_KML_FILE = 106;
|
|
||||||
public static final int MENU_SAVE_TCX_FILE = 107;
|
|
||||||
public static final int MENU_SEND_TO_GOOGLE = 108;
|
|
||||||
public static final int MENU_SHARE = 109;
|
|
||||||
public static final int MENU_SHARE_CSV_FILE = 110;
|
|
||||||
public static final int MENU_SHARE_FUSION_TABLE = 111;
|
|
||||||
public static final int MENU_SHARE_GPX_FILE = 112;
|
|
||||||
public static final int MENU_SHARE_KML_FILE = 113;
|
|
||||||
public static final int MENU_SHARE_MAP = 114;
|
|
||||||
public static final int MENU_SHARE_TCX_FILE = 115;
|
|
||||||
public static final int MENU_SHOW = 116;
|
|
||||||
public static final int MENU_WRITE_TO_SD_CARD = 117;
|
|
||||||
/*
|
/*
|
||||||
* Main screen tab tags:
|
* Main screen tab tags:
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,42 +23,23 @@ import com.google.android.apps.mytracks.content.TrackDataHub;
|
|||||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
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.stats.TripStatistics;
|
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
|
||||||
import com.google.android.apps.mytracks.util.GeoRect;
|
import com.google.android.apps.mytracks.util.GeoRect;
|
||||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||||
import com.google.android.apps.mytracks.util.PlayTrackUtils;
|
|
||||||
import com.google.android.maps.GeoPoint;
|
import com.google.android.maps.GeoPoint;
|
||||||
import com.google.android.maps.MapController;
|
import com.google.android.maps.MapController;
|
||||||
import com.google.android.maps.MapView;
|
import com.google.android.maps.MapView;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.SharedPreferences.Editor;
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.speech.tts.TextToSpeech;
|
import android.speech.tts.TextToSpeech;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextMenu;
|
|
||||||
import android.view.ContextMenu.ContextMenuInfo;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.SubMenu;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnCreateContextMenuListener;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -76,9 +57,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
|||||||
implements View.OnTouchListener, View.OnClickListener,
|
implements View.OnTouchListener, View.OnClickListener,
|
||||||
TrackDataListener {
|
TrackDataListener {
|
||||||
|
|
||||||
private static final int DIALOG_INSTALL_EARTH_ID = 0;
|
|
||||||
private static final int DIALOG_DELETE_CURRENT_ID = 1;
|
|
||||||
|
|
||||||
// Saved instance state keys:
|
// Saved instance state keys:
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
|
|
||||||
@@ -133,7 +111,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
|||||||
private LinearLayout messagePane;
|
private LinearLayout messagePane;
|
||||||
private TextView messageText;
|
private TextView messageText;
|
||||||
private LinearLayout busyPane;
|
private LinearLayout busyPane;
|
||||||
private ImageButton optionsBtn;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We are not displaying driving directions. Just an arbitrary track that is
|
* We are not displaying driving directions. Just an arbitrary track that is
|
||||||
@@ -185,10 +162,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
|||||||
messagePane = (LinearLayout) findViewById(R.id.messagepane);
|
messagePane = (LinearLayout) findViewById(R.id.messagepane);
|
||||||
messageText = (TextView) findViewById(R.id.messagetext);
|
messageText = (TextView) findViewById(R.id.messagetext);
|
||||||
busyPane = (LinearLayout) findViewById(R.id.busypane);
|
busyPane = (LinearLayout) findViewById(R.id.busypane);
|
||||||
optionsBtn = (ImageButton) findViewById(R.id.showOptions);
|
|
||||||
|
|
||||||
optionsBtn.setOnCreateContextMenuListener(contextMenuListener);
|
|
||||||
optionsBtn.setOnClickListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -243,45 +216,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
|||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Dialog onCreateDialog(int id) {
|
|
||||||
switch (id) {
|
|
||||||
case DIALOG_INSTALL_EARTH_ID:
|
|
||||||
return PlayTrackUtils.createInstallEarthDialog(this);
|
|
||||||
case DIALOG_DELETE_CURRENT_ID:
|
|
||||||
return DialogUtils.createConfirmationDialog(this,
|
|
||||||
R.string.track_list_delete_track_confirm_message,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
long trackId = dataHub.getSelectedTrackId();
|
|
||||||
MyTracksProviderUtils.Factory.get(MapActivity.this).deleteTrack(trackId);
|
|
||||||
// If the deleted track was selected, unselect it.
|
|
||||||
String selectedTrackKey = getString(R.string.selected_track_key);
|
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(
|
|
||||||
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
|
||||||
if (sharedPreferences.getLong(selectedTrackKey, -1L) == trackId) {
|
|
||||||
Editor editor = sharedPreferences.edit().putLong(selectedTrackKey, -1L);
|
|
||||||
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility functions:
|
|
||||||
// -------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the options button if a track is selected, or hide it if not.
|
|
||||||
*/
|
|
||||||
private void updateOptionsButton(boolean trackSelected) {
|
|
||||||
optionsBtn.setVisibility(
|
|
||||||
trackSelected ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if a location is visible.
|
* Tests if a location is visible.
|
||||||
*
|
*
|
||||||
@@ -451,8 +385,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
boolean trackSelected = track != null;
|
boolean trackSelected = track != null;
|
||||||
updateOptionsButton(trackSelected);
|
|
||||||
|
|
||||||
mapOverlay.setTrackDrawingEnabled(trackSelected);
|
mapOverlay.setTrackDrawingEnabled(trackSelected);
|
||||||
|
|
||||||
if (trackSelected) {
|
if (trackSelected) {
|
||||||
@@ -473,134 +405,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private final OnCreateContextMenuListener contextMenuListener =
|
|
||||||
new OnCreateContextMenuListener() {
|
|
||||||
@Override
|
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
|
||||||
menu.setHeaderTitle(R.string.track_list_context_menu_title);
|
|
||||||
menu.add(Menu.NONE, Constants.MENU_EDIT, Menu.NONE, R.string.track_list_edit_track);
|
|
||||||
if (!dataHub.isRecordingSelected()) {
|
|
||||||
String saveFileFormat = getString(R.string.track_list_save_file);
|
|
||||||
String shareFileFormat = getString(R.string.track_list_share_file);
|
|
||||||
String fileTypes[] = getResources().getStringArray(R.array.file_types);
|
|
||||||
|
|
||||||
menu.add(Menu.NONE, Constants.MENU_PLAY, Menu.NONE, R.string.track_list_play);
|
|
||||||
menu.add(Menu.NONE, Constants.MENU_SEND_TO_GOOGLE, Menu.NONE,
|
|
||||||
R.string.track_list_send_google);
|
|
||||||
SubMenu share = menu.addSubMenu(
|
|
||||||
Menu.NONE, Constants.MENU_SHARE, Menu.NONE, R.string.track_list_share_track);
|
|
||||||
share.add(
|
|
||||||
Menu.NONE, Constants.MENU_SHARE_MAP, Menu.NONE, R.string.track_list_share_map);
|
|
||||||
share.add(Menu.NONE, Constants.MENU_SHARE_FUSION_TABLE, Menu.NONE,
|
|
||||||
R.string.track_list_share_fusion_table);
|
|
||||||
share.add(Menu.NONE, Constants.MENU_SHARE_GPX_FILE, Menu.NONE,
|
|
||||||
String.format(shareFileFormat, fileTypes[0]));
|
|
||||||
share.add(Menu.NONE, Constants.MENU_SHARE_KML_FILE, Menu.NONE,
|
|
||||||
String.format(shareFileFormat, fileTypes[1]));
|
|
||||||
share.add(Menu.NONE, Constants.MENU_SHARE_CSV_FILE, Menu.NONE,
|
|
||||||
String.format(shareFileFormat, fileTypes[2]));
|
|
||||||
share.add(Menu.NONE, Constants.MENU_SHARE_TCX_FILE, Menu.NONE,
|
|
||||||
String.format(shareFileFormat, fileTypes[3]));
|
|
||||||
SubMenu save = menu.addSubMenu(
|
|
||||||
Menu.NONE, Constants.MENU_WRITE_TO_SD_CARD, Menu.NONE, R.string.track_list_save_sd);
|
|
||||||
save.add(Menu.NONE, Constants.MENU_SAVE_GPX_FILE, Menu.NONE,
|
|
||||||
String.format(saveFileFormat, fileTypes[0]));
|
|
||||||
save.add(Menu.NONE, Constants.MENU_SAVE_KML_FILE, Menu.NONE,
|
|
||||||
String.format(saveFileFormat, fileTypes[1]));
|
|
||||||
save.add(Menu.NONE, Constants.MENU_SAVE_CSV_FILE, Menu.NONE,
|
|
||||||
String.format(saveFileFormat, fileTypes[2]));
|
|
||||||
save.add(Menu.NONE, Constants.MENU_SAVE_TCX_FILE, Menu.NONE,
|
|
||||||
String.format(saveFileFormat, fileTypes[3]));
|
|
||||||
menu.add(Menu.NONE, Constants.MENU_CLEAR_MAP, Menu.NONE, R.string.track_list_clear_map);
|
|
||||||
menu.add(Menu.NONE, Constants.MENU_DELETE, Menu.NONE, R.string.track_list_delete_track);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
|
||||||
Intent intent;
|
|
||||||
long trackId = dataHub.getSelectedTrackId();
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case Constants.MENU_EDIT:
|
|
||||||
intent = new Intent(this, TrackEditActivity.class)
|
|
||||||
.putExtra(TrackEditActivity.TRACK_ID, trackId);
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_PLAY:
|
|
||||||
if (PlayTrackUtils.isEarthInstalled(this)) {
|
|
||||||
PlayTrackUtils.playTrack(this, trackId);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
showDialog(DIALOG_INSTALL_EARTH_ID);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case Constants.MENU_SEND_TO_GOOGLE:
|
|
||||||
intent = new Intent(this, UploadServiceChooserActivity.class)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, true, true, true));
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SHARE_MAP:
|
|
||||||
intent = new Intent(this, UploadServiceChooserActivity.class)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, true, false, false));
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SHARE_FUSION_TABLE:
|
|
||||||
intent = new Intent(this, UploadServiceChooserActivity.class)
|
|
||||||
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, false, true, false));
|
|
||||||
startActivity(intent);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SHARE_GPX_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.GPX, true);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SHARE_KML_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.KML, true);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SHARE_CSV_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.CSV, true);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SHARE_TCX_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.TCX, true);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SAVE_GPX_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.GPX, false);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SAVE_KML_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.KML, false);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SAVE_CSV_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.CSV, false);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_SAVE_TCX_FILE:
|
|
||||||
startSaveActivity(trackId, TrackFileFormat.TCX, false);
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_CLEAR_MAP:
|
|
||||||
dataHub.unloadCurrentTrack();
|
|
||||||
return true;
|
|
||||||
case Constants.MENU_DELETE:
|
|
||||||
showDialog(DIALOG_DELETE_CURRENT_ID);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onMenuItemSelected(featureId, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the {@link SaveActivity} to save a track.
|
|
||||||
*
|
|
||||||
* @param trackId the track id
|
|
||||||
* @param trackFileFormat the track file format
|
|
||||||
* @param shareTrack true to share the track after saving
|
|
||||||
*/
|
|
||||||
private void startSaveActivity(
|
|
||||||
long trackId, TrackFileFormat trackFileFormat, boolean shareTrack) {
|
|
||||||
Intent intent = new Intent(this, SaveActivity.class)
|
|
||||||
.putExtra(SaveActivity.EXTRA_TRACK_ID, trackId)
|
|
||||||
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat)
|
|
||||||
.putExtra(SaveActivity.EXTRA_SHARE_TRACK, shareTrack);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the map is currently in satellite view mode.
|
* Returns whether the map is currently in satellite view mode.
|
||||||
*/
|
*/
|
||||||
@@ -619,8 +423,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
|||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (v == messagePane) {
|
if (v == messagePane) {
|
||||||
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
|
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
|
||||||
} else if (v == optionsBtn) {
|
|
||||||
optionsBtn.performLongClick();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public class SearchActivity extends ListActivity {
|
|||||||
resultMap.put(DESCRIPTION_FIELD, waypoint.getDescription());
|
resultMap.put(DESCRIPTION_FIELD, waypoint.getDescription());
|
||||||
resultMap.put(CATEGORY_FIELD, waypoint.getCategory());
|
resultMap.put(CATEGORY_FIELD, waypoint.getCategory());
|
||||||
// In the same place as we show time for tracks, show the track name for waypoints.
|
// In the same place as we show time for tracks, show the track name for waypoints.
|
||||||
resultMap.put(TIME_FIELD, getString(R.string.track_list_track_name, trackName));
|
resultMap.put(TIME_FIELD, getString(R.string.search_track_location, trackName));
|
||||||
resultMap.put(STATS_FIELD, StringUtils.formatDateTime(this, waypoint.getLocation().getTime()));
|
resultMap.put(STATS_FIELD, StringUtils.formatDateTime(this, waypoint.getLocation().getTime()));
|
||||||
resultMap.put(TRACK_ID_FIELD, waypoint.getTrackId());
|
resultMap.put(TRACK_ID_FIELD, waypoint.getTrackId());
|
||||||
resultMap.put(WAYPOINT_ID_FIELD, waypoint.getId());
|
resultMap.put(WAYPOINT_ID_FIELD, waypoint.getId());
|
||||||
|
|||||||
@@ -18,25 +18,33 @@ package com.google.android.apps.mytracks;
|
|||||||
import static com.google.android.apps.mytracks.Constants.CHART_TAB_TAG;
|
import static com.google.android.apps.mytracks.Constants.CHART_TAB_TAG;
|
||||||
import static com.google.android.apps.mytracks.Constants.MAP_TAB_TAG;
|
import static com.google.android.apps.mytracks.Constants.MAP_TAB_TAG;
|
||||||
import static com.google.android.apps.mytracks.Constants.STATS_TAB_TAG;
|
import static com.google.android.apps.mytracks.Constants.STATS_TAB_TAG;
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||||
import com.google.android.apps.mytracks.content.Waypoint;
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
||||||
|
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.ITrackRecordingService;
|
import com.google.android.apps.mytracks.services.ITrackRecordingService;
|
||||||
import com.google.android.apps.mytracks.services.ServiceUtils;
|
import com.google.android.apps.mytracks.services.ServiceUtils;
|
||||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
||||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||||
|
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||||
|
import com.google.android.apps.mytracks.util.PlayTrackUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
import android.app.TabActivity;
|
import android.app.TabActivity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Parcelable;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.speech.tts.TextToSpeech;
|
import android.speech.tts.TextToSpeech;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -58,24 +66,27 @@ import android.widget.Toast;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class TrackDetailActivity extends TabActivity implements OnTouchListener {
|
public class TrackDetailActivity extends TabActivity implements OnTouchListener {
|
||||||
|
|
||||||
public static final String TRACK_ID = "track_id";
|
public static final String TRACK_ID = "track_id";
|
||||||
public static final String WAYPOINT_ID = "waypoint_id";
|
public static final String WAYPOINT_ID = "waypoint_id";
|
||||||
|
|
||||||
private MyTracksProviderUtils myTracksProviderUtils;
|
private static final String TAG = TrackDetailActivity.class.getSimpleName();
|
||||||
|
private static final int DIALOG_INSTALL_EARTH_ID = 0;
|
||||||
|
private static final int DIALOG_DELETE_CURRENT_ID = 1;
|
||||||
|
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private TrackDataHub trackDataHub;
|
private TrackDataHub trackDataHub;
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
private NavControls navControls;
|
private NavControls navControls;
|
||||||
|
|
||||||
private MenuItem recordTrack;
|
|
||||||
private MenuItem stopRecording;
|
private MenuItem stopRecording;
|
||||||
|
private MenuItem insertMarker;
|
||||||
/**
|
private MenuItem play;
|
||||||
* True if a new track should be created after the track recording service
|
private MenuItem share;
|
||||||
* binds.
|
private MenuItem sendGoogle;
|
||||||
*/
|
private MenuItem save;
|
||||||
private boolean startNewTrackRequested = false;
|
private MenuItem edit;
|
||||||
|
private MenuItem delete;
|
||||||
|
|
||||||
private final Runnable changeTab = new Runnable() {
|
private final Runnable changeTab = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -83,21 +94,22 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Callback when {@linkk TrackRecordingServiceConnection} binding changes.
|
* Note that sharedPreferenceChangeListener cannot be an anonymous inner
|
||||||
|
* class. Anonymous inner class will get garbage collected.
|
||||||
*/
|
*/
|
||||||
private final Runnable serviceBindCallback = new Runnable() {
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener =
|
||||||
|
new OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
synchronized (trackRecordingServiceConnection) {
|
if (key == null) {
|
||||||
ITrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
|
return;
|
||||||
if (startNewTrackRequested && service != null) {
|
}
|
||||||
Log.i(TAG, "Starting recording");
|
if (key.equals(getString(R.string.recording_track_key))) {
|
||||||
startNewTrackRequested = false;
|
if (isRecording()) {
|
||||||
startRecordingNewTrack(service);
|
trackRecordingServiceConnection.startAndBind();
|
||||||
} else if (startNewTrackRequested) {
|
|
||||||
Log.w(TAG, "Not yet starting recording");
|
|
||||||
}
|
}
|
||||||
|
updateMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -106,10 +118,10 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(this);
|
|
||||||
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||||
|
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
trackDataHub = ((MyTracksApplication) getApplication()).getTrackDataHub();
|
trackDataHub = ((MyTracksApplication) getApplication()).getTrackDataHub();
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, serviceBindCallback);
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, null);
|
||||||
|
|
||||||
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
|
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
|
||||||
|
|
||||||
@@ -119,8 +131,7 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
final Resources res = getResources();
|
final Resources res = getResources();
|
||||||
final TabHost tabHost = getTabHost();
|
final TabHost tabHost = getTabHost();
|
||||||
tabHost.addTab(tabHost.newTabSpec(MAP_TAB_TAG)
|
tabHost.addTab(tabHost.newTabSpec(MAP_TAB_TAG)
|
||||||
.setIndicator("Map", res.getDrawable(
|
.setIndicator("Map", res.getDrawable(android.R.drawable.ic_menu_mapmode))
|
||||||
android.R.drawable.ic_menu_mapmode))
|
|
||||||
.setContent(new Intent(this, MapActivity.class)));
|
.setContent(new Intent(this, MapActivity.class)));
|
||||||
tabHost.addTab(tabHost.newTabSpec(STATS_TAB_TAG)
|
tabHost.addTab(tabHost.newTabSpec(STATS_TAB_TAG)
|
||||||
.setIndicator("Stats", res.getDrawable(R.drawable.ic_menu_statistics))
|
.setIndicator("Stats", res.getDrawable(R.drawable.ic_menu_statistics))
|
||||||
@@ -134,14 +145,10 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
tabHost.getTabWidget().setVisibility(View.GONE);
|
tabHost.getTabWidget().setVisibility(View.GONE);
|
||||||
|
|
||||||
RelativeLayout layout = new RelativeLayout(this);
|
RelativeLayout layout = new RelativeLayout(this);
|
||||||
LayoutParams params =
|
LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
|
||||||
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
|
|
||||||
layout.setLayoutParams(params);
|
layout.setLayoutParams(params);
|
||||||
navControls =
|
navControls = new NavControls(this, layout, getResources().obtainTypedArray(R.array.left_icons),
|
||||||
new NavControls(this, layout,
|
getResources().obtainTypedArray(R.array.right_icons), changeTab);
|
||||||
getResources().obtainTypedArray(R.array.left_icons),
|
|
||||||
getResources().obtainTypedArray(R.array.right_icons),
|
|
||||||
changeTab);
|
|
||||||
navControls.show();
|
navControls.show();
|
||||||
tabHost.addView(layout);
|
tabHost.addView(layout);
|
||||||
layout.setOnTouchListener(this);
|
layout.setOnTouchListener(this);
|
||||||
@@ -152,9 +159,7 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
super.onStart();
|
super.onStart();
|
||||||
trackDataHub.start();
|
trackDataHub.start();
|
||||||
|
|
||||||
// Ensure that service is running and bound if we're supposed to be recording
|
if (isRecording()) {
|
||||||
if (ServiceUtils.isRecording(
|
|
||||||
this, trackRecordingServiceConnection.getServiceIfBound(), sharedPreferences)) {
|
|
||||||
trackRecordingServiceConnection.startAndBind();
|
trackRecordingServiceConnection.startAndBind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,18 +169,26 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
trackDataHub.loadTrack(trackId);
|
trackDataHub.loadTrack(trackId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long waypointId = intent.getLongExtra(WAYPOINT_ID, -1L);
|
long waypointId = intent.getLongExtra(WAYPOINT_ID, -1L);
|
||||||
if (waypointId != -1L) {
|
if (waypointId != -1L) {
|
||||||
Waypoint waypoint = myTracksProviderUtils.getWaypoint(waypointId);
|
Waypoint waypoint = MyTracksProviderUtils.Factory.get(this).getWaypoint(waypointId);
|
||||||
trackId = waypoint.getTrackId();
|
if (waypoint != null) {
|
||||||
|
trackId = waypoint.getTrackId();
|
||||||
// Request that the waypoint is shown (now or when the right track is loaded).
|
trackDataHub.loadTrack(trackId);
|
||||||
showWaypoint(trackId, waypointId);
|
MapActivity mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
// Load the right track, if not loaded already.
|
getTabHost().setCurrentTab(0);
|
||||||
trackDataHub.loadTrack(trackId);
|
mapActivity.showWaypoint(trackId, waypointId);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "MapActivity is null");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No track id or waypoint id, return to the track list activity.
|
||||||
|
startTrackListActivity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -196,98 +209,166 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
trackRecordingServiceConnection.unbind();
|
trackRecordingServiceConnection.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Dialog onCreateDialog(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case DIALOG_INSTALL_EARTH_ID:
|
||||||
|
return PlayTrackUtils.createInstallEarthDialog(this);
|
||||||
|
case DIALOG_DELETE_CURRENT_ID:
|
||||||
|
return DialogUtils.createConfirmationDialog(this,
|
||||||
|
R.string.track_detail_delete_confirm_message, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
long trackId = trackDataHub.getSelectedTrackId();
|
||||||
|
MyTracksProviderUtils.Factory.get(TrackDetailActivity.this).deleteTrack(trackId);
|
||||||
|
startTrackListActivity();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.track_detail, menu);
|
getMenuInflater().inflate(R.menu.track_detail, menu);
|
||||||
recordTrack = menu.findItem(R.id.menu_record_track);
|
String fileTypes[] = getResources().getStringArray(R.array.file_types);
|
||||||
|
menu.findItem(R.id.menu_save_gpx).setTitle(getString(R.string.menu_save_format, fileTypes[0]));
|
||||||
|
menu.findItem(R.id.menu_save_kml).setTitle(getString(R.string.menu_save_format, fileTypes[1]));
|
||||||
|
menu.findItem(R.id.menu_save_csv).setTitle(getString(R.string.menu_save_format, fileTypes[2]));
|
||||||
|
menu.findItem(R.id.menu_save_tcx).setTitle(getString(R.string.menu_save_format, fileTypes[3]));
|
||||||
|
|
||||||
|
menu.findItem(R.id.menu_share_gpx).setTitle(getString(R.string.menu_share_file, fileTypes[0]));
|
||||||
|
menu.findItem(R.id.menu_share_kml).setTitle(getString(R.string.menu_share_file, fileTypes[1]));
|
||||||
|
menu.findItem(R.id.menu_share_csv).setTitle(getString(R.string.menu_share_file, fileTypes[2]));
|
||||||
|
menu.findItem(R.id.menu_share_tcx).setTitle(getString(R.string.menu_share_file, fileTypes[3]));
|
||||||
|
|
||||||
stopRecording = menu.findItem(R.id.menu_stop_recording);
|
stopRecording = menu.findItem(R.id.menu_stop_recording);
|
||||||
|
insertMarker = menu.findItem(R.id.menu_insert_marker);
|
||||||
|
play = menu.findItem(R.id.menu_play);
|
||||||
|
share = menu.findItem(R.id.menu_share);
|
||||||
|
sendGoogle = menu.findItem(R.id.menu_send_google);
|
||||||
|
save = menu.findItem(R.id.menu_save);
|
||||||
|
edit = menu.findItem(R.id.menu_edit);
|
||||||
|
delete = menu.findItem(R.id.menu_delete);
|
||||||
|
|
||||||
|
updateMenu();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
updateMenuItems(ServiceUtils.isRecording(
|
|
||||||
this, trackRecordingServiceConnection.getServiceIfBound(), sharedPreferences));
|
|
||||||
|
|
||||||
String currentTabTag = getTabHost().getCurrentTabTag();
|
String currentTabTag = getTabHost().getCurrentTabTag();
|
||||||
menu.findItem(R.id.menu_chart_settings).setVisible(CHART_TAB_TAG.equals(currentTabTag));
|
menu.findItem(R.id.menu_chart_settings).setVisible(CHART_TAB_TAG.equals(currentTabTag));
|
||||||
menu.findItem(R.id.menu_my_location).setVisible(MAP_TAB_TAG.equals(currentTabTag));
|
menu.findItem(R.id.menu_my_location).setVisible(MAP_TAB_TAG.equals(currentTabTag));
|
||||||
|
|
||||||
// Set map or satellite mode
|
// Set map or satellite mode
|
||||||
MapActivity mapActivity = (MapActivity) getLocalActivityManager().getActivity(MAP_TAB_TAG);
|
MapActivity mapActivity = getMapActivity();
|
||||||
boolean isSatelliteMode = mapActivity != null ? mapActivity.isSatelliteView() : false;
|
boolean isSatelliteMode = mapActivity != null ? mapActivity.isSatelliteView() : false;
|
||||||
menu.findItem(R.id.menu_satellite_mode)
|
menu.findItem(R.id.menu_satellite_mode).setVisible(MAP_TAB_TAG.equals(currentTabTag))
|
||||||
.setVisible(MAP_TAB_TAG.equals(currentTabTag))
|
|
||||||
.setTitle(isSatelliteMode ? R.string.menu_map_mode : R.string.menu_satellite_mode);
|
.setTitle(isSatelliteMode ? R.string.menu_map_mode : R.string.menu_satellite_mode);
|
||||||
|
|
||||||
return super.onPrepareOptionsMenu(menu);
|
return super.onPrepareOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates menu item
|
|
||||||
*
|
|
||||||
* @param isRecording true if recording
|
|
||||||
*/
|
|
||||||
private void updateMenuItems(boolean isRecording) {
|
|
||||||
if (recordTrack != null) {
|
|
||||||
recordTrack.setVisible(!isRecording);
|
|
||||||
}
|
|
||||||
if (stopRecording != null) {
|
|
||||||
stopRecording.setVisible(isRecording);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
MapActivity mapActivity;
|
MapActivity mapActivity;
|
||||||
|
Intent intent;
|
||||||
|
long trackId = trackDataHub.getSelectedTrackId();
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_record_track:
|
|
||||||
updateMenuItems(true);
|
|
||||||
startRecording();
|
|
||||||
return true;
|
|
||||||
case R.id.menu_stop_recording:
|
case R.id.menu_stop_recording:
|
||||||
updateMenuItems(false);
|
updateMenuItems(false);
|
||||||
stopRecording();
|
stopRecording();
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.menu_insert_marker:
|
||||||
|
// TODO:
|
||||||
|
return true;
|
||||||
|
case R.id.menu_play:
|
||||||
|
if (PlayTrackUtils.isEarthInstalled(this)) {
|
||||||
|
PlayTrackUtils.playTrack(this, trackId);
|
||||||
|
} else {
|
||||||
|
showDialog(DIALOG_INSTALL_EARTH_ID);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case R.id.menu_share_map:
|
||||||
|
intent = new Intent(this, UploadServiceChooserActivity.class)
|
||||||
|
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, true, false, false));
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_share_fusion_table:
|
||||||
|
intent = new Intent(this, UploadServiceChooserActivity.class)
|
||||||
|
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, false, true, false));
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_share_gpx:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.GPX, true);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_share_kml:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.KML, true);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_share_csv:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.CSV, true);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_share_tcx:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.TCX, true);
|
||||||
|
return true;
|
||||||
case R.id.menu_markers:
|
case R.id.menu_markers:
|
||||||
Intent intent = new Intent(this, WaypointsList.class)
|
intent = new Intent(this, WaypointsList.class)
|
||||||
.putExtra("trackid", trackDataHub.getSelectedTrackId());
|
.putExtra("trackid", trackDataHub.getSelectedTrackId());
|
||||||
startActivityForResult(intent, Constants.SHOW_WAYPOINT);
|
startActivityForResult(intent, Constants.SHOW_WAYPOINT);
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.menu_send_google:
|
||||||
|
intent = new Intent(this, UploadServiceChooserActivity.class)
|
||||||
|
.putExtra(SendRequest.SEND_REQUEST_KEY, new SendRequest(trackId, true, true, true));
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_save_gpx:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.GPX, false);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_save_kml:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.KML, false);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_save_csv:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.CSV, false);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_save_tcx:
|
||||||
|
startSaveActivity(trackId, TrackFileFormat.TCX, false);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_edit:
|
||||||
|
startActivity(new Intent(this, TrackEditActivity.class)
|
||||||
|
.putExtra(TrackEditActivity.TRACK_ID, trackId));
|
||||||
|
return true;
|
||||||
|
case R.id.menu_delete:
|
||||||
|
showDialog(DIALOG_DELETE_CURRENT_ID);
|
||||||
|
return true;
|
||||||
|
case R.id.menu_my_location:
|
||||||
|
mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
mapActivity.showMyLocation();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case R.id.menu_satellite_mode:
|
||||||
|
mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
mapActivity.setSatelliteView(!mapActivity.isSatelliteView());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case R.id.menu_chart_settings:
|
||||||
|
ChartActivity chartActivity = getChartActivity();
|
||||||
|
if (chartActivity != null) {
|
||||||
|
chartActivity.showChartSettingsDialog();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
case R.id.menu_sensor_state:
|
case R.id.menu_sensor_state:
|
||||||
startActivity(new Intent(this, SensorStateActivity.class));
|
startActivity(new Intent(this, SensorStateActivity.class));
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_settings:
|
case R.id.menu_settings:
|
||||||
startActivity(new Intent(this, SettingsActivity.class));
|
startActivity(new Intent(this, SettingsActivity.class));
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_aggregated_statistics:
|
|
||||||
startActivity(new Intent(this, AggregatedStatsActivity.class));
|
|
||||||
return true;
|
|
||||||
case R.id.menu_help:
|
case R.id.menu_help:
|
||||||
startActivity(new Intent(this, WelcomeActivity.class));
|
startActivity(new Intent(this, WelcomeActivity.class));
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_search:
|
|
||||||
onSearchRequested();
|
|
||||||
return true;
|
|
||||||
case R.id.menu_chart_settings:
|
|
||||||
ChartActivity chartActivity = (ChartActivity) getLocalActivityManager()
|
|
||||||
.getActivity(CHART_TAB_TAG);
|
|
||||||
if (chartActivity != null) {
|
|
||||||
chartActivity.showChartSettingsDialog();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case R.id.menu_my_location:
|
|
||||||
mapActivity = (MapActivity) getLocalActivityManager().getActivity(MAP_TAB_TAG);
|
|
||||||
if (mapActivity != null) {
|
|
||||||
mapActivity.showMyLocation();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case R.id.menu_satellite_mode:
|
|
||||||
mapActivity = (MapActivity) getLocalActivityManager().getActivity(MAP_TAB_TAG);
|
|
||||||
if (mapActivity != null) {
|
|
||||||
mapActivity.setSatelliteView(!mapActivity.isSatelliteView());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -296,7 +377,7 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, final Intent results) {
|
public void onActivityResult(int requestCode, int resultCode, final Intent results) {
|
||||||
if (requestCode != Constants.SHOW_WAYPOINT) {
|
if (requestCode != Constants.SHOW_WAYPOINT) {
|
||||||
Log.d(TAG, "Warning unhandled request code: " + requestCode);
|
Log.d(TAG, "Invalid request code: " + requestCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (results != null) {
|
if (results != null) {
|
||||||
@@ -314,18 +395,30 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
@Override
|
@Override
|
||||||
public boolean onTrackballEvent(MotionEvent event) {
|
public boolean onTrackballEvent(MotionEvent event) {
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
if (ServiceUtils.isRecording(this, trackRecordingServiceConnection.getServiceIfBound(), sharedPreferences)) {
|
if (isRecording()) {
|
||||||
try {
|
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection
|
||||||
insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
|
.getServiceIfBound();
|
||||||
} catch (RemoteException e) {
|
if (trackRecordingService == null) {
|
||||||
Log.e(TAG, "Cannot insert statistics marker.", e);
|
Log.e(TAG, "The track recording service is null");
|
||||||
} catch (IllegalStateException e) {
|
return true;
|
||||||
Log.e(TAG, "Cannot insert statistics marker.", e);
|
|
||||||
}
|
}
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
long waypointId = trackRecordingService.insertWaypoint(
|
||||||
|
WaypointCreationRequest.DEFAULT_STATISTICS);
|
||||||
|
if (waypointId != -1L) {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Unable to insert waypoint", e);
|
||||||
|
}
|
||||||
|
Toast.makeText(this,
|
||||||
|
success ? R.string.marker_insert_success : R.string.marker_insert_error,
|
||||||
|
success ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG)
|
||||||
|
.show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onTrackballEvent(event);
|
return super.onTrackballEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,85 +430,87 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showWaypoint(long trackId, long waypointId) {
|
/**
|
||||||
MapActivity map =
|
* Updates the menu.
|
||||||
(MapActivity) getLocalActivityManager().getActivity("tab1");
|
*/
|
||||||
if (map != null) {
|
private void updateMenu() {
|
||||||
getTabHost().setCurrentTab(0);
|
updateMenuItems(isRecording());
|
||||||
map.showWaypoint(trackId, waypointId);
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Couldnt' get map tab");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a waypoint marker.
|
* s Updates the menu items.
|
||||||
*
|
*
|
||||||
* TODO: Merge with WaypointsList#insertWaypoint.
|
* @param isRecording true if recording
|
||||||
|
*/
|
||||||
|
private void updateMenuItems(boolean isRecording) {
|
||||||
|
if (stopRecording != null) {
|
||||||
|
stopRecording.setVisible(isRecording);
|
||||||
|
}
|
||||||
|
if (insertMarker != null) {
|
||||||
|
insertMarker.setVisible(isRecording);
|
||||||
|
}
|
||||||
|
if (play != null) {
|
||||||
|
play.setVisible(!isRecording);
|
||||||
|
}
|
||||||
|
if (share != null) {
|
||||||
|
share.setVisible(!isRecording);
|
||||||
|
}
|
||||||
|
if (sendGoogle != null) {
|
||||||
|
sendGoogle.setVisible(!isRecording);
|
||||||
|
}
|
||||||
|
if (save != null) {
|
||||||
|
save.setVisible(!isRecording);
|
||||||
|
}
|
||||||
|
if (edit != null) {
|
||||||
|
edit.setVisible(!isRecording);
|
||||||
|
}
|
||||||
|
if (delete != null) {
|
||||||
|
delete.setVisible(!isRecording);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the {@link TrackListActivity} and ends this activity.
|
||||||
|
*/
|
||||||
|
private void startTrackListActivity() {
|
||||||
|
Intent intent = new Intent(this, TrackListActivity.class)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the {@link SaveActivity} to save a track.
|
||||||
*
|
*
|
||||||
* @return Id of the inserted statistics marker.
|
* @param trackId the track id
|
||||||
* @throws RemoteException If the call on the service failed.
|
* @param trackFileFormat the track file format
|
||||||
|
* @param shareTrack true to share the track after saving
|
||||||
*/
|
*/
|
||||||
private long insertWaypoint(WaypointCreationRequest request) throws RemoteException {
|
private void startSaveActivity(
|
||||||
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
long trackId, TrackFileFormat trackFileFormat, boolean shareTrack) {
|
||||||
if (trackRecordingService == null) {
|
Intent intent = new Intent(this, SaveActivity.class)
|
||||||
throw new IllegalStateException("The recording service is not bound.");
|
.putExtra(SaveActivity.EXTRA_TRACK_ID, trackId)
|
||||||
}
|
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat)
|
||||||
try {
|
.putExtra(SaveActivity.EXTRA_SHARE_TRACK, shareTrack);
|
||||||
long waypointId = trackRecordingService.insertWaypoint(request);
|
startActivity(intent);
|
||||||
if (waypointId >= 0) {
|
|
||||||
Toast.makeText(this, R.string.marker_insert_success, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
return waypointId;
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Toast.makeText(this, R.string.marker_insert_error, Toast.LENGTH_LONG).show();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRecordingNewTrack(
|
|
||||||
ITrackRecordingService trackRecordingService) {
|
|
||||||
try {
|
|
||||||
long recordingTrackId = trackRecordingService.startNewTrack();
|
|
||||||
// Select the recording track.
|
|
||||||
trackDataHub.loadTrack(recordingTrackId);
|
|
||||||
Toast.makeText(this, getString(R.string.track_record_success), Toast.LENGTH_SHORT).show();
|
|
||||||
// TODO: We catch Exception, because after eliminating the service process
|
|
||||||
// all exceptions it may throw are no longer wrapped in a RemoteException.
|
|
||||||
} catch (Exception e) {
|
|
||||||
Toast.makeText(this, getString(R.string.track_record_error), Toast.LENGTH_SHORT).show();
|
|
||||||
Log.w(TAG, "Unable to start recording.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the track recording service (if not already running) and binds to
|
* Returns true if recording.
|
||||||
* it. Starts recording a new track.
|
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
private boolean isRecording() {
|
||||||
void startRecording() {
|
return ServiceUtils.isRecording(
|
||||||
synchronized (trackRecordingServiceConnection) {
|
this, trackRecordingServiceConnection.getServiceIfBound(), sharedPreferences);
|
||||||
startNewTrackRequested = true;
|
|
||||||
trackRecordingServiceConnection.startAndBind();
|
|
||||||
|
|
||||||
// Binding was already requested before, it either already happened
|
|
||||||
// (in which case running the callback manually triggers the actual recording start)
|
|
||||||
// or it will happen in the future
|
|
||||||
// (in which case running the callback now will have no effect).
|
|
||||||
serviceBindCallback.run();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the track recording service and unbinds from it. Will display a toast
|
* Stops the recording and the track recording service connection and shows
|
||||||
* "Stopped recording" and pop up the Track Details activity.
|
* {@link TrackEditActivity}.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
private void stopRecording() {
|
||||||
void stopRecording() {
|
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection
|
||||||
// Save the track id as the shared preference will overwrite the recording track id.
|
.getServiceIfBound();
|
||||||
long currentTrackId = sharedPreferences.getLong(getString(R.string.recording_track_key), -1L);
|
|
||||||
|
|
||||||
ITrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
|
||||||
if (trackRecordingService != null) {
|
if (trackRecordingService != null) {
|
||||||
try {
|
try {
|
||||||
trackRecordingService.endCurrentTrack();
|
trackRecordingService.endCurrentTrack();
|
||||||
@@ -423,14 +518,28 @@ public class TrackDetailActivity extends TabActivity implements OnTouchListener
|
|||||||
Log.e(TAG, "Unable to stop recording.", e);
|
Log.e(TAG, "Unable to stop recording.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackRecordingServiceConnection.stop();
|
trackRecordingServiceConnection.stop();
|
||||||
|
|
||||||
if (currentTrackId > 0) {
|
long recordingTrackId = sharedPreferences.getLong(getString(R.string.recording_track_key), -1L);
|
||||||
|
if (recordingTrackId != -1L) {
|
||||||
Intent intent = new Intent(this, TrackEditActivity.class)
|
Intent intent = new Intent(this, TrackEditActivity.class)
|
||||||
.putExtra(TrackEditActivity.SHOW_CANCEL, false)
|
.putExtra(TrackEditActivity.SHOW_CANCEL, false)
|
||||||
.putExtra(TrackEditActivity.TRACK_ID, currentTrackId);
|
.putExtra(TrackEditActivity.TRACK_ID, recordingTrackId);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the map activity, can be null.
|
||||||
|
*/
|
||||||
|
private MapActivity getMapActivity() {
|
||||||
|
return (MapActivity) getLocalActivityManager().getActivity(MAP_TAB_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the chart activity, can be null.
|
||||||
|
*/
|
||||||
|
private ChartActivity getChartActivity() {
|
||||||
|
return (ChartActivity) getLocalActivityManager().getActivity(CHART_TAB_TAG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -35,6 +35,7 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
@@ -67,11 +68,11 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
private static final String TAG = TrackListActivity.class.getSimpleName();
|
private static final String TAG = TrackListActivity.class.getSimpleName();
|
||||||
private static final String CHECK_UNITS_DIALOG_TAG = "checkUnitsDialog";
|
private static final String CHECK_UNITS_DIALOG_TAG = "checkUnitsDialog";
|
||||||
private static final String DELETE_ALL_DIALOG_TAG = "deleteAllDialog";
|
private static final String DELETE_ALL_DIALOG_TAG = "deleteAllDialog";
|
||||||
private static final String EULA_DIALOG_TAG = "eulaDialog";
|
private static final String EULA_DIALOG_TAG = "eulaDialog";
|
||||||
private static final String EXPORT_ALL_DIALOG_TAG = "exportAllDialog";
|
private static final String EXPORT_ALL_DIALOG_TAG = "exportAllDialog";
|
||||||
|
|
||||||
private static final int WELCOME_ACTIVITY_REQUEST_CODE = 0;
|
private static final int WELCOME_ACTIVITY_REQUEST_CODE = 0;
|
||||||
|
|
||||||
private static final String[] PROJECTION = new String[] {
|
private static final String[] PROJECTION = new String[] {
|
||||||
TracksColumns._ID,
|
TracksColumns._ID,
|
||||||
TracksColumns.NAME,
|
TracksColumns.NAME,
|
||||||
@@ -81,21 +82,57 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
TracksColumns.STARTTIME,
|
TracksColumns.STARTTIME,
|
||||||
TracksColumns.DESCRIPTION };
|
TracksColumns.DESCRIPTION };
|
||||||
|
|
||||||
// Callback when the trackRecordingServiceConnection binding changes
|
// Callback when the trackRecordingServiceConnection binding changes.
|
||||||
private final Runnable bindChangedCallback = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized (trackRecordingServiceConnection) {
|
if (startNewRecording) {
|
||||||
if (startNewRecording) {
|
ITrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
startRecording();
|
if (service != null) {
|
||||||
|
try {
|
||||||
|
recordingTrackId = service.startNewTrack();
|
||||||
|
startNewRecording = false;
|
||||||
|
Toast.makeText(
|
||||||
|
TrackListActivity.this, R.string.track_list_record_success, Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
Log.d(TAG, "Started a new recording");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Toast.makeText(
|
||||||
|
TrackListActivity.this, R.string.track_list_record_error, Toast.LENGTH_LONG).show();
|
||||||
|
Log.d(TAG, "Unable to start a new recording.", e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
updateMenu();
|
Log.d(TAG, "service not available to start a new recording");
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that sharedPreferenceChangeListenr cannot be an anonymous inner class.
|
||||||
|
* Anonymous inner class will get garbage collected.
|
||||||
|
*/
|
||||||
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener =
|
||||||
|
new OnSharedPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
|
if (key == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (key.equals(getString(R.string.metric_units_key))) {
|
||||||
|
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
|
||||||
|
}
|
||||||
|
if (key.equals(getString(R.string.recording_track_key))) {
|
||||||
|
recordingTrackId = sharedPreferences.getLong(getString(R.string.recording_track_key), -1L);
|
||||||
|
if (isRecording()) {
|
||||||
|
trackRecordingServiceConnection.startAndBind();
|
||||||
|
}
|
||||||
|
updateMenu();
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private boolean metricUnits;
|
private boolean metricUnits;
|
||||||
@@ -103,7 +140,7 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
private ListView listView;
|
private ListView listView;
|
||||||
private ResourceCursorAdapter adapter;
|
private ResourceCursorAdapter adapter;
|
||||||
|
|
||||||
// True to start a new recording
|
// True to start a new recording.
|
||||||
private boolean startNewRecording = false;
|
private boolean startNewRecording = false;
|
||||||
|
|
||||||
private MenuItem recordTrack;
|
private MenuItem recordTrack;
|
||||||
@@ -119,28 +156,12 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
|
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
|
||||||
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
|
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
|
||||||
setContentView(R.layout.track_list);
|
setContentView(R.layout.track_list);
|
||||||
|
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(
|
||||||
this, bindChangedCallback);
|
this, bindChangedCallback);
|
||||||
|
|
||||||
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||||
sharedPreferences.registerOnSharedPreferenceChangeListener(
|
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
|
||||||
new SharedPreferences.OnSharedPreferenceChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
|
||||||
if (key == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (key.equals(getString(R.string.metric_units_key))) {
|
|
||||||
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
|
|
||||||
}
|
|
||||||
if (key.equals(getString(R.string.recording_track_key))) {
|
|
||||||
recordingTrackId = sharedPreferences.getLong(
|
|
||||||
getString(R.string.recording_track_key), -1L);
|
|
||||||
}
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
metricUnits = sharedPreferences.getBoolean(getString(R.string.metric_units_key), true);
|
metricUnits = sharedPreferences.getBoolean(getString(R.string.metric_units_key), true);
|
||||||
recordingTrackId = sharedPreferences.getLong(getString(R.string.recording_track_key), -1L);
|
recordingTrackId = sharedPreferences.getLong(getString(R.string.recording_track_key), -1L);
|
||||||
|
|
||||||
@@ -216,7 +237,7 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
adapter.swapCursor(null);
|
adapter.swapCursor(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!EulaUtils.getEulaValue(this)) {
|
if (!EulaUtils.getEulaValue(this)) {
|
||||||
new EulaDialogFragment().show(getSupportFragmentManager(), EULA_DIALOG_TAG);
|
new EulaDialogFragment().show(getSupportFragmentManager(), EULA_DIALOG_TAG);
|
||||||
}
|
}
|
||||||
@@ -225,18 +246,16 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
if (ServiceUtils.isRecording(
|
if (isRecording()) {
|
||||||
this, trackRecordingServiceConnection.getServiceIfBound(), sharedPreferences)) {
|
|
||||||
trackRecordingServiceConnection.startAndBind();
|
trackRecordingServiceConnection.startAndBind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
trackRecordingServiceConnection.bindIfRunning();
|
trackRecordingServiceConnection.bindIfRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
@@ -250,9 +269,10 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
if (!CheckUnitsUtils.getCheckUnitsValue(this)) {
|
if (!CheckUnitsUtils.getCheckUnitsValue(this)) {
|
||||||
/*
|
/*
|
||||||
* See bug http://code.google.com/p/android/issues/detail?id=23761.
|
* See bug http://code.google.com/p/android/issues/detail?id=23761.
|
||||||
* Instead of
|
* Cannot use
|
||||||
* new CheckUnitsDialogFragment().show(getSupportFragmentManager(), CHECK_UNITS_DIALOG_TAG)
|
* CheckUnitsDialogFragment().show(getSupportFragmentManager(),
|
||||||
* Need to use commitAllowingStateLoss with the support package.
|
* CHECK_UNITS_DIALOG_TAG). Need to use commitAllowingStateLoss with the
|
||||||
|
* support package.
|
||||||
*/
|
*/
|
||||||
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
|
||||||
fragmentTransaction.add(new CheckUnitsDialogFragment(), CHECK_UNITS_DIALOG_TAG);
|
fragmentTransaction.add(new CheckUnitsDialogFragment(), CHECK_UNITS_DIALOG_TAG);
|
||||||
@@ -260,7 +280,7 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.track_list, menu);
|
getMenuInflater().inflate(R.menu.track_list, menu);
|
||||||
@@ -281,8 +301,7 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
* Updates the menu based on whether My Tracks is recording or not.
|
* Updates the menu based on whether My Tracks is recording or not.
|
||||||
*/
|
*/
|
||||||
private void updateMenu() {
|
private void updateMenu() {
|
||||||
boolean isRecording = ServiceUtils.isRecording(
|
boolean isRecording = isRecording();
|
||||||
this, trackRecordingServiceConnection.getServiceIfBound(), sharedPreferences);
|
|
||||||
updateMenuItems(isRecording);
|
updateMenuItems(isRecording);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,23 +333,11 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_record_track:
|
case R.id.menu_record_track:
|
||||||
updateMenuItems(true);
|
updateMenuItems(true);
|
||||||
synchronized (trackRecordingServiceConnection) {
|
startRecording();
|
||||||
startNewRecording = true;
|
|
||||||
trackRecordingServiceConnection.startAndBind();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the binding has happened, then invoke the callback to start a
|
|
||||||
* new recording. If the binding hasn't happened, then invoking the
|
|
||||||
* callback will have no effect. But when the binding occurs, the
|
|
||||||
* callback will get invoked.
|
|
||||||
*/
|
|
||||||
bindChangedCallback.run();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_stop_recording:
|
case R.id.menu_stop_recording:
|
||||||
updateMenuItems(false);
|
updateMenuItems(false);
|
||||||
stopRecording();
|
stopRecording();
|
||||||
trackRecordingServiceConnection.stop();
|
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_search:
|
case R.id.menu_search:
|
||||||
return ApiAdapterFactory.getApiAdapter().handleSearchMenuSelection(this);
|
return ApiAdapterFactory.getApiAdapter().handleSearchMenuSelection(this);
|
||||||
@@ -358,27 +365,28 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if recording.
|
||||||
|
*/
|
||||||
|
private boolean isRecording() {
|
||||||
|
return ServiceUtils.isRecording(
|
||||||
|
this, trackRecordingServiceConnection.getServiceIfBound(), sharedPreferences);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a new recording.
|
* Starts a new recording.
|
||||||
*/
|
*/
|
||||||
private void startRecording() {
|
private void startRecording() {
|
||||||
ITrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
|
startNewRecording = true;
|
||||||
if (service != null) {
|
trackRecordingServiceConnection.startAndBind();
|
||||||
try {
|
|
||||||
recordingTrackId = service.startNewTrack();
|
/*
|
||||||
startNewRecording = false;
|
* If the binding has happened, then invoke the callback to start a new
|
||||||
adapter.notifyDataSetChanged();
|
* recording. If the binding hasn't happened, then invoking the callback
|
||||||
Toast.makeText(TrackListActivity.this, R.string.track_record_success, Toast.LENGTH_SHORT)
|
* will have no effect. But when the binding occurs, the callback will get
|
||||||
.show();
|
* invoked.
|
||||||
Log.d(TAG, "Started a new recording");
|
*/
|
||||||
} catch (Exception e) {
|
bindChangedCallback.run();
|
||||||
Toast.makeText(TrackListActivity.this, R.string.track_record_error, Toast.LENGTH_LONG)
|
|
||||||
.show();
|
|
||||||
Log.d(TAG, "Unable to start a new recording.", e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "service not available to start a new recording");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -396,17 +404,27 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
recordingTrackId = -1L;
|
recordingTrackId = -1L;
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d(TAG, "Unable to stop recording.", e);
|
Log.d(TAG, "Unable to stop recording.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
trackRecordingServiceConnection.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||||
|
if (ApiAdapterFactory.getApiAdapter().handleSearchKey(search)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onKeyUp(keyCode, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check Units DialogFragment.
|
* Check Units DialogFragment.
|
||||||
*/
|
*/
|
||||||
private static class CheckUnitsDialogFragment extends DialogFragment {
|
public static class CheckUnitsDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
@@ -438,7 +456,7 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
/**
|
/**
|
||||||
* Delete All DialogFragment.
|
* Delete All DialogFragment.
|
||||||
*/
|
*/
|
||||||
private static class DeleteAllDialogFragment extends DialogFragment {
|
public static class DeleteAllDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
@@ -446,7 +464,7 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
R.string.track_list_delete_all_confirm_message, new DialogInterface.OnClickListener() {
|
R.string.track_list_delete_all_confirm_message, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
MyTracksProviderUtils.Factory.get(getActivity()).deleteAllTracks();
|
MyTracksProviderUtils.Factory.get(getActivity()).deleteAllTracks();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -455,14 +473,13 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
/**
|
/**
|
||||||
* Eula DialogFragment.
|
* Eula DialogFragment.
|
||||||
*/
|
*/
|
||||||
private static class EulaDialogFragment extends DialogFragment {
|
public static class EulaDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
return new AlertDialog.Builder(getActivity())
|
return new AlertDialog.Builder(getActivity())
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setMessage(
|
.setMessage(EulaUtils.getEulaMessage(getActivity()))
|
||||||
EulaUtils.getEulaMessage(getActivity()))
|
|
||||||
.setNegativeButton(R.string.eula_decline, new DialogInterface.OnClickListener() {
|
.setNegativeButton(R.string.eula_decline, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
@@ -491,15 +508,14 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
/**
|
/**
|
||||||
* Export All DialogFragment.
|
* Export All DialogFragment.
|
||||||
*/
|
*/
|
||||||
private static class ExportAllDialogFragment extends DialogFragment {
|
public static class ExportAllDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
String exportFileFormat = getString(R.string.track_list_export_file);
|
|
||||||
String fileTypes[] = getResources().getStringArray(R.array.file_types);
|
String fileTypes[] = getResources().getStringArray(R.array.file_types);
|
||||||
String[] choices = new String[fileTypes.length];
|
String[] choices = new String[fileTypes.length];
|
||||||
for (int i = 0; i < fileTypes.length; i++) {
|
for (int i = 0; i < fileTypes.length; i++) {
|
||||||
choices[i] = String.format(exportFileFormat, fileTypes[i]);
|
choices[i] = getString(R.string.menu_export_all_format, fileTypes[i]);
|
||||||
}
|
}
|
||||||
return new AlertDialog.Builder(getActivity()).setNegativeButton(R.string.generic_cancel, null)
|
return new AlertDialog.Builder(getActivity()).setNegativeButton(R.string.generic_cancel, null)
|
||||||
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
||||||
@@ -516,15 +532,5 @@ public class TrackListActivity extends FragmentActivity {
|
|||||||
.setTitle(R.string.menu_export_all)
|
.setTitle(R.string.menu_export_all)
|
||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
|
||||||
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
|
||||||
if (ApiAdapterFactory.getApiAdapter().handleSearchKey(search)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onKeyUp(keyCode, event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.google.android.apps.mytracks.io.backup;
|
package com.google.android.apps.mytracks.io.backup;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.TrackDetailActivity;
|
import com.google.android.apps.mytracks.TrackListActivity;
|
||||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ public class RestoreActivity extends Activity {
|
|||||||
removeDialog(DIALOG_PROGRESS_ID);
|
removeDialog(DIALOG_PROGRESS_ID);
|
||||||
Toast.makeText(this, messageId, success ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show();
|
Toast.makeText(this, messageId, success ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show();
|
||||||
startActivity(
|
startActivity(
|
||||||
new Intent(this, TrackDetailActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
|
new Intent(this, TrackListActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -484,9 +484,10 @@ public class TrackRecordingService extends Service {
|
|||||||
Notification notification = new Notification(
|
Notification notification = new Notification(
|
||||||
R.drawable.arrow_320, null /* tickerText */,
|
R.drawable.arrow_320, null /* tickerText */,
|
||||||
System.currentTimeMillis());
|
System.currentTimeMillis());
|
||||||
|
Intent intent = new Intent(this, TrackDetailActivity.class)
|
||||||
|
.putExtra(TrackDetailActivity.TRACK_ID, recordingTrackId);
|
||||||
PendingIntent contentIntent = PendingIntent.getActivity(
|
PendingIntent contentIntent = PendingIntent.getActivity(
|
||||||
this, 0 /* requestCode */, new Intent(this, TrackDetailActivity.class),
|
this, 0 /* requestCode */, intent, 0 /* flags */);
|
||||||
0 /* flags */);
|
|
||||||
notification.setLatestEventInfo(this, getString(R.string.my_tracks_app_name),
|
notification.setLatestEventInfo(this, getString(R.string.my_tracks_app_name),
|
||||||
getString(R.string.track_record_notification), contentIntent);
|
getString(R.string.track_record_notification), contentIntent);
|
||||||
notification.flags += Notification.FLAG_NO_CLEAR;
|
notification.flags += Notification.FLAG_NO_CLEAR;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class PlayTrackUtils {
|
|||||||
public static Dialog createInstallEarthDialog(final Context context) {
|
public static Dialog createInstallEarthDialog(final Context context) {
|
||||||
return new AlertDialog.Builder(context)
|
return new AlertDialog.Builder(context)
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setMessage(R.string.track_list_play_install_earth_message)
|
.setMessage(R.string.track_detail_install_earth_message)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -146,6 +146,9 @@ public class TrackWidgetProvider
|
|||||||
|
|
||||||
// Make all of the stats open the mytracks activity.
|
// Make all of the stats open the mytracks activity.
|
||||||
Intent intent = new Intent(context, TrackDetailActivity.class);
|
Intent intent = new Intent(context, TrackDetailActivity.class);
|
||||||
|
if (track != null) {
|
||||||
|
intent.putExtra(TrackDetailActivity.TRACK_ID, track.getId());
|
||||||
|
}
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
||||||
views.setOnClickPendingIntent(R.id.appwidget_track_statistics, pendingIntent);
|
views.setOnClickPendingIntent(R.id.appwidget_track_statistics, pendingIntent);
|
||||||
|
|
||||||
|
|||||||
@@ -19,15 +19,12 @@ import com.google.android.apps.mytracks.services.ServiceUtils;
|
|||||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Instrumentation.ActivityMonitor;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.Editor;
|
import android.content.SharedPreferences.Editor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
@@ -112,62 +109,6 @@ public class TrackDetailActivityTest extends ActivityInstrumentationTestCase2<Tr
|
|||||||
// TODO: Finish this test.
|
// TODO: Finish this test.
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRecording_startAndStop() throws Exception {
|
|
||||||
assertInitialized();
|
|
||||||
|
|
||||||
// Check if not recording.
|
|
||||||
clearSelectedAndRecordingTracks();
|
|
||||||
waitForIdle();
|
|
||||||
|
|
||||||
assertFalse(isRecording());
|
|
||||||
assertEquals(-1, getRecordingTrackId());
|
|
||||||
|
|
||||||
// Start a new track.
|
|
||||||
getActivity().startRecording();
|
|
||||||
serviceConnection.bindIfRunning();
|
|
||||||
long recordingTrackId = awaitRecordingStatus(5000, true);
|
|
||||||
assertTrue(recordingTrackId >= 0);
|
|
||||||
|
|
||||||
// Wait until we are done and make sure that selectedTrack = recordingTrack.
|
|
||||||
waitForIdle();
|
|
||||||
assertEquals(recordingTrackId, getSharedPreferences().getLong(
|
|
||||||
getActivity().getString(R.string.recording_track_key), -1));
|
|
||||||
long selectedTrackId = getSharedPreferences().getLong(
|
|
||||||
getActivity().getString(R.string.selected_track_key), -1);
|
|
||||||
assertEquals(recordingTrackId, selectedTrackId);
|
|
||||||
|
|
||||||
// Watch for MyTracksDetails activity.
|
|
||||||
ActivityMonitor monitor = getInstrumentation().addMonitor(
|
|
||||||
TrackEditActivity.class.getName(), null, false);
|
|
||||||
|
|
||||||
// Now, stop the track and make sure that it is still selected, but
|
|
||||||
// no longer recording.
|
|
||||||
getActivity().stopRecording();
|
|
||||||
|
|
||||||
// Check if we got back MyTracksDetails activity.
|
|
||||||
Activity activity = getInstrumentation().waitForMonitor(monitor);
|
|
||||||
assertTrue(activity instanceof TrackEditActivity);
|
|
||||||
|
|
||||||
// TODO: Update track name and other properties and test if they were
|
|
||||||
// properly saved.
|
|
||||||
|
|
||||||
// Simulate a click on Save button.
|
|
||||||
final Button save = (Button) activity.findViewById(R.id.track_edit_save);
|
|
||||||
getActivity().runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
save.performClick();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check the remaining properties.
|
|
||||||
recordingTrackId = awaitRecordingStatus(5000, false);
|
|
||||||
assertEquals(-1, recordingTrackId);
|
|
||||||
assertEquals(recordingTrackId, getRecordingTrackId());
|
|
||||||
assertEquals(recordingTrackId, getSharedPreferences().getLong(
|
|
||||||
getActivity().getString(R.string.recording_track_key), -1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertInitialized() {
|
private void assertInitialized() {
|
||||||
assertNotNull(getActivity());
|
assertNotNull(getActivity());
|
||||||
|
|
||||||
|
|||||||