Android Question android.intent.action.MEDIA_BUTTON again...

lemonisdead

Well-Known Member
Licensed User
Longtime User
Hello,

I have made some tests trying to detect a press on the small button included on some wired headsets.

When the activity is not paused, I get the activity keypress with value 79 each time. But when trying to detect it from a service using the code below, the service never starts. I am sorry as I am not still understanding the intent process so perhaps my code is not for this button ?

B4X:
AddReceiverText(MyService, <intent-filter>
    <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>)

Many thanks :)
 

stari

Active Member
Licensed User
Longtime User
You have a lot of ideas dear DonManfred and I do thank you to have learned me that way I had never thought about. Many thanks (publicly)

Vielen Dank
hi, i have the same problem. But, look here: https://www.b4x.com/android/forum/threads/headset-button.47242/#post-296979 this is, what works for me on almost all phones.
On Samsung S3 , S4 ,.. with Android 4.3 a have another problem: By pressing the headset button audio player is playing.
So, i wish to know, how to Broadcast intenet "Unplugged", - programmatically disconnecting the headphones. I'm shure, this will help.
 
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
Hello,

That's me again. I do have a problem with the receiver of the MEDIA_BUTTON.
I have seen that the intent is redirected to my registered application but nothing happens. I mean the service won't receive the intent.

b4a.example is the package's name and s1 is the registered service using the code kindly provided by Erel.

Broadcast: Intent { act=android.intent.action.MEDIA_BUTTON flg=0x10 cmp=b4a.example/s1 (has extras) } ordered=true userid=0 callerApp=null
Broadcast: Intent { act=android.intent.action.MEDIA_BUTTON flg=0x10 cmp=b4a.example/s1 (has extras) } ordered=true userid=0 callerApp=null
interceptKeyTq keycode=79 scanCode=164 screenIsOn=true keyguardActive=false policyFlags = #2000000 down =true canceled = false isWakeKey=false mVolumeDownKeyTriggered =false mVolumeUpKeyTriggered =false
interceptKeyTq keycode=79 scanCode=164 screenIsOn=true keyguardActive=false policyFlags = #2000000 down =false canceled = false isWakeKey=false mVolumeDownKeyTriggered =false mVolumeUpKeyTriggered =false
interceptKeyTi keyCode=79 down=true repeatCount=0 keyguardOn=false mHomePressed=false canceled=false
interceptKeyTi keyCode=79 down=false repeatCount=0 keyguardOn=false mHomePressed=false canceled=false
Broadcast: Intent { act=android.intent.action.MEDIA_BUTTON flg=0x10 cmp=b4a.example/s1 (has extras) } ordered=true userid=0 callerApp=null
Broadcast: Intent { act=android.intent.action.MEDIA_BUTTON flg=0x10 cmp=b4a.example/s1 (has extras) } ordered=true userid=0 callerApp=null

@Erel: I have seen nothing in the logs about a missing permission. Please could you tell me if the code you have provided should be used from the Activity or the Service. I had put it in the Activity after having started the service.
 
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
I have noticed that the default Media Player registers with "com.android.music/.MediaButtonIntentReceiver" and my app registers with "b4a.example/s1"
Could it be the missing dot before the service's name ?
I have tried by providing a service name including the dot, to the RegisterForMediaButton sub, and it didn't fix
 
Upvote 0

stari

Active Member
Licensed User
Longtime User
I have noticed that the default Media Player registers with "com.android.music/.MediaButtonIntentReceiver" and my app registers with "b4a.example/s1"
Could it be the missing dot before the service's name ?
I have tried by providing a service name including the dot, to the RegisterForMediaButton sub, and it didn't fix
Hello, i have the same problem. On older phones all is working, but not on Android 4.3 . In fact, i found solution, but i can't work and change library. the solution is here: http://android.amberfog.com/?p=415. Mybe this will help.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Activity.onKeyDown.

@lemonisdead try this code:
B4X:
Sub RegisterForMediaButton (ServiceName As String)
   Dim am As JavaObject = GetContext.RunMethodJO("getSystemService", Array("audio"))
   Dim component As JavaObject
   component.InitializeNewInstance("android.content.ComponentName", Array(Application.PackageName, ServiceName.ToLowerCase))
   am.RunMethod("registerMediaButtonEventReceiver", Array(component))
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
You might need to add a permission (check the logs).


