Tôi đã tìm ra cách gửi và nhận tin nhắn SMS. Để gửi tin nhắn SMS, tôi đã phải gọi sendTextMessage()
và sendMultipartTextMessage()
phương thức của SmsManager
lớp. Để nhận được tin nhắn SMS, tôi đã phải đăng ký một người nhận trong AndroidMainfest.xml
tập tin. Sau đó, tôi đã phải ghi đè onReceive()
phương thức của BroadcastReceiver
. Tôi đã bao gồm các ví dụ dưới đây.
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>
Tuy nhiên, tôi đã tự hỏi nếu bạn có thể gửi và nhận tin nhắn MMS theo cách tương tự. Sau khi thực hiện một số nghiên cứu, nhiều ví dụ được cung cấp trên blog chỉ cần chuyển một Intent
ứng dụng Nhắn tin gốc. Tôi đang cố gắng gửi MMS mà không cần rời khỏi ứng dụng của mình. Dường như không có một cách tiêu chuẩn nào để gửi và nhận MMS. Có ai từng nhận làm công việc này chưa?
Ngoài ra, tôi biết rằng SMS / MMS ContentProvider không phải là một phần của SDK Android chính thức, nhưng tôi đã nghĩ ai đó có thể đã thực hiện được điều này. Bất kỳ trợ giúp nào cũng được đánh giá rất cao.
Cập nhật
Tôi đã thêm một BroadcastReceiver
đến AndroidManifest.xml
tập tin để nhận tin nhắn 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>
Trong lớp MMSReceiver, onReceive()
phương thức chỉ có thể lấy số điện thoại mà tin nhắn được gửi từ đó. Làm thế nào để bạn lấy những thứ quan trọng khác từ MMS như đường dẫn tệp đến tệp đính kèm phương tiện (hình ảnh / âm thanh / video) hoặc văn bản trong 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...
}
}
Theo Tài liệu của android.provider.Telephony :
Phát hành động: Một tin nhắn SMS dựa trên văn bản mới đã được thiết bị nhận được. Mục đích sẽ có các giá trị bổ sung sau:
pdus
- MộtObject[]
trong cácbyte[]
s chứa PDU tạo nên thông điệp.Các giá trị bổ sung có thể được trích xuất bằng cách sử dụng
getMessagesFromIntent(android.content.Intent)
Nếu BroadcastReceiver gặp lỗi trong khi xử lý ý định này, nó sẽ đặt mã kết quả một cách thích hợp.@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
Phát hành động: Một tin nhắn SMS dựa trên dữ liệu mới đã được thiết bị nhận được. Mục đích sẽ có các giá trị bổ sung sau:
pdus
- MộtObject[]
trong cácbyte[]
s chứa PDU tạo nên thông điệp.Các giá trị bổ sung có thể được trích xuất bằng getMessagesFromIntent (android.content.Intent). Nếu BroadcastReceiver gặp lỗi trong khi xử lý ý định này, nó sẽ đặt mã kết quả một cách thích hợp.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
Phát hành hành động: Thiết bị nhận được thông báo WAP PUSH mới. Mục đích sẽ có các giá trị bổ sung sau:
transactionId (Integer)
- ID giao dịch WAP
pduType (Integer)
- Kiểu PDU của Wap`
header (byte[])
- Tiêu đề của tin nhắn
data (byte[])
- Tải trọng dữ liệu của tin nhắn
contentTypeParameters (HashMap<String,String>)
- Bất kỳ tham số nào được liên kết với loại nội dung (được giải mã từ tiêu đề Loại nội dung WSP)Nếu BroadcastReceiver gặp lỗi trong khi xử lý ý định này, nó sẽ đặt mã kết quả một cách thích hợp. Giá trị bổ sung của ContentTypeParameter là bản đồ của các tham số nội dung được khóa bởi tên của chúng. Nếu gặp phải bất kỳ tham số nổi tiếng nào chưa được gán, khóa của bản đồ sẽ là 'chưa được gán / 0x ...', trong đó '...' là giá trị hex của tham số chưa được gán. Nếu một tham số có No-Value, giá trị trong bản đồ sẽ là null.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
Cập nhật số 2
Tôi đã tìm ra cách vượt qua các tính năng bổ sung PendingIntent
để được nhận bởi BroadcastReceiver
:
Phần mở rộng Android PendingIntent, không được BroadcastReceiver nhận
Tuy nhiên, phần bổ sung được chuyển đến SendBroadcastReceiver chứ không phải SMSReceiver . Làm cách nào tôi có thể chuyển thêm cho SMSReceiver ?
Cập nhật số 3
Nhận MMS
Vì vậy, sau khi thực hiện nhiều nghiên cứu hơn, tôi thấy một số gợi ý đăng ký a ContentObserver
. Bằng cách đó, bạn có thể phát hiện khi có bất kỳ thay đổi nào đối với content://mms-sms/conversations
Nhà cung cấp nội dung, do đó cho phép bạn phát hiện MMS đến. Đây là ví dụ gần nhất để làm việc này mà tôi đã tìm thấy: Nhận MMS
Tuy nhiên, có một biến mainActivity
kiểu ServiceController
. Đâu là ServiceController
lớp thực hiện? Có bất kỳ thực hiện khác của một đăng ký ContentObserver
?
Gửi MMS
Đối với việc gửi MMS, tôi đã bắt gặp ví dụ này: Gửi MMS
Vấn đề là tôi đã thử chạy mã này trên Nexus 4, trên Android v4.2.2 và tôi nhận được lỗi này:
java.lang.SecurityException: No permission to write APN settings: Neither user 10099 nor current process has android.permission.WRITE_APN_SETTINGS.
Lỗi được đưa ra sau khi truy vấn Carriers
ContentProvider trong getMMSApns()
phương thức của APNHelper
lớp.
final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);
Rõ ràng bạn không thể đọc APN trong Android 4.2
Lựa chọn thay thế nào cho tất cả các ứng dụng sử dụng dữ liệu di động để thực hiện các thao tác (như gửi MMS) và không biết cài đặt APN mặc định có trong thiết bị?
Cập nhật số 4
Gửi MMS
Tôi đã thử làm theo ví dụ này: Gửi MMS
Như @Sam đề xuất trong câu trả lời của anh ấy:
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.
Vì vậy, bây giờ tôi không còn nhận được lỗi SecurityException. Tôi hiện đang thử nghiệm trên Nexus 5 trên Android KitKat. Sau khi chạy mã mẫu, nó cung cấp cho tôi mã phản hồi 200 sau cuộc gọi đến
MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);
Tuy nhiên, tôi đã kiểm tra với người mà tôi đã thử gửi MMS đến. Và họ nói họ không bao giờ nhận được MMS.