Chiamare ed intercettare una chiamata

15 novembre 2014

Nella lezione precedente abbiamo imparato ad accedere allo storico delle chiamate. In questo capitolo vedremo come si può inoltrare una chiamata dalla propria app ed ottenere i dati delle telefonate in arrivo.

Nonostante si tratti di due casistiche differenti, le classi predisposte nel framework sono in buona parte le stesse; pertanto, i due argomenti potranno essere affrontati insieme.

Classi e strumenti per la telefonia

Sfrutteremo le classi messe a disposizione dal sottosistema Telephony del framework Android. Particolarmente utili saranno:

  • TelephonyManager: ogni sottosistema Android viene utilizzato mediante un system service, al quale si accede tramite Context. Questo ci fornirà la controparte con cui dialogare dalla nostra app per interagire con la telefonia;
  • PhoneStateListener: è un listener in grado di intercettare la variazione di stato del sistema telefonico. Ci avvertirà se il telefono inizia a squillare, se c’è una chiamata in corso o se attualmente è inattivo. Sarà utilizzato sia relativamente alle chiamate in uscita, che per quanto riguarda quelle in entrata, e le fasi descritte saranno utili in entrambi i casi;
  • le costanti di stato: il TelephonyManager è dotato di una serie di costanti che identificano tutte le possibili situazioni. Anche le tre circostanze descritte al punto precedente corrispondono ad opportuni valori: CALL_STATE_RINGING (telefono squilla), CALL_STATE_OFFHOOK (telefonata in corso), CALL_STATE_IDLE (nessun evento in corso).

Altro elemento fondamentale, di cui si è già discusso nei capitoli precedenti, è il BroadcastReceiver. Riepilogando, si tratta di una delle quattro componenti delle applicazioni Android – oltre ad Activity, ContentProvider e Service – ed ha la caratteristica di rimanere “in attesa” finché qualche evento lo sveglia. Quando ciò si verifica, il BroadcastReceiver attiva un metodo – l’unico che normalmente il programmatore deve implementare – denominato onReceive. Nell’AndroidManifest della nostra app saremo noi a specificare quale evento riattiverà il BroadcastReceiver, mediante un apposito IntentFilter che sarà connotato da una specifica action.

Le permission necessarie

Come abbiamo già fatto diverse volte nei capitoli precedenti, dovremo anche in questo caso dichiarare le necessarie permission ogni volta che la nostra app effettua meccanismi di comunicazione particolari. Anche la telefonia ricade in questa casistica, pertanto alcune permission saranno necessarie.

Negli esempi successivi se ne renderanno utili due in particolare:

  • una necessaria per effettuare chiamate dall’app:
    <uses-permission android:name=”android.permission.CALL_PHONE”/>
  • un’altra per poter leggere lo stato del sistema telefonico, ed ottenere i dettagli della telefonata (in partenza o in arrivo):
    <uses-permission android:name=”android.permission.READ_PHONE_STATE”/>

Effettuare una chiamata

Inizieremo con l’imparare ad effettuare telefonate direttamente dalla nostra app. Utilizziamo un layout molto elementare: totalmente vuoto e con un solo pulsante al centro. Il funzionamento che vogliamo applicare consiste nell’inoltro di una chiamata ad un numero prestabilito, che sarà associato al click sul pulsante. Il recapito telefonico da contattare sarà definito in una stringa.

Il file del layout (res/layout/activity_main.xml) è il seguente:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<Button  
	    android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_centerInParent="true"
    	android:text="Invia"
    	android:onClick="invio"/>
</RelativeLayout>

All’interno dell’Activity predisporremo due metodi – onCreate ed il metodo denominato invio per l’inoltro della telefonata – ed una classe interna, estensione di PhoneStateListener per il controllo della chiamata.

public class MainActivity extends Activity 
{
		@Override
		protected void onCreate(Bundle savedInstanceState) 
		{
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
			telephonyManager.listen(new Listener(),PhoneStateListener.LISTEN_CALL_STATE);
		}
		
		public void invio(View v)
		{
			Intent callIntent = new Intent(Intent.ACTION_CALL);
			callIntent.setData(Uri.parse("tel:0611223344"));
			startActivity(callIntent);
		}
		