Hi Erel

What permissions are required for this to work. I am trying to achieve the same as @lemonisdead

Regards

John.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
I have noticed that the default Media Player registers with "com.android.music/.MediaButtonIntentReceiver" and my app registers with "b4a.example/s1"
Could it be the missing dot before the service's name ?
I have tried by providing a service name including the dot, to the RegisterForMediaButton sub, and it didn't fix

Hey, have you solved your problem, I am trying to do the same, but with out any luck yet

Regards

John
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Do you see the intent description in the unfiltered logs?

Hi Erel

Below is the unfiltered log. My service does not get called.


B4X:
[onKeyDown] In finishInput state
Load KCM of non-default device may incur unexpected result
voice input key event: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_HEADSETHOOK, scanCode=226, metaState=0, flags=0x8, repeatCount=0, eventTime=718143187, downTime=718143187, deviceId=7, source=0x101 }, needWakeLock=false
  ignore key event
CatService: Return current sInstance
[onKeyUp] In finishInput state
handleHeadsetHook(): lEventTime = 718143648
voice input key event: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_HEADSETHOOK, scanCode=226, metaState=0, flags=0x8, repeatCount=0, eventTime=718143648, downTime=718143187, deviceId=7, source=0x101 }, needWakeLock=false
  send simulated key event, wakelock=false
RX ctrl_iface - hexdump(len=11): 53 49 47 4e 41 4c 5f 50 4f 4c 4c
fetchRssiAndLinkSpeedNative RSSI = -71
fetchRssiAndLinkSpeedNative mLinkspeedCount = 3, mLinkspeedSum: 162
fetchRssiAndLinkSpeedNative send RSSIChange intent, newSignalLevel =2mLastSignalLevel = 3
updateWifiState: action=android.net.wifi.RSSI_CHANGED newRssi=-71 freq=2412 newLevel=2 lastWifiLevel=3
HTC_WIFI_OFFLOAD_flag
onAirplaneModeChange:false
refreshViews: mWifiIconId -> stat_sys_wifi_signal_3
dumpIconState[dataVisible=false dataIconId=stat_sys_data_connected_h signalIconId=stat_sys_5signal_2 lastSignalLevel=2 wifiVisible=true wifiIconId=stat_sys_wifi_signal_3 simCardVisible=false simCardIconId=(null) airplaneMode=false femotcellVisible=false femtocellIconId=(null)]
RX ctrl_iface - hexdump(len=11): 53 49 47 4e 41 4c 5f 50 4f 4c 4c
fetchRssiAndLinkSpeedNative RSSI = -70
fetchRssiAndLinkSpeedNative mLinkspeedCount = 4, mLinkspeedSum: 220
fetchRssiAndLinkSpeedNative send RSSIChange intent, newSignalLevel =3mLastSignalLevel = 2
updateWifiState: action=android.net.wifi.RSSI_CHANGED newRssi=-70 freq=2412 newLevel=3 lastWifiLevel=2
HTC_WIFI_OFFLOAD_flag
onAirplaneModeChange:false
refreshViews: mWifiIconId -> stat_sys_wifi_signal_4
dumpIconState[dataVisible=false dataIconId=stat_sys_data_connected_h signalIconId=stat_sys_5signal_2 lastSignalLevel=2 wifiVisible=true wifiIconId=stat_sys_wifi_signal_4 simCardVisible=false simCardIconId=(null) airplaneMode=false femotcellVisible=false femtocellIconId=(null)]

Regards

John.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User

Hi Erel

Still not receiving the intent: Here is the code, pretty small project:

Main
B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.

   Private ListView1 As ListView

End Sub

Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:

   Activity.LoadLayout("main")
   ListView1.SingleLineLayout.Label.TextSize = 10
   If FirstTime Then
     requestAudioFocus
     RegisterForMediaButton("intentfilters")
   End If

End Sub

Sub Activity_Resume



End Sub

Sub Activity_Pause (UserClosed As Boolean)



End Sub

Sub add_intent(i As Intent )

   ListView1.AddSingleLine(DateTime.Time(DateTime.Now) & " - " & i.Action )
   ListView1.AddSingleLine(DateTime.Time(DateTime.Now) & " - " & i.ExtrasToString)

End Sub

Sub requestAudioFocus


   Dim jo As JavaObject
     jo.InitializeContext
     jo = jo.RunMethod("getSystemService", Array("audio"))
  
   Dim event As Object = jo.CreateEventFromUI("android.media.AudioManager.OnAudioFocusChangeListener", "audio", Null)
     Dim p As Phone
   jo.RunMethod("requestAudioFocus", Array (event, p.VOLUME_MUSIC, 2))

End Sub

Sub RegisterForMediaButton (ServiceName As String)

  Dim am As JavaObject = GetContext.RunMethodJO("getSystemService", Array("audio"))
  Dim component As JavaObject

  component.InitializeNewInstance("android.content.ComponentName", Array(Application.PackageName, ServiceName.ToLowerCase))
  am.RunMethod("registerMediaButtonEventReceiver", Array(component))

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

Service model - intentfilter

B4X:
Sub Service_Create


End Sub

Sub Service_Start (StartingIntent As Intent)


     ToastMessageShow(StartingIntent.Action ,False)
   CallSub2(Main,"add_intent",StartingIntent)

End Sub

Sub Service_Destroy


End Sub

Manifest file

B4X:
AddManifestText(
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="21"/>
<supports-screens android:largeScreens="true"
  android:normalScreens="true"
  android:smallScreens="true"
  android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")

' // headset MEDIA_BUTTON intent handler
AddReceiverText(intentfilters,<intent-filter android:priority="2147483647">
                   <action android:name="android.intent.action.MEDIA_BUTTON" />
                   </intent-filter> )
                
AddPermission(android.permission.BLUETOOTH)
AddPermission(android.permission.RECORD_AUDIO)


We have a customer who want to use our app https://play.google.com/store/apps/details?id=com.is.vitllinkSOS&hl=en without our button. There are in the medical industry and the phone they are using have a panic button but the button intents are not produced (by design), motorola phone, so we want to use the headphone jack to trap a button press/depress and active the alert. The app runs in the background and uses intent for pretty much everything (Bluetooth), also service callback so we don't really use much power. We want to achieve the same thing with the headphone jack, make sense to you ?

The above code us just a sample to get it working before I incorporate into the main app. I have set the priority very high to work over google talk thing.

Regards

John.
 
Last edited:
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Hello, i have the same problem. On older phones all is working, but not on Android 4.3 . In fact, i found solution, but i can't work and change library. the solution is here: http://android.amberfog.com/?p=415. Mybe this will help.

Hi, I am tryinh to get this working. Here is my simple project, can you help ?
 

Attachments

  • headphone.zip
    9.6 KB · Views: 377
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Hello, i have a sample, works on Android 4.0.3 on my HTC.
Try attached file.

I get this when I try to run it
B4X:
** Activity (main) Create, isFirst = true **
** Activity (main) Create, isFirst = true **
java.lang.reflect.InvocationTargetException
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.DynamicBuilder.build(DynamicBuilder.java:21)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayoutHelper(LayoutBuilder.java:345)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayoutHelper(LayoutBuilder.java:425)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:144)
   at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:208)
   at tps.stari.main._activity_create(main.java:374)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:697)
   at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
   at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
   at tps.stari.main.afterFirstLayout(main.java:102)
   at tps.stari.main.access$000(main.java:17)
   at tps.stari.main$WaitForLayout.run(main.java:80)
   at android.os.Handler.handleCallback(Handler.java:725)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:158)
   at android.app.ActivityThread.main(ActivityThread.java:5751)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1083)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:850)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: java.io.FileNotFoundException: /storage/sdcard0/Android/data/tps.stari/files/virtual_assets/slusalke2.jpg: open failed: ENOENT (No such file or directory)
   at anywheresoftware.b4a.objects.ImageViewWrapper.setImage(ImageViewWrapper.java:92)
   at anywheresoftware.b4a.objects.ImageViewWrapper.build(ImageViewWrapper.java:113)
   ... 28 more
Caused by: java.io.FileNotFoundException: /storage/sdcard0/Android/data/tps.stari/files/virtual_assets/slusalke2.jpg: open failed: ENOENT (No such file or directory)
   at libcore.io.IoBridge.open(IoBridge.java:416)
   at java.io.FileInputStream.<init>(FileInputStream.java:78)
   at anywheresoftware.b4a.objects.streams.File.OpenInput(File.java:199)
   at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize(CanvasWrapper.java:498)
   at anywheresoftware.b4a.objects.drawable.BitmapDrawable.build(BitmapDrawable.java:69)
   at anywheresoftware.b4a.objects.ImageViewWrapper.setImage(ImageViewWrapper.java:90)
   ... 29 more
Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
   at libcore.io.Posix.open(Native Method)
   at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
   at libcore.io.IoBridge.open(IoBridge.java:400)
   ... 34 more
Error occurred on line: 52 (Main)
Error occurred on line: 52 (Main)
java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (ImageView).
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:166)
   at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:208)
   at tps.stari.main._activity_create(main.java:374)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:697)
   at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
   at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
   at tps.stari.main.afterFirstLayout(main.java:102)
   at tps.stari.main.access$000(main.java:17)
   at tps.stari.main$WaitForLayout.run(main.java:80)
   at android.os.Handler.handleCallback(Handler.java:725)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:158)
   at android.app.ActivityThread.main(ActivityThread.java:5751)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1083)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:850)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Object should first be initialized (ImageView).
   at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
   at anywheresoftware.b4a.objects.ViewWrapper.innerInitialize(ViewWrapper.java:71)
   at anywheresoftware.b4a.objects.ImageViewWrapper.innerInitialize(ImageViewWrapper.java:35)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayoutHelper(LayoutBuilder.java:406)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayoutHelper(LayoutBuilder.java:425)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:144)
   ... 22 more
java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (ImageView).
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:166)
   at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:208)
   at tps.stari.main._activity_create(main.java:374)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:697)
   at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
   at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
   at tps.stari.main.afterFirstLayout(main.java:102)
   at tps.stari.main.access$000(main.java:17)
   at tps.stari.main$WaitForLayout.run(main.java:80)
   at android.os.Handler.handleCallback(Handler.java:725)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:158)
   at android.app.ActivityThread.main(ActivityThread.java:5751)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1083)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:850)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Object should first be initialized (ImageView).
   at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
   at anywheresoftware.b4a.objects.ViewWrapper.innerInitialize(ViewWrapper.java:71)
   at anywheresoftware.b4a.objects.ImageViewWrapper.innerInitialize(ImageViewWrapper.java:35)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayoutHelper(LayoutBuilder.java:406)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayoutHelper(LayoutBuilder.java:425)
   at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:144)
   ... 22 more
** Activity (main) Resume **
** Activity (main) Resume **

Also the lib reference's Audiotrack, notificationbuilder and ACL, they are not used ? is this correct ?
 
Upvote 0

stari

Active Member
Licensed User
Longtime User
Hi

Your sample does not seem to receive the ""android.intent.action.MEDIA_BUTTON"" intent.

Thanks anyway

Regards

John.
Hello,
my sample recieves Media button. I have removed jpg file slusalke2, but i don0t know, what you get error. Here, new sample, but, i i say, i receive proprly when the button on headphones is pressed.
 

Attachments

  • PHC.ZIP
    6.7 KB · Views: 381
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
hi @Erel

I have the OnAudioFocusChangeListener event occurring in a service now.


B4X:
Sub audio_Event(MethodName As String, Args() As Object) As Object

   Dim bc As ByteConverter
   
   If MethodName = "onAudioFocusChange" Then
       Log("audio_Event() MethodName = " & MethodName)
     If Args.Length = 1 Then
       
       Log("audio_Event() Args = " &  Args.Length)
         Log("audio_Event() Args = " &  Args)
       Log("audio_Event() Args = " &  bc.HexFromBytes(Args(0)))
       
     End If
  End If
   
  Return Null

End Sub

The args parameter give me the following:

audio_Event() Args = [Ljava.lang.Object;@414a4750

how do I decode this so I can see the data.

Regards

John.
 
Upvote 0
Top