Я придумав, як надсилати та отримувати SMS. Щоб надсилати SMS-повідомлення, мені довелося зателефонувати в клас sendTextMessage()
та sendMultipartTextMessage()
методи SmsManager
. Щоб отримувати SMS-повідомлення, мені довелося зареєструвати приймач у 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
до рідної програми Messaging. Я намагаюся надіслати MMS, не виходячи із заявки. Здається, не існує стандартного способу надсилання та отримання MMS. Хтось змусив це працювати?
Крім того, мені відомо, що SMS / MMS ContentProvider не є частиною офіційного пакета SDK для Android, але я думав, що хтось, можливо, зміг це здійснити. Будь-яка допомога дуже цінується.
Оновлення
Я додав файл 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.Телефонія :
Дія трансляції: пристрій отримав нове текстове SMS-повідомлення. У намірі будуть такі додаткові значення:
pdus
- AnObject[]
з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
- AnObject[]
з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)
- ідентифікатор транзакції WAP
pduType (Integer)
- Тип PDU WAP`
header (byte[])
- Заголовок повідомлення
data (byte[])
- Навантаження даних повідомлення
contentTypeParameters (HashMap<String,String>)
- Будь-які параметри, пов'язані з типом вмісту (декодується із заголовка WSP Content-Type)Якщо BroadcastReceiver зіткнувся з помилкою під час обробки цього наміру, він повинен відповідним чином встановити код результату. Додатковим значенням contentTypeParameters є карта параметрів вмісту, введених їх іменами. Якщо зустрічаються будь-які непризначені загальновідомі параметри, ключ карти буде "непризначений / 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 . Як я можу передати додатково до SMS-приймача ?
Оновлення №3
Отримання MMS
Отож, зробивши додаткові дослідження, я побачив деякі пропозиції щодо реєстрації ContentObserver
. Таким чином ви зможете виявити, коли є якісь зміни у content://mms-sms/conversations
постачальнику вмісту, отже, ви зможете виявити вхідні 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.