Come effettuare chiamate e utilizzare SMS nelle app Android

In questo tutorial, imparerai a conoscere la Telefonia Android e l'API SMS. Imparerai come effettuare una chiamata dalla tua app e come monitorare gli eventi di chiamata telefonica, nonché come inviare e ricevere SMS.

1. Come fare una chiamata 

Per iniziare, ti mostrerò come avviare una chiamata dalla tua applicazione utilizzando l'app di composizione telefonica o direttamente dalla tua app per rendere più semplice per i tuoi utenti.

Crea un nuovo progetto per Android Studio

Avvia Android Studio e crea un nuovo progetto con un'attività vuota chiamata Attività principale.


Lay Out the Screen

Per ora, il nostro layout avrà solo un Modifica il testo campo e a Comporre pulsante:

   

Modifica il Attività principale Classe

Nel blocco di codice qui sotto, stiamo creando un ACTION_DIAL intenzione di visualizzare il dialer telefonico. Il numero di telefono è analizzato dal nostro tel Schema URI: tel: XXXXXXXX. Tieni presente che non hai bisogno di alcuna autorizzazione perché funzioni:

import android.content.Intent; import android.net.Uri; importare android.os.Bundle; import android.support.v7.app.AppCompatActivity; importare android.text.TextUtils; importa android.view.View; importa android.widget.Button; importare android.widget.EditText; importare android.widget.Toast; public class MainActivity estende AppCompatActivity @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); Pulsante mDialButton = (Button) findViewById (R.id.btn_dial); final EditText mPhoneNoEt = (EditText) findViewById (R.id.et_phone_no); mDialButton.setOnClickListener (new View.OnClickListener () @Override public void onClick (Visualizza vista) String phoneNo = mPhoneNoEt.getText (). toString (); if (! TextUtils.isEmpty (phoneNo)) String dial = "tel : "+ phoneNo; startActivity (new Intent (Intent.ACTION_DIAL, Uri.parse (dial))); else Toast.makeText (MainActivity.questo," Immettere un numero di telefono ", Toast.LENGTH_SHORT) .show (); ); 

Se esegui l'app e fai clic sul pulsante di composizione, verrai indirizzato all'app Dialer e da lì dovrai effettivamente comporre il numero. Puoi cambiare questo flusso per effettuare effettivamente la chiamata dalla tua app semplicemente cambiando la ACTION_DIAL intento a ACTION_CALL anziché. Ciò richiederà il android.permission.CALL_PHONE permesso, però. 

2. Monitoraggio degli eventi di chiamata telefonica

