Eu descobri como enviar e receber mensagens SMS. Para enviar mensagens SMS, tive que chamar os métodos sendTextMessage()
e sendMultipartTextMessage()
da SmsManager
classe. Para receber mensagens SMS, tive que registrar um receptor no AndroidMainfest.xml
arquivo. Então eu tive que substituir o onReceive()
método do BroadcastReceiver
. Eu incluí exemplos abaixo.
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>
No entanto, eu queria saber se você poderia enviar e receber mensagens MMS de maneira semelhante. Depois de fazer algumas pesquisas, muitos exemplos fornecidos em blogs simplesmente passam um Intent
para o aplicativo de mensagens nativo. Estou tentando enviar um MMS sem sair do meu aplicativo. Não parece haver uma maneira padrão de enviar e receber MMS. Alguém conseguiu fazer isso funcionar?
Além disso, estou ciente de que o SMS / MMS ContentProvider não faz parte do SDK oficial do Android, mas estava pensando que alguém poderia implementá-lo. Qualquer ajuda é muito apreciada.
Atualizar
Adicionei um BroadcastReceiver
ao AndroidManifest.xml
arquivo para receber mensagens 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>
Na classe MMSReceiver, o onReceive()
método só pode capturar o phoneNumber do qual a mensagem foi enviada. Como você pega outras coisas importantes de um MMS, como o caminho do arquivo para o anexo de mídia (imagem / áudio / vídeo) ou o texto no 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...
}
}
De acordo com a documentação do android.provider.Telephony :
Ação de transmissão: Uma nova mensagem SMS baseada em texto foi recebida pelo dispositivo. A intenção terá os seguintes valores extras:
pdus
- UmObject[]
debyte[]
s contendo as PDUs que compõem a mensagem.Os valores extras podem ser extraídos usando
getMessagesFromIntent(android.content.Intent)
Se um BroadcastReceiver encontrar um erro ao processar essa intenção, ele deverá definir o código de resultado adequadamente.@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
Ação de transmissão: Uma nova mensagem SMS baseada em dados foi recebida pelo dispositivo. A intenção terá os seguintes valores extras:
pdus
- UmObject[]
debyte[]
s contendo as PDUs que compõem a mensagem.Os valores extras podem ser extraídos usando getMessagesFromIntent (android.content.Intent). Se um BroadcastReceiver encontrar um erro durante o processamento dessa intenção, ele deverá definir o código do resultado adequadamente.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
Ação de transmissão: Uma nova mensagem WAP PUSH foi recebida pelo dispositivo. A intenção terá os seguintes valores extras:
transactionId (Integer)
- O ID da transação WAP
pduType (Integer)
- O tipo de WAP PDU`
header (byte[])
- O cabeçalho da mensagem
data (byte[])
- A carga útil de dados da mensagem
contentTypeParameters (HashMap<String,String>)
- Quaisquer parâmetros associados ao tipo de conteúdo (decodificados no cabeçalho WSP Content-Type)Se um BroadcastReceiver encontrar um erro durante o processamento dessa intenção, ele deverá definir o código do resultado adequadamente. O valor extra contentTypeParameters é um mapa dos parâmetros de conteúdo codificados por seus nomes. Se algum parâmetro conhecido não atribuído for encontrado, a chave do mapa será 'não atribuído / 0x ...', onde '...' é o valor hexadecimal do parâmetro não atribuído. Se um parâmetro tiver No-Value, o valor no mapa será nulo.
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
Atualização # 2
Eu descobri como passar extras em a PendingIntent
para serem recebidos por um BroadcastReceiver
:
Android PendingIntent extras, não recebidos por BroadcastReceiver
No entanto, o extra é passado para o SendBroadcastReceiver e não para o SMSReceiver . Como posso passar um extra para o SMSReceiver ?
Atualização # 3
Recebendo MMS
Então, depois de fazer mais pesquisas, vi algumas sugestões de registro de um ContentObserver
. Dessa forma, você pode detectar quando há alguma alteração no content://mms-sms/conversations
Provedor de Conteúdo, consequentemente permitindo detectar MMS de entrada. Aqui está o exemplo mais próximo para que isso funcione, que eu encontrei: Recebendo MMS
No entanto, não é uma variável mainActivity
do tipo ServiceController
. Onde a ServiceController
classe é implementada? Existem outras implementações de um registrado ContentObserver
?
Enviando MMS
Quanto ao envio de MMS, me deparei com este exemplo: Enviar MMS
O problema é que tentei executar esse código no meu Nexus 4, que está no Android v4.2.2, e estou recebendo este erro:
java.lang.SecurityException: No permission to write APN settings: Neither user 10099 nor current process has android.permission.WRITE_APN_SETTINGS.
O erro é gerado após consultar o Carriers
ContentProvider no getMMSApns()
método da APNHelper
classe.
final Cursor apnCursor = this.context.getContentResolver().query(Uri.withAppendedPath(Carriers.CONTENT_URI, "current"), null, null, null, null);
Aparentemente, você não pode ler APNs no Android 4.2
Qual é a alternativa para todos os aplicativos que usam dados móveis para realizar operações (como enviar MMS) e não conhecem a configuração padrão de APN presente no dispositivo?
Atualização # 4
Enviando MMS
Eu tentei seguir este exemplo: Enviar MMS
Como @Sam sugeriu em sua resposta:
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.
Então agora eu não recebo mais os erros SecurityException. Agora estou testando um Nexus 5 no Android KitKat. Depois de executar o código de amostra, ele me fornece um código de 200 respostas após a chamada para
MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);
No entanto, verifiquei com a pessoa para quem tentei enviar o MMS. E eles disseram que nunca receberam o MMS.
fonte
Respostas:
Eu tive exatamente o mesmo problema que você descreveu acima (Galaxy Nexus no t-mobile USA) é porque os dados móveis estão desativados.
No Jelly Bean, é: Configurações> Uso de Dados> dados móveis
Observe que eu preciso ativar os dados móveis antes de enviar um MMS OU receber um. Se eu receber um MMS com os dados móveis desativados, receberei a notificação de uma nova mensagem e a mensagem com o botão de download. Mas se eu não tiver dados móveis anteriormente, o anexo MMS recebido não será recebido. Mesmo se eu ligá-lo depois que a mensagem foi recebida.
Por algum motivo, quando o seu provedor de telefonia permitir que você envie e receba MMS, você deve ativar os Dados Móveis, mesmo se estiver usando Wifi, se os Dados Móveis estiverem ativados, você poderá receber e enviar MMS, mesmo que Wifi está aparecendo como sua internet no seu dispositivo.
É uma dor real, como se você não a estivesse ativada, a mensagem pode travar muito, mesmo ao ativar o Mobile Data, e pode exigir uma reinicialização do dispositivo.
fonte
Não há suporte oficial à API, o que significa que ele não está documentado para o público e as bibliotecas podem mudar a qualquer momento. Sei que você não deseja sair do aplicativo, mas veja como você o faz com a intenção de alguém se perguntar.
Ainda não descobri completamente como fazer coisas como rastrear a entrega da mensagem, mas isso deve ser enviado.
Você pode ser alertado para o recebimento de mms da mesma maneira que sms. O filtro de intenção no receptor deve ficar assim.
fonte
BroadcastReceiver
e usei oIntent Filter
que você postou. Vou atualizar esta pergunta em breve.Para enviar um mms para o Android 4.0 api 14 ou superior sem permissão para escrever configurações de apn, você pode usar esta biblioteca : Recupere códigos mnc e mcc do android e chame
Para usar isso, adicione Jsoup e droid prism jar ao caminho da construção e importe com.droidprism. *;
fonte
java.lang.NoClassDefFoundError: com.droidprism.Carrier
isso está acontecendo com você?Eu não acho que existe algum suporte sdk para o envio de mms no android. Olhe aqui Pelo menos eu ainda não encontrei. Mas um cara alegou tê-lo. Dê uma olhada neste post.
Enviar MMS do meu aplicativo no android
fonte
Eu não entendo as frustrações. Por que não fazer um receptor de radiodifusão que filtre essa intenção:
Verifiquei um pouco mais e talvez você precise de acesso no nível do sistema para obter este (telefone root).
fonte
fonte