WP_20130916_08_23_11_Pro

Qualche tempo fa, un amico che lavorava su un grosso progetto WP8, mi chiese se conoscevo un modo di determinare quando il jack della cuffia venisse inserito o disinserito dal device, visto che all’apparenza non c’erano API specifiche che espletassero a questa funzione.

Anche io non conoscevo la risposta e nemmeno le mie ricerche su internet sortirono esito positivo.

Una idea che mi venne in mente fu quella di utilizzare le API della radio FM per misurare la potenza del segnale, poichè l’auricolare viene sfruttata come antenna per la sintonizzazioine della radio, pensai che la presenza dello spinotto nel device avrebbe fatto aumentare il livello del segnale ricevuto.

Feci qualche esperimento con FMRadio.Instance.SignalStrength misurando il cambiamento del SignalStrength inserendo o togliento una auricolare.

Questo approccio però presentava dei problemi, infatti sui device Windows Phone 8 di prima generazione (quelli per intenderci fino all’aggiornamento GDR1) non avevamo accesso alle API della radio FM ed il semplice istanziamento generava una eccezione.

Ho quindi condotto le mie prove con dei device WP7, ma anche lì le variazioni nel segnale non erano tali da determinare nettamente ed inequivocabilmente la presenza o meno dell’auricolare.

Ho condotto delle prove analoghe su device WP8 con GDR2, ma I risultati sono stati gli stessi.

Capito che questo approccio non era risolutivo ho cercato nelle API di WP8 ed ho trovato che fra quel relative al VOIP esisteva una interessante classe AudioRoutingManager.

Di per sé l’utilizzo di questa API è quello di indirizzare l’audio di comunicazioni VOIP ad endpoint diversi dall’altoparlante del telefono.

Tuttavia la classe implementa un evento AudioEndPointChanged che permette di conoscere l’attuale endpoint audio del device o se c’è stato un cambiamento dallo stato precedente, I valori riportati sono esposti da un enumeratore AudioRoutingEndpoint con I seguenti membri:

Membro

Descrizione

Default L’endpoint di default, il vivavoce
Earpiece Una auricolare
Speakerphone Il vivavoce (dall’altoparlante)
Bluetooth Un dispositivo Bluetooth
WiredHeadset Una cuffia con cavo
WiredHeadsetSpeakerOnly Cuffia cablata solo per Out, l’IN dal microfono predefinito
BluetoothWithNoiseAndEchoCancellation Disp. Bluetooth con cancellazione eco e rumori

 

Voilà! registrandosi all’evento è possibile essere “avvisati” quando lo stato cambia e di conseguenza sapere se il famoso jack è inserito o meno.

In realtà possiamo sapere anche molto di più, come visto nella tabella precedente, dipenderà quindi dalle nostre necessità nel gestire tutti I casi o solo quelli di nostro interesse.

Vediamo allora un po’ di codice tratto dall’esempio che troverete linkato alla fine del post.

Per prima cosa dobbiamo aggiungere una capability al WMAppManifest, ed in particolare la ID_CAP_VOIP.

Poi vediamo come registrare l’evento con il nostro handler:

1: AudioRoutingManager.GetDefault().AudioEndpointChanged += MainPage_AudioEndpointChanged;

 

Poi vediamo come gestire I vari casi nel nostro metodo:

   1:  public void MainPage_AudioEndpointChanged(AudioRoutingManager sender, object args)
   2:  {
   3:     var AudioEndPoint = sender.GetAudioEndpoint();
   4:     switch (AudioEndPoint)
   5:     {
   6:         case AudioRoutingEndpoint.Default:
   7:             {
   8:                 txtActual = "Default";
   9:                 break;
  10:             }
  11:         case AudioRoutingEndpoint.Earpiece:
  12:             {
  13:                 txtActual = "Earpiece";
  14:                 break;
  15:             }
  16:         case AudioRoutingEndpoint.Speakerphone:
  17:             {
  18:                 txtActual = "Speakerphone";
  19:                 break;
  20:             }
  21:         case AudioRoutingEndpoint.Bluetooth:
  22:             {
  23:                 txtActual = "Bluetooth";
  24:                 break;
  25:             }
  26:         case AudioRoutingEndpoint.WiredHeadset:
  27:             {
  28:                 txtActual = "WiredHeadset";
  29:                 break;
  30:             }
  31:         case AudioRoutingEndpoint.WiredHeadsetSpeakerOnly:
  32:             {
  33:                 txtActual = "WiredHeadsetSpeakerOnly";
  34:                 break;
  35:             }
  36:         case AudioRoutingEndpoint.BluetoothWithNoiseAndEchoCancellation:
  37:             {
  38:                 txtActual = "BluetoothWithNoiseAndEchoCancellation";
  39:                 break;
  40:             }
  41:         default:
  42:             throw new ArgumentOutOfRangeException();
  43:     }
  44:  }

 

Nel mio caso come potete vedere ho gestito tutti I casi possibili per poter verificare tutte le casistiche possibili all’interno della applicazione.

Una volta lanciata la applicazione è sufficiente inserire una auricolare o disinserirla per vedere un messaggio corrispondente indicante lo stato attuale.

wp_ss_20130915_0003

ATTENZIONE: ho effettuato test su device GDR1 e GDR2, benchè l’applicazione giri correttamente su tutti I device, su GDR1 NON vedrete cambiare I valori visualizzati.

Non ho idea del perchè non funzioni, visto che le API del VOIP sono implementate e funzionanti fin dall’uscita di WP8.

Ovviamente quanto detto si applica SOLO a device WP8.

Potete trovare I sorgenti dell’applicazione di esempio a questo link.