android.netmaui

.NET MAUI How to receive button action on earphone


I tried with BroadcastReceiver and ActionMediaButton but I never receive anything. A priori the code is good since it works with android.intent.action.PHONE_STATE which allows me to cut off music playback when the phone is playing. I looked on the internet, I found nothing. I find it hard to believe that you have to go through Bluetooth to do this. Obviously my question seems out of scope. I try this question without much hope.

I tried with BroadcastReceiver and ActionMediaButton but I never receive anything. A priori the code is good since it works with android.intent.action.PHONE_STATE which allows me to cut off music playback when the phone is playing.

This is the code :

public class MainActivity : MauiAppCompatActivity
{
   private PhoneCallReceiver _phoneCallReceiver;

   protected override void OnCreate(Bundle savedInstanceState)
   {
      base.OnCreate(savedInstanceState);
      IntentFilter filterPhone = new IntentFilter();
      filterPhone.AddAction("android.intent.action.MEDIA_BUTTON");
      filterPhone.AddAction("android.intent.action.PHONE_STATE");
      _phoneCallReceiver = new Platforms.Android.PhoneCallReceiver();
      if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu) // Android 33
      {
        RegisterReceiver(_phoneCallReceiver, filterPhone,    ReceiverFlags.Exported);
      }
      else
      {
        RegisterReceiver(_phoneCallReceiver, filterPhone);
      }
    }....
  Another file
    [BroadcastReceiver(Enabled = false, Exported = true)]
    public class PhoneCallReceiver : BroadcastReceiver
    {
      public delegate void PlayMusic();
      static public PlayMusic DelegatePlayMusic;
      static bool tantQuePasRacroche = false ;
      public override void OnReceive(Context context, Intent intent)
      {
        System.Diagnostics.Debug.WriteLine("MaMusique", intent.Action);
        if (intent.Action == "android.intent.action.PHONE_STATE")
        {
          System.Diagnostics.Debug.WriteLine("MaMusique",    "android.intent.action.PHONE_STATE");
          string state = intent.GetStringExtra(TelephonyManager.ExtraState);
          if (state == TelephonyManager.ExtraStateRinging)
          {
            // Traitement à effectuer lors d'un appel entrant
            //Toast.MakeText(context, "Appel entrant détecté",         ToastLength.Long).Show();
            if (!tantQuePasRacroche)
            {
              tantQuePasRacroche = true;
              DelegatePlayMusic();
            }
          }
          else if (state == TelephonyManager.ExtraStateIdle)
          {
            // Traitement à effectuer lors de la fin de l'appel
            //Toast.MakeText(context, "Appel terminé", ToastLength.Long).Show();
            DelegatePlayMusic();
            tantQuePasRacroche = false;
          }
        }
        else if (intent.Action == "android.intent.action.MEDIA_BUTTON")
        {
          // Traitement à effectuer lors de l'appui sur un bouton de         commande de la musique
          //Toast.MakeText(context, "Bouton de commande de la musique appuyé", ToastLength.Long).Show();
          System.Diagnostics.Debug.WriteLine("MaMusique", "android.intent.action.MEDIA_BUTTON");
          KeyEvent keyEvent;
          if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu) // Android 13 (API 33)
          {
            keyEvent = intent.GetParcelableExtra(Intent.ExtraKeyEvent, Java.Lang.Class.FromType(typeof(KeyEvent))) as KeyEvent;
          }
          else
          {
            keyEvent = (KeyEvent)intent.GetParcelableExtra(Intent.ExtraKeyEvent);
          }
          System.Diagnostics.Debug.WriteLine($"Sending KeyEvent multimédia appuyé keycode = {keyEvent.KeyCode}");
          if (keyEvent != null && keyEvent.Action == KeyEventActions.Down)
          {
            if (keyEvent.KeyCode == Keycode.MediaPlayPause)
            {
              //Gérer l'événement du bouton multimédia ici
              System.Diagnostics.Debug.WriteLine("MaMusique", "Sending KeyEvent Pause appuyé");

            }
            else if (keyEvent.KeyCode == Keycode.MediaNext)
            {
              //Gérer l'événement du bouton multimédia ici
              System.Diagnostics.Debug.WriteLine("MaMusique", "Sending KeyEvent Next  appuyé");
            }
            else if (keyEvent.KeyCode == Keycode.MediaPrevious)
            {
              //Gérer l'événement du bouton multimédia ici
              System.Diagnostics.Debug.WriteLine("MaMusique", "Sending KeyEvent Previous appuyé");
            }
            else if (keyEvent.KeyCode == Keycode.MediaPlay)
            {
              System.Diagnostics.Debug.WriteLine("MaMusique", "Sending KeyEvent Play appuyé");
            }
          }
        }
      }

And this is the Manifest : enter image description here

But I have to say that I use the MediaElement Nuget in my app to listen to music and I ended up thinking that it was the nuget that was receiving the MediaButton and that was the reason why I was not receiving anything in the BroadcastReveiver. I don't have any other app. I worked with GitHub Copilot, which offered me 36,000 code possibilities to do it, but none of them worked. It even makes completely crazy propositions. It can't say I don't know.


Solution

  • SOLUTION So it's very simple, the MediaElement nuget to listen to music opens a media session and you can't have two listens in the same application on the same media. So I loaded the code of the MediaElement Nuget and I modified the code to create an event that passes the MediaButton code. And it works perfectly. So be careful to develop on the MediaElement code you have to load the workload which is far from negligible. I'm going to try to do without the Nuget to just listen to music.