Я понял, как отправлять и получать SMS-сообщения. Для отправки SMS - сообщений , которые я должен был назвать sendTextMessage()
и sendMultipartTextMessage()
методы SmsManager
класса. Чтобы получать смс-сообщения, мне пришлось прописать получателя в AndroidMainfest.xml
файле. Затем мне пришлось переопределить onReceive()
метод BroadcastReceiver
. Я привел примеры ниже.
MainActivity.java
public class MainActivity extends Activity {
private static String SENT = "SMS_SENT";
private static String DELIVERED = "SMS_DELIVERED";
private static int MAX_SMS_MESSAGE_LENGTH = 160;
// ---sends an SMS message to another device---
public static void sendSMS(String phoneNumber, String message) {
PendingIntent piSent = PendingIntent.getBroadcast(mContext, 0, new Intent(SENT), 0);
PendingIntent piDelivered = PendingIntent.getBroadcast(mContext, 0,new Intent(DELIVERED), 0);
SmsManager smsManager = SmsManager.getDefault();
int length = message.length();
if(length > MAX_SMS_MESSAGE_LENGTH) {
ArrayList<String> messagelist = smsManager.divideMessage(message);
smsManager.sendMultipartTextMessage(phoneNumber, null, messagelist, null, null);
}
else
smsManager.sendTextMessage(phoneNumber, null, message, piSent, piDelivered);
}
}
//More methods of MainActivity ...
}
SMSReceiver.java
public class SMSReceiver extends BroadcastReceiver {
private final String DEBUG_TAG = getClass().getSimpleName().toString();
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private Context mContext;
private Intent mIntent;
// Retrieve SMS
public void onReceive(Context context, Intent intent) {
mContext = context;
mIntent = intent;
String action = intent.getAction();
if(action.equals(ACTION_SMS_RECEIVED)){
String address, str = "";
int contactId = -1;
SmsMessage[] msgs = getMessagesFromIntent(mIntent);
if (msgs != null) {
for (int i = 0; i < msgs.length; i++) {
address = msgs[i].getOriginatingAddress();
contactId = ContactsUtils.getContactId(mContext, address, "address");
str += msgs[i].getMessageBody().toString();
str += "\n";
}
}
if(contactId != -1){
showNotification(contactId, str);
}
// ---send a broadcast intent to update the SMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
public static SmsMessage[] getMessagesFromIntent(Intent intent) {
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++) {
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++) {
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
/**
* The notification is the icon and associated expanded entry in the status
* bar.
*/
protected void showNotification(int contactId, String message) {
//Display notification...
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myexample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.WRITE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:debuggable="true"
android:icon="@drawable/ic_launcher_icon"
android:label="@string/app_name" >
<activity
//Main activity...
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
//Activity 2 ...
</activity>
//More acitivies ...
// SMS Receiver
<receiver android:name="com.myexample.receivers.SMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Однако мне было интересно, можно ли аналогичным образом отправлять и получать сообщения MMS. После некоторых исследований многие примеры, представленные в блогах, просто передаются Intent
в собственное приложение обмена сообщениями. Я пытаюсь отправить MMS, не выходя из приложения. Кажется, нет стандартного способа отправки и получения MMS. У кого-нибудь это работает?
Кроме того, я знаю, что ContentProvider SMS / MMS не является частью официального Android SDK, но я думал, что кто-то, возможно, смог это реализовать. Любая помощь очень ценится.
Обновить
Я добавил BroadcastReceiver
в AndroidManifest.xml
файл, чтобы получать сообщения MMS
<receiver android:name="com.sendit.receivers.MMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
В классе MMSReceiver onReceive()
метод может получить только номер телефона, с которого было отправлено сообщение. Как получить другие важные данные из MMS, такие как путь к файлу во вложении мультимедиа (изображение / аудио / видео) или текст в MMS?
MMSReceiver.java
public class MMSReceiver extends BroadcastReceiver {
private final String DEBUG_TAG = getClass().getSimpleName().toString();
private static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED";
private static final String MMS_DATA_TYPE = "application/vnd.wap.mms-message";
// Retrieve MMS
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String type = intent.getType();
if(action.equals(ACTION_MMS_RECEIVED) && type.equals(MMS_DATA_TYPE)){
Bundle bundle = intent.getExtras();
Log.d(DEBUG_TAG, "bundle " + bundle);
SmsMessage[] msgs = null;
String str = "";
int contactId = -1;
String address;
if (bundle != null) {
byte[] buffer = bundle.getByteArray("data");
Log.d(DEBUG_TAG, "buffer " + buffer);
String incomingNumber = new String(buffer);
int indx = incomingNumber.indexOf("/TYPE");
if(indx>0 && (indx-15)>0){
int newIndx = indx - 15;
incomingNumber = incomingNumber.substring(newIndx, indx);
indx = incomingNumber.indexOf("+");
if(indx>0){
incomingNumber = incomingNumber.substring(indx);
Log.d(DEBUG_TAG, "Mobile Number: " + incomingNumber);
}
}
int transactionId = bundle.getInt("transactionId");
Log.d(DEBUG_TAG, "transactionId " + transactionId);
int pduType = bundle.getInt("pduType");
Log.d(DEBUG_TAG, "pduType " + pduType);
byte[] buffer2 = bundle.getByteArray("header");
String header = new String(buffer2);
Log.d(DEBUG_TAG, "header " + header);
if(contactId != -1){
showNotification(contactId, str);
}
// ---send a broadcast intent to update the MMS received in the
// activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("MMS_RECEIVED_ACTION");
broadcastIntent.putExtra("mms", str);
context.sendBroadcast(broadcastIntent);
}
}
}
/**
* The notification is the icon and associated expanded entry in the status
* bar.
*/
protected void showNotification(int contactId, String message) {
//Display notification...
}
}
Согласно документации android.provider.Telephony :
Действие широковещательной рассылки: устройство получило новое текстовое SMS-сообщение. У намерения будут следующие дополнительные значения:
pdus
- ЭлементObject[]
изbyte[]
s, содержащий блоки PDU, составляющие сообщение.Дополнительные значения могут быть извлечены с помощью.
getMessagesFromIntent(android.content.Intent)
Если BroadcastReceiver обнаруживает ошибку при обработке этого намерения, он должен соответствующим образом установить код результата.@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
Действие широковещательной передачи: устройство получило новое SMS-сообщение на основе данных. У намерения будут следующие дополнительные значения:
pdus
- ЭлементObject[]
изbyte[]
s, содержащий блоки PDU, составляющие сообщение.Дополнительные значения можно извлечь с помощью getMessagesFromIntent (android.content.Intent). Если BroadcastReceiver обнаруживает ошибку при обработке этого намерения, он должен соответствующим образом установить код результата.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
Действие широковещательной рассылки: устройство получило новое сообщение WAP PUSH. У намерения будут следующие дополнительные значения:
transactionId (Integer)
- ID транзакции WAP
pduType (Integer)
- Тип WAP PDU`
header (byte[])
- Заголовок сообщения
data (byte[])
- Полезные данные сообщения
contentTypeParameters (HashMap<String,String>)
- Любые параметры, связанные с типом контента (декодированные из заголовка WSP Content-Type)Если BroadcastReceiver обнаруживает ошибку при обработке этого намерения, он должен соответствующим образом установить код результата. Дополнительное значение contentTypeParameters - это карта параметров содержимого, привязанных к их именам. Если встречаются какие-либо неназначенные общеизвестные параметры, ключ карты будет 'unassigned / 0x ...', где '...' - шестнадцатеричное значение неназначенного параметра. Если параметр не имеет значения, значение на карте будет нулевым.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
Обновление № 2
Я выяснил, как передать дополнения в объект, PendingIntent
который будет получен BroadcastReceiver
:
дополнениями Android PendingIntent, не полученными BroadcastReceiver
Однако дополнительная информация передается в SendBroadcastReceiver, а не в SMSReceiver . Как передать SMSReceiver дополнительную услугу ?
Обновление № 3
Получение MMS
Итак, после дополнительных исследований я увидел несколько предложений по регистрации домена ContentObserver
. Таким образом, вы можете определить, есть ли какие-либо изменения в content://mms-sms/conversations
Content Provider, что позволит вам обнаруживать входящие MMS. Вот ближайший из обнаруженных мною пример того, как это работает: получение MMS.
Однако есть переменная mainActivity
типа ServiceController
. Где ServiceController
реализован класс? Есть ли другие реализации зарегистрированного ContentObserver
?
Отправка MMS
Что касается отправки MMS, я встречал такой пример: Отправить MMS
Проблема в том, что я пытался запустить этот код на своем Nexus 4, который находится на Android v4.2.2, и получаю следующую ошибку:
java.lang.SecurityException: No permission to write APN settings: Neither user 10099 nor current process has android.permission.WRITE_APN_SETTINGS.
Ошибка возникает после запроса Carriers
ContentProvider в getMMSApns()
методе APNHelper
класса.
final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);
Похоже, вы не можете читать APN в Android 4.2
Какая альтернатива для всех тех приложений, которые используют мобильные данные для выполнения операций (например, отправки MMS) и не знают настройки APN по умолчанию, присутствующей в устройстве?
Обновление № 4
Отправка MMS
Я пробовал следовать этому примеру: Отправить MMS
Как предположил @Sam в своем ответе:
You have to add jsoup to the build path, the jar to the build path and import com.droidprism.*; To do that in android, add the jars to the libs directory first, then configure the project build path to use the jars already in the libs directory, then on the build path config click order and export and check the boxes of the jars and move jsoup and droidprism jar to the top of the build order.
Итак, теперь я больше не получаю ошибки SecurityException. Сейчас я тестирую Nexus 5 на Android KitKat. После запуска примера кода он дает мне код ответа 200 после вызова
MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);
Однако я посоветовался с человеком, которому пытался отправить MMS. И они сказали, что никогда не получали MMS.