9

我的应用程序有一个要求,我需要在应用程序中集成消息传递。我想使用 android 原生 SMS API 来发送和接收消息。主要挑战是我不想在消息应用程序中显示收到的消息。所有消息都应仅从我的应用程序打开和发送。

我尝试在我的广播接收器中接收以下意图:

<intent-filter>
    <action android:name="android.provider.telephony.SMS_RECEIVED"></action>
</intent-filter>

但是,当消息同时到达我的应用程序时,本机消息应用程序会收到我不想要的消息。

我还尝试在模拟器的特定端口上发送数据消息,它正在发送消息但我的应用程序以及其他模拟器上的消息本机应用程序没有收到。

意图过滤器是:

<intent-filter> 
        <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
        <data android:port="8901"/>
        <data android:scheme="sms"/>
</intent-filter>

我正在使用带有给定端口的 sendDataMessage() 函数。

是否有可能以更好、更安全的方式发送消息,这样就不可能使用 android 中的本机 SMS API 窃取您的数据?如果不是什么替代方案,我可以去实施相同的方案。

4

3 回答 3

10

这是我已经实现的,它的工作方式正是我想要的。

输入电话号码和短信后调用此方法。

private static final int MAX_SMS_MESSAGE_LENGTH = 160;
private static final int SMS_PORT = 8901;
private static final String SMS_DELIVERED = "SMS_DELIVERED";
private static final String SMS_SENT = "SMS_SENT";

private void sendSms(String phonenumber,String message) { 

    SmsManager manager = SmsManager.getDefault();
    PendingIntent piSend = PendingIntent.getBroadcast(this, 0, new Intent(SMS_SENT), 0);
    PendingIntent piDelivered = PendingIntent.getBroadcast(this, 0, new Intent(SMS_DELIVERED), 0);

byte[] data = new byte[message.length()];

for(int index=0; index<message.length() && index < MAX_SMS_MESSAGE_LENGTH; ++index)
    {
       data[index] = (byte)message.charAt(index);
    }

manager.sendDataMessage(phonenumber, null, (short) SMS_PORT, data,piSend, piDelivered);

}



 private BroadcastReceiver sendreceiver = new BroadcastReceiver()
 {
         @Override
         public void onReceive(Context context, Intent intent)
         {
                 String info = "Send information: ";

                 switch(getResultCode())
                 {
                         case Activity.RESULT_OK: info += "send successful"; break;
                         case SmsManager.RESULT_ERROR_GENERIC_FAILURE: info += "send failed, generic failure"; break;
                         case SmsManager.RESULT_ERROR_NO_SERVICE: info += "send failed, no service"; break;
                         case SmsManager.RESULT_ERROR_NULL_PDU: info += "send failed, null pdu"; break;
                         case SmsManager.RESULT_ERROR_RADIO_OFF: info += "send failed, radio is off"; break;
                 }

                 Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();

         }
 };

 private BroadcastReceiver deliveredreceiver = new BroadcastReceiver()
 {
         @Override
         public void onReceive(Context context, Intent intent)
         {
                 String info = "Delivery information: ";

                 switch(getResultCode())
                 {
                         case Activity.RESULT_OK: info += "delivered"; break;
                         case Activity.RESULT_CANCELED: info += "not delivered"; break;
                 }

                 Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();
         }
 };

您的消息接收者应如下所示:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.telephony.SmsMessage;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

public class MySMSReceiver extends BroadcastReceiver {

String action,from,message;

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


     action=intent.getAction();

    Bundle bundle = intent.getExtras();        
    SmsMessage[] msgs = null;


        if(null != bundle)
        {
            String info = "Binary SMS from ";
            Object[] pdus = (Object[]) bundle.get("pdus");
            msgs = new SmsMessage[pdus.length];

            byte[] data = null;

            for (int i=0; i<msgs.length; i++){
                msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);                
                info += msgs[i].getOriginatingAddress();                    
                info += "\n*****BINARY MESSAGE*****\n";
                from= msgs[i].getOriginatingAddress(); 
                data = msgs[i].getUserData();

                for(int index=0; index<data.length; ++index) {
                   info += Character.toString((char)data[index]);
                   message += Character.toString((char)data[index]);
                }
            }

        }

    Intent showMessage=new Intent(context, AlertMessage.class);
    showMessage.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    showMessage.putExtra("from", from);
    showMessage.putExtra("message", message);
    context.startActivity(showMessage);

}

}

我创建了一个简单的活动 AlertMessage.java 来显示收到的消息。

我在 Manifest 中注册广播接收器的方式:

 <receiver android:name=".MySMSReceiver">
     <intent-filter>
        <action android:name="android.intent.action.DATA_SMS_RECEIVED" /> 
        <data android:scheme="sms" /> 
        <data android:port="8901" />      
     </intent-filter> 
 </receiver>

这里提到的端口必须与我们在方法 sendSMS() 中指定的用于发送消息的端口相同。

更新 :

工作项目的 Github 存储库

https://github.com/pyus-13/MySMSSender

于 2013-11-22T20:12:52.940 回答
3

在我看来这是可能的。您可以为您的应用设置更高的优先级,例如

<intent-filter android:priority="100"> 

在您的 manifest.xml 中。这样所有消息都会首先通过您的应用程序,您可以将这些消息存储在您的数据库中。同时,如果您要中止广播,请说

abortbroadcast();

您也不会在任何地方收到任何通知。

于 2013-10-02T09:15:30.727 回答
2

无法以任何方式阻止默认消息应用程序接收 SMS 消息,因为您的应用程序无法更改其他应用程序的权限。

于 2013-10-02T06:54:44.740 回答