Android Question Voice recognition via Bluetooth Headset

Nerdworld

Member
Licensed User
Longtime User
Hello folks!

Following situations keeps bugging me, any ideas are welcome!

Working:
+ App is running a service.
+ User presses a headset button.
+ App is starting / voice recognition starts.

Not working:
If i use a bluetooth headset, the sound is still being recorded over the internal microphone.

Someone with the same problem:
http://stackoverflow.com/questions/...oid-recognizerintent-with-a-bluetooth-headset

The Bluetooth headset API seems to have a function named startVoiceRecognition(BluetoothDevice device) [ http://developer.android.com/reference/android/bluetooth/BluetoothHeadset.html ] to start listening though the bluetooth microphone, but i don't know how to use Reflection to call this method.

B4X:
Sub Process_Globals
    Dim Voice As VoiceRecognition
End Sub

Sub Globals
    Dim RecognitionDone As Boolean = False
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Voice.Initialize("Voice")
    '
    'If (IsPaused(Events)) Then
    '    StartService(Events)
    'End If
End Sub

Sub Voice_Result(Success As Boolean, Text As List)
    If (Success) Then
        Dim Lines As String = ""
        For i = 0 To Text.Size - 1
            Lines = Lines & "|" & Text.Get(i)
        Next
        'CallSub2(Events, "SendData", Lines)
    End If
    RecognitionDone = True
End Sub

Sub Activity_Resume
    If (RecognitionDone) Then
        RecognitionDone = False
        Activity.Finish
    Else
        Voice.Listen
    End If
End Sub

Sub Activity_Pause(UserClosed As Boolean)
End Sub
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Start with this code and see whether the event is raised:
B4X:
Sub GetProfileProxy
   Dim adapter As JavaObject = BluetoothAdapter
   Dim listener As Object = adapter.CreateEvent("android.bluetooth.BluetoothProfile.ServiceListener", _
     "profile", Null)
   Log("Success: " & adapter.RunMethod("getProfileProxy", Array(GetContext, listener, 1)))'1 = headset
End Sub

Sub Profile_Event (MethodName As String, Args() As Object) As Object
   Log(MethodName)
   If MethodName = "onServiceConnected" Then
     Dim profile As JavaObject = args(1)
     Log(profile)
   End If
   Return Null
End Sub

Sub BluetoothAdapter As JavaObject
   Dim adapter As JavaObject
   adapter = adapter.InitializeStatic("android.bluetooth.BluetoothAdapter").RunMethod("getDefaultAdapter", Null)
   Return adapter
End Sub

Sub GetContext As JavaObject
  Return GetBA.GetField("context")
End Sub

Sub GetBA As JavaObject
  Dim jo As JavaObject
  Dim cls As String = Me
  cls = cls.SubString("class ".Length)
  jo.InitializeStatic(cls)
  Return jo.GetFieldJO("processBA")
End Sub
Add this line to the manifest editor: AddPermission(android.permission.BLUETOOTH)

You need to call GetProfileProxy.
Profile_Event should be raised when there is a new connection.
 
Upvote 0

Nerdworld

Member
Licensed User
Longtime User
Working like a charm.
I guess i can now modify it like this:

B4X:
Sub Profile_Event (MethodName As String, Args() As Object) As Object
  Log(MethodName)
  If MethodName = "onServiceConnected" Then
  Dim profile As JavaObject = Args(1)
  "profile", Null)
' ---
' Not sure about this part
Dim headset As JavaObject
headset = headset.InitializeStatic("android.bluetooth.BluetoothHeadset").RunMethod("getDefaultAdapter", Array(profile))
' ---
  End If
  Return Null
End Sub
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0

Nerdworld

Member
Licensed User
Longtime User
One more question:

B4X:
  Dim R As Reflector
  R.Target = R.GetContext
  R.Target = R.RunMethod2("getSystemService", "audio", "java.lang.String")
  R.RunMethod2("registerMediaButtonEventReceiver", "?", "android.app.PendingIntent")

Am i on the right way? :D

Tryied to pass an Intent as parameter:

java.lang.IllegalArgumentException: argument 1 should have type android.app.PendingIntent, got java.lang.String
 
Upvote 0

Nerdworld

Member
Licensed User
Longtime User
I think i finally have it working:

B4X:
  Dim CompName As JavaObject : CompName.InitializeNewInstance("android.content.ComponentName", Array("com.package.app", "com.package.app.Main"))
  '
  Dim R As Reflector
  R.Target = R.GetContext
  R.Target = R.RunMethod2("getSystemService", "audio", "java.lang.String")
  R.RunPublicmethod("registerMediaButtonEventReceiver", Array As Object(CompName), Array As String("android.content.ComponentName"))

Since the headset button isn't starting the music anymore. But my BroadcastReceiver still won't listen to android.intent.action.MEDIA_BUTTON...
 
Upvote 0

Nerdworld

Member
Licensed User
Longtime User
Unfortunately not - it's always starting the music, because i.e. the Sony Walkman app is registering the app as "the only receiver", as mentioned here:
http://android-developers.blogspot.de/2010/06/allowing-applications-to-play-nicer.html
(Becoming the “preferred” media button responder)

After calling the registerMediaButtonEventReceiver from my app the music won't start anymore - but i'm still having problems to setup the BroadcastReceiver.

B4X:
#Region  Service Attributes
    #StartAtBoot: False
#End Region

Sub Process_Globals
    Dim Broadcast As BroadCastReceiver
End Sub

Sub Service_Create
    Broadcast.Initialize("Broadcast")
End Sub

Sub Service_Start(StartingIntent As Intent)
    Broadcast.addAction("android.intent.action.MEDIA_BUTTON")
    Broadcast.SetPriority(2147483647)
    Broadcast.registerReceiver("")
    Log("Broadcaster listening...")
End Sub

Sub Broadcast_OnReceive(Action As String, Intent As Intent)
    Log(Action)
    Log(Intent.Action)
    Broadcast.AbortBroadcast
End Sub

Sub Service_Destroy
End Sub
 
Last edited:
Upvote 0

Nerdworld

Member
Licensed User
Longtime User
Finally, i got it working! - JavaObject and Reflector are really amazing, once understood! :)

B4X:
  Dim Intent As Intent
  Intent.Initialize(Intent.ACTION_VIEW, "http://google.de")
  '
  Dim PendingIntentClass As JavaObject
  PendingIntentClass.InitializeStatic("android.app.PendingIntent")
  Dim PendingIntent As JavaObject = PendingIntentClass.RunMethod("getActivity", Array As Object(GetContext, 0, Intent, 0))
  '
  Dim R As Reflector
  R.Target = R.GetContext
  R.Target = R.RunMethod2("getSystemService", "audio", "java.lang.String")
  R.RunPublicmethod("registerMediaButtonEventReceiver", Array As Object(PendingIntent), Array As String("android.app.PendingIntent"))

Edit: It's also possible to RunMethod "getBroadcast" instead of "getActivity" to improve speed and performance.
 
Last edited:
Upvote 0
Top