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.
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.
Avvia Android Studio e crea un nuovo progetto con un'attività vuota chiamata Attività principale
.
Per ora, il nostro layout avrà solo un Modifica il testo
campo e a Comporre pulsante:
Attività principale
ClasseNel 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ò.
In questa sezione, impareremo come monitorare gli eventi di chiamata telefonica nel sistema Android. Il telefono può essere in tre stati:
Abbiamo bisogno del permesso READ_PHONE_STATE
essere in grado di monitorare lo stato del telefono. Aggiungilo a AndroidManifest.xml:
PhoneStateListener
OggettoCreiamo 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 ()
.
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_LOCATION
, LISTEN_SIGNAL_STRENGTH
, LISTEN_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.
È 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.
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;
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
.
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 +:
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.
Per prima cosa, dobbiamo modificare il nostro layout principale per avere un Modifica il testo
campo per il messaggio e a Invia messaggio pulsante.
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.
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.
Vediamo ora come inviare gli SMS direttamente dalla nostra applicazione invece di utilizzare il client SMS del dispositivo.
Come al solito, dobbiamo registrare il permesso in AndroidManifest.xml.
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_FAILURE
, RESULT_ERROR_RADIO_OFF
, e RESULT_ERROR_NULL_PDU
per indicare un errore.
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 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); // ...
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.
In questo tutorial, hai imparato a conoscere:
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!