Ho capito come inviare e ricevere messaggi SMS. Per inviare messaggi SMS ho dovuto chiamare i metodi sendTextMessage()
e sendMultipartTextMessage()
della SmsManager
classe. Per ricevere messaggi SMS, ho dovuto registrare un destinatario nel AndroidMainfest.xml
file. Quindi ho dovuto ignorare il onReceive()
metodo di BroadcastReceiver
. Ho incluso esempi di seguito.
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>
Tuttavia, mi chiedevo se fosse possibile inviare e ricevere messaggi MMS in modo simile. Dopo aver fatto qualche ricerca, molti esempi forniti sui blog passano semplicemente Intent
all'applicazione di messaggistica nativa. Sto cercando di inviare un MMS senza lasciare la mia domanda. Non sembra esserci un modo standard per inviare e ricevere MMS. Qualcuno l'ha fatto funzionare?
Inoltre, sono consapevole che ContentProvider SMS / MMS non fa parte dell'SDK Android ufficiale, ma pensavo che qualcuno potesse essere in grado di implementarlo. Qualsiasi aiuto è molto apprezzato.
Aggiornare
Ho aggiunto BroadcastReceiver
a al AndroidManifest.xml
file per ricevere messaggi 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>
Nella classe MMSReceiver, il onReceive()
metodo è in grado di catturare solo il numero di telefono da cui è stato inviato il messaggio. Come afferrare altre cose importanti da un MMS come il percorso del file all'allegato multimediale (immagine / audio / video) o il testo nell'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...
}
}
Secondo la documentazione di android.provider.Telephony :
Broadcast Action: il dispositivo ha ricevuto un nuovo messaggio SMS basato su testo. L'intento avrà i seguenti valori extra:
pdus
- UnoObject[]
dibyte[]
s contenente le PDU che compongono il messaggio.I valori extra possono essere estratti usando
getMessagesFromIntent(android.content.Intent)
Se un BroadcastReceiver rileva un errore durante l'elaborazione di questo intento, dovrebbe impostare il codice del risultato in modo appropriato.@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
Broadcast Action: il dispositivo ha ricevuto un nuovo messaggio SMS basato su dati. L'intento avrà i seguenti valori extra:
pdus
- UnoObject[]
dibyte[]
s contenente le PDU che compongono il messaggio.I valori extra possono essere estratti usando getMessagesFromIntent (android.content.Intent). Se BroadcastReceiver rileva un errore durante l'elaborazione di questo intento, dovrebbe impostare il codice risultato in modo appropriato.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
Azione di trasmissione: un nuovo messaggio WAP PUSH è stato ricevuto dal dispositivo. L'intento avrà i seguenti valori extra:
transactionId (Integer)
- L'ID transazione WAP
pduType (Integer)
- Il tipo di PDU WAP`
header (byte[])
- L'intestazione del messaggio
data (byte[])
- Il payload di dati del messaggio
contentTypeParameters (HashMap<String,String>)
- Qualsiasi parametro associato al tipo di contenuto (decodificato dall'intestazione Content-Type di WSP)Se BroadcastReceiver rileva un errore durante l'elaborazione di questo intento, dovrebbe impostare il codice risultato in modo appropriato. Il valore aggiuntivo contentTypeParameters è la mappa dei parametri del contenuto codificati dai loro nomi. Se vengono rilevati parametri noti non assegnati, la chiave della mappa sarà "non assegnata / 0x ...", dove "..." è il valore esadecimale del parametro non assegnato. Se un parametro ha nessun valore, il valore nella mappa sarà nullo.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
Aggiornamento n. 2
Ho capito come passare gli extra in a che PendingIntent
devono essere ricevuti da BroadcastReceiver
:
Android PendingIntent extra, non ricevuti da BroadcastReceiver
Tuttavia, l'extra viene passato a SendBroadcastReceiver e non a SMSReceiver . Come posso passare un extra a SMSReceiver ?
Aggiornamento n. 3
Ricezione di MMS
Quindi, dopo aver fatto ulteriori ricerche, ho visto alcuni suggerimenti per la registrazione di a ContentObserver
. In questo modo è possibile rilevare eventuali modifiche al content://mms-sms/conversations
provider di contenuti, consentendo di rilevare gli MMS in arrivo. Ecco l'esempio più vicino per farlo funzionare che ho trovato: Ricezione di MMS
Tuttavia, esiste una variabile mainActivity
di tipo ServiceController
. Dove viene ServiceController
implementata la classe? Ci sono altre implementazioni di una registrazione ContentObserver
?
Invio di MMS
Per quanto riguarda l'invio di MMS, mi sono imbattuto in questo esempio: Invia MMS
Il problema è che ho provato a eseguire questo codice sul mio Nexus 4, che è su Android v4.2.2, e ricevo questo errore:
java.lang.SecurityException: No permission to write APN settings: Neither user 10099 nor current process has android.permission.WRITE_APN_SETTINGS.
L'errore viene generato dopo aver interrogato Carriers
ContentProvider nel getMMSApns()
metodo della APNHelper
classe.
final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);
Apparentemente non puoi leggere APN su Android 4.2
Qual è l'alternativa per tutte quelle applicazioni che usano i dati mobili per eseguire operazioni (come l'invio di MMS) e non conoscono l'impostazione APN predefinita presente nel dispositivo?
Aggiornamento n. 4
Invio di MMS
Ho provato a seguire questo esempio: Invia MMS
Come suggerito da @Sam nella sua risposta:
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.
Quindi ora non ricevo più gli errori SecurityException. Sto testando ora su un Nexus 5 su Android KitKat. Dopo aver eseguito il codice di esempio mi dà un codice di 200 risposte dopo la chiamata a
MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);
Tuttavia, ho verificato con la persona a cui ho provato a inviare l'MMS. E hanno detto di non aver mai ricevuto l'MMS.