In questa sezione, impareremo come monitorare gli eventi di chiamata telefonica nel sistema Android. Il telefono può essere in tre stati: 

  1. inattivo (quando non è utilizzato)
  2. suoneria (quando c'è una chiamata in arrivo)
  3. sganciato (quando si risponde alla chiamata)

Aggiungi l'autorizzazione 

Abbiamo bisogno del permesso READ_PHONE_STATE essere in grado di monitorare lo stato del telefono. Aggiungilo a AndroidManifest.xml:

Crea il PhoneStateListener Oggetto

Creiamo un oggetto di PhoneStateListener classe, e quindi eseguirne l'override onCallStateChanged () metodo (in IntelliJ è facile farlo con Control-O, e quindi selezionare o cercare il metodo da sovrascrivere). Gestiremo le modifiche alle modifiche allo stato della chiamata visualizzando a Crostini. Tieni presente che possiamo anche accedere ai numeri di telefono in entrata quando viene attivato questo metodo:

// ... PhoneStateListener mPhoneStateListener = new PhoneStateListener () @Override public void onCallStateChanged (stato int, String incomingNumber) super.onCallStateChanged (stato, incomingNumber); switch (state) case TelephonyManager.CALL_STATE_IDLE: Toast.makeText (MainActivity.this, "CALL_STATE_IDLE", Toast.LENGTH_SHORT) .show (); rompere; case TelephonyManager.CALL_STATE_RINGING: Toast.makeText (MainActivity.this, "CALL_STATE_RINGING", Toast.LENGTH_SHORT) .show (); rompere; case TelephonyManager.CALL_STATE_OFFHOOK: Toast.makeText (MainActivity.this, "CALL_STATE_OFFHOOK", Toast.LENGTH_SHORT) .show (); rompere; ; // ... 

A seconda delle esigenze dell'applicazione, è anche possibile sovrascrivere uno di questi altri metodi di evento: onCellInfoChanged ()onCallForwardingIndicatorChanged ()onCellLocationChanged (), o onSignalStrengthChanged ().

Ascoltando lo stato della chiamata del telefono

Per iniziare ad ascoltare lo stato della telefonata, abbiamo bisogno di ottenere il TelephonyManager dal servizio di sistema e inizializzarlo onCreate ().

// ... private TelephonyManager mTelephonyManager; @Override protected void onCreate (Bundle savedInstanceState) // ... mTelephonyManager = (TelephonyManager) getSystemService (getApplicationContext (). TELEPHONY_SERVICE); 

Nel onResume () metodo, possiamo iniziare ad ascoltare usando il TelephonyManager ascolta() metodo, passando il PhoneStateListener istanza e statica LISTEN_CALL_STATE. Smettiamo di ascoltare nel onStop () metodo passando il LISTEN_NONE come secondo argomento di ascolta().

// ... @Override protected void onResume () super.onResume (); mTelephonyManager.listen (mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);  @Override protected void onStop () super.onStop (); mTelephonyManager.listen (mPhoneStateListener, PhoneStateListener.LISTEN_NONE);  // ... 

Altre opzioni di ascolto del telefono sono possibili LISTEN_CELL_LOCATIONLISTEN_SIGNAL_STRENGTHLISTEN_CALL_FORWARDING_INDICATOR, e LISTEN_CELL_INFO.

Infine, avvia l'app e assicurati che arrivi una chiamata in arrivo. 

Questo monitoraggio funziona solo quando l'app è in primo piano. Affinché ciò funzioni in background (quando la nostra applicazione non è in esecuzione), avremmo bisogno di creare un BroadcastReceiver in modo che anche se l'app non è in esecuzione, possiamo ancora monitorare gli stati delle chiamate telefoniche. A seconda dei requisiti dell'app, questo potrebbe essere un modo molto migliore per ascoltare le modifiche allo stato delle telefonate. Ti mostrerò come farlo nella prossima sezione.

Tieni presente che stiamo monitorando solo le chiamate in arrivo. Per noi per monitorare le chiamate in uscita, abbiamo bisogno di ulteriori permessi. Per monitorare le chiamate in uscita, includi la seguente riga nel tuo AndroidManifest.xml file.

 

Come utilizzare l'emulatore per effettuare chiamate e inviare messaggi SMS

È possibile utilizzare il proprio emulatore per simulare effettuare una chiamata o inviare un messaggio SMS, ma è necessario eseguire una piccola configurazione. Apri l'emulatore, fai clic sull'ultimo pulsante sulla barra di navigazione a destra per aprire la finestra di dialogo di controllo estesa, quindi seleziona il pulsante di controllo del telefono. 

3. Monitoraggio degli eventi di chiamata telefonica in background

Crea un BroadcastReceiver

Proprio come nella sezione precedente, dobbiamo creare un listener di eventi per monitorare le modifiche dello stato del telefono. La differenza principale è che questa volta estenderemo il BroadcastReceiver classe base in modo che possiamo ascoltare lo stato della telefonata anche se l'applicazione non è in esecuzione. Assicurati di non registrare l'ascoltatore più di una volta! Il nostro controllo per questo è sulla linea 36.

importare android.content.BroadcastReceiver; importare android.content.Context; import android.content.Intent; import android.telephony.PhoneStateListener; importare android.telephony.TelephonyManager; importare android.widget.Toast; public class PhoneCallStateReceiver estende BroadcastReceiver private TelephonyManager mTelephonyManager; public static boolean isListening = false; @Override public void onReceive (contesto Context finale, Intent intent) mTelephonyManager = (TelephonyManager) context.getSystemService (context.TELEPHONY_SERVICE); PhoneStateListener mPhoneStateListener = new PhoneStateListener () @Override public void onCallStateChanged (stato int, String incomingNumber) super.onCallStateChanged (stato, incomingNumber); switch (state) case TelephonyManager.CALL_STATE_IDLE: Toast.makeText (context, "CALL_STATE_IDLE", Toast.LENGTH_SHORT) .show (); rompere; case TelephonyManager.CALL_STATE_RINGING: Toast.makeText (context, "CALL_STATE_RINGING", Toast.LENGTH_SHORT) .show (); rompere; case TelephonyManager.CALL_STATE_OFFHOOK: Toast.makeText (context, "CALL_STATE_OFFHOOK", Toast.LENGTH_SHORT) .show (); rompere; ; if (! isListening) mTelephonyManager.listen (mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); isListening = true; 

Modificare AndroidManifest.xml

Un ricevitore broadcast funziona solo se è registrato. Abbiamo bisogno di dire al sistema Android del nostro ricevitore di trasmissione registrandolo nel AndroidManifest.xml file collegando il nostro PhoneCallStateReceiver classe al che descrive la trasmissione di sistema che desideriamo ricevere, in questo caso, PHONE_STATE.

    

Monitoraggio delle chiamate in uscita

Per le chiamate in uscita, è necessario includere il NEW_OUTGOING_CALL intento d'azione  nel del ricevitore in AndroidManifest.xml

Per ottenere il numero di telefono della chiamata in uscita, all'interno del onReceive (Context, Intent) metodo, otteniamo il numero dall'intenzione come un extra. Per evitare che quella chiamata intenzionale passi attraverso, possiamo chiamare setResultData () e passargli un argomento nullo. Il resultData viene utilizzato come numero effettivo da chiamare. 

@Override public void onReceive (contesto Context finale, Intent intent) // per la chiamata in uscita String outgoingPhoneNo = intent.getStringExtra (Intent.EXTRA_PHONE_NUMBER) .toString (); // impedisce la chiamata in uscita setResultData (null); 

Puoi saperne di più su trasmissioni e ricevitori broadcast nel nostro tutorial qui su Envato Tuts +:

4. Invio di messaggi SMS

Hai solo due scelte principali per l'invio di SMS: utilizzando l'applicazione client SMS del dispositivo o ignorando il client inviando l'SMS direttamente dalla tua app. Analizzeremo entrambi gli scenari e potrai decidere quale è il migliore per il tuo caso d'uso. Iniziamo inviando un SMS utilizzando il client SMS del dispositivo.

Imposta il layout

Per prima cosa, dobbiamo modificare il nostro layout principale per avere un Modifica il testo campo per il messaggio e a Invia messaggio pulsante.

  

Modifica la MainActivity 

Dentro il nostro onCreate () metodo nel nostro Attività principale classe, creare un intento con ACTION_SENDTO come il primo argomento e a smsto: URI come secondo argomento. Il messaggio di testo sarà il valore del sms_body extra: 

// ... Button sendMessageBtn = (Button) findViewById (R.id.btn_send_message); final EditText messagetEt = (EditText) findViewById (R.id.et_message); sendMessageBtn.setOnClickListener (new View.OnClickListener () @Override public void onClick (Visualizza vista) String message = messagetEt.getText (). toString (); String PhoneNo = mPhoneNoEt.getText (). toString (); if (! TextUtils.isEmpty (message) &&! TextUtils.isEmpty (phoneNo)) Intent smsIntent = new Intent (Intent.ACTION_SENDTO, Uri.parse ("smsto:" + phoneNo)); smsIntent.putExtra ("sms_body", messaggio); startActivity (smsIntent);); // ... 

Qui, il client SMS monitorerà lo stato del recapito dei messaggi. 

Esegui l'app

Quando vengono inseriti tutti i campi richiesti, fare clic su Inviare SMS il pulsante aprirà il client SMS dell'utente o darà all'utente le opzioni per selezionare un'app se non è già stata scelta.

5. Invio di messaggi SMS direttamente

Vediamo ora come inviare gli SMS direttamente dalla nostra applicazione invece di utilizzare il client SMS del dispositivo. 

Aggiungi autorizzazione in AndroidManifest.xml

Come al solito, dobbiamo registrare il permesso in AndroidManifest.xml.

 

Modifica la classe MainActivity 

Successivamente, per Android 6.0 (livello API 23) e versioni successive, è necessario richiedere il file INVIARE SMS permesso durante il runtime. 

Per ulteriori informazioni sulle autorizzazioni di runtime di Android e su come sono cambiate nella versione 6.0, consulta il nostro tutorial qui su Envato Tuts +:

Per inviare un SMS, otteniamo il valore predefinito SmsManager istanza e poi chiama il suo invia un messaggio di testo() metodo, passando il numero di telefono come primo argomento e il messaggio come secondo argomento:

// ... final int SEND_SMS_PERMISSION_REQUEST_CODE = 111; Pulsante privato mSendMessageBtn; @Override protected void onCreate (Bundle savedInstanceState) // ... mSendMessageBtn = (Button) findViewById (R.id.btn_send_message); final EditText messagetEt = (EditText) findViewById (R.id.et_message); mSendMessageBtn.setEnabled (false); if (checkPermission (Manifest.permission.SEND_SMS)) mSendMessageBtn.setEnabled (true);  else ActivityCompat.requestPermissions (this, new String [] Manifest.permission.SEND_SMS, SEND_SMS_PERMISSION_REQUEST_CODE);  mSendMessageBtn.setOnClickListener (new View.OnClickListener () @Override public void onClick (Visualizza vista) String message = messagetEt.getText (). toString (); String PhoneNo = mPhoneNoEt.getText (). toString (); if ( ! TextUtils.isEmpty (messaggio) &&! TextUtils.isEmpty (phoneNo)) if (checkPermission (Manifest.permission.SEND_SMS)) SmsManager smsManager = SmsManager.getDefault (); smsManager.sendTextMessage (phoneNo, null, message, null, null); else Toast.makeText (MainActivity.this, "Autorizzazione negata", Toast.LENGTH_SHORT) .show (););  private boolean checkPermission (autorizzazione String) int checkPermission = ContextCompat.checkSelfPermission (questa autorizzazione); return (checkPermission == PackageManager.PERMISSION_GRANTED);  @Override public void onRequestPermissionsResult (int requestCode, @NonNull String [] autorizzazioni, @NonNull int [] grantResults) switch (requestCode) caso SEND_SMS_PERMISSION_REQUEST_CODE: if (grantResults.length> 0 && (grantResults [0] == PackageManager .PERMISSION_GRANTED)) mSendMessageBtn.setEnabled (true);  ritorno;  // ... 

Per monitorare lo stato di consegna, il SMSManager invia un messaggio di testo() il metodo ha due facoltativi PendingIntent parametri: sentIntent e deliveryIntent.

void sendTextMessage (String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)

Se vuoi usarlo sentIntent, guarda il codice del risultato Activity.RESULT_OK sul successo, o su uno di RESULT_ERROR_GENERIC_FAILURERESULT_ERROR_RADIO_OFF, e RESULT_ERROR_NULL_PDU per indicare un errore.

6. Ricezione di un messaggio SMS

Affinché la tua app inizi a ricevere i messaggi SMS dal telefono dell'utente, è meglio avere un destinatario della trasmissione registrato in modo che possa essere avvisato quando arriva un nuovo SMS anche se la tua app non è in esecuzione in primo piano. 

Aggiungi l'autorizzazione 

Aggiungi il RECEIVE_SMS permesso di AndroidManifest.xml:

Successivamente, dobbiamo verificare e vedere se l'app ha il permesso di ricevere messaggi SMS in fase di runtime. Quindi nel Attività principale classe, controlla per il RECEIVE_SMS autorizzazione. Se non viene trovato, richiederlo.

// ... @Override void onCreate protetto (Bundle savedInstanceState) // ... if (! CheckPermission (Manifest.permission.RECEIVE_SMS)) ActivityCompat.requestPermissions (this, new String [] Manifest.permission.RECEIVE_SMS, 222);  // ... 

Creare un ricevitore Broadcast

Stiamo recuperando ogni oggetto del smsmessage classe usando il metodo createFromPdu (byte [] pdu), passandogli una PDU (unità di dati del protocollo). Lo aggiungeremo quindi al nostro array di messaggi. 

Per supportare API 23 e versioni successive, è necessario includere il formato String extra ("3gpp" per i messaggi GSM / UMTS / LTE in formato 3GPP o "3gpp2" per i messaggi CDMA / LTE in formato 3GPP2). 

importare android.content.BroadcastReceiver; importare android.content.Context; import android.content.Intent; importa android.os.Build; importare android.os.Bundle; import android.telephony.SmsMessage; importare android.widget.Toast; public class SMSReceiver estende BroadcastReceiver @Override public void onReceive (Context context, Intent intent) Bundle bundle = intent.getExtras (); if (bundle! = null) Object [] pdus = (Object []) bundle.get ("pdus"); Formato stringa = bundle.getString ("format"); messaggi finali SmsMessage [] = nuovo SmsMessage [pdus.length]; per (int i = 0; i < pdus.length; i++)  if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) messages [i] = SmsMessage.createFromPdu ((byte []) pdus [i], formato);  else messages [i] = SmsMessage.createFromPdu ((byte []) pdus [i]);  String senderPhoneNo = messages [i] .getDisplayOriginatingAddress (); Toast.makeText (context, "Message" + messages [0] .getMessageBody () + ", from" + senderPhoneNo, Toast.LENGTH_SHORT) .show (); 