		private class Listener extends PhoneStateListener
		{
			@Override
			public void onCallStateChanged(int state, String incomingNumber) 
			{
				switch (state) 
				{
				case TelephonyManager.CALL_STATE_OFFHOOK:
	         		Log.i("CHIAMATA IN USCITA",   "TERMINALE IMPEGNATO");
	         		break;
	         		
	         	case TelephonyManager.CALL_STATE_IDLE:
	         		Log.i("CHIAMATA IN USCITA",   "IDLE");
				
				}
			}
		}
		
}

La vera e propria chiamata è effettuata dall’Intent. Come al solito questo potente meccanismo di sistema può attivare una funzionalità – in questo caso la chiamata – semplicemente richiedendo un’azione (Intent.ACTION_CALL) e inserendo nei dati a corredo il numero da contattare (nell’esempio precedente, tel:0611223344).

Si noti che l’invocazione al TelephonyManager nel metodo onCreate non è quella che consente di effettuare la chiamata, ma serve solo per la registrazione del listener. Quest’ultimo ci è d’aiuto per capire il momento esatto in cui il nostro terminale diventa occupato (cioè quando viene registrato un evento di CALL_STATE_OFFHOOK). Quando si ritornerà al successivo stato CALL_STATE_IDLE, non ci sarà più alcuna chiamata in corso. La stringa incomingNumber in questi casi sarà sempre vuota.

In questo esempio, le permission indicate in precedenza servono entrambe: una perché si effettua la chiamata, l’altra per potere consultare lo stato del telefono.

Intercettare chiamate in arrivo

Vediamo ora come intercettare una chiamata in arrivo, ed ottenerne il recapito telefonico di provenienza utilizzando solo un BroadcastReceiver.

Per fare ciò creeremo una classe denominata IncomingReceiver, che sarà registrata nel file AndroidManifest.xml:

        <receiver android:name=".IncomingReceiver">   
                 <intent-filter>
                    <action android:name="android.intent.action.PHONE_STATE" />
                 </intent-filter>
        </receiver>

L’implementazione è la seguente:

public class IncomingReceiver extends BroadcastReceiver
{
	
	@Override
	public void onReceive(Context context, Intent intent) 
	{
		TelephonyManager manager = (TelephonyManager) context
                     .getSystemService(Context.TELEPHONY_SERVICE);
                     
         Listener PhoneListener = new Listener();
             
         manager.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
     
     

 }

 private class Listener extends PhoneStateListener 
 {

     public void onCallStateChanged(int state, String incomingNumber) 
     {
    	 switch(state)
         {
         	case TelephonyManager.CALL_STATE_RINGING: 
         		 Log.d("CHIAMATA",   "SQUILLO DA "+incomingNumber);
	             break;
         	case TelephonyManager.CALL_STATE_OFFHOOK:
         		Log.d("CHIAMATA",   "RISPOSTO");
         		break;
         		
         	case TelephonyManager.CALL_STATE_IDLE:
         		Log.d("CHIAMATA",   "IDLE");
         }
     }
	}
	
}

Come si vede è necessario estendere la classe BroadcastReceiver ed implementi il metodo onReceive che sarà eseguito al momento della chiamata in ingresso.

Anche in questo caso, il TelephonyManager è richiesto per registrare il listener. In questo caso esso servirà a recuperare i dettagli relativi alla chiamata in entrata, tramite la lettura degli stati del sistema telefonico.

All’interno del listener, la stringa incomingNumber non sarà vuota, bensì valorizzata con il numero che ci sta chiamando.

Quando il nostro telefono inizia a squillare, il nostro terminale entra nello stato CALL_STATE_RINGING. Se rifiuteremo la chiamata passeremo ancora a CALL_STATE_IDLE, altrimenti quando la conversazione verrà accettata, lo stato rilevato sarà CALL_STATE_OFFHOOK.

Per quest’ultimo esempio, la sola permission richiesta è android.permission.READ_PHONE_STATE.

Tutte le lezioni

1 ... 56 57 58 ... 80

Se vuoi aggiornamenti su Chiamare ed intercettare una chiamata inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Chiamare ed intercettare una chiamata

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy