/*
* RapidPro Android Channel - Relay SMS messages where MNO connections aren't practical.
* Copyright (C) 2014 Nyaruka, UNICEF
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.rapidpro.androidchannel;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.telephony.SmsManager;
import android.util.Log;
import java.util.ArrayList;
public class SendMessageService extends IntentService {
public static final String TAG = SendMessageService.class.getSimpleName();
private static final String SMS_SENT_REPORT_ACTION = "io.rapidpro.androidchannel.SMS_SENT_REPORT";
private static final String SMS_SENT_REPORT_TOKEN_EXTRA = "token";
private static final String SMS_FAILED_REPORT_ACTION = "io.rapidpro.androidchannel.SMS_FAILED_REPORT";
private static final String SMS_FAILED_REPORT_TOKEN_EXTRA = "token";
private static final String SMS_DELIVERED_REPORT_ACTION = "io.rapidpro.androidchannel.SMS_DELIVERED_REPORT";
private static final String SMS_DELIVERED_REPORT_TOKEN_EXTRA = "token";
public SendMessageService() {
super(SendMessageService.class.getSimpleName());
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent.getAction().equals("io.rapidpro.androidchannel.SendMessage")) {
String address = intent.getStringExtra("address");
ArrayList<String> message = intent.getStringArrayListExtra("message");
String token = intent.getStringExtra("token");
sendSms(getBaseContext(), address, message, token);
}
}
public void sendSms(Context context, String address, ArrayList<String> message, String token) {
if (message != null && address != null && token != null) {
SmsManager smsManager = SmsManager.getDefault();
// make sure we've got a plus for international format
if (!address.startsWith("+") && address.length() > 10) {
address = "+" + address;
}
final Intent intent = new Intent(SMS_SENT_REPORT_ACTION);
intent.setData(Uri.fromParts("sms", token, ""));
intent.putExtra(SMS_SENT_REPORT_TOKEN_EXTRA, token);
final PendingIntent queueIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
final ArrayList<PendingIntent> queueingIntents = new ArrayList<PendingIntent>();
for (int i = 0; i < message.size(); i++) {
queueingIntents.add(queueIntent);
}
final Intent intent1 = new Intent(SMS_DELIVERED_REPORT_ACTION);
intent1.setData(Uri.fromParts("sms", token, ""));
intent1.putExtra(SMS_DELIVERED_REPORT_TOKEN_EXTRA, token);
final PendingIntent deliveryIntent = PendingIntent.getBroadcast(context, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
final ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
for (int i = 0; i < message.size(); i++){
deliveryIntents.add(deliveryIntent);
}
Log.d(TAG, "Sending [" + intent.getData() + "] " + address + " - " + message.size());
try{
smsManager.sendMultipartTextMessage(address, null, message, queueingIntents, deliveryIntents);
} catch (Throwable t){
// Mark that the message failed to send
final Intent failedIntent = new Intent(SMS_FAILED_REPORT_ACTION);
failedIntent.setData(Uri.fromParts("sms", token, ""));
failedIntent.putExtra(SMS_FAILED_REPORT_TOKEN_EXTRA, token);
// send a broadcast out that this failed
sendBroadcast(failedIntent);
Log.e(TAG, "Error trying to send message, ignoring", t);
}
}
}
}