Ora esegui l'app, chiudila e invia un SMS al tuo telefono emulato.

Conclusione

In questo tutorial, hai imparato a conoscere:

  • effettuare una chiamata dalla tua app
  • monitoraggio degli eventi di chiamata telefonica
  • inviare messaggi SMS utilizzando l'app di messaggistica del dispositivo o direttamente dalla propria app
  • ricevere messaggi SMS in background

C'è molto di più che puoi fare con le telefonate e gli SMS in Android. Visita l'API Telefonia Android e la documentazione dell'API di SMSManager per ulteriori informazioni. 

Nel frattempo, dai uno sguardo ad alcuni dei nostri altri post sullo sviluppo di Android!

  • Sensori Android in profondità: prossimità e giroscopio

    Giroscopi e sensori di prossimità sono oggi disponibili sulla maggior parte dei telefoni Android. Usandoli in modo creativo, puoi aggiungere una nuova dimensione al tuo utente ...
    Ashraff Hathibelagal
    SDK Android
  • 6 Cosa fare e cosa non fare per una grande esperienza utente Android

    Le app Android più popolari hanno qualcosa in comune: offrono un'esperienza utente eccezionale. In questo post, condividerò alcuni suggerimenti che aiuteranno la tua app ...
    Jessica Thornsby
    SDK Android
  • Audio di sottofondo in Android con MediaSessionCompat

    Uno degli usi più popolari per i dispositivi mobili è la riproduzione audio attraverso servizi di streaming musicale, podcast scaricati o qualsiasi altro numero di audio ...
    Paul Trebilcox-Ruiz
    SDK Android
  • Migrare un'app Android a Material Design

    Anni fa, quando Android era ancora un sistema operativo mobile in erba, era piuttosto noto per la sua brutta interfaccia utente. Perché non c'erano progetti ...
    Ashraff Hathibelagal
    androide