середу, 8 серпня 2012 р.

Учимся отправлять смс

Введение
Всем привет! Сегодня будем учиться отправлять смс. Научимся так же отправлять смс "пачками", отслеживать доставку.

Отправка sms
Передача смс осуществлятся при помощи объекта SmsManager:

SmsManager smsManager = SmsManager.getDefault();

получили ссылку на системный SmsManager. Так же стоит обновить манифест:

<uses-permission android:name="android.permission.SEND_SMS"/> //разрешение на отправку смс сообщений

Далее следует прописать номер поулчателя (запустите ещё один эмулятор) и тело сообщения:

String phoneNumber = "5556";
String message = "Hello world!!!";

и непосредственно с помощу нашего менеджера отправляем смс:

smsManager.sendTextMessage(phoneNumber, null, message, null, null);

метод sendTextMessage отправляет текстовое сообщение, в него мы передаём номер получателя и тело сообщения, остальные поля пока что не трогаем. Всё, можете отправлять.

Подтверждение доставки sms
Что бы отследить подтверждение о доставке необходимо зарегистрировать два слушателя. Первый слушатель будет срабатывать когда смс будет отправляться, второе сработает тогда когда получатель получил смс. Лучше всего для наглядности переопределить слушатели:

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsManager;
import android.util.Log;
 
public class SendSms extends BroadcastReceiver {
 
 private final static String MY_TAG = "MyTag";
 
 public void onReceive(Context context, Intent intent) {
  switch(getResultCode()) {
  case Activity.RESULT_OK:
   Log.i(MY_TAG, "SMS send");
   break;
  case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
   Log.i(MY_TAG, "unknown problems");
   break;
  case SmsManager.RESULT_ERROR_RADIO_OFF:
   Log.i(MY_TAG, "modul is down");
   break;
  case SmsManager.RESULT_ERROR_NULL_PDU:
   Log.i(MY_TAG, "PDU error");
   break;
  }
 }
 
}

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
 
public class DeliverySms extends BroadcastReceiver {
 
 private final static String MY_TAG = "MyTag";
 
 public void onReceive(Context context, Intent intent) {
  switch(getResultCode()) {
  case Activity.RESULT_OK:
   Log.i(MY_TAG, "SMS delivered");
   break;
  case Activity.RESULT_CANCELED:
   Log.i(MY_TAG, "SMS not delivered");
   break;
  }
 }
 
}

И так что мы здесь накодили =) ... Создали два слушателя (SendSms - будет срабатывать когда смс будет отправленно, DeliverySms - когда смс доходит до получателя). В слушателях нужно переопределить только один метод onReceive, он вызывается тогда когда слушатель получает сообщение. Полученные сообщения можно отсортировать с помощу метода getResultCode(). Есть такие сообщения:

  • Activity.RESULT_OK - операция успешна;
  • Activity.RESULT_CANCELED - операция отмененна;
  • SmsManager.RESULT_ERROR_GENERIC_FAILURE - при отправке возникли неизвестные  проблемы;
  • SmsManager.RESULT_ERROR_RADIO_OFF - телефонный модуль выключен;
  • SmsManager.RESULT_ERROR_NULL_PDU - возникла проблема формата PDU;
Теперь осталось зарегистрировать слушатили в главном активити:

private final static String SENT = "SENT_SMS_ACTION", DELIVERED = "DELIVERED_SMS_ACTION", ISNULL = "Entered, not all data";
 
SendSms sendSms = new SendSms();
DeliverySms deliverySms = new DeliverySms();
registerReceiver(sendSms, new IntentFilter(SENT));
registerReceiver(deliverySms, new IntentFilter(DELIVERED));
 
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0);
PendingIntent delivertPI = PendingIntent.getBroadcast(this, 0, new Intent(DELIVERED), 0);
 
И так, видим один метод и класс которые нам не известны. registerReceiver - регистрирует слушатель, первый параметр сам слушатель, второй параметр интентфильтр передачи (в него передаём текст что бы как то отличать фильтры). PendingIntent - передаётся в другое приложение.
Собственно наверное немножко не понятно, BroadcasReceiver и PendingIntent своеобразные "мосты". BroadcasReceiver слушатель который слушает что получает PendingIntent на всём телефоне, а не только в вашем приложении.
Так же стоит отметить что стоит переопределить метод onStop() главного активити:

    protected void onStop() {
     //когда приложение переходит в ожидание или же закрывается то снимаем с регистрации приёмники
     unregisterReceiver(sendSms);
     unregisterReceiver(deliverySms);
     super.onStop();
    }
как следует из комментария, приёмники следует снять с регистрации, в том числе для экономии памяти.
Далее можете отправить сообщение и посмотреть за результатами.

Отправка несколько сообщений сразу.
Что же делать если сообщение вышло на две и более смс-ки? ведь метод sendTextMessage отправляет только одно сообщение. А вот для этого существует метод sendMultipartTextMessage:

PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0);
PendingIntent delivertPI = PendingIntent.getBroadcast(this, 0, new Intent(DELIVERED), 0);
SmsManager smsManager = SmsManager.getDefault();
if(message.length() > 160) {
 ArrayList<String> mArray = smsManager.divideMessage(message);
 ArrayList<PendingIntent> sentArrayIntents = new ArrayList<PendingIntent>();
 for(int i = 0; i < mArray.size(); i++)
  sentArrayIntents.add(sentPI);
 smsManager.sendMultipartTextMessage(phoneNumber, null, mArray, sentArrayIntents, null);

Если наше сообщение больше 160 символов, то разбиваем его на нескольк сообщений. Для этого нам не нужно делать это в ручную, за нас это сделает метод divideMessage в который мы должны передать набранное сообщение. Этот метод возвращает список с сообщениями, который мы потом разбиваем и по очереди добавляем в список слушателей, присоединяя таким способом к каждому слушателю по сообщению. Далее метод sendMultipartTextMessage идентичен sendTextMessage только отличается тем что мы передаём списки.
Теперь можете проверить как это всё работает отправив большое сообщение.

The end...
В конце предоставлю маленькое тестовое приложение:


Скачать можно по ссылкам:
http://uafile.com.ua/get/39754/
http://файлообменник.рф/ewdnmr1e60er.html

2 коментарі:

  1. ссылки для скачивания недоступны. Немного неверен код для отправки длинных СМС.
    Во-первых, проверять сообщение на длину в 160 символов имеет смысл только для СМС, написанных латиницей. Для СМС, написанных кириллицей, максимальная длина 70 символов. Условие лучше убрать вообще - код будет работать одинаково хорошо как для длинных, так и для коротких СМС.
    Во-вторых не используется ресивер подтверждения отправки и в-третьих забыта фигурная скобка :)
    Правильный код привожу ниже:

    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);

    registerReceiver(sendBroadcastReceiver, new IntentFilter(SENT));
    registerReceiver(deliveryBroadcastReciever, new IntentFilter(DELIVERED));

    SmsManager sms = SmsManager.getDefault();

    ArrayList mArray = sms.divideMessage(message);
    ArrayList sentArrayIntents = new ArrayList();
    ArrayList deliveredArrayIntents = new ArrayList();

    for(int i = 0; i < mArray.size(); i++) {
    sentArrayIntents.add(sentPI);
    deliveredArrayIntents.add(deliveredPI);
    }

    sms.sendMultipartTextMessage(phoneNumber, null, mArray, sentArrayIntents, deliveredArrayIntents);

    ВідповістиВидалити
  2. Для себя настраивал сервис по отправке СМСок здесь http://kupdam.sms.ru/
    Нравиться что можно отправлять даже в Европу

    ВідповістиВидалити