In deze zelfstudie leert u meer over de Android-telefonie en SMS-API. U leert hoe u belt vanuit uw app en hoe u telefoonoproepgebeurtenissen controleert en hoe u sms-berichten kunt verzenden en ontvangen.
Om te beginnen, laat ik u zien hoe u een oproep vanuit uw toepassing kunt starten door de telefoonkiezer-app of rechtstreeks vanuit uw app te gebruiken om het uw gebruikers gemakkelijker te maken.
Start Android Studio en maak een nieuw project met een lege activiteit genaamd Hoofdactiviteit
.
Voor nu heeft onze lay-out gewoon een Tekst bewerken
veld en een Wijzerplaat knop:
Hoofdactiviteit
KlasseIn het onderstaande codeblok maken we een ACTION_DIAL
bedoeling om de telefoonkiezer weer te geven. Het telefoonnummer wordt geparseerd vanuit onze tel
URI-schema: tel: XXXXXXXX
. Merk op dat u hiervoor geen toestemming nodig heeft om te werken:
importeer android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; importeer android.text.TextUtils; import android.view.View; importeer android.widget.Button; importeer android.widget.EditText; import android.widget.Toast; public class MainActivity breidt AppCompatActivity uit @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); Knop mDialButton = (Knop) findViewById (R.id.btn_dial); final EditText mPhoneNoEt = (EditText) findViewById (R.id.et_phone_no); mDialButton.setOnClickListener (nieuwe View.OnClickListener () @Override public void onClick (View view) 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.this," Voer een telefoonnummer in ", Toast.LENGTH_SHORT) .show (); );
Als u de app uitvoert en op de knop klikt, wordt u naar de dialer-app geleid en vanaf daar moet u het nummer daadwerkelijk bellen. U kunt deze stroom wijzigen om de oproep vanuit uw app daadwerkelijk te voeren door simpelweg de ACTION_DIAL
bedoeling om ACTION_CALL
in plaats daarvan. Dit vereist de android.permission.CALL_PHONE
toestemming.
In dit gedeelte gaan we leren hoe we telefoonoproepgebeurtenissen in het Android-systeem kunnen volgen. De telefoon kan in drie staten zijn:
We hebben de toestemming nodig READ_PHONE_STATE
om de telefoonstatus te kunnen controleren. Voeg het toe aan AndroidManifest.xml:
PhoneStateListener
VoorwerpWe maken een object van de PhoneStateListener
klasse en negeer de bijbehorende onCallStateChanged ()
methode (in IntelliJ is dit eenvoudig om mee te doen Ctrl-O, en selecteer dan of zoek naar de methode om te negeren). We behandelen wijzigingen in de statuswijzigingen door een a weer te geven Geroosterd brood
. Houd er rekening mee dat we ook toegang kunnen krijgen tot de inkomende telefoonnummers wanneer deze methode wordt geactiveerd:
// ... PhoneStateListener mPhoneStateListener = new PhoneStateListener () @Override public void onCallStateChanged (int state, String incoming Number) super.onCallStateChanged (state, incomingNumber); switch (state) case TelephonyManager.CALL_STATE_IDLE: Toast.makeText (MainActivity.this, "CALL_STATE_IDLE", Toast.LENGTH_SHORT) .show (); breken; case TelephonyManager.CALL_STATE_RINGING: Toast.makeText (MainActivity.this, "CALL_STATE_RINGING", Toast.LENGTH_SHORT) .show (); breken; case TelephonyManager.CALL_STATE_OFFHOOK: Toast.makeText (MainActivity.this, "CALL_STATE_OFFHOOK", Toast.LENGTH_SHORT) .show (); breken; ; // ...
Afhankelijk van uw toepassingsbehoeften, kunt u ook een van deze andere evenementmethoden overschrijven: onCellInfoChanged ()
, onCallForwardingIndicatorChanged ()
, onCellLocationChanged ()
, of onSignalStrengthChanged ()
.
Om te beginnen met luisteren naar de status van het telefoongesprek, moeten we de TelephonyManager
van de systeemservice en initialiseer het in onCreate ()
.
// ... private TelephonyManager mTelephonyManager; @Override protected void onCreate (Bundle savedInstanceState) // ... mTelephonyManager = (TelephonyManager) getSystemService (getApplicationContext (). TELEPHONY_SERVICE);
In de onResume ()
methode, kunnen we beginnen te luisteren met behulp van de TelephonyManager
luister()
methode, het doorgeven van de PhoneStateListener
instantie en de statische LISTEN_CALL_STATE
. We stoppen met luisteren in de onStop ()
methode door de LISTEN_NONE
als het tweede argument voor luister()
.
// ... @Override beschermde leegte onResume () super.onResume (); mTelephonyManager.listen (mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); @Override beschermde ongeldig onStop () super.onStop (); mTelephonyManager.listen (mPhoneStateListener, PhoneStateListener.LISTEN_NONE); // ...
Andere telefoonbeluisteropties zijn mogelijk LISTEN_CELL_LOCATION
, LISTEN_SIGNAL_STRENGTH
, LISTEN_CALL_FORWARDING_INDICATOR
, en LISTEN_CELL_INFO
.
Eindelijk, voer de app uit en zorg ervoor dat er een binnenkomend gesprek binnenkomt.
Deze monitoring werkt alleen als de app op de voorgrond staat. Om dit op de achtergrond te laten werken (als onze applicatie niet actief is), moeten we een Uitzending ontvanger
zodat zelfs als de app niet actief is, we nog steeds kunnen controleren op telefoongesprekken. Afhankelijk van uw app-vereisten, zou dat een veel betere manier kunnen zijn om te luisteren naar statuswijzigingen van telefoongesprekken. Ik zal je laten zien hoe je dit in het volgende gedeelte kunt doen.
Houd er rekening mee dat we alleen inkomende oproepen controleren. Voor ons om uitgaande oproepen te controleren, hebben we extra rechten nodig. Als u uitgaande oproepen wilt controleren, neemt u de volgende regel op in uw AndroidManifest.xml het dossier.
U kunt uw emulator gebruiken om te simuleren om te bellen of een SMS-bericht te verzenden, maar u moet wel een beetje instellen. Open uw emulator, klik op de laatste knop op de navigatiebalk aan de rechterkant om het uitgebreide besturingsvenster te openen en selecteer vervolgens de regelknop voor de telefoon.
Net als in het vorige gedeelte moeten we een gebeurtenislistener maken om wijzigingen in de telefoonstatus te controleren. Het grote verschil is dat we deze keer de Uitzending ontvanger
basisklasse, zodat we kunnen luisteren naar de status van het telefoongesprek, zelfs als de toepassing niet actief is. Zorg ervoor dat u de luisteraar niet meerdere keren registreert! Onze controle hierop is op regel 36.
import android.content.BroadcastReceiver; importeer android.content.Context; importeer android.content.Intent; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.widget.Toast; openbare klasse PhoneCallStateReceiver breidt BroadcastReceiver uit private TelephonyManager mTelephonyManager; public static boolean isListening = false; @Override public void onReceive (laatste context context, Intent opzet) mTelephonyManager = (TelephonyManager) context.getSystemService (context.TELEPHONY_SERVICE); PhoneStateListener mPhoneStateListener = new PhoneStateListener () @Override public void onCallStateChanged (int state, String incoming Number) super.onCallStateChanged (state, incomingNumber); switch (state) case TelephonyManager.CALL_STATE_IDLE: Toast.makeText (context, "CALL_STATE_IDLE", Toast.LENGTH_SHORT) .show (); breken; case TelephonyManager.CALL_STATE_RINGING: Toast.makeText (context, "CALL_STATE_RINGING", Toast.LENGTH_SHORT) .show (); breken; case TelephonyManager.CALL_STATE_OFFHOOK: Toast.makeText (context, "CALL_STATE_OFFHOOK", Toast.LENGTH_SHORT) .show (); breken; ; if (! isListening) mTelephonyManager.listen (mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); isListening = true;
Een uitzendontvanger werkt alleen als deze is geregistreerd. We moeten het Android-systeem vertellen over onze uitzendontvanger door het te registreren in de AndroidManifest.xml bestand door ons te verbinden PhoneCallStateReceiver
klasse voor de
die de systeemuitzending beschrijft die we willen ontvangen, in dit geval, PHONE_STATE
.
Voor uitgaande oproepen moet u de NEW_OUTGOING_CALL
actie opzet
in de
van de ontvanger in AndroidManifest.xml.
Om het telefoonnummer van de geplande uitgaande oproep te krijgen, in de onReceive (Context, Intent)
methode, we krijgen het nummer van de intentie als een extra. Om te voorkomen dat de bedoelde oproep doorkomt, kunnen we bellen setResultData ()
en geef het een nul argument. De resultData
wordt gebruikt als het daadwerkelijke nummer om te bellen.
@Override public void onReceive (laatste context context, Intent opzet) // voor uitgaand gesprek String outgoingPhoneNo = intent.getStringExtra (Intent.EXTRA_PHONE_NUMBER) .toString (); // verhinder uitgaand gesprek setResultData (nul);
U kunt meer leren over uitzendingen en uitzendontvangers in onze tutorial hier op Envato Tuts +:
U hebt slechts twee belangrijke keuzes voor het verzenden van sms-berichten: het gebruik van de sms-clienttoepassing van het apparaat of het overslaan van de client door de sms rechtstreeks vanuit uw app te verzenden. We zullen beide scenario's bekijken en u kunt beslissen welke het beste is voor uw gebruik. Laten we beginnen met het verzenden van een sms met de SMS-client van het apparaat.
Ten eerste moeten we onze hoofdlay-out wijzigen om een Tekst bewerken
veld voor het bericht en een Bericht versturen knop.
In onze onCreate ()
methode in onze Hoofdactiviteit
klasse, maak een intentie aan met ACTION_SENDTO
als het eerste argument en een smsto:
URI als het tweede argument. Het SMS-bericht is de waarde van de 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 (View view) String message = messagetEt.getText (). toString (); String phoneNo = mPhoneNoEt.getText (). toString (); if (! TextUtils.isEmpty (bericht) &&! TextUtils.isEmpty (phoneNo)) Intent smsIntent = new Intent (Intent.ACTION_SENDTO, Uri.parse ("smsto:" + phoneNo)); smsIntent.putExtra ("sms_body", bericht); startActivity (smsIntent);); // ...
Hier controleert de SMS-client de status van de bezorging van het bericht.
Wanneer alle verplichte velden zijn ingevoerd, klikt u op Verstuur sms knop opent de SMS-client van de gebruiker of geeft de gebruiker opties om een app te selecteren als er nog geen is gekozen.
Laten we hierna eens kijken hoe we de sms direct vanuit onze applicatie kunnen verzenden in plaats van de sms-client van het apparaat te gebruiken.
Zoals gewoonlijk moeten we de toestemming registreren in AndroidManifest.xml.
Vervolgens moeten we voor Android 6.0 (API level 23) en hoger de VERSTUUR SMS
toestemming tijdens runtime.
Voor meer informatie over Android-runtimemachtigingen en hoe deze zijn gewijzigd in versie 6.0, raadpleegt u onze zelfstudie hier op Envato Tuts +:
Voor het verzenden van een sms krijgen we de standaard SmsManager
voorbeeld en bel dan de sendTextMessage ()
methode, waarbij het telefoonnummer als het eerste argument wordt doorgegeven en het bericht als het tweede argument:
// ... final int SEND_SMS_PERMISSION_REQUEST_CODE = 111; private Button 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 (View view) String message = messagetEt.getText (). toString (); String phoneNo = mPhoneNoEt.getText (). toString (); if ( ! TextUtils.isEmpty (bericht) &&! 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, "Toestemming geweigerd", Toast.LENGTH_SHORT) .show ();); private boolean checkPermission (String permission) int checkPermission = ContextCompat.checkSelfPermission (this, permission); return (checkPermission == PackageManager.PERMISSION_GRANTED); @Override public void onRequestPermissionsResult (int requestCode, @NonNull String [] permissies, @NonNull int [] grantResults) switch (requestCode) case SEND_SMS_PERMISSION_REQUEST_CODE: if (grantResults.length> 0 && (grantResults [0] == PackageManager .PERMISSION_GRANTED)) mSendMessageBtn.setEnabled (true); terug; // ...
Om de status van levering te controleren, de SMSManager
sendTextMessage ()
methode heeft twee optionele PendingIntent
parameters: sentIntent
en deliveryIntent
.
void sendTextMessage (String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)
Als je wilt gebruiken sentIntent
, let op de resultaatcode Activity.RESULT_OK
op succes, of een van RESULT_ERROR_GENERIC_FAILURE
, RESULT_ERROR_RADIO_OFF
, en RESULT_ERROR_NULL_PDU
om een fout aan te geven.
Om ervoor te zorgen dat uw app begint met het ontvangen van sms-berichten van de telefoon van de gebruiker, is het het beste om een uitzendontvanger geregistreerd te hebben zodat deze kan worden gewaarschuwd wanneer een nieuw sms-bericht binnenkomt, zelfs als uw app niet op de voorgrond wordt uitgevoerd.
Voeg de toe RECEIVE_SMS
toestemming om AndroidManifest.xml:
Vervolgens moeten we controleren of de app toestemming heeft om tijdens runtime sms-berichten te ontvangen. Dus in de Hoofdactiviteit
klas, kijk voor de RECEIVE_SMS
toestemming. Als het niet wordt gevonden, vraag het dan aan.
// ... @Override protected void onCreate (Bundle savedInstanceState) // ... if (! CheckPermission (Manifest.permission.RECEIVE_SMS)) ActivityCompat.requestPermissions (this, new String [] Manifest.permission.RECEIVE_SMS, 222); // ...
We halen elk object van de SmsMessage
klasse door de methode te gebruiken createFromPdu (byte [] pdu)
, het doorgeven van een PDU (protocol data-eenheid). We voegen het dan toe aan onze berichtenreeks.
Als u API 23 en hoger wilt ondersteunen, moet u de indeling String extra opnemen (ofwel "3gpp" voor GSM / UMTS / LTE-berichten in 3GPP-indeling of "3gpp2" voor CDMA / LTE-berichten in 3GPP2-indeling).
import android.content.BroadcastReceiver; importeer android.content.Context; importeer android.content.Intent; import android.os.Build; import android.os.Bundle; import android.telephony.SmsMessage; import android.widget.Toast; openbare klasse SMSReceiver breidt BroadcastReceiver uit @Overleden openbare ongeldig voor Ongewenst (Contextcontext, Intent opzet) Bundel bundle = intent.getExtras (); if (bundle! = null) Object [] pdus = (Object []) bundle.get ("pdus"); Tekenreeksindeling = bundle.getString ("indeling"); laatste SmsMessage [] berichten = nieuwe SmsMessage [pdus.length]; voor (int i = 0; i < pdus.length; i++) if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) messages [i] = SmsMessage.createFromPdu ((byte []) pdus [i], format); else messages [i] = SmsMessage.createFromPdu ((byte []) pdus [i]); String senderPhoneNo = berichten [i] .getDisplayOriginatingAddress (); Toast.makeText (context, "Message" + messages [0] .getMessageBody () + ", from" + senderPhoneNo, Toast.LENGTH_SHORT) .show ();
Start nu de app, sluit hem en verzend uw geëmuleerde telefoon een sms.
In deze tutorial leerde je over:
Er is veel meer dat u kunt doen met telefoontjes en sms-berichten in Android. Ga naar de Android Telephony API en de API-documentatie van SMSManager voor meer informatie.
Bekijk in de tussentijd enkele van onze andere berichten over Android-ontwikkeling!