Как это ни удивительно, SMS сообщений сегодня остаются одним из самых востребованных сервисов, что вполне объясняет интерес, проявляемый Android разработчики к этой тема. Из данного урока Вы узнаете, как программно отправлять и получать SMS сообщения. Будет показано, как провести тестирование приложения на эмуляторе.
Создайте в Eclipse новый проект со следующими параметрами:
Для того, чтобы наше прилоение могло работать с SMS, ему необходимо дать соответствующие разрешения: SEND_SMS для отправки и RECEIVE_SMS - для получения. Откройте файл AndroidManifest.xml и приведите его к виду:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.learn2develop.SMSMessaging" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".SMS" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.SEND_SMS"> </uses-permission> <uses-permission android:name="android.permission.RECEIVE_SMS"> </uses-permission> </manifest>
Настроим шаблон дизайна приложения. Откройте файл res/layout/main.xml и приведите его к виду
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Enter the phone number of recipient" /> <EditText android:id="@+id/txtPhoneNo" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Message" /> <EditText android:id="@+id/txtMessage" android:layout_width="fill_parent" android:layout_height="150px" android:gravity="top" /> <Button android:id="@+id/btnSendSMS" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Send SMS" /> </LinearLayout>
В результате у Вас должен получиться следующий шаблон:
Перейдем к редактированию кода. В SMS activity напишем обработчик нажатия на кнопку. После щелчка мы должны проверить введен ли номер телефона и текстовое сообщение. Если все в порядке, мы вызываем функцию sendSMS(), которая отправляет сообщение.
package net.learn2develop.SMSMessaging; import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.os.Bundle; import android.telephony.gsm.SmsManager; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; publicclass SMSextends Activity { Button btnSendSMS; EditText txtPhoneNo; EditText txtMessage; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnSendSMS=(Button) findViewById(R.id.btnSendSMS); txtPhoneNo=(EditText) findViewById(R.id.txtPhoneNo); txtMessage=(EditText) findViewById(R.id.txtMessage); btnSendSMS.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { String phoneNo= txtPhoneNo.getText().toString(); String message= txtMessage.getText().toString(); if(phoneNo.length()>0&& message.length()>0) sendSMS(phoneNo, message); else Toast.makeText(getBaseContext(), "Please enter both phone number and message.", Toast.LENGTH_SHORT).show(); } }); } }
Напишем реализацию функции sendSMS()
private void sendSMS(String phoneNumber, String message) { PendingIntentpi= PendingIntent.getActivity(this,0, new Intent(this, SMS.class),0); SmsManager sms= SmsManager.getDefault(); sms.sendTextMessage(phoneNumber,null, message,pi,null); }
Для отправки SMS сообщения в Android используется класс SmsManager. в отличии от друих классов, мы не можем получить экземпляр SmsManager напрямую. Для решения этой задачи необходимо вызвать статический метод getDefault(), который возвращает требуемый объект класса SmsManager. Метод sendTextMessage() отправляет sms сообщение с помощью PendingIntent. Объект PendingIntent используется для определения activity, которая будет вызвана после отправки сообщения. В приведенном выше коде объект pi ссылается на ту же activity из которой он вызывается, то есть после отправки SMS сообщения activity не поменяется.
Если Вы хотите отслеживать состояние процесса отправки сообщения, вам понадобится два объекта PendingIntent и два объекта BroadcastReceiver
private void sendSMS(String phoneNumber, String message) { String SENT="SMS_SENT"; String DELIVERED="SMS_DELIVERED"; PendingIntent sentPI= PendingIntent.getBroadcast(this,0, new Intent(SENT),0); PendingIntent deliveredPI= PendingIntent.getBroadcast(this,0, new Intent(DELIVERED),0); //---когда SMS отправлено--- registerReceiver(new BroadcastReceiver(){ @Override public void onReceive(Context arg0, Intent arg1){ switch(getResultCode()) { case Activity.RESULT_OK: Toast.makeText(getBaseContext(),"SMS sent", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: Toast.makeText(getBaseContext(),"Generic failure", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_NO_SERVICE: Toast.makeText(getBaseContext(),"No service", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_NULL_PDU: Toast.makeText(getBaseContext(),"Null PDU", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_RADIO_OFF: Toast.makeText(getBaseContext(),"Radio off", Toast.LENGTH_SHORT).show(); break; } } },new IntentFilter(SENT)); //---когда SMS доставлено--- registerReceiver(new BroadcastReceiver(){ @Override public void onReceive(Context arg0, Intent arg1){ switch(getResultCode()) { case Activity.RESULT_OK: Toast.makeText(getBaseContext(),"SMS delivered", Toast.LENGTH_SHORT).show(); break; case Activity.RESULT_CANCELED: Toast.makeText(getBaseContext(),"SMS not delivered", Toast.LENGTH_SHORT).show(); break; } } },new IntentFilter(DELIVERED)); SmsManager sms= SmsManager.getDefault(); sms.sendTextMessage(phoneNumber,null, message, sentPI, deliveredPI); }
В приведенном выше листинге объект sentPI используется для отслеживания процесса отправки. Когда SMS сообщение отправлено, генерируется первое событие onReceive для BroadcastReceiver. Именно здесь можно проверить статус процесса отправки. Объект PendingIntent (deliveredPI) используется для мониторинга доставки. Когда сообщение успешно доставлено, генерируется еще одно событие onReceive для BroadcastReceiver.
Теперь можно провести тесстирование приложения. При отладке на компьютере можно посылать сообщения от одного эмулятора другому. Для этого просто запустите два эмулятора (в папке android SDK зайдите в каталог Tools Emulator.exe). В качестве номера, куда вы отправляете SMS, нужно указать номер порта эмулятора. Его можно увидеть в загаловке окна эмулятора в круглых скобках. На рисунке показан пример отправки сообщения с эмултора 5554 на эмулятор 5556.
После успешной отправки SMS пользователю будет показано сообщение "SMS sent". После того, как сообщение будет принято на другом устройстве, пользователь увидит "SMS delivered". К сожалению, в случае тестирования на эмуляторе Вы не увидите этого сообщения. Возможность проверять успешность доставки доступна только на реальных устройствах.
Если Вы не хотите разбираться в тонкостях отправки SMS сообщений, то можете воспользоваться встроенным в Android стандартным приложением, дав ему задание через интент.
Intent sendIntent=new Intent(Intent.ACTION_VIEW); sendIntent.putExtra("sms_body","Content of the SMS goes here..."); sendIntent.setType("vnd.android-dir/mms-sms"); startActivity(sendIntent);
Помимо отправки SMS вы также можете организовать перехват входящих SMS сообщений. Делается это с помощью все того же объекта BroadcastReceiver.
Чтобы Ваше приложение могло перехватывать SMS-ки, нужно в файле AndroidManifest.xml добавить элемент <receiver>. В приведенном ниже примере для получения сообщений будет использоваться класс SmsReceiver.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.learn2develop.SMSMessaging" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".SMS" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".SmsReceiver"> <intent-filter> <action android:name= "android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> </application> <uses-permission android:name="android.permission.SEND_SMS"> </uses-permission> <uses-permission android:name="android.permission.RECEIVE_SMS"> </uses-permission> </manifest>
Теперь нужно добавить в проект новый класс SmsReceiver.java, который является наследником BroadcastReceiver. Внутри SmsReceiver нужно написать собственную реализацию метода onReceive()
package net.learn2develop.SMSMessaging; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; publicclass SmsReceiverextends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { } }
При получении SMS сообщения вызывается метод onReceive. SMS сообщение упаковывается и присоединяется к объекту intent (второй параметр метода onReceive). SMS сохраняется в массиве Object в PDU формате. Чтобы распаковать SMS сообщение нужно воспользоваться методом createFromPdu() класса SmsMessage. После этого можно отобразить сообщения с помощью класса Toast
package net.learn2develop.SMSMessaging; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.gsm.SmsMessage; import android.widget.Toast; publicclass SmsReceiverextends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //---получить входящее SMS сообщение--- Bundle bundle= intent.getExtras(); SmsMessage[] msgs=null; String str=""; if(bundle!=null) { //---извлечь полученное SMS --- Object[] pdus=(Object[]) bundle.get("pdus"); msgs=new SmsMessage[pdus.length]; for(int i=0; i<msgs.length; i++){ msgs[i]= SmsMessage.createFromPdu((byte[])pdus[i]); str+="SMS from "+ msgs[i].getOriginatingAddress(); str+=" :"; str+= msgs[i].getMessageBody().toString(); str+="\n"; } //---Показать новое SMS сообщение--- Toast.makeText(context, str, Toast.LENGTH_SHORT).show(); } } }
Вот, собственно, и все! Можете запускать эмуляторы и тестировать приложение. На приведенном ниже рисунке с помощью класса Toast показано полученное сообщение.
В этой небольшой статье было показано, как можно отправлять и получать SMS сообщения в Android. Это очень интересная и нужная возможность. Например, вы можете написать приложение, которое будет отслеживать положение телефона. Вы можете отправлять зашифрованные SMS сообщения этому приложению, и оно будет отправлять вам ответ с координатами аппарата.
Исходный код примера можно скачатьздесь.
Перевод: Александр Ледков
Источник:Wei-Meng Lee "SMS Messaging in Android"