merge heads

This commit is contained in:
Jimmy Shih
2012-04-02 14:49:12 -07:00
parent 0bd4461c32
commit 2d05ff98ca
75 changed files with 783 additions and 794 deletions
+1 -2
View File
@@ -137,8 +137,7 @@ limitations under the License.
android:icon="@drawable/arrow_icon" android:icon="@drawable/arrow_icon"
android:label="@string/my_tracks_app_name" android:label="@string/my_tracks_app_name"
android:name="com.google.android.apps.mytracks.MyTracksApplication" android:name="com.google.android.apps.mytracks.MyTracksApplication"
android:theme="@style/ThemeSelector" android:theme="@style/ThemeSelector" >
android:uiOptions="splitActionBarWhenNarrow" >
<!-- For data backup --> <!-- For data backup -->
<meta-data <meta-data
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -49,8 +49,7 @@ limitations under the License.
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:singleLine="true" android:singleLine="true"
android:autoText="true" android:inputType="textAutoCorrect|textCapWords"
android:capitalize="words"
android:selectAllOnFocus="true" android:selectAllOnFocus="true"
android:hint="@string/marker_detail_marker_name" android:hint="@string/marker_detail_marker_name"
android:imeOptions="actionNext"/> android:imeOptions="actionNext"/>
@@ -78,8 +77,7 @@ limitations under the License.
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:singleLine="false" android:singleLine="false"
android:autoText="true" android:inputType="textAutoCorrect|textCapSentences"
android:capitalize="sentences"
android:selectAllOnFocus="true" android:selectAllOnFocus="true"
android:minLines="5" android:minLines="5"
android:maxLines="50" android:maxLines="50"
-2
View File
@@ -204,8 +204,6 @@ limitations under the License.
style="@style/StatsUnit" /> style="@style/StatsUnit" />
<TextView <TextView
style="@style/StatsDivider" /> style="@style/StatsDivider" />
android:layout_height="3dp"
android:layout_width="fill_parent" />
<TextView <TextView
android:id="@+id/average_moving_speed_unit_label_bottom" android:id="@+id/average_moving_speed_unit_label_bottom"
style="@style/StatsUnit" /> style="@style/StatsUnit" />
+2 -4
View File
@@ -52,8 +52,7 @@ limitations under the License.
android:src="@drawable/track" android:src="@drawable/track"
/> />
<EditText <EditText
android:autoText="true" android:inputType="textAutoCorrect|textCapWords"
android:capitalize="words"
android:hint="@string/track_detail_track_name" android:hint="@string/track_detail_track_name"
android:id="@+id/track_detail_track_name" android:id="@+id/track_detail_track_name"
android:imeOptions="actionNext" android:imeOptions="actionNext"
@@ -81,8 +80,7 @@ limitations under the License.
android:text="@string/track_detail_track_description" android:text="@string/track_detail_track_description"
/> />
<EditText <EditText
android:autoText="true" android:inputType="textAutoCorrect|textCapSentences"
android:capitalize="sentences"
android:hint="@string/track_detail_track_description" android:hint="@string/track_detail_track_description"
android:id="@+id/track_detail_track_description" android:id="@+id/track_detail_track_description"
android:imeOptions="actionDone" android:imeOptions="actionDone"
+2 -2
View File
@@ -54,7 +54,7 @@ limitations under the License.
style="@style/WidgetTextView" style="@style/WidgetTextView"
android:text="@string/stat_total_distance" /> android:text="@string/stat_total_distance" />
</LinearLayout> </LinearLayout>
<ImageView <LinearLayout
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="1dp" android:layout_height="1dp"
android:background="@color/appwidget_hr" /> android:background="@color/appwidget_hr" />
@@ -70,7 +70,7 @@ limitations under the License.
style="@style/WidgetTextView" style="@style/WidgetTextView"
android:text="@string/stat_moving_time" /> android:text="@string/stat_moving_time" />
</LinearLayout> </LinearLayout>
<ImageView <LinearLayout
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="1dp" android:layout_height="1dp"
android:background="@color/appwidget_hr" /> android:background="@color/appwidget_hr" />
+16 -39
View File
@@ -18,20 +18,16 @@ limitations under the License.
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_margin="8dp" android:layout_margin="8dp"
android:layout_width="fill_parent" > android:layout_width="fill_parent" >
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:orientation="vertical" > android:orientation="vertical" >
<!-- Google Maps result --> <!-- Google Maps result -->
<LinearLayout <LinearLayout
android:id="@+id/upload_result_maps_result" android:id="@+id/upload_result_maps_result"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:orientation="horizontal" > android:orientation="horizontal" >
<ImageView <ImageView
android:contentDescription="@string/generic_success_title" android:contentDescription="@string/generic_success_title"
android:id="@+id/upload_result_maps_result_icon" android:id="@+id/upload_result_maps_result_icon"
@@ -39,35 +35,29 @@ limitations under the License.
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:src="@drawable/success" /> android:src="@drawable/success" />
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="8dp" > android:paddingLeft="8dp" >
<TextView <TextView
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_maps"
android:text="@string/send_google_maps" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
<TextView <TextView
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Small" android:text="@string/send_google_maps_url"
android:text="@string/send_google_maps_url" /> style="@android:style/TextAppearance.DeviceDefault.Small" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<!-- Google Fusion Tables result --> <!-- Google Fusion Tables result -->
<LinearLayout <LinearLayout
android:id="@+id/upload_result_fusion_tables_result" android:id="@+id/upload_result_fusion_tables_result"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:orientation="horizontal" > android:orientation="horizontal" >
<ImageView <ImageView
android:contentDescription="@string/generic_success_title" android:contentDescription="@string/generic_success_title"
android:id="@+id/upload_result_fusion_tables_result_icon" android:id="@+id/upload_result_fusion_tables_result_icon"
@@ -75,35 +65,29 @@ limitations under the License.
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:src="@drawable/success" /> android:src="@drawable/success" />
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="8dp" > android:paddingLeft="8dp" >
<TextView <TextView
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_fusion_tables"
android:text="@string/send_google_fusion_tables" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
<TextView <TextView
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Small" android:text="@string/send_google_fusion_tables_url"
android:text="@string/send_google_fusion_tables_url" /> style="@android:style/TextAppearance.DeviceDefault.Small" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<!-- Google Docs result --> <!-- Google Docs result -->
<LinearLayout <LinearLayout
android:id="@+id/upload_result_docs_result" android:id="@+id/upload_result_docs_result"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:orientation="horizontal" > android:orientation="horizontal" >
<ImageView <ImageView
android:contentDescription="@string/generic_success_title" android:contentDescription="@string/generic_success_title"
android:id="@+id/upload_result_docs_result_icon" android:id="@+id/upload_result_docs_result_icon"
@@ -111,44 +95,37 @@ limitations under the License.
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:src="@drawable/success" /> android:src="@drawable/success" />
<LinearLayout <LinearLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="8dp" > android:paddingLeft="8dp" >
<TextView <TextView
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_docs"
android:text="@string/send_google_docs" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
<TextView <TextView
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Small" android:text="@string/send_google_docs_url"
android:text="@string/send_google_docs_url" /> style="@android:style/TextAppearance.DeviceDefault.Small" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<!-- Footer --> <!-- Footer -->
<TextView <TextView
android:id="@+id/upload_result_success_footer" android:id="@+id/upload_result_success_footer"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:padding="8dp" android:padding="8dp"
style="@android:style/TextAppearance.DeviceDefault.Small" android:text="@string/send_google_success_footer"
android:text="@string/send_google_success_footer" /> style="@android:style/TextAppearance.DeviceDefault.Small" />
<TextView <TextView
android:id="@+id/upload_result_error_footer" android:id="@+id/upload_result_error_footer"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:padding="8dp" android:padding="8dp"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_error"
android:text="@string/send_google_error" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
+10 -24
View File
@@ -17,89 +17,75 @@ limitations under the License.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_width="fill_parent" > android:layout_width="fill_parent" >
<TableLayout <TableLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="8dp" android:layout_margin="8dp"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:stretchColumns="1" > android:stretchColumns="1" >
<TableRow android:id="@+id/send_google_maps_row" > <TableRow android:id="@+id/send_google_maps_row" >
<ImageView <ImageView
android:contentDescription="@string/send_google_maps" android:contentDescription="@string/send_google_maps"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:src="@drawable/maps_icon" /> android:src="@drawable/maps_icon" />
<CheckBox <CheckBox
android:id="@+id/send_google_maps" android:id="@+id/send_google_maps"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:layout_width="0dp" android:layout_width="0dp"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_maps"
android:text="@string/send_google_maps" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
</TableRow> </TableRow>
<TableRow android:id="@+id/send_google_maps_option_row" > <TableRow android:id="@+id/send_google_maps_option_row" >
<RadioGroup <RadioGroup
android:layout_column="1" android:layout_column="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:layout_width="0dp" > android:layout_width="0dp" >
<RadioButton <RadioButton
android:id="@+id/send_google_new_map" android:id="@+id/send_google_new_map"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_new_map"
android:text="@string/send_google_new_map" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
<RadioButton <RadioButton
android:id="@+id/send_google_existing_map" android:id="@+id/send_google_existing_map"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_existing_map"
android:text="@string/send_google_existing_map" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
</RadioGroup> </RadioGroup>
</TableRow> </TableRow>
<TableRow android:id="@+id/send_google_fusion_tables_row" > <TableRow android:id="@+id/send_google_fusion_tables_row" >
<ImageView <ImageView
android:contentDescription="@string/send_google_fusion_tables" android:contentDescription="@string/send_google_fusion_tables"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:src="@drawable/googledocs_icon" /> android:src="@drawable/googledocs_icon" />
<CheckBox <CheckBox
android:id="@+id/send_google_fusion_tables" android:id="@+id/send_google_fusion_tables"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:layout_width="0dp" android:layout_width="0dp"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_fusion_tables"
android:text="@string/send_google_fusion_tables" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
</TableRow> </TableRow>
<TableRow android:id="@+id/send_google_docs_row" > <TableRow android:id="@+id/send_google_docs_row" >
<ImageView <ImageView
android:contentDescription="@string/send_google_docs" android:contentDescription="@string/send_google_docs"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:src="@drawable/googledocs_icon" /> android:src="@drawable/googledocs_icon" />
<CheckBox <CheckBox
android:id="@+id/send_google_docs" android:id="@+id/send_google_docs"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:layout_width="0dp" android:layout_width="0dp"
style="@android:style/TextAppearance.DeviceDefault.Medium" android:text="@string/send_google_docs"
android:text="@string/send_google_docs" /> style="@android:style/TextAppearance.DeviceDefault.Medium" />
</TableRow> </TableRow>
</TableLayout> </TableLayout>
</ScrollView> </ScrollView>
+8 -25
View File
@@ -15,78 +15,61 @@ 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 <item
android:icon="@drawable/ic_menu_recordtrack" android:icon="@drawable/menu_record_track"
android:id="@+id/menu_record_track" android:id="@+id/menu_record_track"
android:showAsAction="always" android:showAsAction="always"
android:title="@string/menu_record_track"/> android:title="@string/menu_record_track"/>
<item <item
android:icon="@drawable/ic_menu_stoprecording" 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 <item
android:icon="@drawable/ic_menu_tracklist" android:icon="@drawable/ic_menu_tracklist"
android:id="@+id/menu_tracks" android:id="@+id/menu_tracks"
android:showAsAction="ifRoom" android:showAsAction="ifRoom"
android:title="@string/menu_tracks"/> android:title="@string/menu_tracks"/>
<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:showAsAction="ifRoom"
android:title="@string/menu_markers"/> android:title="@string/menu_markers"/>
<item <item
android:icon="@drawable/ic_menu_chartsettings" android:icon="@drawable/ic_menu_chartsettings"
android:id="@+id/menu_chart_settings" android:id="@+id/menu_chart_settings"
android:showAsAction="ifRoom" android:showAsAction="ifRoom"
android:title="@string/menu_chart_view_chart_settings" android:title="@string/menu_chart_settings"
android:visible="false"/> android:visible="false"/>
<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:showAsAction="ifRoom"
android:title="@string/menu_map_view_my_location" android:title="@string/menu_my_location"
android:visible="false"/> 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:showAsAction="ifRoom"
android:title="@string/menu_map_view_satellite_mode" android:title="@string/menu_satellite_mode"
android:visible="false"/> android:visible="false"/>
<item <item
android:icon="@android:drawable/ic_menu_search" android:icon="@drawable/menu_search"
android:id="@+id/menu_search" android:id="@+id/menu_search"
android:title="@string/menu_search"/> android:title="@string/menu_search"/>
<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"
android:orderInCategory="1000"
android:title="@string/menu_sensor_state"/> android:title="@string/menu_sensor_state"/>
<item <item
android:icon="@android:drawable/ic_menu_preferences" android:icon="@drawable/menu_settings"
android:id="@+id/menu_settings" android:id="@+id/menu_settings"
android:orderInCategory="1001"
android:title="@string/menu_settings"/> android:title="@string/menu_settings"/>
<item <item
android:id="@+id/menu_aggregated_statistics" android:id="@+id/menu_aggregated_statistics"
android:orderInCategory="1002"
android:title="@string/menu_aggregated_statistics"/> android:title="@string/menu_aggregated_statistics"/>
<item <item
android:icon="@android:drawable/ic_menu_info_details" android:icon="@drawable/menu_help"
android:id="@+id/menu_help" android:id="@+id/menu_help"
android:orderInCategory="1003"
android:title="@string/menu_help"/> android:title="@string/menu_help"/>
</menu> </menu>
+1 -1
View File
@@ -16,7 +16,7 @@ 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 <item
android:icon="@android:drawable/ic_menu_search" android:icon="@drawable/menu_search"
android:id="@+id/menu_search" android:id="@+id/menu_search"
android:showAsAction="always" android:showAsAction="always"
android:title="@string/menu_search"/> android:title="@string/menu_search"/>
+25 -69
View File
@@ -643,15 +643,12 @@ limitations under the License.
<string name="eula_body" <string name="eula_body"
translation_description="The body in the 'Terms of Service. See http://m.google.com/toscountry. translation_description="The body in the 'Terms of Service. See http://m.google.com/toscountry.
%1$s: host name, 'm.google.com' %1$s: host name, 'm.google.com'">
%2$s: host name, 'm.google.com'
%3$s: host name, 'm.google.com'
%4$s: host name, 'm.google.com'">
By using Google\'s mobile products and services ("Services"), you agree to be bound by a) the By using Google\'s mobile products and services ("Services"), you agree to be bound by a) the
YouTube Terms of Use (%1$s/tos_youtube) for YouTube-related Services, b) the Google Maps Terms YouTube Terms of Use (%1$s/tos_youtube) for YouTube-related Services, b) the Google Maps Terms
and Conditions (%2$s/tos_maps) for mapping, local and location-based Services, c) the Google and Conditions (%1$s/tos_maps) for mapping, local and location-based Services, c) the Google
Books Terms of Service (%3$s/tos_books) for Books-related Services, and e) the Google Terms of Books Terms of Service (%1$s/tos_books) for Books-related Services, and e) the Google Terms of
Service (%4$s/utos) for all other Services, as updated from time to time. Service (%1$s/utos) for all other Services, as updated from time to time.
</string> </string>
<string name="eula_title" <string name="eula_title"
translation_description="The title for the 'Terms of Service' dialog."> translation_description="The title for the 'Terms of Service' dialog.">
@@ -689,10 +686,6 @@ limitations under the License.
translation_description="The title on an alert dialog indicating error."> translation_description="The title on an alert dialog indicating error.">
Error Error
</string> </string>
<string name="generic_no"
translation_description="The text on a button to say no.">
No
</string>
<string name="generic_ok" <string name="generic_ok"
translation_description="The text on a button to say ok."> translation_description="The text on a button to say ok.">
OK OK
@@ -713,10 +706,6 @@ limitations under the License.
Screenshot: sd_card_success_write_file.png"> Screenshot: sd_card_success_write_file.png">
Success Success
</string> </string>
<string name="generic_yes"
translation_description="The text on a button to say yes.">
Yes
</string>
<!-- GPS --> <!-- GPS -->
<string name="gps_need_to_enable" <string name="gps_need_to_enable"
@@ -977,80 +966,55 @@ limitations under the License.
<!-- Menu Items --> <!-- Menu Items -->
<string name="menu_aggregated_statistics" <string name="menu_aggregated_statistics"
translation_description="In the menu, to go to the aggregated statistics page. translation_description="In the menu, to go to the aggregated statistics page.">
Screenshot: menu_record_track_more.png">
Aggregated statistics Aggregated statistics
</string> </string>
<string name="menu_chart_view_chart_settings" <string name="menu_chart_settings"
translation_description="In the menu for the chart view, to change the chart settings. translation_description="In the menu, to change the chart settings.">
Screenshot: menu_chart_settings.png">
Chart settings Chart settings
</string> </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.">
Screenshot: menu_record_track_more.png">
Help Help
</string> </string>
<string name="menu_map_view_map_mode" <string name="menu_map_mode"
translation_description="In the menu for the map view, to switch the display to the map mode. translation_description="In the menu, to switch the display to the map mode.">
Screenshot: menu_map_mode.png">
Map mode Map mode
</string> </string>
<string name="menu_map_view_my_location"
translation_description="In the menu for the map view, to display user's current location.
Screenshot: menu_record_track.png">
My location
</string>
<string name="menu_map_view_satellite_mode"
translation_description="In the menu for the map view, to switch the display to the satellite
mode.
Screenshot: menu_record_track.png">
Satellite mode
</string>
<string name="menu_markers" <string name="menu_markers"
translation_description="In the menu, to show a list of markers for the current track. translation_description="In the menu, to show a list of markers for the current track.">
Screenshot: menu_record_track.png">
Markers Markers
</string> </string>
<string name="menu_my_location"
translation_description="In the menu, to display the user's current location.">
My location
</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.">
Screenshot: menu_record_track.png">
Record track Record track
</string> </string>
<string name="menu_satellite_mode"
translation_description="In the menu, to switch the display to the satellite mode.">
Satellite mode
</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_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.">
Screenshot: menu_record_track_more.png">
Sensor state Sensor state
</string> </string>
<string name="menu_settings" <string name="menu_settings"
translation_description="In the menu, to go to the settings page. translation_description="In the menu, to go to the settings page.">
Screenshot: menu_record_track_more.png">
Settings Settings
</string> </string>
<string name="menu_stop_recording" <string name="menu_stop_recording"
translation_description="In the menu, to stop recording a track. translation_description="In the menu, to stop recording a track.">
Screenshot: menu_stop_recording.png">
Stop recording Stop recording
</string> </string>
<string name="menu_tracks" <string name="menu_tracks"
translation_description="In the menu, to show a list of all the tracks. translation_description="In the menu, to show a list of all the tracks.">
Screenshot: menu_record_track.png">
Tracks Tracks
</string> </string>
@@ -1298,7 +1262,7 @@ limitations under the License.
<string name="send_google_no_service_selected" <string name="send_google_no_service_selected"
translation_description="When sending a track to Google, a message indicating that the user has translation_description="When sending a track to Google, a message indicating that the user has
not selected any Google service and no data is sent."> not selected any Google service and no data is sent.">
You did not select any service. No data is sent. You did not select any service. The track was not sent.
</string> </string>
<string name="send_google_progress_message" <string name="send_google_progress_message"
translation_description="When sending a track to a Google service, the progress message. translation_description="When sending a track to a Google service, the progress message.
@@ -2511,14 +2475,6 @@ limitations under the License.
translation_description="Abbreviation for minutes. E.g, '2 min'."> translation_description="Abbreviation for minutes. E.g, '2 min'.">
min min
</string> </string>
<string name="unit_minute_per_kilometer"
translation_description="Abbreviation for minutes per kilometer. E.g, '5 min/km'.">
min/km
</string>
<string name="unit_minute_per_mile"
translation_description="Abbreviation for minutes per mile. E.g, '5 min/mi'.">
min/mi
</string>
<!-- Value --> <!-- Value -->
<string name="value_adapt_accuracy" <string name="value_adapt_accuracy"
@@ -187,53 +187,50 @@ public class ChartActivity extends Activity implements TrackDataListener {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_CHART_SETTINGS_ID) {
case DIALOG_CHART_SETTINGS_ID: return null;
View view = getLayoutInflater().inflate(R.layout.chart_settings, null);
final RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.chart_settings_x);
radioGroup.check(chartView.getMode() == Mode.BY_DISTANCE
? R.id.chart_settings_by_distance : R.id.chart_settings_by_time);
final CheckBox[] checkBoxes = new CheckBox[ChartView.NUM_SERIES];
checkBoxes[ChartView.ELEVATION_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_elevation);
checkBoxes[ChartView.SPEED_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_speed);
checkBoxes[ChartView.POWER_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_power);
checkBoxes[ChartView.CADENCE_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_cadence);
checkBoxes[ChartView.HEART_RATE_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_heart_rate);
// set checkboxes values
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
checkBoxes[i].setChecked(chartView.isChartValueSeriesEnabled(i));
}
checkBoxes[ChartView.SPEED_SERIES]
.setText(reportSpeed ? R.string.stat_speed : R.string.stat_pace);
return new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.generic_cancel, null)
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setMode(radioGroup.getCheckedRadioButtonId() == R.id.chart_settings_by_distance
? Mode.BY_DISTANCE
: Mode.BY_TIME);
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
chartView.setChartValueSeriesEnabled(i, checkBoxes[i].isChecked());
}
chartView.postInvalidate();
}
})
.setTitle(R.string.menu_chart_view_chart_settings)
.setView(view)
.create();
default:
return null;
} }
View view = getLayoutInflater().inflate(R.layout.chart_settings, null);
final RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.chart_settings_x);
radioGroup.check(chartView.getMode() == Mode.BY_DISTANCE
? R.id.chart_settings_by_distance : R.id.chart_settings_by_time);
final CheckBox[] checkBoxes = new CheckBox[ChartView.NUM_SERIES];
checkBoxes[ChartView.ELEVATION_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_elevation);
checkBoxes[ChartView.SPEED_SERIES] = (CheckBox) view.findViewById(R.id.chart_settings_speed);
checkBoxes[ChartView.POWER_SERIES] = (CheckBox) view.findViewById(R.id.chart_settings_power);
checkBoxes[ChartView.CADENCE_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_cadence);
checkBoxes[ChartView.HEART_RATE_SERIES] = (CheckBox) view.findViewById(
R.id.chart_settings_heart_rate);
// set checkboxes values
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
checkBoxes[i].setChecked(chartView.isChartValueSeriesEnabled(i));
}
checkBoxes[ChartView.SPEED_SERIES].setText(reportSpeed
? R.string.stat_speed : R.string.stat_pace);
return new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.generic_cancel, null)
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setMode(radioGroup.getCheckedRadioButtonId() == R.id.chart_settings_by_distance
? Mode.BY_DISTANCE
: Mode.BY_TIME);
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
chartView.setChartValueSeriesEnabled(i, checkBoxes[i].isChecked());
}
chartView.postInvalidate();
}
})
.setTitle(R.string.menu_chart_settings)
.setView(view)
.create();
} }
/** /**
@@ -66,20 +66,18 @@ public class ExportActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_PROGRESS_ID) {
case DIALOG_PROGRESS_ID: return null;
progressDialog = DialogUtils.createHorizontalProgressDialog(this,
getString(R.string.export_progress_message), new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
exportAsyncTask.cancel(true);
finish();
}
});
return progressDialog;
default:
return null;
} }
progressDialog = DialogUtils.createHorizontalProgressDialog(
this, R.string.export_progress_message, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
exportAsyncTask.cancel(true);
finish();
}
});
return progressDialog;
} }
/** /**
@@ -73,7 +73,7 @@ public class ImportActivity extends Activity {
Intent intent = getIntent(); Intent intent = getIntent();
importAll = intent.getBooleanExtra(EXTRA_IMPORT_ALL, false); importAll = intent.getBooleanExtra(EXTRA_IMPORT_ALL, false);
if (importAll) { if (importAll) {
path = new FileUtils().buildExternalDirectoryPath("gpx"); path = FileUtils.buildExternalDirectoryPath("gpx");
} else { } else {
String action = intent.getAction(); String action = intent.getAction();
if (!(Intent.ACTION_ATTACH_DATA.equals(action) || Intent.ACTION_VIEW.equals(action))) { if (!(Intent.ACTION_ATTACH_DATA.equals(action) || Intent.ACTION_VIEW.equals(action))) {
@@ -111,8 +111,8 @@ public class ImportActivity extends Activity {
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { switch (id) {
case DIALOG_PROGRESS_ID: case DIALOG_PROGRESS_ID:
progressDialog = DialogUtils.createHorizontalProgressDialog(this, progressDialog = DialogUtils.createHorizontalProgressDialog(
getString(R.string.import_progress_message), new DialogInterface.OnCancelListener() { this, R.string.import_progress_message, new DialogInterface.OnCancelListener() {
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
importAsyncTask.cancel(true); importAsyncTask.cancel(true);
@@ -121,8 +121,7 @@ public class ImportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
@Override @Override
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
try { try {
FileUtils fileUtils = new FileUtils(); if (!FileUtils.isSdCardAvailable()) {
if (!fileUtils.isSdCardAvailable()) {
return false; return false;
} }
@@ -250,7 +250,7 @@ public class MapActivity extends com.google.android.maps.MapActivity
return PlayTrackUtils.createInstallEarthDialog(this); return PlayTrackUtils.createInstallEarthDialog(this);
case DIALOG_DELETE_CURRENT_ID: case DIALOG_DELETE_CURRENT_ID:
return DialogUtils.createConfirmationDialog(this, return DialogUtils.createConfirmationDialog(this,
getString(R.string.track_list_delete_track_confirm_message), R.string.track_list_delete_track_confirm_message,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
@@ -81,9 +81,7 @@ class MenuManager {
.setVisible(isMapTab); .setVisible(isMapTab);
menu.findItem(R.id.menu_satellite_mode) menu.findItem(R.id.menu_satellite_mode)
.setVisible(isMapTab) .setVisible(isMapTab)
.setTitle(isSatelliteMode .setTitle(isSatelliteMode ? R.string.menu_map_mode : R.string.menu_satellite_mode);
? R.string.menu_map_view_map_mode
: R.string.menu_map_view_satellite_mode);
} }
/** /**
@@ -32,8 +32,8 @@ import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection
import com.google.android.apps.mytracks.util.AnalyticsUtils; import com.google.android.apps.mytracks.util.AnalyticsUtils;
import com.google.android.apps.mytracks.util.ApiAdapterFactory; import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.apps.mytracks.util.EulaUtils; import com.google.android.apps.mytracks.util.EulaUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.apps.mytracks.util.UriUtils; import com.google.android.apps.mytracks.util.UriUtils;
import com.google.android.maps.mytracks.BuildConfig;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.app.Activity; import android.app.Activity;
@@ -140,7 +140,7 @@ public class MyTracks extends TabActivity implements OnTouchListener {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "MyTracks.onCreate"); Log.d(TAG, "MyTracks.onCreate");
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (!SystemUtils.isRelease(this)) { if (BuildConfig.DEBUG) {
ApiAdapterFactory.getApiAdapter().enableStrictMode(); ApiAdapterFactory.getApiAdapter().enableStrictMode();
} }
@@ -30,7 +30,6 @@ import com.google.android.maps.mytracks.R;
import android.app.Dialog; import android.app.Dialog;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
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;
@@ -178,7 +177,7 @@ public class SettingsActivity extends PreferenceActivity {
switch (id) { switch (id) {
case DIALOG_CONFIRM_RESET_ID: case DIALOG_CONFIRM_RESET_ID:
return DialogUtils.createConfirmationDialog( return DialogUtils.createConfirmationDialog(
this, getString(R.string.settings_reset_confirm_message), new OnClickListener() { this, R.string.settings_reset_confirm_message, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int button) { public void onClick(DialogInterface dialog, int button) {
onResetPreferencesConfirmed(); onResetPreferencesConfirmed();
@@ -186,8 +185,8 @@ public class SettingsActivity extends PreferenceActivity {
}); });
case DIALOG_CONFIRM_ACCESS_ID: case DIALOG_CONFIRM_ACCESS_ID:
return DialogUtils.createConfirmationDialog(this, return DialogUtils.createConfirmationDialog(this,
getString(R.string.settings_sharing_allow_access_confirm_message), R.string.settings_sharing_allow_access_confirm_message,
new OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int button) { public void onClick(DialogInterface dialog, int button) {
CheckBoxPreference pref = (CheckBoxPreference) findPreference( CheckBoxPreference pref = (CheckBoxPreference) findPreference(
@@ -196,8 +195,9 @@ public class SettingsActivity extends PreferenceActivity {
} }
}); });
case DIALOG_CONFIRM_RESTORE_ID: case DIALOG_CONFIRM_RESTORE_ID:
return DialogUtils.createConfirmationDialog( return DialogUtils.createConfirmationDialog(this,
this, getString(R.string.settings_backup_restore_confirm_message), new OnClickListener() { R.string.settings_backup_restore_confirm_message,
new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(SettingsActivity.this, RestoreChooserActivity.class)); startActivity(new Intent(SettingsActivity.this, RestoreChooserActivity.class));
@@ -365,8 +365,7 @@ public class TrackList extends ListActivity
.create(); .create();
case DIALOG_DELETE_ALL_ID: case DIALOG_DELETE_ALL_ID:
return DialogUtils.createConfirmationDialog(this, return DialogUtils.createConfirmationDialog(this,
getString(R.string.track_list_delete_all_confirm_message), R.string.track_list_delete_all_confirm_message, new DialogInterface.OnClickListener() {
new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
MyTracksProviderUtils.Factory.get(TrackList.this).deleteAllTracks(); MyTracksProviderUtils.Factory.get(TrackList.this).deleteAllTracks();
@@ -380,7 +379,7 @@ public class TrackList extends ListActivity
}); });
case DIALOG_DELETE_CURRENT_ID: case DIALOG_DELETE_CURRENT_ID:
return DialogUtils.createConfirmationDialog(this, return DialogUtils.createConfirmationDialog(this,
getString(R.string.track_list_delete_track_confirm_message), R.string.track_list_delete_track_confirm_message,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
@@ -203,20 +203,17 @@ public class WaypointsList extends ListActivity implements View.OnClickListener
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_DELETE_CURRENT_ID) {
case DIALOG_DELETE_CURRENT_ID: return null;
return DialogUtils.createConfirmationDialog(this,
getString(R.string.marker_list_delete_marker_confirm_message),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
providerUtils.deleteWaypoint(
selectedWaypointId, new DescriptionGeneratorImpl(WaypointsList.this));
}
});
default:
return null;
} }
return DialogUtils.createConfirmationDialog(this,
R.string.marker_list_delete_marker_confirm_message, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
providerUtils.deleteWaypoint(
selectedWaypointId, new DescriptionGeneratorImpl(WaypointsList.this));
}
});
} }
@Override @Override
@@ -61,7 +61,6 @@ public class WelcomeActivity extends Activity {
View view = getLayoutInflater().inflate(R.layout.about, null); View view = getLayoutInflater().inflate(R.layout.about, null);
TextView aboutVersion = (TextView) view.findViewById(R.id.about_version); TextView aboutVersion = (TextView) view.findViewById(R.id.about_version);
aboutVersion.setText(SystemUtils.getMyTracksVersion(this)); aboutVersion.setText(SystemUtils.getMyTracksVersion(this));
return new AlertDialog.Builder(this) return new AlertDialog.Builder(this)
.setCancelable(true) .setCancelable(true)
.setNegativeButton(R.string.about_license, new DialogInterface.OnClickListener() { .setNegativeButton(R.string.about_license, new DialogInterface.OnClickListener() {
@@ -15,21 +15,24 @@
*/ */
package com.google.android.apps.mytracks.io.backup; package com.google.android.apps.mytracks.io.backup;
import android.annotation.TargetApi;
import android.app.backup.BackupManager; import android.app.backup.BackupManager;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
/** /**
* Implementation of {@link BackupPreferencesListener} that calls the * Implementation of {@link BackupPreferencesListener} that calls the
* {@link BackupManager}. * {@link BackupManager}. <br>
* For API Level 8 or higher.
* *
* @author Jimmy Shih * @author Jimmy Shih
*/ */
public class BackupPreferencesListenerImpl implements BackupPreferencesListener { @TargetApi(8)
public class Api8BackupPreferencesListener implements BackupPreferencesListener {
private final BackupManager backupManager; private final BackupManager backupManager;
public BackupPreferencesListenerImpl(Context context) { public Api8BackupPreferencesListener(Context context) {
this.backupManager = new BackupManager(context); this.backupManager = new BackupManager(context);
} }
@@ -58,19 +58,16 @@ public class BackupActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_PROGRESS_ID) {
case DIALOG_PROGRESS_ID: return null;
return DialogUtils.createSpinnerProgressDialog(this,
getString(R.string.settings_backup_now_progress_message),
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
default:
return null;
} }
return DialogUtils.createSpinnerProgressDialog(
this, R.string.settings_backup_now_progress_message, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
} }
/** /**
@@ -53,7 +53,7 @@ public class BackupAsyncTask extends AsyncTask<Void, Integer, Boolean> {
*/ */
public BackupAsyncTask(BackupActivity backupActivity) { public BackupAsyncTask(BackupActivity backupActivity) {
this.backupActivity = backupActivity; this.backupActivity = backupActivity;
this.externalFileBackup = new ExternalFileBackup(backupActivity, new FileUtils()); this.externalFileBackup = new ExternalFileBackup(backupActivity);
success = false; success = false;
completed = false; completed = false;
messageId = R.string.sd_card_error_write_file; messageId = R.string.sd_card_error_write_file;
@@ -80,9 +80,7 @@ public class BackupAsyncTask extends AsyncTask<Void, Integer, Boolean> {
@Override @Override
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
FileUtils fileUtils = new FileUtils(); if (!FileUtils.isSdCardAvailable()) {
if (!fileUtils.isSdCardAvailable()) {
messageId = R.string.sd_card_error_no_storage; messageId = R.string.sd_card_error_no_storage;
return false; return false;
} }
@@ -65,11 +65,9 @@ class ExternalFileBackup {
private static final int COMPRESSION_LEVEL = 8; private static final int COMPRESSION_LEVEL = 8;
private final Context context; private final Context context;
private final FileUtils fileUtils;
public ExternalFileBackup(Context context, FileUtils fileUtils) { public ExternalFileBackup(Context context) {
this.context = context; this.context = context;
this.fileUtils = fileUtils;
} }
/** /**
@@ -87,12 +85,12 @@ class ExternalFileBackup {
* @param create whether to try creating the directory if it doesn't exist * @param create whether to try creating the directory if it doesn't exist
*/ */
private File getBackupsDirectory(boolean create) { private File getBackupsDirectory(boolean create) {
String dirName = fileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR); String dirName = FileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR);
final File dir = new File(dirName); final File dir = new File(dirName);
Log.d(Constants.TAG, "Dir: " + dir.getAbsolutePath()); Log.d(Constants.TAG, "Dir: " + dir.getAbsolutePath());
if (create) { if (create) {
// Try to create - if that fails, return null // Try to create - if that fails, return null
return fileUtils.ensureDirectoryExists(dir) ? dir : null; return FileUtils.ensureDirectoryExists(dir) ? dir : null;
} else { } else {
// Return it if it already exists, otherwise return null // Return it if it already exists, otherwise return null
return dir.isDirectory() ? dir : null; return dir.isDirectory() ? dir : null;
@@ -17,6 +17,7 @@ package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import android.annotation.TargetApi;
import android.app.backup.BackupAgent; import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput; import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput; import android.app.backup.BackupDataOutput;
@@ -34,6 +35,7 @@ import java.io.IOException;
* *
* @author Rodrigo Damazio * @author Rodrigo Damazio
*/ */
@TargetApi(8)
public class MyTracksBackupAgent extends BackupAgent { public class MyTracksBackupAgent extends BackupAgent {
private static final String PREFERENCES_ENTITY = "prefs"; private static final String PREFERENCES_ENTITY = "prefs";
@@ -71,19 +71,16 @@ public class RestoreActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_PROGRESS_ID) {
case DIALOG_PROGRESS_ID: return null;
return DialogUtils.createSpinnerProgressDialog(this,
getString(R.string.settings_backup_restore_progress_message),
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
default:
return null;
} }
return DialogUtils.createSpinnerProgressDialog(this,
R.string.settings_backup_restore_progress_message, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
} }
/** /**
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.io.backup; package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.os.AsyncTask; import android.os.AsyncTask;
@@ -57,7 +56,7 @@ public class RestoreAsyncTask extends AsyncTask<Void, Integer, Boolean> {
public RestoreAsyncTask(RestoreActivity restoreActivity, Date date) { public RestoreAsyncTask(RestoreActivity restoreActivity, Date date) {
this.restoreActivity = restoreActivity; this.restoreActivity = restoreActivity;
this.date = date; this.date = date;
this.externalFileBackup = new ExternalFileBackup(restoreActivity, new FileUtils()); this.externalFileBackup = new ExternalFileBackup(restoreActivity);
success = false; success = false;
completed = false; completed = false;
messageId = R.string.sd_card_error_read_file; messageId = R.string.sd_card_error_read_file;
@@ -24,8 +24,6 @@ import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Toast; import android.widget.Toast;
@@ -55,11 +53,10 @@ public class RestoreChooserActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
FileUtils fileUtils = new FileUtils(); ExternalFileBackup externalFileBackup = new ExternalFileBackup(this);
ExternalFileBackup externalFileBackup = new ExternalFileBackup(this, fileUtils);
// Get the list of existing backups // Get the list of existing backups
if (!fileUtils.isSdCardAvailable()) { if (!FileUtils.isSdCardAvailable()) {
Toast.makeText(this, R.string.sd_card_error_no_storage, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.sd_card_error_no_storage, Toast.LENGTH_LONG).show();
finish(); finish();
return; return;
@@ -91,32 +88,30 @@ public class RestoreChooserActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_CHOOSER_ID) {
case DIALOG_CHOOSER_ID: return null;
String items[] = new String[backupDates.length];
for (int i = 0; i < backupDates.length; i++) {
items[i] = StringUtils.formatDateTime(this, backupDates[i].getTime());
}
return new AlertDialog.Builder(this)
.setCancelable(true)
.setItems(items, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(RestoreChooserActivity.this, RestoreActivity.class)
.putExtra(RestoreActivity.EXTRA_DATE, backupDates[which].getTime()));
finish();
}
})
.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
})
.setTitle(R.string.settings_backup_restore_select_title)
.create();
default:
return null;
} }
String items[] = new String[backupDates.length];
for (int i = 0; i < backupDates.length; i++) {
items[i] = StringUtils.formatDateTime(this, backupDates[i].getTime());
}
return new AlertDialog.Builder(this)
.setCancelable(true)
.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(RestoreChooserActivity.this, RestoreActivity.class).putExtra(
RestoreActivity.EXTRA_DATE, backupDates[which].getTime()));
finish();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
})
.setTitle(R.string.settings_backup_restore_select_title)
.create();
} }
} }
@@ -28,8 +28,6 @@ import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@@ -102,7 +100,7 @@ public class SaveActivity extends Activity {
} }
if (shareTrack || playTrack) { if (shareTrack || playTrack) {
// Save to the temp directory // Save to the temp directory
String dirName = new FileUtils().buildExternalDirectoryPath( String dirName = FileUtils.buildExternalDirectoryPath(
trackFileFormat.getExtension(), "tmp"); trackFileFormat.getExtension(), "tmp");
trackWriter.setDirectory(new File(dirName)); trackWriter.setDirectory(new File(dirName));
} }
@@ -121,9 +119,8 @@ public class SaveActivity extends Activity {
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { switch (id) {
case DIALOG_PROGRESS_ID: case DIALOG_PROGRESS_ID:
progressDialog = DialogUtils.createHorizontalProgressDialog(this, progressDialog = DialogUtils.createHorizontalProgressDialog(
getString(R.string.sd_card_progress_message), this, R.string.sd_card_progress_message, new DialogInterface.OnCancelListener() {
new DialogInterface.OnCancelListener() {
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
saveAsyncTask.cancel(true); saveAsyncTask.cancel(true);
@@ -137,14 +134,14 @@ public class SaveActivity extends Activity {
.setIcon(success .setIcon(success
? android.R.drawable.ic_dialog_info : android.R.drawable.ic_dialog_alert) ? android.R.drawable.ic_dialog_info : android.R.drawable.ic_dialog_alert)
.setMessage(messageId) .setMessage(messageId)
.setOnCancelListener(new OnCancelListener() { .setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
dialog.dismiss(); dialog.dismiss();
onPostResultDialog(); onPostResultDialog();
} }
}) })
.setPositiveButton(R.string.generic_ok, new OnClickListener() { .setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int arg1) { public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss(); dialog.dismiss();
@@ -52,7 +52,6 @@ class TrackWriterImpl implements TrackWriter {
private final MyTracksProviderUtils providerUtils; private final MyTracksProviderUtils providerUtils;
private final Track track; private final Track track;
private final TrackFormatWriter writer; private final TrackFormatWriter writer;
private final FileUtils fileUtils;
private boolean success = false; private boolean success = false;
private int errorMessage = -1; private int errorMessage = -1;
private File directory = null; private File directory = null;
@@ -66,7 +65,6 @@ class TrackWriterImpl implements TrackWriter {
this.providerUtils = providerUtils; this.providerUtils = providerUtils;
this.track = track; this.track = track;
this.writer = writer; this.writer = writer;
this.fileUtils = new FileUtils();
} }
@Override @Override
@@ -175,7 +173,7 @@ class TrackWriterImpl implements TrackWriter {
} }
// Make sure the file doesn't exist yet (possibly by changing the filename) // Make sure the file doesn't exist yet (possibly by changing the filename)
String fileName = fileUtils.buildUniqueFileName( String fileName = FileUtils.buildUniqueFileName(
directory, track.getName(), writer.getExtension()); directory, track.getName(), writer.getExtension());
if (fileName == null) { if (fileName == null) {
Log.e(Constants.TAG, Log.e(Constants.TAG,
@@ -200,16 +198,16 @@ class TrackWriterImpl implements TrackWriter {
protected boolean canWriteFile() { protected boolean canWriteFile() {
if (directory == null) { if (directory == null) {
String dirName = String dirName =
fileUtils.buildExternalDirectoryPath(writer.getExtension()); FileUtils.buildExternalDirectoryPath(writer.getExtension());
directory = newFile(dirName); directory = newFile(dirName);
} }
if (!fileUtils.isSdCardAvailable()) { if (!FileUtils.isSdCardAvailable()) {
Log.i(Constants.TAG, "Could not find SD card."); Log.i(Constants.TAG, "Could not find SD card.");
errorMessage = R.string.sd_card_error_no_storage; errorMessage = R.string.sd_card_error_no_storage;
return false; return false;
} }
if (!fileUtils.ensureDirectoryExists(directory)) { if (!FileUtils.ensureDirectoryExists(directory)) {
Log.i(Constants.TAG, "Could not create export directory."); Log.i(Constants.TAG, "Could not create export directory.");
errorMessage = R.string.sd_card_error_create_dir; errorMessage = R.string.sd_card_error_create_dir;
return false; return false;
@@ -25,8 +25,6 @@ import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
@@ -122,7 +120,7 @@ public class ChooseMapActivity extends Activity {
switch (id) { switch (id) {
case DIALOG_PROGRESS_ID: case DIALOG_PROGRESS_ID:
return DialogUtils.createSpinnerProgressDialog( return DialogUtils.createSpinnerProgressDialog(
this, getString(R.string.maps_list_progress_message), new DialogInterface.OnCancelListener() { this, R.string.maps_list_progress_message, new DialogInterface.OnCancelListener() {
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
asyncTask.cancel(true); asyncTask.cancel(true);
@@ -134,13 +132,13 @@ public class ChooseMapActivity extends Activity {
.setCancelable(true) .setCancelable(true)
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.maps_list_error) .setMessage(R.string.maps_list_error)
.setOnCancelListener(new OnCancelListener() { .setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override @Override
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
finish(); finish();
} }
}) })
.setPositiveButton(R.string.generic_ok, new OnClickListener() { .setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int arg1) { public void onClick(DialogInterface dialog, int arg1) {
finish(); finish();
@@ -71,21 +71,18 @@ public abstract class AbstractSendActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_PROGRESS_ID) {
case DIALOG_PROGRESS_ID: return null;
progressDialog = DialogUtils.createHorizontalProgressDialog(this,
getString(R.string.send_google_progress_message, getServiceName()),
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
asyncTask.cancel(true);
startNextActivity(false, true);
}
});
return progressDialog;
default:
return null;
} }
progressDialog = DialogUtils.createHorizontalProgressDialog(
this, R.string.send_google_progress_message, new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
asyncTask.cancel(true);
startNextActivity(false, true);
}
}, getServiceName());
return progressDialog;
} }
/** /**
@@ -135,50 +135,57 @@ public class AccountChooserActivity extends Activity {
.setTitle(R.string.send_google_no_account_title) .setTitle(R.string.send_google_no_account_title)
.create(); .create();
case DIALOG_CHOOSER_ID: case DIALOG_CHOOSER_ID:
String[] choices = new String[accounts.length]; return createChooserDialog();
for (int i = 0; i < accounts.length; i++) {
choices[i] = accounts[i].name;
}
return new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.generic_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
})
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Account account = accounts[selectedAccountIndex];
SharedPreferences sharedPreferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();
editor.putString(getString(R.string.preferred_account_key), account.name);
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
sendRequest.setAccount(account);
getPermission(MapsConstants.SERVICE_NAME, sendRequest.isSendMaps(), mapsCallback);
}
})
.setSingleChoiceItems(
choices, selectedAccountIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
selectedAccountIndex = which;
}
})
.setTitle(R.string.send_google_choose_account_title)
.create();
default: default:
return null; return null;
} }
} }
/**
* Creates a chooser dialog.
*/
private Dialog createChooserDialog() {
String[] choices = new String[accounts.length];
for (int i = 0; i < accounts.length; i++) {
choices[i] = accounts[i].name;
}
return new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.generic_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
})
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Account account = accounts[selectedAccountIndex];
SharedPreferences sharedPreferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();
editor.putString(getString(R.string.preferred_account_key), account.name);
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
sendRequest.setAccount(account);
getPermission(MapsConstants.SERVICE_NAME, sendRequest.isSendMaps(), mapsCallback);
}
})
.setSingleChoiceItems(
choices, selectedAccountIndex, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
selectedAccountIndex = which;
}
})
.setTitle(R.string.send_google_choose_account_title)
.create();
}
private PermissionCallback spreadsheetsCallback = new PermissionCallback() { private PermissionCallback spreadsheetsCallback = new PermissionCallback() {
@Override @Override
public void onSuccess() { public void onSuccess() {
@@ -80,100 +80,94 @@ public class UploadResultActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_RESULT_ID) {
case DIALOG_RESULT_ID: return null;
View view = getLayoutInflater().inflate(R.layout.upload_result, null);
LinearLayout mapsResult = (LinearLayout) view.findViewById(R.id.upload_result_maps_result);
LinearLayout fusionTablesResult = (LinearLayout) view.findViewById(
R.id.upload_result_fusion_tables_result);
LinearLayout docsResult = (LinearLayout) view.findViewById(R.id.upload_result_docs_result);
ImageView mapsResultIcon = (ImageView) view.findViewById(
R.id.upload_result_maps_result_icon);
ImageView fusionTablesResultIcon = (ImageView) view.findViewById(
R.id.upload_result_fusion_tables_result_icon);
ImageView docsResultIcon = (ImageView) view.findViewById(
R.id.upload_result_docs_result_icon);
TextView successFooter = (TextView) view.findViewById(R.id.upload_result_success_footer);
TextView errorFooter = (TextView) view.findViewById(R.id.upload_result_error_footer);
boolean hasError = false;
if (!sendRequest.isSendMaps()) {
mapsResult.setVisibility(View.GONE);
} else {
if (!sendRequest.isMapsSuccess()) {
mapsResultIcon.setImageResource(R.drawable.failure);
mapsResultIcon.setContentDescription(getString(R.string.generic_error_title));
hasError = true;
}
}
if (!sendRequest.isSendFusionTables()) {
fusionTablesResult.setVisibility(View.GONE);
} else {
if (!sendRequest.isFusionTablesSuccess()) {
fusionTablesResultIcon.setImageResource(R.drawable.failure);
fusionTablesResultIcon.setContentDescription(getString(R.string.generic_error_title));
hasError = true;
}
}
if (!sendRequest.isSendDocs()) {
docsResult.setVisibility(View.GONE);
} else {
if (!sendRequest.isDocsSuccess()) {
docsResultIcon.setImageResource(R.drawable.failure);
docsResultIcon.setContentDescription(getString(R.string.generic_error_title));
hasError = true;
}
}
if (hasError) {
successFooter.setVisibility(View.GONE);
} else {
errorFooter.setVisibility(View.GONE);
}
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setCancelable(true)
.setIcon(hasError ? android.R.drawable.ic_dialog_alert
: android.R.drawable.ic_dialog_info)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
})
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (!sendRequest.isShowAll() && shareUrl != null) {
startShareUrlActivity(shareUrl);
}
finish();
}
})
.setTitle(hasError ? R.string.generic_error_title : R.string.generic_success_title)
.setView(view);
// Add a Share URL button if showing all the options and a shareUrl
// exists
if (sendRequest.isShowAll() && shareUrl != null) {
builder.setNegativeButton(getString(R.string.send_google_result_share_url),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startShareUrlActivity(shareUrl);
finish();
}
});
}
return builder.create();
default:
return null;
} }
View view = getLayoutInflater().inflate(R.layout.upload_result, null);
LinearLayout mapsResult = (LinearLayout) view.findViewById(R.id.upload_result_maps_result);
LinearLayout fusionTablesResult = (LinearLayout) view.findViewById(
R.id.upload_result_fusion_tables_result);
LinearLayout docsResult = (LinearLayout) view.findViewById(R.id.upload_result_docs_result);
ImageView mapsResultIcon = (ImageView) view.findViewById(R.id.upload_result_maps_result_icon);
ImageView fusionTablesResultIcon = (ImageView) view.findViewById(
R.id.upload_result_fusion_tables_result_icon);
ImageView docsResultIcon = (ImageView) view.findViewById(R.id.upload_result_docs_result_icon);
TextView successFooter = (TextView) view.findViewById(R.id.upload_result_success_footer);
TextView errorFooter = (TextView) view.findViewById(R.id.upload_result_error_footer);
boolean hasError = false;
if (!sendRequest.isSendMaps()) {
mapsResult.setVisibility(View.GONE);
} else {
if (!sendRequest.isMapsSuccess()) {
mapsResultIcon.setImageResource(R.drawable.failure);
mapsResultIcon.setContentDescription(getString(R.string.generic_error_title));
hasError = true;
}
}
if (!sendRequest.isSendFusionTables()) {
fusionTablesResult.setVisibility(View.GONE);
} else {
if (!sendRequest.isFusionTablesSuccess()) {
fusionTablesResultIcon.setImageResource(R.drawable.failure);
fusionTablesResultIcon.setContentDescription(getString(R.string.generic_error_title));
hasError = true;
}
}
if (!sendRequest.isSendDocs()) {
docsResult.setVisibility(View.GONE);
} else {
if (!sendRequest.isDocsSuccess()) {
docsResultIcon.setImageResource(R.drawable.failure);
docsResultIcon.setContentDescription(getString(R.string.generic_error_title));
hasError = true;
}
}
if (hasError) {
successFooter.setVisibility(View.GONE);
} else {
errorFooter.setVisibility(View.GONE);
}
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setCancelable(true)
.setIcon(hasError ? android.R.drawable.ic_dialog_alert : android.R.drawable.ic_dialog_info)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
})
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (!sendRequest.isShowAll() && shareUrl != null) {
startShareUrlActivity(shareUrl);
}
finish();
}
})
.setTitle(hasError ? R.string.generic_error_title : R.string.generic_success_title)
.setView(view);
// Add a Share URL button if showing all the options and a shareUrl exists
if (sendRequest.isShowAll() && shareUrl != null) {
builder.setNegativeButton(
R.string.send_google_result_share_url, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startShareUrlActivity(shareUrl);
finish();
}
});
}
return builder.create();
} }
/** /**
@@ -78,77 +78,73 @@ public class UploadServiceChooserActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
switch (id) { if (id != DIALOG_CHOOSER_ID) {
case DIALOG_CHOOSER_ID: return null;
View view = getLayoutInflater().inflate(R.layout.upload_service_chooser, null);
mapsTableRow = (TableRow) view.findViewById(R.id.send_google_maps_row);
fusionTablesTableRow = (TableRow) view.findViewById(R.id.send_google_fusion_tables_row);
docsTableRow = (TableRow) view.findViewById(R.id.send_google_docs_row);
mapsCheckBox = (CheckBox) view.findViewById(R.id.send_google_maps);
fusionTablesCheckBox = (CheckBox) view.findViewById(R.id.send_google_fusion_tables);
docsCheckBox = (CheckBox) view.findViewById(R.id.send_google_docs);
mapsOptionTableRow = (TableRow) view.findViewById(R.id.send_google_maps_option_row);
newMapRadioButton = (RadioButton) view.findViewById(R.id.send_google_new_map);
existingMapRadioButton = (RadioButton) view.findViewById(R.id.send_google_existing_map);
// Setup checkboxes
OnCheckedChangeListener checkBoxListener = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton button, boolean checked) {
updateStateBySelection();
}
};
mapsCheckBox.setOnCheckedChangeListener(checkBoxListener);
fusionTablesCheckBox.setOnCheckedChangeListener(checkBoxListener);
docsCheckBox.setOnCheckedChangeListener(checkBoxListener);
// Setup initial state
initState();
// Update state based on sendRequest
updateStateBySendRequest();
// Update state based on current selection
updateStateBySelection();
alertDialog = new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.generic_cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface d) {
finish();
}
})
.setPositiveButton(
R.string.send_google_send_now, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
saveState();
if (sendMaps() || sendFusionTables() || sendDocs()) {
startNextActivity();
} else {
Toast.makeText(UploadServiceChooserActivity.this,
R.string.send_google_no_service_selected, Toast.LENGTH_LONG).show();
finish();
}
}
})
.setTitle(R.string.send_google_title)
.setView(view)
.create();
return alertDialog;
default:
return null;
} }
View view = getLayoutInflater().inflate(R.layout.upload_service_chooser, null);
mapsTableRow = (TableRow) view.findViewById(R.id.send_google_maps_row);
fusionTablesTableRow = (TableRow) view.findViewById(R.id.send_google_fusion_tables_row);
docsTableRow = (TableRow) view.findViewById(R.id.send_google_docs_row);
mapsCheckBox = (CheckBox) view.findViewById(R.id.send_google_maps);
fusionTablesCheckBox = (CheckBox) view.findViewById(R.id.send_google_fusion_tables);
docsCheckBox = (CheckBox) view.findViewById(R.id.send_google_docs);
mapsOptionTableRow = (TableRow) view.findViewById(R.id.send_google_maps_option_row);
newMapRadioButton = (RadioButton) view.findViewById(R.id.send_google_new_map);
existingMapRadioButton = (RadioButton) view.findViewById(R.id.send_google_existing_map);
// Setup checkboxes
OnCheckedChangeListener checkBoxListener = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton button, boolean checked) {
updateStateBySelection();
}
};
mapsCheckBox.setOnCheckedChangeListener(checkBoxListener);
fusionTablesCheckBox.setOnCheckedChangeListener(checkBoxListener);
docsCheckBox.setOnCheckedChangeListener(checkBoxListener);
// Setup initial state
initState();
// Update state based on sendRequest
updateStateBySendRequest();
// Update state based on current selection
updateStateBySelection();
alertDialog = new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.generic_cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface d) {
finish();
}
})
.setPositiveButton(R.string.send_google_send_now, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
saveState();
if (sendMaps() || sendFusionTables() || sendDocs()) {
startNextActivity();
} else {
Toast.makeText(UploadServiceChooserActivity.this,
R.string.send_google_no_service_selected, Toast.LENGTH_LONG).show();
finish();
}
}
})
.setTitle(R.string.send_google_title)
.setView(view)
.create();
return alertDialog;
} }
/** /**
@@ -91,10 +91,7 @@ public class RemoveTempFilesService extends Service {
} }
private void cleanTempDirectory(String name) { private void cleanTempDirectory(String name) {
FileUtils fileUtils = new FileUtils(); cleanTempDirectory(new File(FileUtils.buildExternalDirectoryPath(name, "tmp")));
String dirName = fileUtils.buildExternalDirectoryPath(name, "tmp");
File dir = new File(dirName);
cleanTempDirectory(dir);
} }
/** /**
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.services;
import static com.google.android.apps.mytracks.Constants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.util.SystemUtils; import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.BuildConfig;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@@ -157,7 +158,7 @@ public class TrackRecordingServiceConnection {
Log.i(TAG, "Binding to the service"); Log.i(TAG, "Binding to the service");
Intent intent = new Intent(context, TrackRecordingService.class); Intent intent = new Intent(context, TrackRecordingService.class);
int flags = SystemUtils.isRelease(context) ? 0 : Context.BIND_DEBUG_UNBIND; int flags = BuildConfig.DEBUG ? Context.BIND_DEBUG_UNBIND : 0;
context.bindService(intent, serviceConnection, flags); context.bindService(intent, serviceConnection, flags);
} }
@@ -23,7 +23,7 @@ import com.dsi.ant.exception.AntInterfaceException;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.util.ApiAdapterFactory; import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.apps.mytracks.util.SystemUtils; import com.google.android.maps.mytracks.BuildConfig;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
import android.content.Context; import android.content.Context;
@@ -85,7 +85,7 @@ public class AntSrmBridgeSensorManager extends AntSensorManager {
return true; return true;
} }
if (!SystemUtils.isRelease(context)) { if (BuildConfig.DEBUG) {
Log.d(TAG, "Received ANT msg: " + AntUtils.antMessageToString(messageId) + "(" + messageId + ")"); Log.d(TAG, "Received ANT msg: " + AntUtils.antMessageToString(messageId) + "(" + messageId + ")");
} }
@@ -205,7 +205,7 @@ public class AntSrmBridgeSensorManager extends AntSensorManager {
private void handleMessageResponse(byte[] rawMessage) { private void handleMessageResponse(byte[] rawMessage) {
AntChannelResponseMessage message = AntChannelResponseMessage message =
new AntChannelResponseMessage(rawMessage); new AntChannelResponseMessage(rawMessage);
if (!SystemUtils.isRelease(context)) { if (BuildConfig.DEBUG) {
Log.d(TAG, "Received ANT Response: " + AntUtils.antMessageToString(message.getMessageId()) + Log.d(TAG, "Received ANT Response: " + AntUtils.antMessageToString(message.getMessageId()) +
"(" + message.getMessageId() + ")" + "(" + message.getMessageId() + ")" +
", Code: " + AntUtils.antEventToStr(message.getMessageCode()) + ", Code: " + AntUtils.antEventToStr(message.getMessageCode()) +
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.services.tasks;
import static com.google.android.apps.mytracks.Constants.TAG; import static com.google.android.apps.mytracks.Constants.TAG;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.media.AudioManager; import android.media.AudioManager;
import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech;
@@ -28,12 +29,14 @@ import java.util.HashMap;
/** /**
* This class will periodically announce the user's trip statistics for Froyo and future handsets. * This class will periodically announce the user's trip statistics. This class
* This class will request and release audio focus. * will request and release audio focus. <br>
* For API Level 8 or higher.
* *
* @author Sandor Dornbush * @author Sandor Dornbush
*/ */
public class FroyoStatusAnnouncerTask extends StatusAnnouncerTask { @TargetApi(8)
public class Api8StatusAnnouncerTask extends StatusAnnouncerTask {
private final static HashMap<String, String> SPEECH_PARAMS = new HashMap<String, String>(); private final static HashMap<String, String> SPEECH_PARAMS = new HashMap<String, String>();
static { static {
SPEECH_PARAMS.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "not_used"); SPEECH_PARAMS.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "not_used");
@@ -51,7 +54,7 @@ public class FroyoStatusAnnouncerTask extends StatusAnnouncerTask {
} }
}; };
public FroyoStatusAnnouncerTask(Context context) { public Api8StatusAnnouncerTask(Context context) {
super(context); super(context);
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.services.sensors.BluetoothConnectionManager; import com.google.android.apps.mytracks.services.sensors.BluetoothConnectionManager;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothSocket;
import android.util.Log; import android.util.Log;
@@ -29,6 +30,7 @@ import java.io.IOException;
* *
* @author Jimmy Shih * @author Jimmy Shih
*/ */
@TargetApi(10)
public class Api10Adapter extends Api9Adapter { public class Api10Adapter extends Api9Adapter {
@Override @Override
@@ -16,8 +16,8 @@
package com.google.android.apps.mytracks.util; package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener; import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListenerImpl; import com.google.android.apps.mytracks.io.backup.Api8BackupPreferencesListener;
import com.google.android.apps.mytracks.services.tasks.FroyoStatusAnnouncerTask; import com.google.android.apps.mytracks.services.tasks.Api8StatusAnnouncerTask;
import com.google.android.apps.mytracks.services.tasks.PeriodicTask; import com.google.android.apps.mytracks.services.tasks.PeriodicTask;
import android.content.Context; import android.content.Context;
@@ -31,11 +31,11 @@ public class Api8Adapter extends Api7Adapter {
@Override @Override
public PeriodicTask getStatusAnnouncerTask(Context context) { public PeriodicTask getStatusAnnouncerTask(Context context) {
return new FroyoStatusAnnouncerTask(context); return new Api8StatusAnnouncerTask(context);
} }
@Override @Override
public BackupPreferencesListener getBackupPreferencesListener(Context context) { public BackupPreferencesListener getBackupPreferencesListener(Context context) {
return new BackupPreferencesListenerImpl(context); return new Api8BackupPreferencesListener(context);
} }
} }
@@ -19,6 +19,7 @@ import com.google.android.apps.mytracks.Constants;
import com.google.api.client.http.HttpTransport; import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.http.javanet.NetHttpTransport;
import android.annotation.TargetApi;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.os.StrictMode; import android.os.StrictMode;
import android.util.Log; import android.util.Log;
@@ -30,6 +31,7 @@ import java.util.Arrays;
* *
* @author Rodrigo Damazio * @author Rodrigo Damazio
*/ */
@TargetApi(9)
public class Api9Adapter extends Api8Adapter { public class Api9Adapter extends Api8Adapter {
@Override @Override
@@ -37,15 +37,15 @@ public class DialogUtils {
* Creates a confirmation dialog. * Creates a confirmation dialog.
* *
* @param context the context * @param context the context
* @param message the confirmation message * @param messageId the confirmation message id
* @param onClickListener the listener to invoke when the user clicks OK * @param onClickListener the listener to invoke when the user clicks OK
*/ */
public static Dialog createConfirmationDialog( public static Dialog createConfirmationDialog(
Context context, String message, DialogInterface.OnClickListener onClickListener) { Context context, int messageId, DialogInterface.OnClickListener onClickListener) {
return new AlertDialog.Builder(context) return new AlertDialog.Builder(context)
.setCancelable(true) .setCancelable(true)
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(message) .setMessage(context.getString(messageId))
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, onClickListener) .setPositiveButton(android.R.string.ok, onClickListener)
.setTitle(R.string.generic_confirm_title) .setTitle(R.string.generic_confirm_title)
@@ -56,38 +56,46 @@ public class DialogUtils {
* Creates a spinner progress dialog. * Creates a spinner progress dialog.
* *
* @param context the context * @param context the context
* @param message the progress message * @param messageId the progress message id
* @param onCancelListener the listener to invoke when the user cancels * @param onCancelListener the cancel listener
*/ */
public static ProgressDialog createSpinnerProgressDialog( public static ProgressDialog createSpinnerProgressDialog(
Context context, String message, DialogInterface.OnCancelListener onCancelListener) { Context context, int messageId, DialogInterface.OnCancelListener onCancelListener) {
ProgressDialog progressDialog = new ProgressDialog(context); return createProgressDialog(true, context, messageId, onCancelListener);
progressDialog.setCancelable(true);
progressDialog.setIcon(android.R.drawable.ic_dialog_info);
progressDialog.setIndeterminate(true);
progressDialog.setMessage(message);
progressDialog.setOnCancelListener(onCancelListener);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setTitle(R.string.generic_progress_title);
return progressDialog;
} }
/** /**
* Creates a horizontal progress dialog. * Creates a horizontal progress dialog.
* *
* @param context the context * @param context the context
* @param message the progress message * @param messageId the progress message id
* @param onCancelListener the listener to invoke when the user cancels * @param onCancelListener the cancel listener
* @param formatArgs the format arguments for the messageId
*/ */
public static ProgressDialog createHorizontalProgressDialog( public static ProgressDialog createHorizontalProgressDialog(Context context, int messageId,
Context context, String message, DialogInterface.OnCancelListener onCancelListener) { DialogInterface.OnCancelListener onCancelListener, Object... formatArgs) {
return createProgressDialog(false, context, messageId, onCancelListener, formatArgs);
}
/**
* Creates a progress dialog.
*
* @param spinner true to use the spinner style
* @param context the context
* @param messageId the progress message id
* @param onCancelListener the cancel listener
* @param formatArgs the format arguments for the message id
*/
private static ProgressDialog createProgressDialog(boolean spinner, Context context,
int messageId, DialogInterface.OnCancelListener onCancelListener, Object... formatArgs) {
ProgressDialog progressDialog = new ProgressDialog(context); ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setCancelable(true); progressDialog.setCancelable(true);
progressDialog.setIcon(android.R.drawable.ic_dialog_info); progressDialog.setIcon(android.R.drawable.ic_dialog_info);
progressDialog.setIndeterminate(true); progressDialog.setIndeterminate(true);
progressDialog.setMessage(message); progressDialog.setMessage(context.getString(messageId, formatArgs));
progressDialog.setOnCancelListener(onCancelListener); progressDialog.setOnCancelListener(onCancelListener);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setProgressStyle(spinner ? ProgressDialog.STYLE_SPINNER
: ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setTitle(R.string.generic_progress_title); progressDialog.setTitle(R.string.generic_progress_title);
return progressDialog; return progressDialog;
} }
@@ -35,6 +35,7 @@ public class EulaUtils {
// Accepting Google mobile terms of service // Accepting Google mobile terms of service
private static final String EULA_PREFERENCE_KEY = "eula.google_mobile_tos_accepted"; private static final String EULA_PREFERENCE_KEY = "eula.google_mobile_tos_accepted";
// Google's mobile page
private static final String HOST_NAME = "m.google.com"; private static final String HOST_NAME = "m.google.com";
private EulaUtils() {} private EulaUtils() {}
@@ -56,7 +57,7 @@ public class EulaUtils {
public static String getEulaMessage(Context context) { public static String getEulaMessage(Context context) {
return context.getString(R.string.eula_date) return context.getString(R.string.eula_date)
+ "\n\n" + "\n\n"
+ context.getString(R.string.eula_body, HOST_NAME, HOST_NAME, HOST_NAME, HOST_NAME) + context.getString(R.string.eula_body, HOST_NAME)
+ "\n\n" + "\n\n"
+ context.getString(R.string.eula_footer, HOST_NAME) + context.getString(R.string.eula_footer, HOST_NAME)
+ "\n\n" + "\n\n"
@@ -29,6 +29,8 @@ import java.io.File;
*/ */
public class FileUtils { public class FileUtils {
private FileUtils() {}
/** /**
* The maximum FAT32 path length. See the FAT32 spec at * The maximum FAT32 path length. See the FAT32 spec at
* http://msdn.microsoft.com/en-us/windows/hardware/gg463080 * http://msdn.microsoft.com/en-us/windows/hardware/gg463080
@@ -36,13 +38,37 @@ public class FileUtils {
@VisibleForTesting @VisibleForTesting
static final int MAX_FAT32_PATH_LENGTH = 260; static final int MAX_FAT32_PATH_LENGTH = 260;
/**
* Returns whether the SD card is available.
*/
public static boolean isSdCardAvailable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* Ensures the given directory exists by creating it and its parents if
* necessary.
*
* @return whether the directory exists (either already existed or was
* successfully created)
*/
public static boolean ensureDirectoryExists(File dir) {
if (dir.exists() && dir.isDirectory()) {
return true;
}
if (dir.mkdirs()) {
return true;
}
return false;
}
/** /**
* Builds a path inside the My Tracks directory in the SD card. * Builds a path inside the My Tracks directory in the SD card.
* *
* @param components the path components inside the mytracks directory * @param components the path components inside the mytracks directory
* @return the full path to the destination * @return the full path to the destination
*/ */
public String buildExternalDirectoryPath(String... components) { public static String buildExternalDirectoryPath(String... components) {
StringBuilder dirNameBuilder = new StringBuilder(); StringBuilder dirNameBuilder = new StringBuilder();
dirNameBuilder.append(Environment.getExternalStorageDirectory()); dirNameBuilder.append(Environment.getExternalStorageDirectory());
dirNameBuilder.append(File.separatorChar); dirNameBuilder.append(File.separatorChar);
@@ -54,33 +80,6 @@ public class FileUtils {
return dirNameBuilder.toString(); return dirNameBuilder.toString();
} }
/**
* Returns whether the SD card is available.
*/
public boolean isSdCardAvailable() {
return Environment.MEDIA_MOUNTED.equals(
Environment.getExternalStorageState());
}
/**
* Ensures the given directory exists by creating it and its parents if
* necessary.
*
* @return whether the directory exists (either already existed or was
* successfully created)
*/
public boolean ensureDirectoryExists(File dir) {
if (dir.exists() && dir.isDirectory()) {
return true;
}
if (dir.mkdirs()) {
return true;
}
return false;
}
/** /**
* Builds a filename with the given base name (prefix) and the given * Builds a filename with the given base name (prefix) and the given
* extension, possibly adding a suffix to ensure the file doesn't exist. * extension, possibly adding a suffix to ensure the file doesn't exist.
@@ -90,8 +89,8 @@ public class FileUtils {
* @param extension the file's extension * @param extension the file's extension
* @return the complete file name, without the directory * @return the complete file name, without the directory
*/ */
public synchronized String buildUniqueFileName(File directory, public static synchronized String buildUniqueFileName(
String fileBaseName, String extension) { File directory, String fileBaseName, String extension) {
return buildUniqueFileName(directory, fileBaseName, extension, 0); return buildUniqueFileName(directory, fileBaseName, extension, 0);
} }
@@ -105,7 +104,8 @@ public class FileUtils {
* @param suffix the first numeric suffix to try to use, or 0 for none * @param suffix the first numeric suffix to try to use, or 0 for none
* @return the complete filename, without the directory * @return the complete filename, without the directory
*/ */
private String buildUniqueFileName(File directory, String base, String extension, int suffix) { private static String buildUniqueFileName(
File directory, String base, String extension, int suffix) {
String suffixName = ""; String suffixName = "";
if (suffix > 0) { if (suffix > 0) {
suffixName += "(" + Integer.toString(suffix) + ")"; suffixName += "(" + Integer.toString(suffix) + ")";
@@ -116,7 +116,7 @@ public class FileUtils {
baseName = truncateFileName(directory, baseName, suffixName); baseName = truncateFileName(directory, baseName, suffixName);
String fullName = baseName + suffixName; String fullName = baseName + suffixName;
if (!fileExists(directory, fullName)) { if (!new File(directory, fullName).exists()) {
return fullName; return fullName;
} }
return buildUniqueFileName(directory, base, extension, suffix + 1); return buildUniqueFileName(directory, base, extension, suffix + 1);
@@ -131,7 +131,7 @@ public class FileUtils {
* @param name name * @param name name
*/ */
@VisibleForTesting @VisibleForTesting
String sanitizeFileName(String name) { static String sanitizeFileName(String name) {
StringBuffer buffer = new StringBuffer(name.length()); StringBuffer buffer = new StringBuffer(name.length());
for (int i = 0; i < name.length(); i++) { for (int i = 0; i < name.length(); i++) {
int codePoint = name.codePointAt(i); int codePoint = name.codePointAt(i);
@@ -151,7 +151,7 @@ public class FileUtils {
* *
* @param character the character * @param character the character
*/ */
private boolean isSpecialFat32(char character) { private static boolean isSpecialFat32(char character) {
switch (character) { switch (character) {
case '$': case '$':
case '%': case '%':
@@ -191,7 +191,7 @@ public class FileUtils {
* @param suffix suffix * @param suffix suffix
*/ */
@VisibleForTesting @VisibleForTesting
String truncateFileName(File directory, String name, String suffix) { static String truncateFileName(File directory, String name, String suffix) {
// 1 at the end accounts for the FAT32 filename trailing NUL character // 1 at the end accounts for the FAT32 filename trailing NUL character
int requiredLength = directory.getPath().length() + suffix.length() + 1; int requiredLength = directory.getPath().length() + suffix.length() + 1;
if (name.length() + requiredLength > MAX_FAT32_PATH_LENGTH) { if (name.length() + requiredLength > MAX_FAT32_PATH_LENGTH) {
@@ -201,13 +201,4 @@ public class FileUtils {
return name; return name;
} }
} }
/**
* Checks whether a file with the given name exists in the given directory.
* This is isolated so it can be overridden in tests.
*/
protected boolean fileExists(File directory, String fullName) {
File file = new File(directory, fullName);
return file.exists();
}
} }
@@ -24,7 +24,6 @@ import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
@@ -96,7 +95,7 @@ public class PlayTrackUtils {
.setCancelable(true) .setCancelable(true)
.setMessage(R.string.track_list_play_install_earth_message) .setMessage(R.string.track_list_play_install_earth_message)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new OnClickListener() { .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(); Intent intent = new Intent();
@@ -22,7 +22,6 @@ import android.content.Context;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.PowerManager.WakeLock; import android.os.PowerManager.WakeLock;
import android.util.Log; import android.util.Log;
@@ -34,26 +33,6 @@ import android.util.Log;
*/ */
public class SystemUtils { public class SystemUtils {
private static final int RELEASE_SIGNATURE_HASHCODE = -1855564782;
/**
* Returns whether or not this is a release build.
*/
public static boolean isRelease(Context context) {
try {
Signature [] sigs = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
for (Signature sig : sigs) {
if (sig.hashCode() == RELEASE_SIGNATURE_HASHCODE) {
return true;
}
}
} catch (NameNotFoundException e) {
Log.e(Constants.TAG, "Unable to get signatures", e);
}
return false;
}
/** /**
* Get the My Tracks version from the manifest. * Get the My Tracks version from the manifest.
* *
+6 -6
View File
@@ -15,22 +15,22 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.apps.mytracks.lib"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0" android:versionName="1.0" >
package="com.google.android.apps.mytracks.lib" >
<!-- <!--
THIS IS A LIBRARY PROJECT. THIS IS A LIBRARY PROJECT.
See http://developer.android.com/guide/developing/eclipse-adt.html#libraryProject See http://developer.android.com/guide/developing/eclipse-adt.html#libraryProject
for details on what should go here vs in the application project. for details on what should go here vs in the application project.
--> -->
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="15" />
<application <application
android:icon="@drawable/arrow_icon" android:icon="@drawable/arrow_icon"
android:label="@string/lib_name" > android:label="@string/lib_name" >
</application> </application>
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="15" />
</manifest> </manifest>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

+1
View File
@@ -11,5 +11,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/MyTracks"/> <classpathentry combineaccessrules="false" kind="src" path="/MyTracks"/>
<classpathentry kind="lib" path="libs/AndroidMockGenerator.jar"/> <classpathentry kind="lib" path="libs/AndroidMockGenerator.jar"/>
<classpathentry kind="lib" path="libs/robotium-solo-3.1.jar"/> <classpathentry kind="lib" path="libs/robotium-solo-3.1.jar"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/> <classpathentry kind="output" path="bin/classes"/>
</classpath> </classpath>
+8 -9
View File
@@ -15,16 +15,9 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:debuggable="true" package="com.google.android.maps.mytracks.test"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0" android:versionName="1.0" >
package="com.google.android.maps.mytracks.test" >
<application
android:icon="@android:drawable/sym_def_app_icon"
android:label="My Tracks Tests" >
<uses-library android:name="android.test.runner" />
</application>
<instrumentation <instrumentation
android:name="android.test.InstrumentationTestRunner" android:name="android.test.InstrumentationTestRunner"
@@ -34,4 +27,10 @@ limitations under the License.
android:minSdkVersion="7" android:minSdkVersion="7"
android:targetSdkVersion="15" /> android:targetSdkVersion="15" />
<application
android:icon="@android:drawable/sym_def_app_icon"
android:label="My Tracks Tests" >
<uses-library android:name="android.test.runner" />
</application>
</manifest> </manifest>
@@ -0,0 +1,169 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.io.sendtogoogle;
import com.google.android.maps.mytracks.R;
import com.jayway.android.robotium.solo.Solo;
import android.app.Instrumentation;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashSet;
/**
* Tests the {@link UploadResultActivity}.
*
* @author Youtao Liu
*/
public class UploadResultActivityTest extends
ActivityInstrumentationTestCase2<UploadResultActivity> {
private Instrumentation instrumentation;
private UploadResultActivity uploadResultActivity;
private Solo solo;
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
solo = new Solo(instrumentation);
}
/**
* This method is necessary for ActivityInstrumentationTestCase2.
*/
public UploadResultActivityTest() {
super(UploadResultActivity.class);
}
/**
* Checks the display of dialog when send to all and all sends are successful.
*/
public void testAllSuccess() {
initialActivity(true, true, true, true, true, true);
HashSet<String> stringHashSet = new HashSet<String>();
ArrayList<View> view = solo.getViews();
for (View oneView : view) {
if (oneView instanceof TextView && oneView.isShown()) {
stringHashSet.add((String) ((TextView) oneView).getText());
}
}
assertTrue(stringHashSet.contains(uploadResultActivity
.getString(R.string.generic_success_title)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_maps)));
assertTrue(stringHashSet.contains(uploadResultActivity
.getString(R.string.send_google_fusion_tables)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_docs)));
assertTrue(stringHashSet.contains(uploadResultActivity
.getString(R.string.send_google_success_footer)));
assertFalse(stringHashSet
.contains(uploadResultActivity.getString(R.string.generic_error_title)));
assertFalse(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_error)));
}
/**
* Checks the display of dialog when send to all and all sends are failed.
*/
public void testAllFailed() {
// Send all kinds but all failed.
initialActivity(true, true, true, false, false, false);
HashSet<String> stringHashSet = new HashSet<String>();
ArrayList<View> view = solo.getViews();
for (View oneView : view) {
if (oneView instanceof TextView && oneView.isShown()) {
stringHashSet.add((String) ((TextView) oneView).getText());
}
}
assertTrue(stringHashSet.contains((Object) uploadResultActivity
.getString(R.string.generic_error_title)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_maps)));
assertTrue(stringHashSet.contains(uploadResultActivity
.getString(R.string.send_google_fusion_tables)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_docs)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_error)));
assertFalse(stringHashSet.contains(uploadResultActivity
.getString(R.string.generic_success_title)));
assertFalse(stringHashSet.contains(uploadResultActivity
.getString(R.string.send_google_success_footer)));
}
/**
* Checks the display of dialog when match following items:
* <ul>
* <li>Only send to Maps and Docs.</li>
* <li>Send to Maps successful.</li>
* <li>Send to Docs failed.</li>
* </ul>
*/
public void testPartialSuccess() {
initialActivity(true, false, true, true, false, false);
HashSet<String> stringHashSet = new HashSet<String>();
ArrayList<View> view = solo.getViews();
for (View oneView : view) {
if (oneView instanceof TextView && oneView.isShown()) {
stringHashSet.add((String) ((TextView) oneView).getText());
}
}
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.generic_error_title)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_maps)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_docs)));
assertTrue(stringHashSet.contains(uploadResultActivity.getString(R.string.send_google_error)));
assertFalse(stringHashSet.contains(uploadResultActivity
.getString(R.string.send_google_fusion_tables)));
assertFalse(stringHashSet.contains(uploadResultActivity
.getString(R.string.generic_success_title)));
assertFalse(stringHashSet.contains(uploadResultActivity
.getString(R.string.send_google_success_footer)));
}
/**
* Initial a {@link SendRequest} and then initials a activity to be tested.
*
* @param isSendMaps
* @param isSendFusionTables
* @param isSendDocs
* @param isMapsSuccess
* @param isFusionTablesSuccess
* @param isDocsSuccess
*/
private void initialActivity(boolean isSendMaps, boolean isSendFusionTables, boolean isSendDocs,
boolean isMapsSuccess, boolean isFusionTablesSuccess, boolean isDocsSuccess) {
Intent intent = new Intent();
SendRequest sendRequest = new SendRequest(1L, true, true, true);
sendRequest.setSendMaps(isSendMaps);
sendRequest.setSendFusionTables(isSendFusionTables);
sendRequest.setSendDocs(isSendDocs);
sendRequest.setMapsSuccess(isMapsSuccess);
sendRequest.setFusionTablesSuccess(isFusionTablesSuccess);
sendRequest.setDocsSuccess(isDocsSuccess);
intent.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
setActivityIntent(intent);
uploadResultActivity = this.getActivity();
}
}
@@ -20,8 +20,6 @@ import com.google.android.apps.mytracks.Constants;
import android.os.Environment; import android.os.Environment;
import java.io.File; import java.io.File;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase; import junit.framework.TestCase;
@@ -31,76 +29,81 @@ import junit.framework.TestCase;
* @author Rodrigo Damazio * @author Rodrigo Damazio
*/ */
public class FileUtilsTest extends TestCase { public class FileUtilsTest extends TestCase {
private FileUtils fileUtils;
private Set<String> existingFiles;
@Override
protected void setUp() throws Exception {
super.setUp();
existingFiles = new HashSet<String>();
fileUtils = new FileUtils() {
@Override
protected boolean fileExists(File directory, String fullName) {
return existingFiles.contains(fullName);
}
};
}
/**
* Tests {@link FileUtils#buildExternalDirectoryPath(String...)}.
*/
public void testBuildExternalDirectoryPath() { public void testBuildExternalDirectoryPath() {
String expectedName = Environment.getExternalStorageDirectory() String expectedName = Environment.getExternalStorageDirectory() + File.separator
+ File.separator + Constants.SDCARD_TOP_DIR + File.separator + "a" + File.separator + "b" + File.separator
+ Constants.SDCARD_TOP_DIR
+ File.separator
+ "a"
+ File.separator
+ "b"
+ File.separator
+ "c"; + "c";
String dirName = FileUtils.buildExternalDirectoryPath("a", "b", "c");
String dirName = fileUtils.buildExternalDirectoryPath("a", "b", "c");
assertEquals(expectedName, dirName); assertEquals(expectedName, dirName);
} }
/** /**
* Tests sanitize filename. * Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the
* file is new.
*/
public void testBuildUniqueFileName_new() {
String filename = FileUtils.buildUniqueFileName(new File("/dir"), "Filename", "ext");
assertEquals("Filename.ext", filename);
}
/**
* Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the
* file exists already.
*/
public void testBuildUniqueFileName_exist() {
// Expect "/default.prop" to exist on the phone/emulator
String filename = FileUtils.buildUniqueFileName(new File("/"), "default", "prop");
assertEquals("default(1).prop", filename);
}
/**
* Tests {@link FileUtils#sanitizeFileName(String)} with special characters.
* Verifies that they are sanitized.
*/ */
public void testSanitizeFileName() { public void testSanitizeFileName() {
String name = "Swim\10ming-^across:/the/ pacific (ocean)."; String name = "Swim\10ming-^across:/the/ pacific (ocean).";
String expected = "Swim_ming-^across_the_ pacific (ocean)_"; String expected = "Swim_ming-^across_the_ pacific (ocean)_";
assertEquals(expected, fileUtils.sanitizeFileName(name)); assertEquals(expected, FileUtils.sanitizeFileName(name));
} }
/** /**
* Tests characters in other languages, like Chinese and Russian, are allowed. * Tests {@link FileUtils#sanitizeFileName(String)} with i18n characters (in
* Chinese and Russian). Verifies that they are allowed.
*/ */
public void testSanitizeFileName_i18n() { public void testSanitizeFileName_i18n() {
String name = "您好-привет"; String name = "您好-привет";
String expected = "您好-привет"; String expected = "您好-привет";
assertEquals(expected, FileUtils.sanitizeFileName(name));
assertEquals(expected, fileUtils.sanitizeFileName(name));
} }
/** /**
* Tests special FAT32 characters are allowed. * Tests {@link FileUtils#sanitizeFileName(String)} with special FAT32
* characters. Verifies that they are allowed.
*/ */
public void testSanitizeFileName_special_characters() { public void testSanitizeFileName_special_characters() {
String name = "$%'-_@~`!(){}^#&+,;=[] "; String name = "$%'-_@~`!(){}^#&+,;=[] ";
String expected = "$%'-_@~`!(){}^#&+,;=[] "; String expected = "$%'-_@~`!(){}^#&+,;=[] ";
assertEquals(expected, FileUtils.sanitizeFileName(name));
assertEquals(expected, fileUtils.sanitizeFileName(name));
} }
/** /**
* Testing collapsing multiple underscores characters. * Tests {@link FileUtils#sanitizeFileName(String)} with multiple escaped
* characters in a row. Verifies that they are collapsed into one underscore.
*/ */
public void testSanitizeFileName_collapse() { public void testSanitizeFileName_collapse() {
String name = "hello//there"; String name = "hello//there";
String expected = "hello_there"; String expected = "hello_there";
assertEquals(expected, FileUtils.sanitizeFileName(name));
assertEquals(expected, fileUtils.sanitizeFileName(name));
} }
/**
* Tests {@link FileUtils#truncateFileName(File, String, String)}. Verifies
* the a long file name is truncated.
*/
public void testTruncateFileName() { public void testTruncateFileName() {
File directory = new File("/dir1/dir2/"); File directory = new File("/dir1/dir2/");
String suffix = ".gpx"; String suffix = ".gpx";
@@ -109,36 +112,12 @@ public class FileUtilsTest extends TestCase {
name[i] = 'a'; name[i] = 'a';
} }
String nameString = new String(name); String nameString = new String(name);
String truncated = FileUtils.truncateFileName(directory, nameString, suffix);
String truncated = fileUtils.truncateFileName(directory, nameString, suffix);
for (int i = 0; i < truncated.length(); i++) { for (int i = 0; i < truncated.length(); i++) {
assertEquals('a', truncated.charAt(i)); assertEquals('a', truncated.charAt(i));
} }
assertEquals(FileUtils.MAX_FAT32_PATH_LENGTH, assertEquals(FileUtils.MAX_FAT32_PATH_LENGTH,
new File(directory, truncated + suffix).getPath().length()); new File(directory, truncated + suffix).getPath().length());
} }
public void testBuildUniqueFileName_someExist() {
existingFiles = new HashSet<String>();
existingFiles.add("Filename.ext");
existingFiles.add("Filename(1).ext");
existingFiles.add("Filename(2).ext");
existingFiles.add("Filename(3).ext");
existingFiles.add("Filename(4).ext");
String filename = fileUtils.buildUniqueFileName(new File("/dir/"), "Filename", "ext");
assertEquals("Filename(5).ext", filename);
}
public void testBuildUniqueFileName_oneExists() {
existingFiles.add("Filename.ext");
String filename = fileUtils.buildUniqueFileName(new File("/dir/"), "Filename", "ext");
assertEquals("Filename(1).ext", filename);
}
public void testBuildUniqueFileName_noneExists() {
String filename = fileUtils.buildUniqueFileName(new File("/dir/"), "Filename", "ext");
assertEquals("Filename.ext", filename);
}
} }