Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 62 di 97
  • livello avanzato
Indice lezioni

Chiamare ed intercettare una chiamata

Come utilizzare il framework e le API di Android per ottenere informazioni sulle chiamate, o utilizzare la nostra app per effettuarle.
Come utilizzare il framework e le API di Android per ottenere informazioni sulle chiamate, o utilizzare la nostra app per effettuarle.
Link copiato negli appunti

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.

Ti consigliamo anche