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

lemonisdead

Well-Known Member
Licensed 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 :)
 

lemonisdead

Well-Known Member
Licensed User
Hello NJ,

Using the VOLUME_CHANGED_ACTION intent the service is started when I change the volume only (not pressing the button). The Broadcastreceiver acts as the intent in the Manifest (said it won't receive).

Thanks for your ideas btw
 

lemonisdead

Well-Known Member
Licensed User
Humm.. I have a doubt about how this button could be named. It is the round button you can find on most wired headsets.
Is it really a MEDIA_BUTTON ?

 

Attachments

lemonisdead

Well-Known Member
Licensed User
Hello,

Thanks for the idea, Erel. I was able to check that the intent was correct
Broadcast: Intent { act=android.intent.action.MEDIA_BUTTON flg=0x10 cmp=com.android.music/.MediaButtonIntentReceiver (has extras) } ordered=true userid=0 callerApp=null
Broadcast: Intent { act=android.intent.action.MEDIA_BUTTON flg=0x10 cmp=com.android.music/.MediaButtonIntentReceiver (has extras) } ordered=true userid=0 callerApp=null


intentAction android.intent.action.MEDIA_BUTTON
isEventFromMonkey false
onStartCommand: com.android.music.musicservicecommand/togglepause
>> play: init=false, ready=false, listlen=0
AudioFocus requestAudioFocus() from android.media.AudioManager@41ed2a50com.android.music.MediaPlaybackService$3@41ecf880
Remote Control registerMediaButtonIntent() for PendingIntent{42478108: PendingIntentRecord{42acac50 com.android.music broadcastIntent}}
setShuffleMode(2)

But, if I don't get the broadcasted intent, could it be because some other app catches it before it comes to the service ? I have tried (as I was able to understand it) to put a higher priority. But with no success

Main
B4X:
Sub Process_Globals

End Sub

Sub Globals
 
   
End Sub

Sub Activity_Create(FirstTime As Boolean)

      StartService("Receiver")
               
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause(UserClosed As Boolean)
    If UserClosed AND Not(IsPaused(Receiver)) Then
        StopService(Receiver)
    End If
End Sub

Sub Activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
    ToastMessageShow("Activity",False)
    LogColor("Activity " & KeyCode,Colors.red)
    Return False
End Sub
BroadcastReceiver's service (named Receiver)
B4X:
Sub Process_Globals

      'These global variables will be declared once when the application starts.
      'These variables can be accessed from all modules.
   
      Dim Broadcast As BroadCastReceiver

End Sub

Sub Service_Create

    Broadcast.Initialize("BR")

End Sub

Sub Service_Start(StartingIntent As Intent)

      Broadcast.SetPriority(2147483647)
    Broadcast.registerReceiver("android.intent.action.MEDIA_BUTTON")
    LogColor("BR registered: " & Broadcast.isRegistered,Colors.Green)
   


End Sub

Sub Service_Destroy
    Broadcast.unregisterReceiver
End Sub

Sub BR_OnReceive(Action As String, Extras As Object)

    ToastMessageShow("Receiver",False)
    LogColor("Receiver",Colors.Green)  
End Sub

tot service : the service registered to be started from the Manifest
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 Service_Create

End Sub

Sub Service_Start (StartingIntent As Intent)
    ToastMessageShow("tot",False)
    LogColor("tot",Colors.Blue)
    StopService("")
End Sub

Sub Service_Destroy

End Sub
Manifest
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: http://www.basic4ppc.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="8" 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$")
setapplicationattribute(android:theme, "@android:style/Theme.Holo")
'End of default text.

AddReceiverText(tot,
                <intent-filter android:priority="2147483647">
                <action android:name="android.intent.action.MEDIA_BUTTON" />
                </intent-filter>)
 

lemonisdead

Well-Known Member
Licensed User
Many thanks. It is something I really don't understand but if you said... But why Android won't let us do what we want on this system...
Closed BTW :)
 

Erel

Administrator
Staff member
Licensed User
But why Android won't let us do what we want on this system
Overtime you can see that Android becomes more and more locked (see the case with the SD card or SMS interception). Most of these changes are reasonable.

The permissions system should have been the answer for the security / privacy issues. I find the permissions system to not be able to fulfill this task (it was quite funny for me to see my young daughter who doesn't yet read accept a huge list of scarey permissions when she installed a kids game).
 

RFman

New Member
Licensed User
My quesions are (1) how can the popular app "Pressy" (see Play Store) do it? The Pressy app claims you can launch an app of your choice by pressing their button (or you can select instead the headset button). (2) How can the SUB ACTIVITY_KeyUp(Keycode as int) as Boolean detect it for KeyCode = KeyCodes.KEYCODE_HEADSETHOOK ? I know this Sub works only in an activity, but if the intent can only go to the explicit component, how does ACTIVITY_KeyUp work in a B4A Sub?
 

lemonisdead

Well-Known Member
Licensed User
Dear Erel, Dear NJDude, (and the others)

Please had you had time to take a look at my previous code and perhaps checked if I did not made any error ?

I am asking this because, installing a third party app, I have seen the system was able to detect the MEDIA_BUTTON press from a service too. The third party app is "Press Audio Jack Control". Of course, that app receives the intent (I mean its service is only running after a MEDIA_BUTTON press).

By my side and using my code, I never get the necessary intent.
 

RFman

New Member
Licensed User
The activity key handling is a different Android feature. It is not (directly) related to the intents system.
OK. Thanks. Can you tell me what this Android feature is that handles the keys? Can you point me to where I can learn more about how the activity key handling works? That is, so I might be able to modify it so it'll work with the media button in a service?
 

Erel

Administrator
Staff member
Licensed User
Can you tell me what this Android feature is that handles the keys?
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).
 

DonManfred

Expert
Licensed User
See the manifest from the app you posted, @lemonisdead
<?xml version="1.0" encoding="utf-8"?>
<manifest android:versionCode="2" android:versionName="1.1" package="com.ssworkshop.audiopress"
xmlns:android="http://schemas.android.com/apk/res/android">
<application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@drawable/ic_launcher_large" android:allowBackup="true">
<activity android:label="@string/app_name" android:name="com.ssworkshop.audiopress.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:label="Calibrate Your Button" android:name="com.ssworkshop.audiopress.CaliActivity" />
<activity android:label="Setup Actions" android:name="com.ssworkshop.audiopress.SetActionActivity" />
<activity android:label="Power ON/OFF" android:name="com.ssworkshop.audiopress.PowerOnOff" />
<receiver android:name="RemoteControlReceiver">
<intent-filter android:priority="10000">
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
</application>
</manifest>
 

lemonisdead

Well-Known Member
Licensed User
I do thank you very much ALL for the help you kindly provided. Both solutions do work.
@DonManfred : perhaps in Chit Chat could we discuss the way you managed to be provided the Manifest from that app ?
 

lemonisdead

Well-Known Member
Licensed 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
 
Last edited:
Top