From 09e154a818bdc42835b41e67c0dae7e10e13f576 Mon Sep 17 00:00:00 2001 From: Alexey Illarionov Date: Sun, 28 Jul 2013 01:02:08 +0400 Subject: [PATCH] rewrite hard --- .classpath | 17 +- .settings/org.eclipse.jdt.core.prefs | 291 ++++++++ .settings/org.eclipse.jdt.ui.prefs | 61 ++ AndroidManifest.xml | 43 +- project.properties | 2 +- res/layout/about.xml | 14 +- res/values/constants.xml | 2 - res/values/strings.xml | 4 +- res/xml/device_filter.xml | 11 +- res/xml/pref.xml | 3 +- .../provider/BluetoothGpsActivity.java | 274 -------- .../provider/BluetoothGpsProviderService.java | 314 --------- .../android/gps/nmea/util/NmeaParser.java | 475 ++++++------- .../android/gps/usb/UsbAcmController.java | 366 ++++++++++ .../android/gps/usb/UsbGpsManager.java | 399 +++++++++++ .../android/gps/usb/UsbPl2303Controller.java | 355 ++++++++++ .../android/gps/usb/UsbSerialController.java | 236 +++++++ .../android/gps/usb/UsbUtils.java | 168 +++++ .../provider/BlueetoothGpsManager.java | 633 ++++++------------ .../gps/usb/provider/SettingsFragment.java | 283 ++++++++ .../gps/usb/provider/UsbGpsActivity.java | 142 ++++ .../usb/provider/UsbGpsProviderService.java | 290 ++++++++ 22 files changed, 3082 insertions(+), 1301 deletions(-) create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.jdt.ui.prefs delete mode 100644 src/org/broeuschmeul/android/gps/bluetooth/provider/BluetoothGpsActivity.java delete mode 100644 src/org/broeuschmeul/android/gps/bluetooth/provider/BluetoothGpsProviderService.java create mode 100644 src/org/broeuschmeul/android/gps/usb/UsbAcmController.java create mode 100644 src/org/broeuschmeul/android/gps/usb/UsbGpsManager.java create mode 100644 src/org/broeuschmeul/android/gps/usb/UsbPl2303Controller.java create mode 100644 src/org/broeuschmeul/android/gps/usb/UsbSerialController.java create mode 100644 src/org/broeuschmeul/android/gps/usb/UsbUtils.java rename src/org/broeuschmeul/android/gps/{bluetooth => usb}/provider/BlueetoothGpsManager.java (67%) create mode 100644 src/org/broeuschmeul/android/gps/usb/provider/SettingsFragment.java create mode 100644 src/org/broeuschmeul/android/gps/usb/provider/UsbGpsActivity.java create mode 100644 src/org/broeuschmeul/android/gps/usb/provider/UsbGpsProviderService.java diff --git a/.classpath b/.classpath index 8981741b..d57ec025 100644 --- a/.classpath +++ b/.classpath @@ -1,8 +1,9 @@ - - - - - - - - + + + + + + + + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..023543f9 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,291 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=1 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=100 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000..23c2f966 --- /dev/null +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,61 @@ +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_Android +formatter_settings_version=12 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=android;com;dalvik;gov;junit;libcore;net;org;java;javax; +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=false +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ea022b99..b9cb3d14 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3,6 +3,7 @@ Copyright (C) 2010, 2011, 2012, 2013 Herbert von Broeuschmeul Copyright (C) 2010, 2011, 2012, 2013 BluetoothGPS4Droid Project Copyright (C) 2011, 2012, 2013 UsbGPS4Droid Project + Copyright (C) 2013 Alexey Illarionov This file is part of UsbGPS4Droid. @@ -24,17 +25,20 @@ + android:versionName="1.0 beta2"> - + - - + @@ -46,28 +50,17 @@ - - - + + - - - - - - - - - - - - - - - - + + + + + + diff --git a/project.properties b/project.properties index 895c9ce2..73fc6610 100644 --- a/project.properties +++ b/project.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-16 +target=android-18 diff --git a/res/layout/about.xml b/res/layout/about.xml index 197d5e47..6cfdec0c 100644 --- a/res/layout/about.xml +++ b/res/layout/about.xml @@ -28,7 +28,7 @@ > - beta 1 - startGps gpsLocationProviderKey replaceStdtGps diff --git a/res/values/strings.xml b/res/values/strings.xml index 557a5221..bed003d9 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -39,7 +39,9 @@ Mock location provider name Usb GPS name: %s Connection retry number - Number of attempts before exiting: %s + + Number of attempts before exiting: %s + Enable/Disable NMEA log Track recording is off Track recording is on diff --git a/res/xml/device_filter.xml b/res/xml/device_filter.xml index 4ef291b9..4437b1c6 100644 --- a/res/xml/device_filter.xml +++ b/res/xml/device_filter.xml @@ -1,4 +1,11 @@ - - + + + + + + + + + \ No newline at end of file diff --git a/res/xml/pref.xml b/res/xml/pref.xml index f3674afd..f5ef2d6f 100644 --- a/res/xml/pref.xml +++ b/res/xml/pref.xml @@ -79,8 +79,7 @@ android:key="@string/pref_connection_retries_key" android:title="@string/pref_connection_retries_title" android:defaultValue="@string/defaultConnectionRetries" - android:inputType="numberDecimal" - android:summary="@string/pref_connection_retries_summary" /> + android:inputType="numberDecimal" /> . - */ - -package org.broeuschmeul.android.gps.bluetooth.provider; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -import org.broeuschmeul.android.gps.usb.provider.R; - -import android.app.AlertDialog; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -//import android.bluetooth.BluetoothAdapter; -//import android.bluetooth.BluetoothDevice; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.hardware.usb.UsbAccessory; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbDeviceConnection; -import android.hardware.usb.UsbEndpoint; -import android.hardware.usb.UsbInterface; -import android.hardware.usb.UsbManager; -import android.hardware.usb.UsbRequest; -import android.os.Bundle; -import android.preference.CheckBoxPreference; -import android.preference.EditTextPreference; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceActivity; -import android.preference.PreferenceManager; -import android.preference.Preference.OnPreferenceChangeListener; -import android.text.method.LinkMovementMethod; -import android.util.Log; -import android.view.View; -import android.widget.TextView; - -/** - * A PreferenceActivity Class used to configure, start and stop the NMEA tracker service. - * - * @author Herbert von Broeuschmeul - * - */ -public class BluetoothGpsActivity extends PreferenceActivity implements OnPreferenceChangeListener, OnSharedPreferenceChangeListener { - - /** - * Tag used for log messages - */ - private static final String LOG_TAG = "UsbGPS"; - - private SharedPreferences sharedPref ; -// private BluetoothAdapter bluetoothAdapter = null; - private UsbManager usbManager = null; - private String deviceName = ""; - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.pref); - sharedPref = PreferenceManager.getDefaultSharedPreferences(this); - sharedPref.registerOnSharedPreferenceChangeListener(this); - usbManager = (UsbManager) getSystemService(this.USB_SERVICE); - Preference pref = findPreference(BluetoothGpsProviderService.PREF_ABOUT); - pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - BluetoothGpsActivity.this.displayAboutDialog(); - return true; - } - }); - } - - /* (non-Javadoc) - * @see android.app.Activity#onResume() - */ - @Override - protected void onResume() { - this.updateDevicePreferenceList(); - super.onResume(); - } - - private void updateDevicePreferenceSummary(){ - // update bluetooth device summary - String defaultDeviceName = ""; - ListPreference prefDevices = (ListPreference)findPreference(BluetoothGpsProviderService.PREF_GPS_DEVICE); - if (! usbManager.getDeviceList().isEmpty()){ - defaultDeviceName = usbManager.getDeviceList().keySet().iterator().next(); - } - deviceName = sharedPref.getString(BluetoothGpsProviderService.PREF_GPS_DEVICE, defaultDeviceName); - String deviceDisplayedName = ""; - if (! usbManager.getDeviceList().isEmpty() && usbManager.getDeviceList().get(deviceName) != null){ - deviceDisplayedName = usbManager.getDeviceList().get(deviceName).getDeviceName(); - } else if ((usbManager.getDeviceList().size() == 1) && (usbManager.getDeviceList().get(defaultDeviceName) != null)){ - deviceDisplayedName = usbManager.getDeviceList().get(defaultDeviceName).getDeviceName(); - deviceName = defaultDeviceName; - prefDevices.setValue(defaultDeviceName); - } - prefDevices.setSummary(getString(R.string.pref_gps_device_summary, deviceDisplayedName)); - ListPreference prefDeviceSpeed = (ListPreference)findPreference(BluetoothGpsProviderService.PREF_GPS_DEVICE_SPEED); - prefDeviceSpeed.setSummary(getString(R.string.pref_gps_device_speed_summary, sharedPref.getString(BluetoothGpsProviderService.PREF_GPS_DEVICE_SPEED, getString(R.string.defaultGpsDeviceSpeed)))); - } - - private void updateDevicePreferenceList(){ - // update bluetooth device summary - updateDevicePreferenceSummary(); - // update bluetooth device list - ListPreference prefDevices = (ListPreference)findPreference(BluetoothGpsProviderService.PREF_GPS_DEVICE); - HashMap connectedUsbDevices = usbManager.getDeviceList(); - String[] entryValues = new String[connectedUsbDevices.size()]; - String[] entries = new String[connectedUsbDevices.size()]; - int i = 0; - // Loop through usb devices - for (String name : connectedUsbDevices.keySet()) { - // Add the name and address to the ListPreference enties and entyValues - UsbDevice device = connectedUsbDevices.get(name); - Log.v(LOG_TAG, "device: "+name + " -- " + device.getDeviceName()+ " -- "+device); - Log.v(LOG_TAG, "device prot: "+device.getDeviceProtocol() + " class: " + device.getDeviceClass()+ " sub class: " + device.getDeviceSubclass()); - Log.v(LOG_TAG, "device dev id: "+device.getDeviceId() + " prod id: " + device.getProductId()+ " sub vend id: " + device.getVendorId()); - Log.v(LOG_TAG, "device int nb: "+device.getInterfaceCount()); - for (int k=0; k < device.getInterfaceCount(); k++){ - UsbInterface usbIntf = device.getInterface(k); - Log.v(LOG_TAG, "intf id: : "+ usbIntf.getId() + " -- "+usbIntf); - Log.v(LOG_TAG, "intf prot: "+usbIntf.getInterfaceProtocol() + " class: " + usbIntf.getInterfaceClass()+ " sub class: " +usbIntf.getInterfaceSubclass()); - Log.v(LOG_TAG, "intf int nb: "+usbIntf.getEndpointCount()); - for (int j=0; j < usbIntf.getEndpointCount(); j++){ - UsbEndpoint endPt = usbIntf.getEndpoint(j); - Log.v(LOG_TAG, "endPt: : "+endPt + " type: "+endPt.getType()+ " dir: "+endPt.getDirection() ); - } - } - entryValues[i] = device.getDeviceName(); - entries[i] = name; - i++; - } - prefDevices.setEntryValues(entryValues); - prefDevices.setEntries(entries); - Preference pref = (Preference)findPreference(BluetoothGpsProviderService.PREF_TRACK_RECORDING); - pref.setEnabled(sharedPref.getBoolean(BluetoothGpsProviderService.PREF_START_GPS_PROVIDER, false)); - pref = (Preference)findPreference(BluetoothGpsProviderService.PREF_MOCK_GPS_NAME); - String mockProvider = sharedPref.getString(BluetoothGpsProviderService.PREF_MOCK_GPS_NAME, getString(R.string.defaultMockGpsName)); - pref.setSummary(getString(R.string.pref_mock_gps_name_summary,mockProvider)); - pref = (Preference)findPreference(BluetoothGpsProviderService.PREF_CONNECTION_RETRIES); - String maxConnRetries = sharedPref.getString(BluetoothGpsProviderService.PREF_CONNECTION_RETRIES, getString(R.string.defaultConnectionRetries)); - pref.setSummary(getString(R.string.pref_connection_retries_summary,maxConnRetries)); - pref = (Preference)findPreference(BluetoothGpsProviderService.PREF_GPS_LOCATION_PROVIDER); - if (sharedPref.getBoolean(BluetoothGpsProviderService.PREF_REPLACE_STD_GPS, true)){ - String s = getString(R.string.pref_gps_location_provider_summary); - pref.setSummary(s); - Log.v(LOG_TAG, "loc. provider: "+s); - Log.v(LOG_TAG, "loc. provider: "+pref.getSummary()); - } else { - String s = getString(R.string.pref_mock_gps_name_summary, mockProvider); - pref.setSummary(s); - Log.v(LOG_TAG, "loc. provider: "+s); - Log.v(LOG_TAG, "loc. provider: "+pref.getSummary()); - } - this.onContentChanged(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - sharedPref.unregisterOnSharedPreferenceChangeListener(this); - } - - private void displayAboutDialog(){ - View messageView = getLayoutInflater().inflate(R.layout.about, null, false); - // we need this to enable html links - TextView textView = (TextView) messageView.findViewById(R.id.about_license); - textView.setMovementMethod(LinkMovementMethod.getInstance()); - // When linking text, force to always use default color. This works - // around a pressed color state bug. - int defaultColor = textView.getTextColors().getDefaultColor(); - textView.setTextColor(defaultColor); - textView = (TextView) messageView.findViewById(R.id.about_sources); - textView.setTextColor(defaultColor); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.about_title); - builder.setIcon(R.drawable.gplv3_icon); - builder.setView(messageView); - builder.show(); - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (BluetoothGpsProviderService.PREF_START_GPS_PROVIDER.equals(key)){ - boolean val = sharedPreferences.getBoolean(key, false); - CheckBoxPreference pref = (CheckBoxPreference)findPreference(key); - if (pref.isChecked() != val){ - pref.setChecked(val); - } else if (val){ - String device = sharedPreferences.getString(BluetoothGpsProviderService.PREF_GPS_DEVICE, ""); - if (! device.equals(deviceName) && deviceName != null && deviceName.length() > 0){ - sharedPreferences.edit().putString(BluetoothGpsProviderService.PREF_GPS_DEVICE,deviceName).commit(); - } - startService(new Intent(BluetoothGpsProviderService.ACTION_START_GPS_PROVIDER)); - } else { - startService(new Intent(BluetoothGpsProviderService.ACTION_STOP_GPS_PROVIDER)); - } - } else if (BluetoothGpsProviderService.PREF_TRACK_RECORDING.equals(key)){ - boolean val = sharedPreferences.getBoolean(key, false); - CheckBoxPreference pref = (CheckBoxPreference)findPreference(key); - if (pref.isChecked() != val){ - pref.setChecked(val); - } else if (val){ - startService(new Intent(BluetoothGpsProviderService.ACTION_START_TRACK_RECORDING)); - } else { - startService(new Intent(BluetoothGpsProviderService.ACTION_STOP_TRACK_RECORDING)); - } - } else if (BluetoothGpsProviderService.PREF_GPS_DEVICE.equals(key)){ - updateDevicePreferenceSummary(); - } else if (BluetoothGpsProviderService.PREF_GPS_DEVICE_SPEED.equals(key)){ - updateDevicePreferenceSummary(); - } else if (BluetoothGpsProviderService.PREF_SIRF_ENABLE_GLL.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_GGA.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_RMC.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_VTG.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSA.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSV.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_ZDA.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_SBAS.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_NMEA.equals(key) - || BluetoothGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION.equals(key) - ){ - enableSirfFeature(key); - } - this.updateDevicePreferenceList(); - } - private void enableSirfFeature(String key){ - CheckBoxPreference pref = (CheckBoxPreference)(findPreference(key)); - if (pref.isChecked() != sharedPref.getBoolean(key, false)){ - pref.setChecked(sharedPref.getBoolean(key, false)); - } else { - Intent configIntent = new Intent(BluetoothGpsProviderService.ACTION_CONFIGURE_SIRF_GPS); - configIntent.putExtra(key, pref.isChecked()); - startService(configIntent); - } - } -} diff --git a/src/org/broeuschmeul/android/gps/bluetooth/provider/BluetoothGpsProviderService.java b/src/org/broeuschmeul/android/gps/bluetooth/provider/BluetoothGpsProviderService.java deleted file mode 100644 index 852b318b..00000000 --- a/src/org/broeuschmeul/android/gps/bluetooth/provider/BluetoothGpsProviderService.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2010, 2011, 2012 Herbert von Broeuschmeul - * Copyright (C) 2010, 2011, 2012 BluetoothGPS4Droid Project - * Copyright (C) 2011, 2012 UsbGPS4Droid Project - * - * This file is part of UsbGPS4Droid. - * - * UsbGPS4Droid is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * UsbGPS4Droid is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with UsbGPS4Droid. If not, see . - */ - -/** - * - */ -package org.broeuschmeul.android.gps.bluetooth.provider; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.broeuschmeul.android.gps.usb.provider.R; - -import android.app.Notification; -import android.app.PendingIntent; -import android.app.Service; -//import android.bluetooth.BluetoothAdapter; -import android.content.Intent; -import android.content.SharedPreferences; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.location.GpsStatus.NmeaListener; -import android.os.Bundle; -import android.os.IBinder; -import android.preference.PreferenceManager; -import android.util.Config; -import android.util.Log; -import android.widget.Toast; - -/** - * A Service used to replace Android internal GPS with a bluetooth GPS and/or write GPS NMEA data in a File. - * - * @author Herbert von Broeuschmeul - * - */ -public class BluetoothGpsProviderService extends Service implements NmeaListener, LocationListener { - - public static final String ACTION_START_TRACK_RECORDING = "org.broeuschmeul.android.gps.usb.tracker.nmea.intent.action.START_TRACK_RECORDING"; - public static final String ACTION_STOP_TRACK_RECORDING = "org.broeuschmeul.android.gps.usb.tracker.nmea.intent.action.STOP_TRACK_RECORDING"; - public static final String ACTION_START_GPS_PROVIDER = "org.broeuschmeul.android.gps.usb.provider.nmea.intent.action.START_GPS_PROVIDER"; - public static final String ACTION_STOP_GPS_PROVIDER = "org.broeuschmeul.android.gps.usb.provider.nmea.intent.action.STOP_GPS_PROVIDER"; - public static final String ACTION_CONFIGURE_SIRF_GPS = "org.broeuschmeul.android.gps.usb.provider.nmea.intent.action.CONFIGURE_SIRF_GPS"; - public static final String PREF_START_GPS_PROVIDER = "startGps"; - public static final String PREF_GPS_LOCATION_PROVIDER = "gpsLocationProviderKey"; - public static final String PREF_REPLACE_STD_GPS = "replaceStdtGps"; - public static final String PREF_FORCE_ENABLE_PROVIDER = "forceEnableProvider"; - public static final String PREF_MOCK_GPS_NAME = "mockGpsName"; - public static final String PREF_CONNECTION_RETRIES = "connectionRetries"; - public static final String PREF_TRACK_RECORDING = "trackRecording"; - public static final String PREF_TRACK_FILE_DIR = "trackFileDirectory"; - public static final String PREF_TRACK_FILE_PREFIX = "trackFilePrefix"; - public static final String PREF_GPS_DEVICE = "usbDevice"; - public static final String PREF_GPS_DEVICE_SPEED = "gpsDeviceSpeed"; - public static final String PREF_ABOUT = "about"; - - /** - * Tag used for log messages - */ - private static final String LOG_TAG = "UsbGPS"; - - public static final String PREF_SIRF_GPS = "sirfGps"; - public static final String PREF_SIRF_ENABLE_GGA = "enableGGA"; - public static final String PREF_SIRF_ENABLE_RMC = "enableRMC"; - public static final String PREF_SIRF_ENABLE_GLL = "enableGLL"; - public static final String PREF_SIRF_ENABLE_VTG = "enableVTG"; - public static final String PREF_SIRF_ENABLE_GSA = "enableGSA"; - public static final String PREF_SIRF_ENABLE_GSV = "enableGSV"; - public static final String PREF_SIRF_ENABLE_ZDA = "enableZDA"; - public static final String PREF_SIRF_ENABLE_SBAS = "enableSBAS"; - public static final String PREF_SIRF_ENABLE_NMEA = "enableNMEA"; - public static final String PREF_SIRF_ENABLE_STATIC_NAVIGATION = "enableStaticNavigation"; - - private BlueetoothGpsManager gpsManager = null; - private PrintWriter writer; - private File trackFile; - private boolean preludeWritten = false; - private Toast toast ; - - @Override - public void onCreate() { - super.onCreate(); - toast = Toast.makeText(getApplicationContext(), "NMEA track recording... on", Toast.LENGTH_SHORT); - } - - @Override - public void onStart(Intent intent, int startId) { -// super.onStart(intent, startId); - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - SharedPreferences.Editor edit = sharedPreferences.edit(); - String deviceAddress = sharedPreferences.getString(PREF_GPS_DEVICE, ""); - int maxConRetries = Integer.parseInt(sharedPreferences.getString(PREF_CONNECTION_RETRIES, this.getString(R.string.defaultConnectionRetries))); - if (Config.LOGD){ - Log.d(LOG_TAG, "prefs device addr: "+deviceAddress); - } - if (ACTION_START_GPS_PROVIDER.equals(intent.getAction())){ - if (gpsManager == null){ - if (true /*|| BluetoothAdapter.checkBluetoothAddress(deviceAddress)*/){ - String mockProvider = LocationManager.GPS_PROVIDER; - if (! sharedPreferences.getBoolean(PREF_REPLACE_STD_GPS, true)){ - mockProvider = sharedPreferences.getString(PREF_MOCK_GPS_NAME, getString(R.string.defaultMockGpsName)); - } - gpsManager = new BlueetoothGpsManager(this, deviceAddress, maxConRetries); - boolean enabled = gpsManager.enable(); -// Bundle extras = intent.getExtras(); - if (sharedPreferences.getBoolean(PREF_START_GPS_PROVIDER, false) != enabled){ - edit.putBoolean(PREF_START_GPS_PROVIDER,enabled); - edit.commit(); - } - if (enabled) { - gpsManager.enableMockLocationProvider(mockProvider); - Notification notification = new Notification(R.drawable.ic_stat_notify, this.getString(R.string.foreground_gps_provider_started_notification), System.currentTimeMillis()); - Intent myIntent = new Intent(this, BluetoothGpsActivity.class); - PendingIntent myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT); - notification.setLatestEventInfo(getApplicationContext(), this.getString(R.string.foreground_service_started_notification_title), this.getString(R.string.foreground_gps_provider_started_notification), myPendingIntent); - startForeground(R.string.foreground_gps_provider_started_notification, notification); -// if (sharedPreferences.getBoolean(PREF_SIRF_GPS, false)){ -// gpsManager.enableSirfConfig(sharedPreferences); -// } - toast.setText(this.getString(R.string.msg_gps_provider_started)); - toast.show(); - } else { - stopSelf(); - } - } else { - stopSelf(); - } - } else { - toast.setText(this.getString(R.string.msg_gps_provider_already_started)); - toast.show(); - } - } else if (ACTION_START_TRACK_RECORDING.equals(intent.getAction())){ - if (trackFile == null){ - if (gpsManager != null){ - beginTrack(); - gpsManager.addNmeaListener(this); - if (! sharedPreferences.getBoolean(PREF_TRACK_RECORDING, false)){ - edit.putBoolean(PREF_TRACK_RECORDING,true); - edit.commit(); - } - toast.setText(this.getString(R.string.msg_nmea_recording_started)); - toast.show(); - } else { - endTrack(); - if ( sharedPreferences.getBoolean(PREF_TRACK_RECORDING, true)){ - edit.putBoolean(PREF_TRACK_RECORDING,false); - edit.commit(); - } - } - } else { - toast.setText(this.getString(R.string.msg_nmea_recording_already_started)); - toast.show(); - } - } else if (ACTION_STOP_TRACK_RECORDING.equals(intent.getAction())){ - if (gpsManager != null){ - gpsManager.removeNmeaListener(this); - endTrack(); - toast.setText(this.getString(R.string.msg_nmea_recording_stopped)); - toast.show(); - } - if (sharedPreferences.getBoolean(PREF_TRACK_RECORDING, true)){ - edit.putBoolean(PREF_TRACK_RECORDING,false); - edit.commit(); - } - } else if (ACTION_STOP_GPS_PROVIDER.equals(intent.getAction())){ - if (sharedPreferences.getBoolean(PREF_START_GPS_PROVIDER, true)){ - edit.putBoolean(PREF_START_GPS_PROVIDER,false); - edit.commit(); - } - stopSelf(); - } else if (ACTION_CONFIGURE_SIRF_GPS.equals(intent.getAction())){ - if (gpsManager != null){ - Bundle extras = intent.getExtras(); - gpsManager.enableSirfConfig(extras); - } - } - } - - /* (non-Javadoc) - * @see android.app.Service#onStartCommand(android.content.Intent, int, int) - */ - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - onStart(intent, startId); - return Service.START_NOT_STICKY; - } - - @Override - public void onDestroy() { - BlueetoothGpsManager manager = gpsManager; - gpsManager = null; - if (manager != null){ - if (manager.getDisableReason() != 0){ - toast.setText(getString(R.string.msg_gps_provider_stopped_by_problem, getString(manager.getDisableReason()))); - toast.show(); - } else { - toast.setText(R.string.msg_gps_provider_stopped); - toast.show(); - } - manager.removeNmeaListener(this); - manager.disableMockLocationProvider(); - manager.disable(); - } - endTrack(); - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - SharedPreferences.Editor edit = sharedPreferences.edit(); - if (sharedPreferences.getBoolean(PREF_TRACK_RECORDING, true)){ - edit.putBoolean(PREF_TRACK_RECORDING,false); - edit.commit(); - } - if (sharedPreferences.getBoolean(PREF_START_GPS_PROVIDER, true)){ - edit.putBoolean(PREF_START_GPS_PROVIDER,false); - edit.commit(); - } - super.onDestroy(); - } - - private void beginTrack(){ - SimpleDateFormat fmt = new SimpleDateFormat("_yyyy-MM-dd_HH-mm-ss'.nmea'"); - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - String trackDirName = sharedPreferences.getString(PREF_TRACK_FILE_DIR, this.getString(R.string.defaultTrackFileDirectory)); - String trackFilePrefix = sharedPreferences.getString(PREF_TRACK_FILE_PREFIX, this.getString(R.string.defaultTrackFilePrefix)); - trackFile = new File(trackDirName,trackFilePrefix+fmt.format(new Date())); - Log.d(LOG_TAG, "Writing the prelude of the NMEA file: "+trackFile.getAbsolutePath()); - File trackDir = trackFile.getParentFile(); - try { - if ((! trackDir.mkdirs()) && (! trackDir.isDirectory())){ - Log.e(LOG_TAG, "Error while creating parent dir of NMEA file: "+trackDir.getAbsolutePath()); - } - writer = new PrintWriter(new BufferedWriter(new FileWriter(trackFile))); - preludeWritten = true; - } catch (IOException e) { - Log.e(LOG_TAG, "Error while writing the prelude of the NMEA file: "+trackFile.getAbsolutePath(), e); - // there was an error while writing the prelude of the NMEA file, stopping the service... - stopSelf(); - } - } - private void endTrack(){ - if (trackFile != null && writer != null){ - Log.d(LOG_TAG, "Ending the NMEA file: "+trackFile.getAbsolutePath()); - preludeWritten = false; - writer.close(); - trackFile = null; - } - } - private void addNMEAString(String data){ - if (! preludeWritten){ - beginTrack(); - } - Log.v(LOG_TAG, "Adding data in the NMEA file: "+ data); - if (trackFile != null && writer != null){ - writer.print(data); - } - } - /* (non-Javadoc) - * @see android.app.Service#onBind(android.content.Intent) - */ - @Override - public IBinder onBind(Intent intent) { - if (Config.LOGD){ - Log.d(LOG_TAG, "trying access IBinder"); - } - return null; - } - - @Override - public void onLocationChanged(Location location) { - // TODO Auto-generated method stub - } - - @Override - public void onProviderDisabled(String provider) { - Log.i(LOG_TAG, "The GPS has been disabled.....stopping the NMEA tracker service."); - stopSelf(); - } - - @Override - public void onProviderEnabled(String provider) { - // TODO Auto-generated method stub - } - - @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - // TODO Auto-generated method stub - } - - @Override - public void onNmeaReceived(long timestamp, String data) { - addNMEAString(data); - } -} diff --git a/src/org/broeuschmeul/android/gps/nmea/util/NmeaParser.java b/src/org/broeuschmeul/android/gps/nmea/util/NmeaParser.java index 2c5db10c..2dcad537 100644 --- a/src/org/broeuschmeul/android/gps/nmea/util/NmeaParser.java +++ b/src/org/broeuschmeul/android/gps/nmea/util/NmeaParser.java @@ -2,32 +2,25 @@ * Copyright (C) 2010, 2011, 2012 Herbert von Broeuschmeul * Copyright (C) 2010, 2011, 2012 BluetoothGPS4Droid Project * Copyright (C) 2011, 2012 UsbGPS4Droid Project - * + * * This file is part of UsbGPS4Droid. * * UsbGPS4Droid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * UsbGPS4Droid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with UsbGPS4Droid. If not, see . */ package org.broeuschmeul.android.gps.nmea.util; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import android.location.Criteria; import android.location.Location; import android.location.LocationManager; @@ -37,11 +30,18 @@ import android.text.TextUtils.SimpleStringSplitter; import android.util.Log; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * This class is used to parse NMEA sentences an generate the Android Locations when there is a new GPS FIX. * It manage also the Mock Location Provider (enable/disable/fix & status notification) * and can compute the the checksum of a NMEA sentence. - * + * * @author Herbert von Broeuschmeul * */ @@ -51,6 +51,8 @@ public class NmeaParser { */ private static final String LOG_TAG = "UsbGPS"; + private static final Pattern sNmeaSentencePattern = Pattern.compile("\\$([^*$]*)(?:\\*([0-9A-F][0-9A-F]))?\r\n"); + private String fixTime = null; private long fixTimestamp; @@ -97,8 +99,8 @@ public void enableMockLocationProvider(String gpsName, boolean force){ } prov = lm.getProvider(mockLocationProvider); lm.addTestProvider(mockLocationProvider, false, true,false, false, true, true, true, Criteria.POWER_MEDIUM, Criteria.ACCURACY_FINE); - if ( force - || (prov == null) + if ( force + || (prov == null) // || (! LocationManager.GPS_PROVIDER.equals(mockLocationProvider)) ){ Log.d(LOG_TAG, "enabling Mock provider: "+mockLocationProvider); @@ -129,7 +131,7 @@ public void disableMockLocationProvider(){ Log.v(LOG_TAG, "Mock provider: "+prov.getName()+" "+prov.getPowerRequirement()+" "+prov.getAccuracy()+" "+lm.isProviderEnabled(mockLocationProvider)); } mockGpsEnabled = false; - if ( mockGpsAutoEnabled ) { + if ( mockGpsAutoEnabled ) { Log.d(LOG_TAG, "disabling Mock provider: "+mockLocationProvider); lm.setTestProviderEnabled(mockLocationProvider, false); } @@ -150,7 +152,7 @@ public void disableMockLocationProvider(){ } Log.d(LOG_TAG, "removed mock GPS"); } else { - Log.d(LOG_TAG, "Mock provider already disabled: "+mockLocationProvider); + Log.d(LOG_TAG, "Mock provider already disabled: "+mockLocationProvider); } } catch (SecurityException e){ Log.e(LOG_TAG, "Error while enabling Mock Mocations Provider", e); @@ -168,7 +170,7 @@ public void disableMockLocationProvider(){ public boolean isMockGpsEnabled() { return mockGpsEnabled; } - + public void setMockLocationProviderOutOfService(){ notifyStatusChanged(LocationProvider.OUT_OF_SERVICE, null, System.currentTimeMillis()); } @@ -179,7 +181,7 @@ public void setMockLocationProviderOutOfService(){ public String getMockLocationProvider() { return mockLocationProvider; } - + private void notifyFix(Location fix) throws SecurityException { fixTime = null; hasGGA = false; @@ -193,7 +195,7 @@ private void notifyFix(Location fix) throws SecurityException { this.fix = null; } } - + private void notifyStatusChanged(int status, Bundle extras, long updateTime){ fixTime = null; hasGGA = false; @@ -210,24 +212,28 @@ private void notifyStatusChanged(int status, Bundle extras, long updateTime){ this.mockStatus = status; } } - - // parse NMEA Sentence + + // parse NMEA Sentence public String parseNmeaSentence(String gpsSentence) throws SecurityException { String nmeaSentence = null; - Log.v(LOG_TAG, "data: "+System.currentTimeMillis()+" "+gpsSentence); - Pattern xx = Pattern.compile("\\$([^*$]*)(?:\\*([0-9A-F][0-9A-F]))?\r\n"); - Matcher m = xx.matcher(gpsSentence); - if (m.matches()){ - nmeaSentence = m.group(0); - String sentence = m.group(1); - String checkSum = m.group(2); - Log.v(LOG_TAG, "data: "+System.currentTimeMillis()+" "+sentence+" cheksum: "+checkSum +" control: "+String.format("%02X",computeChecksum(sentence))); - SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(','); - splitter.setString(sentence); - String command = splitter.next(); - if (command.equals("GPGGA")){ - /* $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 - + + final Matcher m = sNmeaSentencePattern.matcher(gpsSentence); + + if (!m.matches()) { + Log.v(LOG_TAG, "note NMEA sentence: "+System.currentTimeMillis()+" "+gpsSentence); + return null; + } + + nmeaSentence = m.group(0); + String sentence = m.group(1); + String checkSum = m.group(2); + Log.v(LOG_TAG, "data: "+System.currentTimeMillis()+" "+sentence+" cheksum: "+checkSum +" control: "+String.format("%02X",computeChecksum(sentence))); + SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(sentence); + String command = splitter.next(); + if (command.equals("GPGGA")){ + /* $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 + Where: GGA Global Positioning System Fix Data 123519 Fix taken at 12:35:19 UTC @@ -249,19 +255,19 @@ public String parseNmeaSentence(String gpsSentence) throws SecurityException { ellipsoid (empty field) time in seconds since last DGPS update (empty field) DGPS station ID number - *47 the checksum data, always begins with * - */ - // UTC time of fix HHmmss.S - String time = splitter.next(); - // latitude ddmm.M - String lat = splitter.next(); - // direction (N/S) - String latDir = splitter.next(); - // longitude dddmm.M - String lon = splitter.next(); - // direction (E/W) - String lonDir = splitter.next(); - /* fix quality: + *47 the checksum data, always begins with * + */ + // UTC time of fix HHmmss.S + String time = splitter.next(); + // latitude ddmm.M + String lat = splitter.next(); + // direction (N/S) + String latDir = splitter.next(); + // longitude dddmm.M + String lon = splitter.next(); + // direction (E/W) + String lonDir = splitter.next(); + /* fix quality: 0= invalid 1 = GPS fix (SPS) 2 = DGPS fix @@ -271,62 +277,62 @@ public String parseNmeaSentence(String gpsSentence) throws SecurityException { 6 = estimated (dead reckoning) (2.3 feature) 7 = Manual input mode 8 = Simulation mode - */ - String quality = splitter.next(); - // Number of satellites being tracked - String nbSat = splitter.next(); - // Horizontal dilution of position (float) - String hdop = splitter.next(); - // Altitude, Meters, above mean sea level - String alt = splitter.next(); - // Height of geoid (mean sea level) above WGS84 ellipsoid - String geoAlt = splitter.next(); - // time in seconds since last DGPS update - // DGPS station ID number - if (quality != null && !quality.equals("") && !quality.equals("0") ){ - if (this.mockStatus != LocationProvider.AVAILABLE){ - long updateTime = parseNmeaTime(time); - notifyStatusChanged(LocationProvider.AVAILABLE, null, updateTime); - } - if (! time.equals(fixTime)){ - notifyFix(fix); - fix = new Location(mockLocationProvider); - fixTime = time; - fixTimestamp = parseNmeaTime(time); - fix.setTime(fixTimestamp); - Log.v(LOG_TAG, "Fix: "+fix); - } - if (lat != null && !lat.equals("")){ - fix.setLatitude(parseNmeaLatitude(lat,latDir)); - } - if (lon != null && !lon.equals("")){ - fix.setLongitude(parseNmeaLongitude(lon,lonDir)); - } - if (hdop != null && !hdop.equals("")){ - fix.setAccuracy(Float.parseFloat(hdop)*precision); - } - if (alt != null && !alt.equals("")){ - fix.setAltitude(Double.parseDouble(alt)); - } - if (nbSat != null && !nbSat.equals("")){ - Bundle extras = new Bundle(); - extras.putInt("satellites", Integer.parseInt(nbSat)); - fix.setExtras(extras); - } - Log.v(LOG_TAG, "Fix: "+System.currentTimeMillis()+" "+fix); - hasGGA = true; - if (hasGGA && hasRMC){ - notifyFix(fix); - } - } else if(quality.equals("0")){ - if (this.mockStatus != LocationProvider.TEMPORARILY_UNAVAILABLE){ - long updateTime = parseNmeaTime(time); - notifyStatusChanged(LocationProvider.TEMPORARILY_UNAVAILABLE, null, updateTime); - } - } - } else if (command.equals("GPRMC")){ - /* $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A - + */ + String quality = splitter.next(); + // Number of satellites being tracked + String nbSat = splitter.next(); + // Horizontal dilution of position (float) + String hdop = splitter.next(); + // Altitude, Meters, above mean sea level + String alt = splitter.next(); + // Height of geoid (mean sea level) above WGS84 ellipsoid + String geoAlt = splitter.next(); + // time in seconds since last DGPS update + // DGPS station ID number + if (quality != null && !quality.equals("") && !quality.equals("0") ){ + if (this.mockStatus != LocationProvider.AVAILABLE){ + long updateTime = parseNmeaTime(time); + notifyStatusChanged(LocationProvider.AVAILABLE, null, updateTime); + } + if (! time.equals(fixTime)){ + notifyFix(fix); + fix = new Location(mockLocationProvider); + fixTime = time; + fixTimestamp = parseNmeaTime(time); + fix.setTime(fixTimestamp); + Log.v(LOG_TAG, "Fix: "+fix); + } + if (lat != null && !lat.equals("")){ + fix.setLatitude(parseNmeaLatitude(lat,latDir)); + } + if (lon != null && !lon.equals("")){ + fix.setLongitude(parseNmeaLongitude(lon,lonDir)); + } + if (hdop != null && !hdop.equals("")){ + fix.setAccuracy(Float.parseFloat(hdop)*precision); + } + if (alt != null && !alt.equals("")){ + fix.setAltitude(Double.parseDouble(alt)); + } + if (nbSat != null && !nbSat.equals("")){ + Bundle extras = new Bundle(); + extras.putInt("satellites", Integer.parseInt(nbSat)); + fix.setExtras(extras); + } + Log.v(LOG_TAG, "Fix: "+System.currentTimeMillis()+" "+fix); + hasGGA = true; + if (hasGGA && hasRMC){ + notifyFix(fix); + } + } else if(quality.equals("0")){ + if (this.mockStatus != LocationProvider.TEMPORARILY_UNAVAILABLE){ + long updateTime = parseNmeaTime(time); + notifyStatusChanged(LocationProvider.TEMPORARILY_UNAVAILABLE, null, updateTime); + } + } + } else if (command.equals("GPRMC")){ + /* $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A + Where: RMC Recommended Minimum sentence C 123519 Fix taken at 12:35:19 UTC @@ -337,152 +343,151 @@ public String parseNmeaSentence(String gpsSentence) throws SecurityException { 084.4 Track angle in degrees True 230394 Date - 23rd of March 1994 003.1,W Magnetic Variation - *6A The checksum data, always begins with * - */ - // UTC time of fix HHmmss.S - String time = splitter.next(); - // fix status (A/V) - String status = splitter.next(); - // latitude ddmm.M - String lat = splitter.next(); - // direction (N/S) - String latDir = splitter.next(); - // longitude dddmm.M - String lon = splitter.next(); - // direction (E/W) - String lonDir = splitter.next(); - // Speed over the ground in knots - String speed = splitter.next(); - // Track angle in degrees True - String bearing = splitter.next(); - // UTC date of fix DDMMYY - String date = splitter.next(); - // Magnetic Variation ddd.D - String magn = splitter.next(); - // Magnetic variation direction (E/W) - String magnDir = splitter.next(); - // for NMEA 0183 version 3.00 active the Mode indicator field is added - // Mode indicator, (A=autonomous, D=differential, E=Estimated, N=not valid, S=Simulator ) - if (status != null && !status.equals("") && status.equals("A") ){ - if (this.mockStatus != LocationProvider.AVAILABLE){ - long updateTime = parseNmeaTime(time); - notifyStatusChanged(LocationProvider.AVAILABLE, null, updateTime); - } - if (! time.equals(fixTime)){ - notifyFix(fix); - fix = new Location(mockLocationProvider); - fixTime = time; - fixTimestamp = parseNmeaTime(time); - fix.setTime(fixTimestamp); - Log.v(LOG_TAG, "Fix: "+fix); - } - if (lat != null && !lat.equals("")){ - fix.setLatitude(parseNmeaLatitude(lat,latDir)); - } - if (lon != null && !lon.equals("")){ - fix.setLongitude(parseNmeaLongitude(lon,lonDir)); - } - if (speed != null && !speed.equals("")){ - fix.setSpeed(parseNmeaSpeed(speed, "N")); - } - if (bearing != null && !bearing.equals("")){ - fix.setBearing(Float.parseFloat(bearing)); - } - Log.v(LOG_TAG, "Fix: "+System.currentTimeMillis()+" "+fix); - hasRMC = true; - if (hasGGA && hasRMC){ - notifyFix(fix); - } - } else if(status.equals("V")){ - if (this.mockStatus != LocationProvider.TEMPORARILY_UNAVAILABLE){ - long updateTime = parseNmeaTime(time); - notifyStatusChanged(LocationProvider.TEMPORARILY_UNAVAILABLE, null, updateTime); - } - } - } else if (command.equals("GPGSA")){ - /* $GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39 - + *6A The checksum data, always begins with * + */ + // UTC time of fix HHmmss.S + String time = splitter.next(); + // fix status (A/V) + String status = splitter.next(); + // latitude ddmm.M + String lat = splitter.next(); + // direction (N/S) + String latDir = splitter.next(); + // longitude dddmm.M + String lon = splitter.next(); + // direction (E/W) + String lonDir = splitter.next(); + // Speed over the ground in knots + String speed = splitter.next(); + // Track angle in degrees True + String bearing = splitter.next(); + // UTC date of fix DDMMYY + String date = splitter.next(); + // Magnetic Variation ddd.D + String magn = splitter.next(); + // Magnetic variation direction (E/W) + String magnDir = splitter.next(); + // for NMEA 0183 version 3.00 active the Mode indicator field is added + // Mode indicator, (A=autonomous, D=differential, E=Estimated, N=not valid, S=Simulator ) + if (status != null && !status.equals("") && status.equals("A") ){ + if (this.mockStatus != LocationProvider.AVAILABLE){ + long updateTime = parseNmeaTime(time); + notifyStatusChanged(LocationProvider.AVAILABLE, null, updateTime); + } + if (! time.equals(fixTime)){ + notifyFix(fix); + fix = new Location(mockLocationProvider); + fixTime = time; + fixTimestamp = parseNmeaTime(time); + fix.setTime(fixTimestamp); + Log.v(LOG_TAG, "Fix: "+fix); + } + if (lat != null && !lat.equals("")){ + fix.setLatitude(parseNmeaLatitude(lat,latDir)); + } + if (lon != null && !lon.equals("")){ + fix.setLongitude(parseNmeaLongitude(lon,lonDir)); + } + if (speed != null && !speed.equals("")){ + fix.setSpeed(parseNmeaSpeed(speed, "N")); + } + if (bearing != null && !bearing.equals("")){ + fix.setBearing(Float.parseFloat(bearing)); + } + Log.v(LOG_TAG, "Fix: "+System.currentTimeMillis()+" "+fix); + hasRMC = true; + if (hasGGA && hasRMC){ + notifyFix(fix); + } + } else if(status.equals("V")){ + if (this.mockStatus != LocationProvider.TEMPORARILY_UNAVAILABLE){ + long updateTime = parseNmeaTime(time); + notifyStatusChanged(LocationProvider.TEMPORARILY_UNAVAILABLE, null, updateTime); + } + } + } else if (command.equals("GPGSA")){ + /* $GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39 + Where: GSA Satellite status - A Auto selection of 2D or 3D fix (M = manual) + A Auto selection of 2D or 3D fix (M = manual) 3 3D fix - values include: 1 = no fix 2 = 2D fix 3 = 3D fix - 04,05... PRNs of satellites used for fix (space for 12) - 2.5 PDOP (Position dilution of precision) - 1.3 Horizontal dilution of precision (HDOP) + 04,05... PRNs of satellites used for fix (space for 12) + 2.5 PDOP (Position dilution of precision) + 1.3 Horizontal dilution of precision (HDOP) 2.1 Vertical dilution of precision (VDOP) - *39 the checksum data, always begins with * - */ - // mode : A Auto selection of 2D or 3D fix / M = manual - String mode = splitter.next(); - // fix type : 1 - no fix / 2 - 2D / 3 - 3D - String fixType = splitter.next(); - // discard PRNs of satellites used for fix (space for 12) - for (int i=0 ; ((i<12)&&(! "1".equals(fixType))) ; i++){ - splitter.next(); - } - // Position dilution of precision (float) - String pdop = splitter.next(); - // Horizontal dilution of precision (float) - String hdop = splitter.next(); - // Vertical dilution of precision (float) - String vdop = splitter.next(); - } else if (command.equals("GPVTG")){ - /* $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48 - + *39 the checksum data, always begins with * + */ + // mode : A Auto selection of 2D or 3D fix / M = manual + String mode = splitter.next(); + // fix type : 1 - no fix / 2 - 2D / 3 - 3D + String fixType = splitter.next(); + // discard PRNs of satellites used for fix (space for 12) + for (int i=0 ; ((i<12)&&(! "1".equals(fixType))) ; i++){ + splitter.next(); + } + // Position dilution of precision (float) + String pdop = splitter.next(); + // Horizontal dilution of precision (float) + String hdop = splitter.next(); + // Vertical dilution of precision (float) + String vdop = splitter.next(); + } else if (command.equals("GPVTG")){ + /* $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48 + where: VTG Track made good and ground speed 054.7,T True track made good (degrees) 034.4,M Magnetic track made good 005.5,N Ground speed, knots 010.2,K Ground speed, Kilometers per hour - *48 Checksum - */ - // Track angle in degrees True - String bearing = splitter.next(); - // T - splitter.next(); - // Magnetic track made good - String magn = splitter.next(); - // M - splitter.next(); - // Speed over the ground in knots - String speedKnots = splitter.next(); - // N - splitter.next(); - // Speed over the ground in Kilometers per hour - String speedKm = splitter.next(); - // K - splitter.next(); - // for NMEA 0183 version 3.00 active the Mode indicator field is added - // Mode indicator, (A=autonomous, D=differential, E=Estimated, N=not valid, S=Simulator ) - } else if (command.equals("GPGLL")){ - /* $GPGLL,4916.45,N,12311.12,W,225444,A,*1D - + *48 Checksum + */ + // Track angle in degrees True + String bearing = splitter.next(); + // T + splitter.next(); + // Magnetic track made good + String magn = splitter.next(); + // M + splitter.next(); + // Speed over the ground in knots + String speedKnots = splitter.next(); + // N + splitter.next(); + // Speed over the ground in Kilometers per hour + String speedKm = splitter.next(); + // K + splitter.next(); + // for NMEA 0183 version 3.00 active the Mode indicator field is added + // Mode indicator, (A=autonomous, D=differential, E=Estimated, N=not valid, S=Simulator ) + } else if (command.equals("GPGLL")){ + /* $GPGLL,4916.45,N,12311.12,W,225444,A,*1D + Where: GLL Geographic position, Latitude and Longitude 4916.46,N Latitude 49 deg. 16.45 min. North 12311.12,W Longitude 123 deg. 11.12 min. West 225444 Fix taken at 22:54:44 UTC A Data Active or V (void) - *iD checksum data - */ - // latitude ddmm.M - String lat = splitter.next(); - // direction (N/S) - String latDir = splitter.next(); - // longitude dddmm.M - String lon = splitter.next(); - // direction (E/W) - String lonDir = splitter.next(); - // UTC time of fix HHmmss.S - String time = splitter.next(); - // fix status (A/V) - String status = splitter.next(); - // for NMEA 0183 version 3.00 active the Mode indicator field is added - // Mode indicator, (A=autonomous, D=differential, E=Estimated, N=not valid, S=Simulator ) - } + *iD checksum data + */ + // latitude ddmm.M + String lat = splitter.next(); + // direction (N/S) + String latDir = splitter.next(); + // longitude dddmm.M + String lon = splitter.next(); + // direction (E/W) + String lonDir = splitter.next(); + // UTC time of fix HHmmss.S + String time = splitter.next(); + // fix status (A/V) + String status = splitter.next(); + // for NMEA 0183 version 3.00 active the Mode indicator field is added + // Mode indicator, (A=autonomous, D=differential, E=Estimated, N=not valid, S=Simulator ) } return nmeaSentence; } @@ -491,7 +496,7 @@ public double parseNmeaLatitude(String lat,String orientation){ double latitude = 0.0; if (lat != null && orientation != null && !lat.equals("") && !orientation.equals("")){ double temp1 = Double.parseDouble(lat); - double temp2 = Math.floor(temp1/100); + double temp2 = Math.floor(temp1/100); double temp3 = (temp1/100 - temp2)/0.6; if (orientation.equals("S")){ latitude = -(temp2+temp3); @@ -505,7 +510,7 @@ public double parseNmeaLongitude(String lon,String orientation){ double longitude = 0.0; if (lon != null && orientation != null && !lon.equals("") && !orientation.equals("")){ double temp1 = Double.parseDouble(lon); - double temp2 = Math.floor(temp1/100); + double temp2 = Math.floor(temp1/100); double temp3 = (temp1/100 - temp2)/0.6; if (orientation.equals("W")){ longitude = -(temp2+temp3); @@ -536,7 +541,7 @@ public long parseNmeaTime(String time){ long now = System.currentTimeMillis(); long today = now - (now %86400000L); long temp1; - // sometime we don't have millisecond in the time string, so we have to reformat it + // sometime we don't have millisecond in the time string, so we have to reformat it temp1 = fmt.parse(String.format((Locale)null,"%010.3f", Double.parseDouble(time))).getTime(); long temp2 = today+temp1; // if we're around midnight we could have a problem... @@ -556,7 +561,7 @@ public long parseNmeaTime(String time){ public byte computeChecksum(String s){ byte checksum = 0; for (char c : s.toCharArray()){ - checksum ^= (byte)c; + checksum ^= (byte)c; } return checksum; } diff --git a/src/org/broeuschmeul/android/gps/usb/UsbAcmController.java b/src/org/broeuschmeul/android/gps/usb/UsbAcmController.java new file mode 100644 index 00000000..617e32bf --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/UsbAcmController.java @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2013 Alexey Illarionov + * + * This file is part of UsbGPS4Droid. + * + * UsbGPS4Droid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * UsbGPS4Droid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with UsbGPS4Droid. If not, see . + */ + +package org.broeuschmeul.android.gps.usb; + +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbManager; +import android.util.Log; + +import org.broeuschmeul.android.gps.usb.provider.BuildConfig; + +import java.io.InputStream; +import java.io.OutputStream; + +/* USB CDC ACM (Communication Device Class Abstract Control Model) */ +public class UsbAcmController extends UsbSerialController { + + // Debugging + private static final String TAG = UsbAcmController.class.getSimpleName(); + private static final boolean D = BuildConfig.DEBUG & true; + + private UsbDeviceConnection mUsbConnection; + + private UsbSerialInputStream inputStream = null; + private UsbSerialOutputStream outputStream = null; + private UsbSerialInterruptListener interruptListener = null; + + private int mBaudrate; + + private final AcmConfig mAcmConfig; + + private static class AcmConfig { + + android.hardware.usb.UsbInterface mCommunicationInterface = null; + android.hardware.usb.UsbInterface mDataInterface = null; + + UsbEndpoint mInterruptEndpoint = null; + UsbEndpoint mBulkInEndpoint = null; + UsbEndpoint mBulkOutEndpoint = null; + + public AcmConfig(UsbDevice usbDevice) throws UsbControllerException { + + int ifaceIdx, ifaceCount; + ifaceCount = usbDevice.getInterfaceCount(); + foreachIface: for (ifaceIdx=0; ifaceIdx>> 8) & 0xff); + req[2] = (byte)((baudrate >>> 16) & 0xff); + req[3] = (byte)((baudrate >>> 24) & 0xff); + + /* bCharFormat */ + if (stopBits != 1 && (stopBits != 2)) throw new IllegalArgumentException("Wrong stop bits"); + req[4] = stopBits == 1 ? (byte)0 : (byte)2; + + /* bParityType */ + switch (parity) { + case 'N': req[5] = 0; break; /* None */ + case 'O': req[5] = 1; break; /* Odd */ + case 'E': req[5] = 2; break; /* Even */ + case 'M': req[5] = 3; break; /* Mark */ + case 'S': req[5] = 4; break; /* Space */ + default: throw new IllegalArgumentException("Wrong parity"); + } + + /* bDataBits */ + switch (dataBits) { + case 5: + case 6: + case 7: + case 8: + case 16: + req[6] = (byte)dataBits; + break; + default: throw new IllegalArgumentException("Wrong data bits"); + } + + Log.d(TAG, "SetLineCoding rate=" + baudrate + " " + + Integer.toString(dataBits) + + Character.toString(parity) + + stopBits); + + if (mUsbConnection.controlTransfer( + 0x21, + 0x20, /* SET_LINE_CODING */ + 0, + 0, /* bulk data interface number */ + req, + req.length, + 1000 + ) < 0) + return false; + + return true; + } +} diff --git a/src/org/broeuschmeul/android/gps/usb/UsbGpsManager.java b/src/org/broeuschmeul/android/gps/usb/UsbGpsManager.java new file mode 100644 index 00000000..0277f463 --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/UsbGpsManager.java @@ -0,0 +1,399 @@ +package org.broeuschmeul.android.gps.usb; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; +import android.os.ConditionVariable; +import android.util.Log; + +import org.broeuschmeul.android.gps.usb.UsbSerialController.UsbControllerException; +import org.broeuschmeul.android.gps.usb.provider.BuildConfig; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class UsbGpsManager { + + private static final boolean DBG = BuildConfig.DEBUG & true; + static final String TAG = UsbGpsManager.class.getSimpleName(); + + // Constants that indicate the current connection state + public static final int STATE_IDLE = 0; + public static final int STATE_CONNECTING = 1; + public static final int STATE_CONNECTED = 2; + public static final int STATE_WAITING = 3; + public static final int STATE_RECONNECTING = 4; + + public static final String ACTION_USB_DEVICE_ATTACHED = "ru0xdc.rtkgps.UsbToRtklib.ACTION_USB_DEVICE_ATTACHED"; + + final UsbReceiver mUsbReceiver; + + private Callbacks mCallbacks; + + public static final int RECONNECT_TIMEOUT_MS = 2000; + + private static final Callbacks sDummyCallbacks = new Callbacks() { + @Override + public void onConnected() {} + @Override + public void onStopped() {} + @Override + public void onConnectionLost() {} + }; + + + public interface Callbacks { + + public void onConnected(); + + public void onStopped(); + + public void onConnectionLost(); + + } + + public UsbGpsManager(Context serviceContext) { + mUsbReceiver = new UsbReceiver(serviceContext); + mCallbacks = sDummyCallbacks; + } + + public void start() { + mUsbReceiver.start(); + } + + public void stop() { + mUsbReceiver.stop(); + } + + public void setBaudRate(int baudrate) { + mUsbReceiver.setBaudRate(baudrate); + } + + public int getBaudRate() { + return mUsbReceiver.getBaudRate(); + } + + public void setCallbacks(Callbacks callbacks) { + if (callbacks == null) throw new IllegalStateException(); + mCallbacks = callbacks; + } + + private class UsbReceiver { + + final String ACTION_USB_PERMISSION = UsbReceiver.class.getName() + ".USB_PERMISSION"; + + private int mBaudrate = UsbSerialController.DEFAULT_BAUDRATE; + + private Context mContext; + + private UsbManager mUsbManager; + + final ConditionVariable mIsUsbDeviceReadyCondvar; + + private UsbServiceThread mServiceThread; + + public UsbReceiver(Context pContext) { + + this.mContext = pContext; + this.mUsbManager = (UsbManager) pContext.getSystemService(Context.USB_SERVICE); + mIsUsbDeviceReadyCondvar = new ConditionVariable(false); + + if (mUsbManager == null) throw new IllegalStateException("USB not available"); + } + + public synchronized void start() { + final IntentFilter f; + f = new IntentFilter(); + f.addAction(ACTION_USB_DEVICE_ATTACHED); + f.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); + f.addAction(ACTION_USB_PERMISSION); + + mContext.registerReceiver(mUsbStateListener, f); + + mServiceThread = new UsbServiceThread(); + mServiceThread.start(); + + try { + final UsbDevice d = UsbUtils.findSupportedDevices(mUsbManager).get(0); + requestPermission(d); + }catch (IndexOutOfBoundsException ignore) { } + + } + + public synchronized void setBaudRate(int baudrate) { + this.mBaudrate = baudrate; + } + + public synchronized int getBaudRate() { + return this.mBaudrate; + } + + + public boolean isDeviceReady() { + return mIsUsbDeviceReadyCondvar.block(1); + } + + public void waitDevice() { + mIsUsbDeviceReadyCondvar.block(); + } + + public synchronized void write(byte[] buffer, int offset, int count) throws IOException { + if (mServiceThread == null) throw new IOException("not connected"); + mServiceThread.write(buffer, offset, count); + } + + public synchronized void stop() { + mContext.unregisterReceiver(mUsbStateListener); + mServiceThread.cancel(); + mServiceThread = null; + mIsUsbDeviceReadyCondvar.open(); + } + + + private void requestPermission(UsbDevice d) { + if (DBG) Log.d(TAG, "requestPermission() device=" + d.toString()); + final PendingIntent premissionIntent = PendingIntent.getBroadcast(mContext, + 0, new Intent(ACTION_USB_PERMISSION), 0); + mUsbManager.requestPermission(d, premissionIntent); + } + + void onUsbDeviceAttached(UsbDevice device) { + if (DBG) Log.d(TAG, "onUsbDeviceAttached() device=" + device.toString()); + + if (UsbUtils.probeDevice(mUsbManager, device) != null) { + requestPermission(device); + } + } + + synchronized void onUsbDeviceDetached(UsbDevice device) { + + if (DBG) Log.d(TAG, "onUsbDeviceDetached() device=" + device.toString()); + + UsbSerialController controller = mServiceThread.getController(); + + if (controller == null) return; + if (!device.equals(controller.getDevice())) return; + + mServiceThread.setController(null); + } + + synchronized void onUsbPermissionGranted(UsbDevice device) { + if (DBG) Log.d(TAG, "onUsbPermissionGranted() device=" + device.toString()); + UsbSerialController controller = mServiceThread.getController(); + + if (controller != null) return; + + controller = UsbUtils.probeDevice(mUsbManager, device); + if (controller == null) return; + + controller.setBaudRate(mBaudrate); + + mServiceThread.setController(controller); + + } + + private final BroadcastReceiver mUsbStateListener = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + UsbDevice device; + String action = intent.getAction(); + Log.v(TAG, "Received intent " + action); + + if (action.equals(ACTION_USB_DEVICE_ATTACHED)) { + device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + onUsbDeviceAttached(device); + }else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) { + device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + onUsbDeviceDetached(device); + }else if (action.equals(ACTION_USB_PERMISSION)) { + boolean granted; + device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false); + if (granted) { + onUsbPermissionGranted(device); + } + }else { + Log.e(TAG, "Unknown action " + action); + } + } + }; + + private class UsbServiceThread extends Thread { + + private InputStream mInputStream; + private OutputStream mOutputStream; + + private int mConnectionState; + private volatile boolean cancelRequested; + + private UsbSerialController mUsbController; + + private final ConditionVariable serialControllerSet; + + public UsbServiceThread() { + mInputStream = UsbUtils.DummyInputStream.instance; + mOutputStream = UsbUtils.DummyOutputStream.instance; + mConnectionState = STATE_IDLE; + cancelRequested = false; + mUsbController = null; + serialControllerSet = new ConditionVariable(false); + } + + public synchronized void setController(UsbSerialController controller) { + if (mUsbController != null) { + serialControllerSet.close(); + mUsbController.detach(); + } + mUsbController = controller; + if (controller != null) serialControllerSet.open(); + } + + public synchronized UsbSerialController getController() { + return mUsbController; + } + + private synchronized void setState(int state) { + int oldState = mConnectionState; + mConnectionState = state; + if (DBG) Log.d(TAG, "setState() " + oldState + " -> " + state); + + if (mConnectionState == STATE_CONNECTED) + mIsUsbDeviceReadyCondvar.open(); + else { + mIsUsbDeviceReadyCondvar.close(); + //mLocalSocketThread.disconnect(); + } + } + + public synchronized void cancel() { + cancelRequested = true; + mCallbacks.onStopped(); + if (mUsbController != null) { + mUsbController.detach(); + mUsbController=null; + } + } + + /** + * Write to the connected OutStream. + * @param buffer The bytes to write + */ + public void write(byte[] buffer, int offset, int count) throws IOException { + OutputStream os; + synchronized(this) { + if (mConnectionState != STATE_CONNECTED) { + Log.e(TAG, "write() error: not connected"); + return; + } + os = mOutputStream; + } + os.write(buffer, offset, count); + } + + private synchronized void throwIfCancelRequested() throws CancelRequestedException { + if (cancelRequested) throw new CancelRequestedException(); + } + + private void connect() throws UsbControllerException, CancelRequestedException { + + serialControllerSet.block(); + + synchronized(UsbReceiver.this) { + synchronized (this) { + throwIfCancelRequested(); + if (DBG) Log.v(TAG, "attach(). baudrate: "+ mUsbController.getBaudRate()); + mUsbController.attach(); + mInputStream = mUsbController.getInputStream(); + mOutputStream = mUsbController.getOutputStream(); + } + } + return; + } + + private void connectLoop() throws CancelRequestedException { + + if (DBG) Log.v(TAG, "connectLoop()"); + + while(true) { + try { + connect(); + return; + }catch (UsbControllerException e) { + synchronized(this) { + throwIfCancelRequested(); + setState(STATE_RECONNECTING); + try { + wait(RECONNECT_TIMEOUT_MS); + } catch(InterruptedException ie) { + throwIfCancelRequested(); + } + } + } + } + } + + + private void transferDataLoop() throws CancelRequestedException { + int rcvd; + final byte buf[] = new byte[4096]; + + try { + while(true) { + rcvd = mInputStream.read(buf, 0, buf.length); + if (rcvd >= 0) { + /* + try { + //mLocalSocketThread.write(buf, 0, rcvd); + }catch (IOException e) { + // TODO + e.printStackTrace(); + } + */ + } + if (rcvd < 0) + throw new IOException("EOF"); + } + }catch (IOException e) { + synchronized(this) { + if (mUsbController!=null) mUsbController.detach(); + //mInputStream = RtklibLocalSocketThread.DummyInputStream.instance; + //mOutputStream = RtklibLocalSocketThread.DummyOutputStream.instance; + throwIfCancelRequested(); + } + } + } + + @Override + public void run() { + Log.i(TAG, "BEGIN UsbToLocalSocket-USB"); + setName("UsbToLocalSocket-USB"); + try { + setState(STATE_CONNECTING); + while (true) { + throwIfCancelRequested(); + connectLoop(); + + setState(STATE_CONNECTED); + transferDataLoop(); + + setState(STATE_RECONNECTING); + mCallbacks.onConnectionLost(); + } + }catch(CancelRequestedException cre) {} + } + } + + private class CancelRequestedException extends Exception { + private static final long serialVersionUID = 1L; + } + } + + + +} diff --git a/src/org/broeuschmeul/android/gps/usb/UsbPl2303Controller.java b/src/org/broeuschmeul/android/gps/usb/UsbPl2303Controller.java new file mode 100644 index 00000000..5c53df5e --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/UsbPl2303Controller.java @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2013 Alexey Illarionov + * + * This file is part of UsbGPS4Droid. + * + * UsbGPS4Droid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * UsbGPS4Droid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with UsbGPS4Droid. If not, see . + */ + +package org.broeuschmeul.android.gps.usb; + +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbManager; +import android.util.Log; + +import org.broeuschmeul.android.gps.usb.provider.BuildConfig; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; + + +public class UsbPl2303Controller extends UsbSerialController { + + // Debugging + private static final String TAG = UsbPl2303Controller.class.getSimpleName(); + private static final boolean D = BuildConfig.DEBUG & true; + + private static final int PL2303_INIT_TIMEOUT_MS = 2000; + + private static final int[] PL2303_BAUD_RATES= new int[] { + 75, 150, 300, 600, 1200, + 1800, 2400, 3600, 4800, 7200, + 9600, 14400, 19200, 28800, 38400, + 57600, 115200, 230400, 460800, 614400, + 921600, 1228800, 2457600, 3000000, 6000000, 12000000 + }; + + + private UsbDeviceConnection mUsbConnection; + private android.hardware.usb.UsbInterface mUsbInterfaces[]; + private UsbEndpoint mInterruptEndpoint = null; + private UsbEndpoint mBulkInEndpoint = null; + private UsbEndpoint mBulkOutEndpoint = null; + private int mBaudrate; + private boolean isPl2303Hx; + + private UsbSerialInputStream inputStream = null; + private UsbSerialOutputStream outputStream = null; + private UsbSerialInterruptListener interruptListener = null; + + + public UsbPl2303Controller(UsbManager usbManager, UsbDevice usbDevice) + throws UsbControllerException { + super(usbManager, usbDevice); + + int endpointCount; + + if (!UsbPl2303Controller.probe(usbDevice)) { + throw new UsbControllerException("probe() failed"); + } + + if (usbDevice.getInterfaceCount() != 1) { + throw new UsbControllerException("getInterfaceCount() != 1"); + } + + mUsbInterfaces = new android.hardware.usb.UsbInterface[1]; + mUsbInterfaces[0] = usbDevice.getInterface(0); + endpointCount = mUsbInterfaces[0].getEndpointCount(); + if (endpointCount != 3) { + throw new UsbControllerException("getEndpointCount() != 3 (" + endpointCount + ")"); + } + + for (int i=0; i < endpointCount; i++) { + UsbEndpoint e = mUsbInterfaces[0].getEndpoint(i); + switch (e.getType()) { + case UsbConstants.USB_ENDPOINT_XFER_INT: + mInterruptEndpoint = e; + break; + case UsbConstants.USB_ENDPOINT_XFER_BULK: + if (e.getDirection() == UsbConstants.USB_DIR_IN) + mBulkInEndpoint = e; + else + mBulkOutEndpoint = e; + break; + default: + throw new UsbControllerException("Unexpected endpoint " + i + "type = " + e.getType()); + } + } + + if (mInterruptEndpoint == null) { + throw new UsbControllerException("Interrupt input endpoint not found"); + }else if (mBulkInEndpoint == null) { + throw new UsbControllerException("Bulk data input endpoint not found"); + }else if (mBulkOutEndpoint == null) { + throw new UsbControllerException("Bulk data output endpoint not found"); + } + + isPl2303Hx = (usbDevice.getDeviceClass() != 0x02) + && (mBulkOutEndpoint.getMaxPacketSize() == 0x40); + mBaudrate = DEFAULT_BAUDRATE; + } + + public static boolean probe(UsbDevice d) { + + int vid, pid; + boolean passed = false; + + vid = d.getVendorId(); + pid = d.getProductId(); + + /* Keep in sync usb_device_filter.xml */ + switch (vid) { + case 0x067b: /* Prolific */ + switch (pid) { + case 0x2303: /* 0x067b 0x2303 PL2303 Serial */ + case 0x1234: /* 0x067b 0x1234 DCU-11 Phone Cable */ + passed = true; + break; + } + break; + case 0x5372: /* Prolific2 */ + if (pid == 0x2303) passed = true; /* 0x5372 0x2303 Prolific2 PL2303 */ + break; + } + + if (D) Log.v(TAG, "Probe for " + vid + ":" + pid + " " + (passed ? "passed" : "failed")); + + return passed; + } + + public synchronized boolean isAttached() { + return inputStream != null; + } + + @Override + public synchronized void attach() throws UsbControllerException { + + if (isAttached()) return; + + if (!mUsbManager.hasPermission(mUsbDevice)) { + throw new UsbControllerException("no permission"); + } + + mUsbConnection = mUsbManager.openDevice(mUsbDevice); + if (mUsbConnection == null) { + throw new UsbControllerException("openDevice() failed"); + } + + for (int i=0; i< mUsbInterfaces.length; ++i) { + if (mUsbConnection.claimInterface(mUsbInterfaces[i], true) == false) { + for (int j=0; j= 0; + } + + private boolean pl2303Init() { + byte buf[] = new byte[4]; + final int read = UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_VENDOR; + final int write = UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR; + final int tmout = PL2303_INIT_TIMEOUT_MS; + + if ((mUsbConnection.controlTransfer(read, 0x01, 0x8484, 0, buf, 1, tmout) < 0) + || (mUsbConnection.controlTransfer(write, 0x01, 0x0404, 0, null, 0, tmout) < 0) + || (mUsbConnection.controlTransfer(read, 0x01, 0x8484, 0, buf, 1, tmout) < 0) + || (mUsbConnection.controlTransfer(read, 0x01, 0x8383, 0, buf, 1, tmout) < 0) + || (mUsbConnection.controlTransfer(read, 0x01, 0x8484, 0, buf, 1, tmout) < 0) + || (mUsbConnection.controlTransfer(write, 0x01, 0x0404, 1, null, 0, tmout) < 0) + || (mUsbConnection.controlTransfer(read, 0x01, 0x8484, 0, buf, 1, tmout) < 0) + || (mUsbConnection.controlTransfer(read, 0x01, 0x8383, 0, buf, 1, tmout) < 0) + || (mUsbConnection.controlTransfer(write, 0x01, 0, 1, null, 0, tmout) < 0) + || (mUsbConnection.controlTransfer(write, 0x01, 1, 0, null, 0, tmout) < 0) + ) return false; + if (isPl2303Hx) { + if (mUsbConnection.controlTransfer(write, 0x01, 2, 0x44, null, 0, tmout) < 0) return false; + }else { + if (mUsbConnection.controlTransfer(write, 0x01, 2, 0x24, null, 0, tmout) < 0) return false; + } + + if ((mUsbConnection.controlTransfer(write, 0x01, 8, 0, null, 0, tmout) < 0) + || (mUsbConnection.controlTransfer(write, 0x01, 9, 0, null, 0, tmout) < 0) + ) return false; + + return true; + } + + private boolean pl2303SetLineCoding() { + return pl2303SetLineCoding(this.mBaudrate); + } + + private boolean pl2303SetLineCoding(int baudrate) { + return pl2303SetLineCoding(baudrate, 8, 'N', 1); + } + + private boolean pl2303SetLineCoding(int baudrate, int dataBits, char parity, int stopBits) { + int idx; + byte req[] = new byte[7]; + + /* dwDTERate */ + idx = Arrays.binarySearch(PL2303_BAUD_RATES, baudrate); + if (idx < 0) { + baudrate = PL2303_BAUD_RATES[-idx == PL2303_BAUD_RATES.length ? -idx-1 : -idx]; + } + req[0] = (byte)(baudrate & 0xff); + req[1] = (byte)((baudrate >>> 8) & 0xff); + req[2] = (byte)((baudrate >>> 16) & 0xff); + req[3] = (byte)((baudrate >>> 24) & 0xff); + + /* bCharFormat */ + if (stopBits != 1 && (stopBits != 2)) throw new IllegalArgumentException("Wrong stop bits"); + req[4] = stopBits == 1 ? (byte)0 : (byte)2; + + /* bParityType */ + switch (parity) { + case 'N': req[5] = 0; break; /* None */ + case 'O': req[5] = 1; break; /* Odd */ + case 'E': req[5] = 2; break; /* Even */ + case 'M': req[5] = 3; break; /* Mark */ + case 'S': req[5] = 4; break; /* Space */ + default: throw new IllegalArgumentException("Wrong parity"); + } + + /* bDataBits */ + switch (dataBits) { + case 5: + case 6: + case 7: + case 8: + req[6] = (byte)dataBits; + break; + default: throw new IllegalArgumentException("Wrong data bits"); + } + + Log.d(TAG, "SetLineCoding rate=" + baudrate + " " + + Integer.toString(dataBits) + + Character.toString(parity) + + stopBits); + + if (mUsbConnection.controlTransfer( + 0x21, + 0x20, /* SET_LINE_CODING */ + 0, + 0, /* bulk data interface number */ + req, + req.length, + 1000 + ) < 0) + return false; + + /* CRTSCTS=off */ + if (mUsbConnection.controlTransfer( + UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR, + 0x01, 0, 0, null, 0, 1000) < 0) + return false; + + return true; + } + +} diff --git a/src/org/broeuschmeul/android/gps/usb/UsbSerialController.java b/src/org/broeuschmeul/android/gps/usb/UsbSerialController.java new file mode 100644 index 00000000..b791d0cd --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/UsbSerialController.java @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2013 Alexey Illarionov + * + * This file is part of UsbGPS4Droid. + * + * UsbGPS4Droid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * UsbGPS4Droid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with UsbGPS4Droid. If not, see . + */ + +package org.broeuschmeul.android.gps.usb; + +import android.app.PendingIntent; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbManager; +import android.hardware.usb.UsbRequest; +import android.util.Log; + +import org.broeuschmeul.android.gps.usb.provider.BuildConfig; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; + +public abstract class UsbSerialController { + + // Debugging + private static final String TAG = UsbSerialController.class.getSimpleName(); + private static final boolean D = BuildConfig.DEBUG & true; + + public static final int DEFAULT_BAUDRATE = 4800; + + protected UsbManager mUsbManager; + protected UsbDevice mUsbDevice; + + public UsbSerialController(UsbManager usbManager, + UsbDevice usbDevice) throws UsbControllerException { + this.mUsbDevice = usbDevice; + this.mUsbManager = usbManager; + } + + public abstract void attach() throws UsbControllerException; + public abstract void detach(); + + public abstract void setBaudRate(int baudRate); + public abstract int getBaudRate(); + + public abstract InputStream getInputStream(); + public abstract OutputStream getOutputStream(); + + public boolean hasPermission() { + return this.mUsbManager.hasPermission(this.mUsbDevice); + } + + public void requestPermission(PendingIntent pi) { + this.mUsbManager.requestPermission(mUsbDevice, pi); + } + + public static class UsbControllerException extends Exception { + private static final long serialVersionUID = 1L; + public UsbControllerException(String msg) { super(msg); } + } + + public UsbDevice getDevice() { + return mUsbDevice; + } + + protected static class UsbSerialInterruptListener extends Thread { + + private boolean cancelRequested = false; + private UsbDeviceConnection mUsbConnection; + private ByteBuffer buffer; + private UsbRequest request; + + public UsbSerialInterruptListener(UsbDeviceConnection connection, UsbEndpoint endpoint) { + this.mUsbConnection = connection; + this.setName("PL2303InterruptListener"); + buffer = ByteBuffer.allocate(endpoint.getMaxPacketSize()); + request = new UsbRequest(); + request.initialize(connection, endpoint); + } + + @Override + public void run() { + mainloop: while(!cancelRequested()) { + request.queue(buffer, buffer.capacity()); + if (mUsbConnection.requestWait() == request) { + if (D) Log.v(TAG, "Interrupt received: " + buffer.toString() + + Arrays.toString(buffer.array())); + synchronized(this) { + try { + this.wait(100); + } catch (InterruptedException e) { + break mainloop; + } + if (cancelRequested) break mainloop; + } + }else { + Log.e(TAG, "requestWait failed, exiting"); + break mainloop; + } + } + Log.d(TAG, "Pl2303InterruptListener thread stopped"); + } + + public synchronized void cancel() { + cancelRequested = true; + this.notify(); + } + + private synchronized boolean cancelRequested() { + return this.cancelRequested; + } + + } + + protected class UsbSerialInputStream extends InputStream { + + private static final int DEFAULT_READ_TIMEOUT_MS = 30000; + private int mTimeout = DEFAULT_READ_TIMEOUT_MS; + + private UsbDeviceConnection mUsbConnection; + private UsbEndpoint mUsbEndpoint; + private byte rcvPkt[] = null; + + public UsbSerialInputStream(UsbDeviceConnection connection, + UsbEndpoint bulkInEndpoint, + int writeTmoutMs + ) { + mUsbConnection = connection; + mUsbEndpoint = bulkInEndpoint; + mTimeout = writeTmoutMs; + rcvPkt = new byte[mUsbEndpoint.getMaxPacketSize()]; + } + + public UsbSerialInputStream(UsbDeviceConnection connection, + UsbEndpoint bulkOutEndpoint) { + this(connection, bulkOutEndpoint, DEFAULT_READ_TIMEOUT_MS); + } + + @Override + public int read() throws IOException { + synchronized(this) { + int rcvd = read(rcvPkt, 0, 1); + if (rcvd == 0) throw new IOException("timeout"); + return rcvPkt[0] & 0xff; + } + } + + @Override + public int read(byte[] buffer, int offset, int count) throws IOException { + int rcvd; + + synchronized(this) { + if (offset == 0) { + rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint, buffer, + count, mTimeout); + if (rcvd < 0) throw new IOException("bulkTransfer() error"); + //if (D) Log.d(TAG, "Received " + rcvd + " bytes aligned"); + return rcvd; + }else { + rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint, + rcvPkt, + Math.min(count, rcvPkt.length), + mTimeout); + if (rcvd < 0) throw new IOException("bulkTransfer() error"); + else if (rcvd > 0) { + System.arraycopy(rcvPkt, 0, buffer, offset, rcvd); + } + if (D) Log.d(TAG, "Received " + rcvd + " bytes"); + return rcvd; + } + } + } + } + + protected class UsbSerialOutputStream extends OutputStream { + + private static final int DEFAULT_WRITE_TIMEOUT_MS = 2000; + private int mTimeout = DEFAULT_WRITE_TIMEOUT_MS; + + private UsbDeviceConnection mUsbConnection; + private UsbEndpoint mUsbEndpoint; + private byte sndPkt[] = null; + + public UsbSerialOutputStream(UsbDeviceConnection connection, + UsbEndpoint bulkOutEndpoint, + int writeTmoutMs + ) { + mUsbConnection = connection; + mUsbEndpoint = bulkOutEndpoint; + mTimeout = writeTmoutMs; + sndPkt = new byte[mUsbEndpoint.getMaxPacketSize()]; + } + + public UsbSerialOutputStream(UsbDeviceConnection connection, + UsbEndpoint bulkOutEndpoint) { + this(connection, bulkOutEndpoint, DEFAULT_WRITE_TIMEOUT_MS); + } + + @Override + public void write(int arg0) throws IOException { + write(new byte[] { (byte) arg0 } ); + } + + @Override + public void write(byte[] buffer, int offset, int count) throws IOException { + synchronized(this) { + while(count>0) { + /* XXX: timeout */ + int length = count > sndPkt.length ? sndPkt.length : count; + System.arraycopy(buffer, offset, sndPkt, 0, length); + int snd = mUsbConnection.bulkTransfer(mUsbEndpoint, sndPkt, length, mTimeout); + if (snd<0) throw new IOException("bulkTransfer() failed"); + count -= snd; + offset += snd; + } + } + } + } + +} + diff --git a/src/org/broeuschmeul/android/gps/usb/UsbUtils.java b/src/org/broeuschmeul/android/gps/usb/UsbUtils.java new file mode 100644 index 00000000..1459af43 --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/UsbUtils.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2013 Alexey Illarionov + * + * This file is part of UsbGPS4Droid. + * + * UsbGPS4Droid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * UsbGPS4Droid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with UsbGPS4Droid. If not, see . + */ + +package org.broeuschmeul.android.gps.usb; + +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; +import android.util.Log; + +import org.broeuschmeul.android.gps.usb.UsbSerialController.UsbControllerException; +import org.broeuschmeul.android.gps.usb.provider.BuildConfig; +import org.broeuschmeul.android.gps.usb.provider.R; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class UsbUtils { + + // Debugging + private static final String TAG = UsbUtils.class.getSimpleName(); + private static final boolean DBG = BuildConfig.DEBUG & true; + + + public static boolean isInUsbDeviceFilter(UsbDevice d, Resources appResources) { + int type; + XmlResourceParser parser; + boolean match = false; + + parser = appResources.getXml(R.xml.device_filter); + try { + for (type=parser.getEventType(); + !match && (type != XmlResourceParser.END_DOCUMENT); + type = parser.next()) { + int count; + int vendorId = -1; + int productId = -1; + int deviceClass = -1; + int deviceSubclass = -1; + int deviceProtocol = -1; + + + if (type != XmlResourceParser.START_TAG) continue; + if ("usb-device".equals(parser.getName())) continue; + + count = parser.getAttributeCount(); + for(int i=0; i findSupportedDevices(UsbManager usbManager) { + final ArrayList supportedList; + final HashMap deviceList; + + deviceList = usbManager.getDeviceList(); + supportedList = new ArrayList(deviceList.size()); + + for (UsbDevice d: deviceList.values()) { + if (probeDevice(usbManager, d) != null) { + supportedList.add(d); + } + } + return supportedList; + } + + public static UsbSerialController probeDevice(UsbManager usbManager, UsbDevice d) { + if (DBG) Log.d(TAG, "probeDevice() device=" + d.toString()); + try { + final UsbPl2303Controller c = new UsbPl2303Controller(usbManager, d); + return c; + }catch(UsbControllerException ignore) { } + + try { + final UsbAcmController c = new UsbAcmController(usbManager, d); + return c; + }catch (UsbControllerException ignore) {} + + return null; + } + + static class DummyInputStream extends InputStream { + + public static final DummyInputStream instance = new DummyInputStream(); + + private DummyInputStream() {} + + @Override + public int read() throws IOException { + return -1; + } + + @Override + public int read(byte[] buffer, int offset, int length) throws IOException { + return -1; + } + } + + static class DummyOutputStream extends OutputStream { + + public static final DummyOutputStream instance = new DummyOutputStream(); + + private DummyOutputStream() {} + + @Override + public void write(int arg0) throws IOException { + } + + @Override + public void write(byte[] buffer, int offset, int count) + throws IOException { + } + } + + +} diff --git a/src/org/broeuschmeul/android/gps/bluetooth/provider/BlueetoothGpsManager.java b/src/org/broeuschmeul/android/gps/usb/provider/BlueetoothGpsManager.java similarity index 67% rename from src/org/broeuschmeul/android/gps/bluetooth/provider/BlueetoothGpsManager.java rename to src/org/broeuschmeul/android/gps/usb/provider/BlueetoothGpsManager.java index 51231840..a405fe63 100644 --- a/src/org/broeuschmeul/android/gps/bluetooth/provider/BlueetoothGpsManager.java +++ b/src/org/broeuschmeul/android/gps/usb/provider/BlueetoothGpsManager.java @@ -2,84 +2,72 @@ * Copyright (C) 2010, 2011, 2012 Herbert von Broeuschmeul * Copyright (C) 2010, 2011, 2012 BluetoothGPS4Droid Project * Copyright (C) 2011, 2012 UsbGPS4Droid Project - * + * * This file is part of UsbGPS4Droid. * * UsbGPS4Droid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * UsbGPS4Droid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with UsbGPS4Droid. If not, see . */ -package org.broeuschmeul.android.gps.bluetooth.provider; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.broeuschmeul.android.gps.usb.provider.BuildConfig; -import org.broeuschmeul.android.gps.usb.provider.R; -import org.broeuschmeul.android.gps.nmea.util.NmeaParser; -import org.broeuschmeul.android.gps.sirf.util.SirfUtils; +package org.broeuschmeul.android.gps.usb.provider; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; -//import android.bluetooth.BluetoothAdapter; -//import android.bluetooth.BluetoothDevice; -//import android.bluetooth.BluetoothSocket; import android.content.Context; +import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.Intent; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; -import android.hardware.usb.UsbRequest; -import android.location.LocationManager; import android.location.GpsStatus.NmeaListener; -import android.preference.PreferenceManager; -import android.provider.Settings; +import android.location.LocationManager; import android.os.Bundle; import android.os.SystemClock; +import android.preference.PreferenceManager; +import android.provider.Settings; import android.util.Log; +import org.broeuschmeul.android.gps.nmea.util.NmeaParser; +import org.broeuschmeul.android.gps.sirf.util.SirfUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + /** * This class is used to establish and manage the connection with the bluetooth GPS. - * + * * @author Herbert von Broeuschmeul * */ @@ -95,7 +83,8 @@ public class BlueetoothGpsManager { private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - public void onReceive(Context context, Intent intent) { + @Override + public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { @@ -112,11 +101,6 @@ public void onReceive(Context context, Intent intent) { Log.v(LOG_TAG, "will use default device speed: " + defaultDeviceSpeed); deviceSpeed = defaultDeviceSpeed; } -// // reset eventual disabling cause -// // setDisableReason(0); -// // connection obtained so reset the number of connection try -// nbRetriesRemaining = 1+maxConnectionRetries ; -// notificationManager.cancel(R.string.connection_problem_notification_title); Log.v(LOG_TAG, "starting usb reading task"); connectedGps = new ConnectedGps(device, deviceSpeed); connectionAndReadingPool.execute(connectedGps); @@ -134,47 +118,40 @@ public void onReceive(Context context, Intent intent) { /** * A utility class used to manage the communication with the bluetooth GPS whn the connection has been established. * It is used to read NMEA data from the GPS or to send SIRF III binary commands or SIRF III NMEA commands to the GPS. - * You should run the main read loop in one thread and send the commands in a separate one. - * + * You should run the main read loop in one thread and send the commands in a separate one. + * * @author Herbert von Broeuschmeul * */ private class ConnectedGps extends Thread { - /** - * GPS bluetooth socket used for communication. - */ - private final File gpsDev ; - private final UsbDevice gpsUsbDev ; private final UsbInterface intf; private UsbEndpoint endpointIn = null; private UsbEndpoint endpointOut = null; private final UsbDeviceConnection connection; private boolean closed = false; /** - * GPS InputStream from which we read data. + * GPS InputStream from which we read data. */ private final InputStream in; /** - * GPS output stream to which we send data (SIRF III binary commands). + * GPS output stream to which we send data (SIRF III binary commands). */ private final OutputStream out; /** - * GPS output stream to which we send data (SIRF III NMEA commands). + * GPS output stream to which we send data (SIRF III NMEA commands). */ private final PrintStream out2; /** - * A boolean which indicates if the GPS is ready to receive data. + * A boolean which indicates if the GPS is ready to receive data. * In fact we consider that the GPS is ready when it begins to sends data... */ private boolean ready = false; public ConnectedGps(UsbDevice device) { - this(device, defaultDeviceSpeed); + this(device, defaultDeviceSpeed); } public ConnectedGps(UsbDevice device, String deviceSpeed) { - this.gpsDev = null; - this.gpsUsbDev = device; intf = device.getInterface(0); int i = intf.getEndpointCount(); endpointIn = null; @@ -198,11 +175,11 @@ public ConnectedGps(UsbDevice device, String deviceSpeed) { Log.d(LOG_TAG, "claiming interface"); resclaim = connection.claimInterface(intf, true); Log.d(LOG_TAG, "data claim"+ resclaim); - + InputStream tmpIn = null; OutputStream tmpOut = null; PrintStream tmpOut2 = null; - + tmpIn = new InputStream() { private byte[] buffer = new byte[128]; private byte[] usbBuffer = new byte[64]; @@ -210,8 +187,8 @@ public ConnectedGps(UsbDevice device, String deviceSpeed) { private ByteBuffer bufferWrite = ByteBuffer.wrap(buffer); private ByteBuffer bufferRead = (ByteBuffer)ByteBuffer.wrap(buffer).limit(0); private boolean closed = false; - - @Override + + @Override public int read() throws IOException { int b = 0; if (BuildConfig.DEBUG || debug) Log.d(LOG_TAG, "trying to read data"); @@ -222,7 +199,7 @@ public int read() throws IOException { if (nb > 0){ b = oneByteBuffer[0]; } else { - // TODO : if nb = 0 then we have a pb + // TODO : if nb = 0 then we have a pb b = -1; Log.e(LOG_TAG, "data read() error code: " + nb ); } @@ -280,7 +257,7 @@ public int read(byte[] buffer, int offset, int length) if (n > bufferWrite.remaining()){ bufferRead.rewind(); bufferWrite.clear(); - } + } bufferWrite.put(usbBuffer, 0, n); bufferRead.limit(bufferWrite.position()); // if (BuildConfig.DEBUG || debug) Log.d(LOG_TAG, "data read: nb: " + n + " current: " + bufferRead.position() + " limit: " + bufferRead.limit() + " " + Arrays.toString(bufferRead.array())); @@ -338,7 +315,7 @@ public void close() throws IOException { closed = true; } }; - + tmpOut = new OutputStream() { private byte[] buffer = new byte[128]; private byte[] usbBuffer = new byte[64]; @@ -346,7 +323,7 @@ public void close() throws IOException { private ByteBuffer bufferWrite = ByteBuffer.wrap(buffer); private ByteBuffer bufferRead = (ByteBuffer)ByteBuffer.wrap(buffer).limit(0); private boolean closed = false; - + @Override public void write(int oneByte) throws IOException { if (BuildConfig.DEBUG || debug) Log.d(LOG_TAG, "trying to write data (one byte): " + oneByte + " char: " + (char)oneByte); @@ -367,7 +344,7 @@ public void write(byte[] buffer, int offset, int count) if (BuildConfig.DEBUG || debug) Log.d(LOG_TAG, "trying to write data : " + Arrays.toString(this.buffer)); int n = 0; if (! closed){ - n = connection.bulkTransfer(endpointOut, this.buffer, count, TIMEOUT); + n = connection.bulkTransfer(endpointOut, this.buffer, count, TIMEOUT); } else { Log.e(LOG_TAG, "error while trying to write data: outputStream closed"); } @@ -405,9 +382,9 @@ public void write(byte[] buffer) throws IOException { // TODO Auto-generated method stub super.write(buffer); } - + }; - + try { if (tmpOut != null){ tmpOut2 = new PrintStream(tmpOut, false, "US-ASCII"); @@ -452,7 +429,7 @@ public void run() { // final byte[] datax = new byte[7]; // final ByteBuffer connectionSpeedInfoBuffer = ByteBuffer.wrap(datax,0,7).order(java.nio.ByteOrder.LITTLE_ENDIAN); try { - int res0 = connection.controlTransfer(0xA1, 33, 0, 0, datax, 7, 0); + int res0 = connection.controlTransfer(0xA1, 33, 0, 0, datax, 7, 0); BlueetoothGpsManager.this.deviceSpeed = Integer.toString(connectionSpeedInfoBuffer.getInt(0)); Log.e(LOG_TAG, "info connection: " + Arrays.toString(datax)); Log.e(LOG_TAG, "info connection speed: " + BlueetoothGpsManager.this.deviceSpeed); @@ -464,7 +441,7 @@ public void run() { Log.e(LOG_TAG, "trying to use speed " + speed); Log.d(LOG_TAG, "initializing connection: " + speed + " baud and 8N1 (0 bits no parity 1 stop bit"); connectionSpeedBuffer.putInt(0, speed); - int res2 = connection.controlTransfer(0x21, 32, 0, 0, data, 7, 0); + int res2 = connection.controlTransfer(0x21, 32, 0, 0, data, 7, 0); if (sirfGps){ Log.e(LOG_TAG, "trying to switch from SiRF binaray to NMEA"); connection.bulkTransfer(endpointOut, sirfBin2Nmea, sirfBin2Nmea.length, 0); @@ -473,7 +450,7 @@ public void run() { Thread.sleep(4000); } } - res0 = connection.controlTransfer(0xA1, 33, 0, 0, datax, 7, 0); + res0 = connection.controlTransfer(0xA1, 33, 0, 0, datax, 7, 0); Log.e(LOG_TAG, "info connection: " + Arrays.toString(datax)); Log.e(LOG_TAG, "info connection speed: " + connectionSpeedInfoBuffer.getInt(0)); if (! closed) { @@ -496,13 +473,14 @@ public void run() { ready = false; autoConf.start(); } - + public boolean isReady(){ return ready; } - + private long lastRead = 0; - public void run() { + @Override + public void run() { try { BufferedReader reader = new BufferedReader(new InputStreamReader(in,"US-ASCII"),128); // InputStreamReader reader = new InputStreamReader(in,"US-ASCII"); @@ -583,7 +561,7 @@ public void write(String buffer) { Log.e(LOG_TAG, "Exception during write", e); } } - + public void close(){ ready = false; closed = true; @@ -629,7 +607,7 @@ public void close(){ private boolean enabled = false; private ExecutorService notificationPool; private ScheduledExecutorService connectionAndReadingPool; - private List nmeaListeners = Collections.synchronizedList(new LinkedList()); + private List nmeaListeners = Collections.synchronizedList(new LinkedList()); private LocationManager locationManager; private SharedPreferences sharedPreferences; private ConnectedGps connectedGps; @@ -659,27 +637,27 @@ public BlueetoothGpsManager(Service callingService, String deviceAddress, int ma this.appContext = callingService.getApplicationContext(); locationManager = (LocationManager)callingService.getSystemService(Context.LOCATION_SERVICE); sharedPreferences = PreferenceManager.getDefaultSharedPreferences(callingService); - deviceSpeed = sharedPreferences.getString(BluetoothGpsProviderService.PREF_GPS_DEVICE_SPEED, callingService.getString(R.string.defaultGpsDeviceSpeed)); + deviceSpeed = sharedPreferences.getString(UsbGpsProviderService.PREF_GPS_DEVICE_SPEED, callingService.getString(R.string.defaultGpsDeviceSpeed)); defaultDeviceSpeed = callingService.getString(R.string.defaultGpsDeviceSpeed); setDeviceSpeed = !deviceSpeed.equals(callingService.getString(R.string.autoGpsDeviceSpeed)); - sirfGps = sharedPreferences.getBoolean(BluetoothGpsProviderService.PREF_SIRF_GPS, false); + sirfGps = sharedPreferences.getBoolean(UsbGpsProviderService.PREF_SIRF_GPS, false); notificationManager = (NotificationManager)callingService.getSystemService(Context.NOTIFICATION_SERVICE); - parser.setLocationManager(locationManager); - + parser.setLocationManager(locationManager); + connectionProblemNotification = new Notification(); connectionProblemNotification.icon = R.drawable.ic_stat_notify; - Intent stopIntent = new Intent(BluetoothGpsProviderService.ACTION_STOP_GPS_PROVIDER); + Intent stopIntent = new Intent(UsbGpsProviderService.ACTION_STOP_GPS_PROVIDER); // PendingIntent stopPendingIntent = PendingIntent.getService(appContext, 0, stopIntent, PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent stopPendingIntent = PendingIntent.getService(appContext, 0, stopIntent, PendingIntent.FLAG_CANCEL_CURRENT); connectionProblemNotification.contentIntent = stopPendingIntent; serviceStoppedNotification = new Notification(); serviceStoppedNotification.icon=R.drawable.ic_stat_notify; - Intent restartIntent = new Intent(BluetoothGpsProviderService.ACTION_START_GPS_PROVIDER); + Intent restartIntent = new Intent(UsbGpsProviderService.ACTION_START_GPS_PROVIDER); PendingIntent restartPendingIntent = PendingIntent.getService(appContext, 0, restartIntent, PendingIntent.FLAG_CANCEL_CURRENT); - serviceStoppedNotification.setLatestEventInfo(appContext, - appContext.getString(R.string.service_closed_because_connection_problem_notification_title), - appContext.getString(R.string.service_closed_because_connection_problem_notification), + serviceStoppedNotification.setLatestEventInfo(appContext, + appContext.getString(R.string.service_closed_because_connection_problem_notification_title), + appContext.getString(R.string.service_closed_because_connection_problem_notification), restartPendingIntent); usbManager = (UsbManager) callingService.getSystemService(callingService.USB_SERVICE); @@ -689,14 +667,14 @@ public BlueetoothGpsManager(Service callingService, String deviceAddress, int ma private void setDisableReason(int reasonId){ disableReason = reasonId; } - + /** * @return */ public int getDisableReason(){ return disableReason; } - + /** * @return true if the bluetooth GPS is enabled */ @@ -713,237 +691,63 @@ public synchronized boolean enable() { notificationManager.cancel(R.string.service_closed_because_connection_problem_notification_title); if (! enabled){ Log.d(LOG_TAG, "enabling Bluetooth GPS manager"); -// final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); -// if (bluetoothAdapter == null) { -// // Device does not support Bluetooth -// Log.e(LOG_TAG, "Device does not support Bluetooth"); -// disable(R.string.msg_bluetooth_unsupported); -// } else if (!bluetoothAdapter.isEnabled()) { -// // Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); -// // startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); -// Log.e(LOG_TAG, "Bluetooth is not enabled"); -// disable(R.string.msg_bluetooth_disabled); -// } else if (Settings.Secure.getInt(callingService.getContentResolver(),Settings.Secure.ALLOW_MOCK_LOCATION, 0)==0){ Log.e(LOG_TAG, "Mock location provider OFF"); disable(R.string.msg_mock_location_disabled); -// } else if ( (! locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) -// && (sharedPreferences.getBoolean(BluetoothGpsProviderService.PREF_REPLACE_STD_GPS, true)) -// ) { -// Log.e(LOG_TAG, "GPS location provider OFF"); -// disable(R.string.msg_gps_provider_disabled); } else { -// final BluetoothDevice gpsDevice = bluetoothAdapter.getRemoteDevice(gpsDeviceAddress); final String gpsDevice = gpsDeviceAddress; if (gpsDevice == null || "".equals(gpsDevice)){ - Log.e(LOG_TAG, "GPS device not found"); + Log.e(LOG_TAG, "GPS device not found"); disable(R.string.msg_gps_unavaible); } else { Log.e(LOG_TAG, "current device: "+gpsDevice ); -// try { -// gpsSocket = gpsDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); -// gpsDev = new File(gpsDeviceAddress); gpsDev = usbManager.getDeviceList().get(gpsDevice); -// } catch (IOException e) { -// Log.e(LOG_TAG, "Error during connection", e); -// gpsDev = null; -// } if (gpsDev == null){ Log.e(LOG_TAG, "Error while establishing connection: no device"); disable(R.string.msg_gps_unavaible); } else { - Runnable connectThread = new Runnable() { - @Override - public void run() { - try { - connected = false; - Log.v(LOG_TAG, "current device: "+gpsDevice); - if (/*(bluetoothAdapter.isEnabled()) && */(nbRetriesRemaining > 0 )){ -// try { - if (connectedGps != null){ - connectedGps.close(); - } - PendingIntent permissionIntent = PendingIntent.getBroadcast(callingService, 0, new Intent(ACTION_USB_PERMISSION), 0); -// HashMap connectedUsbDevices = usbManager.getDeviceList(); -// UsbDevice device = connectedUsbDevices.values().iterator().next(); - gpsDev = usbManager.getDeviceList().get(gpsDevice); - UsbDevice device = gpsDev; - if (device != null && usbManager.hasPermission(device)){ - Log.d(LOG_TAG, "We have permession, good!"); - connected = true; - if (setDeviceSpeed){ - Log.v(LOG_TAG, "will set devive speed: " + deviceSpeed); - } else { - Log.v(LOG_TAG, "will use default device speed: " + defaultDeviceSpeed); - deviceSpeed = defaultDeviceSpeed; - } -// // reset eventual disabling cause -// // setDisableReason(0); -// // connection obtained so reset the number of connection try -// nbRetriesRemaining = 1+maxConnectionRetries ; -// notificationManager.cancel(R.string.connection_problem_notification_title); - Log.v(LOG_TAG, "starting usb reading task"); - connectedGps = new ConnectedGps(device, deviceSpeed); - connectionAndReadingPool.execute(connectedGps); - Log.v(LOG_TAG, "usb reading thread started"); - } else if (device != null) { - Log.d(LOG_TAG, "We don't have permession, so resquesting..."); - usbManager.requestPermission(device, permissionIntent); - } else { - Log.e(LOG_TAG, "Error while establishing connection: no device - " + gpsDevice); - disable(R.string.msg_gps_unavaible); - } - -// if ((gpsDev != null) && ((connectedGps == null) || (connectedGps.gpsDev != gpsDev))){ -// Log.d(LOG_TAG, "trying to close old socket"); -// gpsSocket.close(); -// } -// } catch (IOException e) { -// Log.e(LOG_TAG, "Error during disconnection", e); -// } -//// try { -//// gpsSocket = gpsDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); -// gpsDev = new File(gpsDeviceAddress); -// // verify if we have enough rights.. -// Log.v(LOG_TAG, "Will verify if device exists and is a file: "+gpsDev.getAbsolutePath()); -// if (gpsDev.exists()){ -// Log.v(LOG_TAG, "Device exists and is a file: "+gpsDev.getAbsolutePath()); -// if (! gpsDev.canRead()){ -// Log.v(LOG_TAG, "Device is not readable, will try chmod 666 "+gpsDev.getAbsolutePath()); -// try { -// // Try to get root privileges -// Process p = Runtime.getRuntime().exec("su"); -// // change device rights -// PrintStream os = new PrintStream(p.getOutputStream(),true); -// os.println("chmod 666 "+ gpsDev.getAbsolutePath()); -// // exit -// os.println("exit"); -// try { -// p.waitFor(); -//// if (p.exitValue() != 255) { -//// } -//// else { -//// } -// } catch (InterruptedException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while establishing connection: ", e); -// } finally { -// p.destroy(); -// } -// } catch (IOException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while establishing connection: ", e); -// gpsDev = null; -// } catch (SecurityException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while establishing connection: ", e); -// gpsDev = null; -// } -// } else { -// Log.v(LOG_TAG, "Device is readable: "+gpsDev.getAbsolutePath()); -// } -// if (setDeviceSpeed){ -// Log.v(LOG_TAG, "will set devive spped: " + deviceSpeed); -// try { -// // Try to get root privileges -// Process p = Runtime.getRuntime().exec("su"); -// // change device speed -// PrintStream os = new PrintStream(p.getOutputStream(),true); -//// os.println("stty -F "+ gpsDev.getAbsolutePath() + " ispeed "+deviceSpeed); -// os.println("busybox stty -F "+ gpsDev.getAbsolutePath() + " ispeed "+deviceSpeed); -// // exit -// os.println("exit"); -// try { -// p.waitFor(); -//// if (p.exitValue() != 255) { -//// } -//// else { -//// } -// } catch (InterruptedException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while changing device speed: ", e); -// } finally { -// p.destroy(); -// } -// } catch (IOException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while while changing device speed: ", e); -// // gpsDev = null; -// } catch (SecurityException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while changing device speed: ", e); -// // gpsDev = null; -// } -// } else { -// Log.v(LOG_TAG, "Device speed: "+deviceSpeed); -// } -// } else { -// Log.e(LOG_TAG, "Device doesn't exist: "+gpsDev.getAbsolutePath()); -// gpsDev = null; -// } -//// } catch (IOException e) { -//// Log.e(LOG_TAG, "Error during connection", e); -//// gpsDev = null; -//// } -// if (gpsDev == null){ -// Log.e(LOG_TAG, "Error while establishing connection: no device"); -// disable(R.string.msg_gps_unavaible); -// } else { -// // start GPS device -//// try { -//// File gpsControl = new File("/sys/devices/platform/gps_control/enable"); -//// if (gpsControl.isFile()){ -//// if (gpsControl.canWrite()){ -//// OutputStream os = new FileOutputStream(gpsControl); -//// os.write('1'); -//// os.flush(); -//// os.close(); -//// } -//// } -//// } catch (FileNotFoundException e) { -//// // TODO update message -//// Log.e(LOG_TAG, "Error while starting GPS: ", e); -//// } catch (IOException e) { -//// // TODO update message -//// Log.e(LOG_TAG, "Error while starting GPS: ", e); -//// } catch (SecurityException e) { -//// // TODO update message -//// Log.e(LOG_TAG, "Error while starting GPS: ", e); -//// } -// // Cancel discovery because it will slow down the connection -//// bluetoothAdapter.cancelDiscovery(); -// // we increment the number of connection tries -// // Connect the device through the socket. This will block -// // until it succeeds or throws an exception -// Log.v(LOG_TAG, "connecting to socket"); -//// gpsDev.connect(); -// Log.d(LOG_TAG, "connected to socket"); -// connected = true; -// // reset eventual disabling cause -//// setDisableReason(0); -// // connection obtained so reset the number of connection try -// nbRetriesRemaining = 1+maxConnectionRetries ; -// notificationManager.cancel(R.string.connection_problem_notification_title); -// Log.v(LOG_TAG, "starting socket reading task"); -// connectedGps = new ConnectedGps(gpsDev); -// connectionAndReadingPool.execute(connectedGps); -// Log.v(LOG_TAG, "socket reading thread started"); -// } -//// } else if (! bluetoothAdapter.isEnabled()) { -// setDisableReason(R.string.msg_bluetooth_disabled); - } -// } catch (IOException connectException) { -// // Unable to connect -// Log.e(LOG_TAG, "error while connecting to socket", connectException); -// // disable(R.string.msg_bluetooth_gps_unavaible); - } finally { - nbRetriesRemaining--; - if (! connected) { - disableIfNeeded(); - } - } - } - }; + Runnable connectThread = new Runnable() { + @Override + public void run() { + try { + connected = false; + Log.v(LOG_TAG, "current device: "+gpsDevice); + if ((nbRetriesRemaining > 0 )){ + if (connectedGps != null){ + connectedGps.close(); + } + PendingIntent permissionIntent = PendingIntent.getBroadcast(callingService, 0, new Intent(ACTION_USB_PERMISSION), 0); + gpsDev = usbManager.getDeviceList().get(gpsDevice); + UsbDevice device = gpsDev; + if (device != null && usbManager.hasPermission(device)){ + Log.d(LOG_TAG, "We have permession, good!"); + connected = true; + if (setDeviceSpeed){ + Log.v(LOG_TAG, "will set devive speed: " + deviceSpeed); + } else { + Log.v(LOG_TAG, "will use default device speed: " + defaultDeviceSpeed); + deviceSpeed = defaultDeviceSpeed; + } + Log.v(LOG_TAG, "starting usb reading task"); + connectedGps = new ConnectedGps(device, deviceSpeed); + connectionAndReadingPool.execute(connectedGps); + Log.v(LOG_TAG, "usb reading thread started"); + } else if (device != null) { + Log.d(LOG_TAG, "We don't have permession, so resquesting..."); + usbManager.requestPermission(device, permissionIntent); + } else { + Log.e(LOG_TAG, "Error while establishing connection: no device - " + gpsDevice); + disable(R.string.msg_gps_unavaible); + } + } + } finally { + nbRetriesRemaining--; + if (! connected) { + disableIfNeeded(); + } + } + } + }; this.enabled = true; callingService.registerReceiver(mUsbReceiver, filter); Log.d(LOG_TAG, "Bluetooth GPS manager enabled"); @@ -962,11 +766,11 @@ public void run() { } return this.enabled; } - + /** * Disables the bluetooth GPS Provider if the maximal number of connection retries is exceeded. - * This is used when there are possibly non fatal connection problems. - * In these cases the provider will try to reconnect with the bluetooth device + * This is used when there are possibly non fatal connection problems. + * In these cases the provider will try to reconnect with the bluetooth device * and only after a given retries number will give up and shutdown the service. */ private synchronized void disableIfNeeded(){ @@ -976,35 +780,32 @@ private synchronized void disableIfNeeded(){ Log.e(LOG_TAG, "Unable to establish connection"); connectionProblemNotification.when = System.currentTimeMillis(); String pbMessage = appContext.getResources().getQuantityString(R.plurals.connection_problem_notification, nbRetriesRemaining, nbRetriesRemaining); - connectionProblemNotification.setLatestEventInfo(appContext, - appContext.getString(R.string.connection_problem_notification_title), - pbMessage, + connectionProblemNotification.setLatestEventInfo(appContext, + appContext.getString(R.string.connection_problem_notification_title), + pbMessage, connectionProblemNotification.contentIntent); connectionProblemNotification.number = 1 + maxConnectionRetries - nbRetriesRemaining; notificationManager.notify(R.string.connection_problem_notification_title, connectionProblemNotification); } else { -// notificationManager.cancel(R.string.connection_problem_notification_title); -// serviceStoppedNotification.when = System.currentTimeMillis(); -// notificationManager.notify(R.string.service_closed_because_connection_problem_notification_title, serviceStoppedNotification); disable(R.string.msg_two_many_connection_problems); } } } - + /** * Disables the bluetooth GPS provider. - * - * It will: + * + * It will: *
    *
  • close the connection with the bluetooth device
  • *
  • disable the Mock Location Provider used for the bluetooth GPS
  • *
  • stop the BlueGPS4Droid service
  • *
