ฉันได้หาวิธีส่งและรับข้อความ 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 ไม่ได้เป็นส่วนหนึ่งของ Android SDK อย่างเป็นทางการ แต่ฉันคิดว่าอาจมีใครบางคนสามารถใช้สิ่งนี้ได้ ความช่วยเหลือใด ๆ ที่ได้รับการชื่นชมอย่างมาก
ปรับปรุง
ฉันได้เพิ่ม a 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()
เมธอดสามารถคว้า phoneNumber ที่ข้อความนั้นส่งมาได้เท่านั้น คุณดึงสิ่งสำคัญอื่น ๆ จาก 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 :
Broadcast Action: อุปกรณ์ได้รับข้อความ SMS ตามข้อความใหม่ ความตั้งใจจะมีค่าพิเศษดังต่อไปนี้:
pdus
- เป็นObject[]
ของbyte[]
s มี PDUs ที่ทำขึ้นข้อความสามารถแยกค่าพิเศษโดยใช้
getMessagesFromIntent(android.content.Intent)
If a BroadcastReceiver พบข้อผิดพลาดขณะประมวลผลเจตนานี้ควรตั้งค่ารหัสผลลัพธ์ให้เหมาะสม@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
Broadcast Action: อุปกรณ์ได้รับข้อความ SMS ตามข้อมูลใหม่ ความตั้งใจจะมีค่าพิเศษดังต่อไปนี้:
pdus
- เป็นObject[]
ของbyte[]
s มี PDUs ที่ทำขึ้นข้อความสามารถแยกค่าพิเศษได้โดยใช้ getMessagesFromIntent (android.content.Intent) หาก BroadcastReceiver พบข้อผิดพลาดขณะประมวลผลเจตนานี้ควรตั้งค่ารหัสผลลัพธ์ให้เหมาะสม
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
Broadcast Action: อุปกรณ์ได้รับข้อความ WAP PUSH ใหม่ ความตั้งใจจะมีค่าพิเศษดังต่อไปนี้:
transactionId (Integer)
- รหัสธุรกรรม 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
ฉันได้หาวิธีส่งผ่านความพิเศษใน a PendingIntent
ที่จะได้รับโดย a BroadcastReceiver
:
Android PendingIntent extras ที่ 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 เลย