receiver - read sms android example




Envio e recebimento de SMS e MMS no Android(pré Kit Kat Android 4.4) (4)

Eu descobri como enviar e receber mensagens SMS. Para enviar mensagens SMS, tive que chamar os sendTextMessage() e sendMultipartTextMessage() da classe SmsManager . Para receber mensagens SMS, tive que registrar um receptor no arquivo AndroidMainfest.xml . Então eu tive que substituir o método onReceive() 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 alguma pesquisa, muitos exemplos fornecidos em blogs simplesmente passam um Intent para o aplicativo nativo do Messaging. 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 já conseguiu isso para trabalhar?

Além disso, estou ciente de que o SMS / MMS ContentProvider não faz parte do SDK oficial do Android, mas eu estava pensando que alguém poderia ter implementado isso. Qualquer ajuda é muito apreciada.

Atualizar

Eu adicionei um BroadcastReceiver ao arquivo AndroidManifest.xml 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 método onReceive() só é capaz de capturar o phoneNumber de onde 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 Broadcast: Uma nova mensagem SMS baseada em texto foi recebida pelo dispositivo. A intenção terá os seguintes valores extras:

pdus - Um Object[] de byte[] 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 de resultado adequadamente.

 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
 public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";

Ação de Broadcast: Uma nova mensagem SMS baseada em dados foi recebida pelo dispositivo. A intenção terá os seguintes valores extras:

pdus - Um Object[] de byte[] 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 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 PDU WAP`

header (byte[]) - O cabeçalho da mensagem

data (byte[]) - A carga de dados da mensagem

contentTypeParameters (HashMap<String,String>) - Todos os parâmetros associados ao tipo de conteúdo (decodificado no cabeçalho WSP Content-Type)

Se um BroadcastReceiver encontrar um erro ao processar essa intenção, ele deverá definir o código de resultado adequadamente. O valor extra contentTypeParameters é o 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á 'unassigned / 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 um PendingIntent para ser recebido por um BroadcastReceiver : extras do Android PendingIntent, não recebidos pelo BroadcastReceiver

No entanto, o extra é passado para o SendBroadcastReceiver não 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 registrar um ContentObserver . Dessa forma, você pode detectar quando houver alterações no content://mms-sms/conversations Provedor de Conteúdo, permitindo que você detecte MMS de entrada. Aqui está o exemplo mais próximo para fazer isso funcionar, que eu encontrei: Recebendo MMS

No entanto, existe uma variável mainActivity do tipo ServiceController . Onde a classe ServiceController é implementada? Existem outras implementações de um ContentObserver registrado?

Envio de 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 é acionado depois de consultar o ContentProvider Carriers no método getMMSApns() da classe APNHelper .

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 executar operações (como enviar MMS) e não sabem a configuração padrão de APN presente no dispositivo?

Atualização 4

Envio de 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 consigo mais os erros SecurityException. Estou testando agora em um Nexus 5 no Android KitKat. Depois de executar o código de exemplo, ele me fornece um código de resposta 200 após a chamada para

MMResponse mmResponse = sender.send(out, isProxySet, MMSProxy, MMSPort);

No entanto, verifiquei com a pessoa que tentei enviar o MMS para. E eles disseram que nunca receberam o MMS.


SmsListenerClass

public class SmsListener extends BroadcastReceiver {

static final String ACTION =
        "android.provider.Telephony.SMS_RECEIVED";

@Override
public void onReceive(Context context, Intent intent) {

    Log.e("RECEIVED", ":-:-" + "SMS_ARRIVED");

    // TODO Auto-generated method stub
    if (intent.getAction().equals(ACTION)) {

        Log.e("RECEIVED", ":-" + "SMS_ARRIVED");

        StringBuilder buf = new StringBuilder();
        Bundle bundle = intent.getExtras();
        if (bundle != null) {

            Object[] pdus = (Object[]) bundle.get("pdus");

            SmsMessage[] messages = new SmsMessage[pdus.length];
            SmsMessage message = null;

            for (int i = 0; i < messages.length; i++) {

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    String format = bundle.getString("format");
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format);
                } else {
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                }

                message = messages[i];
                buf.append("Received SMS from  ");
                buf.append(message.getDisplayOriginatingAddress());
                buf.append(" - ");
                buf.append(message.getDisplayMessageBody());
            }

            MainActivity inst = MainActivity.instance();
            inst.updateList(message.getDisplayOriginatingAddress(),message.getDisplayMessageBody());

        }

        Log.e("RECEIVED:", ":" + buf.toString());

        Toast.makeText(context, "RECEIVED SMS FROM :" + buf.toString(), Toast.LENGTH_LONG).show();

    }
}

Atividade

@Override
public void onStart() {
    super.onStart();
    inst = this;
}

public static MainActivity instance() {
    return inst;
}

public void updateList(final String msg_from, String msg_body) {

    tvMessage.setText(msg_from + " :- " + msg_body);

    sendSMSMessage(msg_from, msg_body);

}

protected void sendSMSMessage(String phoneNo, String message) {

    try {
        SmsManager smsManager = SmsManager.getDefault();
        smsManager.sendTextMessage(phoneNo, null, message, null, null);
        Toast.makeText(getApplicationContext(), "SMS sent.", Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        Toast.makeText(getApplicationContext(), "SMS faild, please try again.", Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }
}

Manifesto

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS"/>

<receiver android:name=".SmsListener">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>

Eu não acho que há qualquer 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 da minha aplicação no android


Eu tive exatamente o mesmo problema que você descreve acima (Galaxy Nexus no t-mobile EUA) porque os dados móveis estão desativados.

No Jelly Bean é: Configurações> Uso de Dados> dados móveis

Tenha em atenção que tenho de ativar os dados móveis antes de enviar um MMS OU de receber um. Se eu receber um MMS com dados móveis desativados, receberei a notificação de uma nova mensagem e receberei a mensagem com um botão de download. Mas se eu não tiver dados móveis anteriores, o anexo de MMS recebido não será recebido. Mesmo se eu ligá-lo depois que a mensagem foi recebida.

Por algum motivo, quando o seu provedor telefônico permite que você envie e receba MMS, é necessário ativar os dados móveis, mesmo se estiver usando Wi-Fi. Se os dados móveis estiverem ativados, você poderá receber e enviar MMS, mesmo se Wifi está mostrando como sua internet no seu dispositivo.

É um problema real, como se você não o tivesse ativado, a mensagem pode ser muito problemática, mesmo ao ativar os dados móveis, e pode exigir uma reinicialização do dispositivo.


Não há suporte oficial à API, o que significa que ela não está documentada para o público e as bibliotecas podem ser alteradas a qualquer momento. Eu percebo que você não quer deixar o aplicativo, mas aqui está como você faz isso com a intenção de qualquer outra pessoa se perguntando.

public void sendData(int num){
    String fileString = "..."; //put the location of the file here
    Intent mmsIntent = new Intent(Intent.ACTION_SEND);
    mmsIntent.putExtra("sms_body", "text");
    mmsIntent.putExtra("address", num);
    mmsIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(fileString)));
    mmsIntent.setType("image/jpeg");
    startActivity(Intent.createChooser(mmsIntent, "Send"));

}

Eu não descobri completamente como fazer coisas como acompanhar a entrega da mensagem, mas isso deve ser enviado.

Você pode ser alertado para o recebimento de MMS da mesma forma que o SMS. O filtro de intenção no receptor deve ficar assim.

<intent-filter>
    <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
    <data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>




mms