- * The reasonId parameter indicates the reason to close the bluetooth provider. + * The reasonId parameter indicates the reason to close the bluetooth provider. * If its value is zero, it's a normal shutdown (normally, initiated by the user). - * If it's non-zero this value should correspond a valid localized string id (res/values..../...) + * If it's non-zero this value should correspond a valid localized string id (res/values..../...) * which will be used to display a notification. - * + * * @param reasonId the reason to close the bluetooth provider. */ public synchronized void disable(int reasonId) { @@ -1012,11 +813,11 @@ public synchronized void disable(int reasonId) { setDisableReason(reasonId); disable(); } - + /** * Disables the bluetooth GPS provider. - * - * It will: + * + * It will: *
    *
  • close the connection with the bluetooth device
  • *
  • disable the Mock Location Provider used for the bluetooth GPS
  • @@ -1028,8 +829,8 @@ public synchronized void disable() { notificationManager.cancel(R.string.connection_problem_notification_title); if (getDisableReason() != 0){ serviceStoppedNotification.when = System.currentTimeMillis(); - serviceStoppedNotification.setLatestEventInfo(appContext, - appContext.getString(R.string.service_closed_because_connection_problem_notification_title), + serviceStoppedNotification.setLatestEventInfo(appContext, + appContext.getString(R.string.service_closed_because_connection_problem_notification_title), appContext.getString(R.string.service_closed_because_connection_problem_notification, appContext.getString(getDisableReason())), serviceStoppedNotification.contentIntent); notificationManager.notify(R.string.service_closed_because_connection_problem_notification_title, serviceStoppedNotification); @@ -1040,27 +841,7 @@ public synchronized void disable() { enabled = false; connectionAndReadingPool.shutdown(); // stop GPS device -// try { -// File gpsControl = new File("/sys/devices/platform/gps_control/enable"); -// if (gpsControl.isFile()){ -// if (gpsControl.canWrite()){ -// OutputStream os = new FileOutputStream(gpsControl); -// os.write('0'); -// os.flush(); -// os.close(); -// } -// } -// } catch (FileNotFoundException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while stoping GPS: ", e); -// } catch (IOException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while stoping GPS: ", e); -// } catch (SecurityException e) { -// // TODO update message -// Log.e(LOG_TAG, "Error while stoping GPS: ", e); -// } - Runnable closeAndShutdown = new Runnable() { + Runnable closeAndShutdown = new Runnable() { @Override public void run(){ try { @@ -1073,14 +854,6 @@ public void run(){ if (connectedGps != null){ connectedGps.close(); } -// if ((gpsDev != null) && ((connectedGps == null) || (connectedGps.gpsDev != gpsDev))){ -// try { -// Log.d(LOG_TAG, "closing Bluetooth GPS socket"); -// gpsDev.close(); -// } catch (IOException closeException) { -// Log.e(LOG_TAG, "error while closing socket", closeException); -// } -// } } } }; @@ -1088,7 +861,7 @@ public void run(){ nmeaListeners.clear(); disableMockLocationProvider(); notificationPool.shutdown(); -// connectionAndReadingPool.shutdown(); + callingService.stopSelf(); Log.d(LOG_TAG, "Bluetooth GPS manager disabled"); } @@ -1096,8 +869,8 @@ public void run(){ /** * Enables the Mock GPS Location Provider used for the bluetooth GPS. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#enableMockLocationProvider(java.lang.String) * @param gpsName the name of the Location Provider to use for the bluetooth GPS @@ -1112,8 +885,8 @@ public void enableMockLocationProvider(String gpsName, boolean force){ /** * Enables the Mock GPS Location Provider used for the bluetooth GPS. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#enableMockLocationProvider(java.lang.String) * @param gpsName the name of the Location Provider to use for the bluetooth GPS @@ -1121,15 +894,15 @@ public void enableMockLocationProvider(String gpsName, boolean force){ public void enableMockLocationProvider(String gpsName){ if (parser != null){ Log.d(LOG_TAG, "enabling mock locations provider: "+gpsName); - boolean force = sharedPreferences.getBoolean(BluetoothGpsProviderService.PREF_FORCE_ENABLE_PROVIDER, true); + boolean force = sharedPreferences.getBoolean(UsbGpsProviderService.PREF_FORCE_ENABLE_PROVIDER, true); parser.enableMockLocationProvider(gpsName, force); } } /** * Disables the current Mock GPS Location Provider used for the bluetooth GPS. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#disableMockLocationProvider() */ public void disableMockLocationProvider(){ @@ -1141,10 +914,10 @@ public void disableMockLocationProvider(){ /** * Getter use to know if the Mock GPS Listener used for the bluetooth GPS is enabled or not. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#isMockGpsEnabled() - * + * * @return true if the Mock GPS Listener used for the bluetooth GPS is enabled. */ public boolean isMockGpsEnabled() { @@ -1156,10 +929,10 @@ public boolean isMockGpsEnabled() { } /** * Getter for the name of the current Mock Location Provider in use. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#getMockLocationProvider() - * + * * @return the Mock Location Provider name used for the bluetooth GPS */ public String getMockLocationProvider() { @@ -1172,8 +945,8 @@ public String getMockLocationProvider() { /** * Indicates that the bluetooth GPS Provider is out of service. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#setMockLocationProviderOutOfService() */ private void setMockLocationProviderOutOfService(){ @@ -1184,8 +957,8 @@ private void setMockLocationProviderOutOfService(){ /** * Adds an NMEA listener. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#addNmeaListener(NmeaListener) * @param listener a {@link NmeaListener} object to register * @return true if the listener was successfully added @@ -1200,10 +973,10 @@ public boolean addNmeaListener(NmeaListener listener){ /** * Removes an NMEA listener. - * In fact, it delegates to the NMEA parser. - * + * In fact, it delegates to the NMEA parser. + * * @see NmeaParser#removeNmeaListener(NmeaListener) - * @param listener a {@link NmeaListener} object to remove + * @param listener a {@link NmeaListener} object to remove */ public void removeNmeaListener(NmeaListener listener){ Log.d(LOG_TAG, "removing NMEA listener"); @@ -1212,7 +985,7 @@ public void removeNmeaListener(NmeaListener listener){ /** * Notifies the reception of a NMEA sentence from the bluetooth GPS to registered NMEA listeners. - * + * * @param nmeaSentence the complete NMEA sentence received from the bluetooth GPS (i.e. $....*XY where XY is the checksum) * @return true if the input string is a valid NMEA sentence, false otherwise. */ @@ -1240,18 +1013,18 @@ private boolean notifyNmeaSentence(final String nmeaSentence){ @Override public void run() { listener.onNmeaReceived(timestamp, recognizedSentence); - } + } }); } } } } return res; - } + } /** * Sends a NMEA sentence to the bluetooth GPS. - * + * * @param command the complete NMEA sentence (i.e. $....*XY where XY is the checksum). */ public void sendPackagedNmeaCommand(final String command){ @@ -1262,8 +1035,8 @@ public void sendPackagedNmeaCommand(final String command){ /** * Sends a SIRF III binary command to the bluetooth GPS. - * - * @param commandHexa an hexadecimal string representing a complete binary command + * + * @param commandHexa an hexadecimal string representing a complete binary command * (i.e. with the Start Sequence, Payload Length, Payload, Message Checksum and End Sequence). */ public void sendPackagedSirfCommand(final String commandHexa){ @@ -1275,7 +1048,7 @@ public void sendPackagedSirfCommand(final String commandHexa){ /** * Sends a NMEA sentence to the bluetooth GPS. - * + * * @param sentence the NMEA sentence without the first "$", the last "*" and the checksum. */ public void sendNmeaCommand(String sentence){ @@ -1285,7 +1058,7 @@ public void sendNmeaCommand(String sentence){ /** * Sends a SIRF III binary command to the bluetooth GPS. - * + * * @param payload an hexadecimal string representing the payload of the binary command * (i.e. without Start Sequence, Payload Length, Message Checksum and End Sequence). */ @@ -1389,7 +1162,7 @@ private void enableSBAS(boolean enable){ public void enableSirfConfig(final Bundle extra){ Log.e(LOG_TAG, "spooling SiRF config: "+ extra); if (isEnabled()){ - notificationPool.execute( new Runnable() { + notificationPool.execute( new Runnable() { @Override public void run() { while ((enabled) && ((!connected) || (connectedGps == null) || (!connectedGps.isReady()))){ @@ -1398,34 +1171,34 @@ public void run() { } if (isEnabled() && (connected) && (connectedGps != null) && (connectedGps.isReady())){ Log.e(LOG_TAG, "init SiRF config: "+extra); - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GGA)){ - enableNmeaGGA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GGA, true)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_GGA)){ + enableNmeaGGA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GGA, true)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_RMC)){ - enableNmeaRMC(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_RMC, true)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_RMC)){ + enableNmeaRMC(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_RMC, true)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GLL)){ - enableNmeaGLL(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GLL, false)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_GLL)){ + enableNmeaGLL(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GLL, false)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_VTG)){ - enableNmeaVTG(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_VTG, false)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_VTG)){ + enableNmeaVTG(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_VTG, false)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSA)){ - enableNmeaGSA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSA, false)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_GSA)){ + enableNmeaGSA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GSA, false)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSV)){ - enableNmeaGSV(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSV, false)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_GSV)){ + enableNmeaGSV(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GSV, false)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_ZDA)){ - enableNmeaZDA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_ZDA, false)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_ZDA)){ + enableNmeaZDA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_ZDA, false)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION)){ - enableStaticNavigation(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION, false)); - } else if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_NMEA)){ - enableNMEA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_NMEA, true)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION)){ + enableStaticNavigation(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION, false)); + } else if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_NMEA)){ + enableNMEA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_NMEA, true)); } - if (extra.containsKey(BluetoothGpsProviderService.PREF_SIRF_ENABLE_SBAS)){ - enableSBAS(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_SBAS, true)); + if (extra.containsKey(UsbGpsProviderService.PREF_SIRF_ENABLE_SBAS)){ + enableSBAS(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_SBAS, true)); } Log.e(LOG_TAG, "initialized SiRF config: "+extra); } @@ -1437,7 +1210,7 @@ public void run() { public void enableSirfConfig(final SharedPreferences extra){ Log.e(LOG_TAG, "spooling SiRF config: "+ extra); if (isEnabled()){ - notificationPool.execute( new Runnable() { + notificationPool.execute( new Runnable() { @Override public void run() { while ((enabled) && ((!connected) || (connectedGps == null) || (!connectedGps.isReady()))){ @@ -1446,36 +1219,36 @@ public void run() { } if (isEnabled() && (connected) && (connectedGps != null) && (connectedGps.isReady())){ Log.e(LOG_TAG, "init SiRF config: "+extra); - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GLL)){ - enableNmeaGLL(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GLL, false)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_GLL)){ + enableNmeaGLL(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GLL, false)); } - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_VTG)){ - enableNmeaVTG(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_VTG, false)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_VTG)){ + enableNmeaVTG(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_VTG, false)); } - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSA)){ - enableNmeaGSA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSA, false)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_GSA)){ + enableNmeaGSA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GSA, false)); } - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSV)){ - enableNmeaGSV(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GSV, false)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_GSV)){ + enableNmeaGSV(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GSV, false)); } - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_ZDA)){ - enableNmeaZDA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_ZDA, false)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_ZDA)){ + enableNmeaZDA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_ZDA, false)); } - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION)){ - enableStaticNavigation(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION, false)); - } else if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_NMEA)){ - enableNMEA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_NMEA, true)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION)){ + enableStaticNavigation(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION, false)); + } else if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_NMEA)){ + enableNMEA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_NMEA, true)); } - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_SBAS)){ - enableSBAS(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_SBAS, true)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_SBAS)){ + enableSBAS(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_SBAS, true)); } sendNmeaCommand(callingService.getString(R.string.sirf_nmea_gga_on)); sendNmeaCommand(callingService.getString(R.string.sirf_nmea_rmc_on)); - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GGA)){ - enableNmeaGGA(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_GGA, true)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_GGA)){ + enableNmeaGGA(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_GGA, true)); } - if (extra.contains(BluetoothGpsProviderService.PREF_SIRF_ENABLE_RMC)){ - enableNmeaRMC(extra.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_RMC, true)); + if (extra.contains(UsbGpsProviderService.PREF_SIRF_ENABLE_RMC)){ + enableNmeaRMC(extra.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_RMC, true)); } } } @@ -1485,7 +1258,7 @@ public void run() { private void enableStaticNavigation(boolean enable){ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(callingService); - boolean isInNmeaMode = sharedPreferences.getBoolean(BluetoothGpsProviderService.PREF_SIRF_ENABLE_NMEA, true); + boolean isInNmeaMode = sharedPreferences.getBoolean(UsbGpsProviderService.PREF_SIRF_ENABLE_NMEA, true); if (isInNmeaMode){ enableNMEA(false); } diff --git a/src/org/broeuschmeul/android/gps/usb/provider/SettingsFragment.java b/src/org/broeuschmeul/android/gps/usb/provider/SettingsFragment.java new file mode 100644 index 00000000..9a298c75 --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/provider/SettingsFragment.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2010, 2011, 2012 Herbert von Broeuschmeul + * Copyright (C) 2010, 2011, 2012 BluetoothGPS4Droid Project + * Copyright (C) 2011, 2012 UsbGPS4Droid Project + * Copyright (C) 2013 Alexey Illarionov + * + * This file is part of UsbGPS4Droid. + * + * UsbGPS4Droid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * UsbGPS4Droid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with UsbGPS4Droid. If not, see . + */ + +package org.broeuschmeul.android.gps.usb.provider; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.res.Resources; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbInterface; +import android.hardware.usb.UsbManager; +import android.os.Bundle; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.util.Log; + +import java.util.HashMap; + +/** + * A SettingsFragment Class used to configure, start and stop the NMEA tracker service. + * + * @author Herbert von Broeuschmeul + * + */ +public class SettingsFragment extends PreferenceFragment { + + private static final boolean DBG = BuildConfig.DEBUG & false; + private static final String TAG = SettingsFragment.class.getSimpleName(); + + public interface Callbacks { + + void displayAboutDialog(); + + void startGpsProviderService(); + + void stopGpsProviderService(); + + void startTrackRecording(); + + void stopTrackRecording(); + + void setSirfFeature(String key, boolean enabled); + } + + private static final Callbacks sDummyCallbacks = new Callbacks() { + @Override public void displayAboutDialog() {} + @Override public void startGpsProviderService() {} + @Override public void stopGpsProviderService() {} + @Override public void startTrackRecording() {} ; + @Override public void stopTrackRecording() {} ; + @Override public void setSirfFeature(String key, boolean enabled) {} ; + }; + + private Callbacks mCallbacks = sDummyCallbacks; + + private String deviceName = ""; + + private UsbManager usbManager; + + private ListPreference mGpsDevicePreference, mDeviceSpeedPreference; + private EditTextPreference mMockGpsNamePreference, mConnectionRetriesPreference; + private Preference mTrackRecordingPreference; + private PreferenceScreen mGpsLocationProviderPreference; + + @Override + public void onAttach(Activity activity) { + // TODO Auto-generated method stub + super.onAttach(activity); + + if (!(activity instanceof Callbacks)) { + throw new IllegalStateException("Activity must implement fragment's callbacks."); + } + + mCallbacks = (Callbacks)activity; + usbManager = (UsbManager) activity.getSystemService(Context.USB_SERVICE); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref); + + mGpsDevicePreference = (ListPreference)findPreference(UsbGpsProviderService.PREF_GPS_DEVICE); + mDeviceSpeedPreference = (ListPreference)findPreference(UsbGpsProviderService.PREF_GPS_DEVICE_SPEED); + mTrackRecordingPreference = findPreference(UsbGpsProviderService.PREF_TRACK_RECORDING); + mMockGpsNamePreference = (EditTextPreference)findPreference(UsbGpsProviderService.PREF_MOCK_GPS_NAME); + mConnectionRetriesPreference = (EditTextPreference)findPreference(UsbGpsProviderService.PREF_CONNECTION_RETRIES); + mGpsLocationProviderPreference = (PreferenceScreen)findPreference(UsbGpsProviderService.PREF_GPS_LOCATION_PROVIDER); + + Preference pref = findPreference(UsbGpsProviderService.PREF_ABOUT); + pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + mCallbacks.displayAboutDialog(); + return true; + } + }); + } + + @Override + public void onStart() { + super.onStart(); + getPreferenceManager() + .getSharedPreferences() + .registerOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener); + } + + @Override + public void onResume() { + super.onResume(); + updateDevicePreferenceList(); + } + + @Override + public void onStop() { + super.onStop(); + getPreferenceManager() + .getSharedPreferences() + .unregisterOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mGpsDevicePreference = null; + mGpsDevicePreference = null; + mDeviceSpeedPreference = null; + mTrackRecordingPreference = null; + mMockGpsNamePreference = null; + mConnectionRetriesPreference = null; + mGpsLocationProviderPreference = null; + } + + @Override + public void onDetach() { + super.onDetach(); + mCallbacks = sDummyCallbacks; + usbManager = null; + } + + private void updateDevicePreferenceSummary(){ + final SharedPreferences sharedPref = getPreferenceManager().getSharedPreferences(); + + // update USB device summary + String defaultDeviceName = ""; + if (! usbManager.getDeviceList().isEmpty()){ + defaultDeviceName = usbManager.getDeviceList().keySet().iterator().next(); + } + deviceName = sharedPref.getString(UsbGpsProviderService.PREF_GPS_DEVICE, defaultDeviceName); + String deviceDisplayedName = ""; + if (! usbManager.getDeviceList().isEmpty() && usbManager.getDeviceList().get(deviceName) != null){ + deviceDisplayedName = usbManager.getDeviceList().get(deviceName).getDeviceName(); + } else if ((usbManager.getDeviceList().size() == 1) && (usbManager.getDeviceList().get(defaultDeviceName) != null)){ + deviceDisplayedName = usbManager.getDeviceList().get(defaultDeviceName).getDeviceName(); + deviceName = defaultDeviceName; + mGpsDevicePreference.setValue(defaultDeviceName); + } + mGpsDevicePreference.setSummary(getString(R.string.pref_gps_device_summary, deviceDisplayedName)); + mDeviceSpeedPreference.setSummary(getString(R.string.pref_gps_device_speed_summary, sharedPref.getString(UsbGpsProviderService.PREF_GPS_DEVICE_SPEED, getString(R.string.defaultGpsDeviceSpeed)))); + } + + private void updateDevicePreferenceList(){ + final SharedPreferences sharedPref = getPreferenceManager().getSharedPreferences(); + final Resources resources = getResources(); + final String mockProviderName; + + // update bluetooth device summary + updateDevicePreferenceSummary(); + // update bluetooth device list + HashMap connectedUsbDevices = usbManager.getDeviceList(); + String[] entryValues = new String[connectedUsbDevices.size()]; + String[] entries = new String[connectedUsbDevices.size()]; + int i = 0; + // Loop through usb devices + for (String name : connectedUsbDevices.keySet()) { + // Add the name and address to the ListPreference enties and entyValues + UsbDevice device = connectedUsbDevices.get(name); + if (DBG) Log.v(TAG, "device: " + device); + for (int k=0; k < device.getInterfaceCount(); k++){ + UsbInterface usbIntf = device.getInterface(k); + for (int j=0; j < usbIntf.getEndpointCount(); j++){ + UsbEndpoint endPt = usbIntf.getEndpoint(j); + if (DBG) Log.v(TAG, "endPt: : "+endPt + " type: "+endPt.getType()+ " dir: "+endPt.getDirection() ); + } + } + entryValues[i] = device.getDeviceName(); + entries[i] = name; + i++; + } + mGpsDevicePreference.setEntryValues(entryValues); + mGpsDevicePreference.setEntries(entries); + + mTrackRecordingPreference.setEnabled(sharedPref.getBoolean(UsbGpsProviderService.PREF_START_GPS_PROVIDER, false)); + + mockProviderName = mMockGpsNamePreference.getText(); + mMockGpsNamePreference.setSummary(mockProviderName); + + int connRetries; + + try { + connRetries = Integer.valueOf(mConnectionRetriesPreference.getText()); + }catch (NumberFormatException nfe) { + nfe.printStackTrace(); + connRetries = Integer.valueOf(getString(R.string.defaultConnectionRetries)); + } + + mConnectionRetriesPreference.setSummary(resources.getQuantityString( + R.plurals.pref_connection_retries_summary, connRetries, connRetries)); + + if (sharedPref.getBoolean(UsbGpsProviderService.PREF_REPLACE_STD_GPS, true)){ + String s = getString(R.string.pref_gps_location_provider_summary); + mGpsLocationProviderPreference.setSummary(s); + } else { + String s = getString(R.string.pref_mock_gps_name_summary, mockProviderName); + mGpsLocationProviderPreference.setSummary(s); + } + } + + private final OnSharedPreferenceChangeListener mOnSharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (UsbGpsProviderService.PREF_START_GPS_PROVIDER.equals(key)){ + boolean val = sharedPreferences.getBoolean(key, false); + if (val){ + mCallbacks.startGpsProviderService(); + } else { + mCallbacks.stopGpsProviderService(); + } + } else if (UsbGpsProviderService.PREF_TRACK_RECORDING.equals(key)){ + boolean val = sharedPreferences.getBoolean(key, false); + if (val){ + mCallbacks.startTrackRecording(); + } else { + mCallbacks.stopTrackRecording(); + } + } else if (UsbGpsProviderService.PREF_GPS_DEVICE.equals(key)){ + updateDevicePreferenceSummary(); + } else if (UsbGpsProviderService.PREF_GPS_DEVICE_SPEED.equals(key)){ + updateDevicePreferenceSummary(); + } else if (UsbGpsProviderService.PREF_SIRF_ENABLE_GLL.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_GGA.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_RMC.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_VTG.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_GSA.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_GSV.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_ZDA.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_SBAS.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_NMEA.equals(key) + || UsbGpsProviderService.PREF_SIRF_ENABLE_STATIC_NAVIGATION.equals(key) + ){ + final boolean enabled = sharedPreferences.getBoolean(key, false); + mCallbacks.setSirfFeature(key, enabled); + } + updateDevicePreferenceList(); + } + }; + +} diff --git a/src/org/broeuschmeul/android/gps/usb/provider/UsbGpsActivity.java b/src/org/broeuschmeul/android/gps/usb/provider/UsbGpsActivity.java new file mode 100644 index 00000000..a4e5b69d --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/provider/UsbGpsActivity.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2010, 2011, 2012 Herbert von Broeuschmeul + * Copyright (C) 2010, 2011, 2012 BluetoothGPS4Droid Project + * Copyright (C) 2011, 2012 UsbGPS4Droid Project + * + * This file is part of UsbGPS4Droid. + * + * UsbGPS4Droid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * UsbGPS4Droid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with UsbGPS4Droid. If not, see . + */ + +package org.broeuschmeul.android.gps.usb.provider; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import android.text.method.LinkMovementMethod; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +/** + * A PreferenceActivity Class used to configure, start and stop the NMEA tracker service. + * + * @author Herbert von Broeuschmeul + * + */ +public class UsbGpsActivity extends PreferenceActivity implements SettingsFragment.Callbacks { + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (savedInstanceState == null) { + PreferenceManager.setDefaultValues(this, + R.xml.pref, false); + getFragmentManager().beginTransaction().replace(android.R.id.content, + new SettingsFragment()).commit(); + } + } + + @Override + public void displayAboutDialog(){ + (new AboutDialogFragment()).show(getFragmentManager(), null); + } + + @Override + public void startGpsProviderService() { + final Intent intent = new Intent(this, UsbGpsProviderService.class); + intent.setAction(UsbGpsProviderService.ACTION_START_GPS_PROVIDER); + startService(intent); + } + + @Override + public void stopGpsProviderService() { + final Intent intent = new Intent(this, UsbGpsProviderService.class); + intent.setAction(UsbGpsProviderService.ACTION_STOP_GPS_PROVIDER); + startService(intent); + } + + @Override + public void startTrackRecording() { + final Intent intent = new Intent(this, UsbGpsProviderService.class); + intent.setAction(UsbGpsProviderService.ACTION_START_TRACK_RECORDING); + startService(intent); + } + + @Override + public void stopTrackRecording() { + final Intent intent = new Intent(this, UsbGpsProviderService.class); + intent.setAction(UsbGpsProviderService.ACTION_STOP_TRACK_RECORDING); + startService(intent); + } + + @Override + public void setSirfFeature(String key, boolean enabled) { + final Intent intent = new Intent(this, UsbGpsProviderService.class); + intent.setAction(UsbGpsProviderService.ACTION_CONFIGURE_SIRF_GPS); + intent.putExtra(key, enabled); + startService(intent); + } + + public static class AboutDialogFragment extends DialogFragment { + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder builder; + final LayoutInflater inflater; + final View messageView; + final Activity activity; + TextView textView; + + activity = getActivity(); + inflater = activity.getLayoutInflater(); + + messageView = inflater.inflate(R.layout.about, null, false); + // we need this to enable html links + textView = (TextView) messageView.findViewById(R.id.about_license); + textView.setMovementMethod(LinkMovementMethod.getInstance()); + // When linking text, force to always use default color. This works + // around a pressed color state bug. + final int defaultColor = textView.getTextColors().getDefaultColor(); + textView.setTextColor(defaultColor); + ((TextView) messageView.findViewById(R.id.about_sources)).setTextColor(defaultColor); + + try { + final PackageInfo pi = activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0); + ((TextView) messageView.findViewById(R.id.about_version)).setText(pi.versionName); + } catch (NameNotFoundException nnfe) { + nnfe.printStackTrace(); + } + + builder = new AlertDialog.Builder(activity); + builder + .setTitle(R.string.about_title) + .setIcon(R.drawable.gplv3_icon) + .setView(messageView); + + return builder.create(); + } + + } + +} diff --git a/src/org/broeuschmeul/android/gps/usb/provider/UsbGpsProviderService.java b/src/org/broeuschmeul/android/gps/usb/provider/UsbGpsProviderService.java new file mode 100644 index 00000000..97805e44 --- /dev/null +++ b/src/org/broeuschmeul/android/gps/usb/provider/UsbGpsProviderService.java @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2010, 2011, 2012 Herbert von Broeuschmeul + * Copyright (C) 2010, 2011, 2012 BluetoothGPS4Droid Project + * Copyright (C) 2011, 2012 UsbGPS4Droid Project + * + * This file is part of UsbGPS4Droid. + * + * UsbGPS4Droid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * UsbGPS4Droid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with UsbGPS4Droid. If not, see . + */ + +/** + * + */ +package org.broeuschmeul.android.gps.usb.provider; + +import android.app.Notification; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.content.SharedPreferences; +import android.location.GpsStatus.NmeaListener; +import android.os.Bundle; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.util.Log; +import android.widget.Toast; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + + +/** + * A Service used to replace Android internal GPS with a bluetooth GPS and/or write GPS NMEA data in a File. + * + * @author Herbert von Broeuschmeul + * + */ +public class UsbGpsProviderService extends Service { + + private static final boolean DBG = BuildConfig.DEBUG & true; + static final String TAG = UsbGpsProviderService.class.getSimpleName(); + + public static final String ACTION_START_TRACK_RECORDING = "org.broeuschmeul.android.gps.usb.tracker.nmea.intent.action.START_TRACK_RECORDING"; + public static final String ACTION_STOP_TRACK_RECORDING = "org.broeuschmeul.android.gps.usb.tracker.nmea.intent.action.STOP_TRACK_RECORDING"; + public static final String ACTION_START_GPS_PROVIDER = "org.broeuschmeul.android.gps.usb.provider.nmea.intent.action.START_GPS_PROVIDER"; + public static final String ACTION_STOP_GPS_PROVIDER = "org.broeuschmeul.android.gps.usb.provider.nmea.intent.action.STOP_GPS_PROVIDER"; + public static final String ACTION_CONFIGURE_SIRF_GPS = "org.broeuschmeul.android.gps.usb.provider.nmea.intent.action.CONFIGURE_SIRF_GPS"; + + public static final String PREF_START_GPS_PROVIDER = "startGps"; + public static final String PREF_GPS_LOCATION_PROVIDER = "gpsLocationProviderKey"; + public static final String PREF_REPLACE_STD_GPS = "replaceStdtGps"; + public static final String PREF_FORCE_ENABLE_PROVIDER = "forceEnableProvider"; + public static final String PREF_MOCK_GPS_NAME = "mockGpsName"; + public static final String PREF_CONNECTION_RETRIES = "connectionRetries"; + public static final String PREF_TRACK_RECORDING = "trackRecording"; + public static final String PREF_TRACK_FILE_DIR = "trackFileDirectory"; + public static final String PREF_TRACK_FILE_PREFIX = "trackFilePrefix"; + public static final String PREF_GPS_DEVICE = "usbDevice"; + public static final String PREF_GPS_DEVICE_SPEED = "gpsDeviceSpeed"; + public static final String PREF_ABOUT = "about"; + + /** + * Tag used for log messages + */ + private static final String LOG_TAG = "UsbGPS"; + + public static final String PREF_SIRF_GPS = "sirfGps"; + public static final String PREF_SIRF_ENABLE_GGA = "enableGGA"; + public static final String PREF_SIRF_ENABLE_RMC = "enableRMC"; + public static final String PREF_SIRF_ENABLE_GLL = "enableGLL"; + public static final String PREF_SIRF_ENABLE_VTG = "enableVTG"; + public static final String PREF_SIRF_ENABLE_GSA = "enableGSA"; + public static final String PREF_SIRF_ENABLE_GSV = "enableGSV"; + public static final String PREF_SIRF_ENABLE_ZDA = "enableZDA"; + public static final String PREF_SIRF_ENABLE_SBAS = "enableSBAS"; + public static final String PREF_SIRF_ENABLE_NMEA = "enableNMEA"; + public static final String PREF_SIRF_ENABLE_STATIC_NAVIGATION = "enableStaticNavigation"; + + private BlueetoothGpsManager mGpsManager = null; + private PrintWriter writer; + private File trackFile; + private boolean preludeWritten = false; + + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + + if (intent == null) { + Log.v(TAG, "UsbGpsProviderService restarted"); + processStartGpsProvider(); + }else { + final String action = intent.getAction(); + if (action.equals(ACTION_START_GPS_PROVIDER)) processStartGpsProvider(); + else if(action.equals(ACTION_STOP_GPS_PROVIDER)) processStopGpsProvider(); + else if(action.equals(ACTION_START_TRACK_RECORDING)) processStartTrackRecording(); + else if(action.equals(ACTION_STOP_TRACK_RECORDING)) processStopTrackRecording(); + else if(action.equals(ACTION_CONFIGURE_SIRF_GPS)) processConfigureSirfGps(intent.getExtras()); + else Log.e(TAG, "onStartCommand(): unknown action " + action); + } + return START_STICKY; + } + + @Override + public IBinder onBind(Intent arg0) { + return null; + } + + @Override + public void onDestroy() { + stop(); + } + + + public boolean isServiceStarted() { + return mGpsManager != null; + } + + + private void processStartGpsProvider() { + + if (isServiceStarted()) return; + + Notification notification = createForegroundNotification(); + startForeground(R.string.foreground_gps_provider_started_notification, notification); + + +// if (mGpsManager == null){ +// if (true /*|| BluetoothAdapter.checkBluetoothAddress(deviceAddress)*/){ +// String mockProvider = LocationManager.GPS_PROVIDER; +// if (! sharedPreferences.getBoolean(PREF_REPLACE_STD_GPS, true)){ +// mockProvider = sharedPreferences.getString(PREF_MOCK_GPS_NAME, getString(R.string.defaultMockGpsName)); +// } +// mGpsManager = new BlueetoothGpsManager(this, deviceAddress, maxConRetries); +// boolean enabled = mGpsManager.enable(); +// if (sharedPreferences.getBoolean(PREF_START_GPS_PROVIDER, false) != enabled){ +// edit.putBoolean(PREF_START_GPS_PROVIDER,enabled); +// edit.commit(); +// } +// if (enabled) { +// mGpsManager.enableMockLocationProvider(mockProvider); +// Notification notification = new Notification(R.drawable.ic_stat_notify, this.getString(R.string.foreground_gps_provider_started_notification), System.currentTimeMillis()); +// Intent myIntent = new Intent(this, UsbGpsActivity.class); +// PendingIntent myPendingIntent = PendingIntent.getActivity(this, 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT); +// notification.setLatestEventInfo(getApplicationContext(), this.getString(R.string.foreground_service_started_notification_title), this.getString(R.string.foreground_gps_provider_started_notification), myPendingIntent); +// startForeground(R.string.foreground_gps_provider_started_notification, notification); +// toast.setText(this.getString(R.string.msg_gps_provider_started)); +// toast.show(); +// } else { +// stopSelf(); +// } +// } else { +// stopSelf(); +// } +// } else { +// toast.setText(this.getString(R.string.msg_gps_provider_already_started)); +// toast.show(); +// } + } + + private void processStopGpsProvider() { + stop(); + stopSelf(); + } + + private void processStartTrackRecording() { + if (trackFile == null){ + if (mGpsManager != null){ + beginTrack(); + mGpsManager.addNmeaListener(mNmeaListener); + Toast.makeText(this, getText(R.string.msg_nmea_recording_started), + Toast.LENGTH_SHORT).show(); + } else { + endTrack(); + } + } else { + Toast.makeText(this, getText(R.string.msg_nmea_recording_already_started), + Toast.LENGTH_SHORT).show(); + } + } + + private void processStopTrackRecording() { + if (mGpsManager != null){ + mGpsManager.removeNmeaListener(mNmeaListener); + endTrack(); + Toast.makeText(this, getText(R.string.msg_nmea_recording_stopped), + Toast.LENGTH_SHORT).show(); + } + } + + private void processConfigureSirfGps(Bundle extras) { + if (!isServiceStarted()) return; + mGpsManager.enableSirfConfig(extras); + } + + private void stop() { + stopForeground(true); + + if (isServiceStarted()) { + //mGpsManager.stop(); + + Toast.makeText(this, R.string.msg_gps_provider_stopped, Toast.LENGTH_SHORT) + .show(); + + } + } + + + @SuppressWarnings("deprecation") + private Notification createForegroundNotification() { + CharSequence text = getText(R.string.foreground_gps_provider_started_notification); + + Notification notification = new Notification(R.drawable.ic_stat_notify, + text, System.currentTimeMillis()); + + PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + new Intent(this, UsbGpsActivity.class), 0); + + notification.setLatestEventInfo(this, + getText(R.string.foreground_gps_provider_started_notification), text, contentIntent); + + return notification; + } + + private void beginTrack(){ + SimpleDateFormat fmt = new SimpleDateFormat("_yyyy-MM-dd_HH-mm-ss'.nmea'", Locale.US); + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + String trackDirName = sharedPreferences.getString(PREF_TRACK_FILE_DIR, this.getString(R.string.defaultTrackFileDirectory)); + String trackFilePrefix = sharedPreferences.getString(PREF_TRACK_FILE_PREFIX, this.getString(R.string.defaultTrackFilePrefix)); + trackFile = new File(trackDirName,trackFilePrefix+fmt.format(new Date())); + Log.d(LOG_TAG, "Writing the prelude of the NMEA file: "+trackFile.getAbsolutePath()); + File trackDir = trackFile.getParentFile(); + try { + if ((! trackDir.mkdirs()) && (! trackDir.isDirectory())){ + Log.e(LOG_TAG, "Error while creating parent dir of NMEA file: "+trackDir.getAbsolutePath()); + } + writer = new PrintWriter(new BufferedWriter(new FileWriter(trackFile))); + preludeWritten = true; + } catch (IOException e) { + Log.e(LOG_TAG, "Error while writing the prelude of the NMEA file: "+trackFile.getAbsolutePath(), e); + } + } + private void endTrack(){ + if (trackFile != null && writer != null){ + Log.d(LOG_TAG, "Ending the NMEA file: "+trackFile.getAbsolutePath()); + preludeWritten = false; + writer.close(); + trackFile = null; + } + } + + private void addNMEAString(String data){ + if (! preludeWritten){ + beginTrack(); + } + Log.v(LOG_TAG, "Adding data in the NMEA file: "+ data); + if (trackFile != null && writer != null){ + writer.print(data); + } + } + + private final NmeaListener mNmeaListener = new NmeaListener() { + @Override + public void onNmeaReceived(long timestamp, String data) { + addNMEAString(data); + } + }; + + +}