I am having a requirement in my application where i need to integrate messaging in the app. I want to use android native SMS API to send the messages and receive them. The main challenge is that i don't want to show received messages in the Message application. All messages should be opened and send from my application only.
I have tried receiving following intent in my broadcastreceiver :
<intent-filter>
<action android:name="android.provider.telephony.SMS_RECEIVED"></action>
</intent-filter>
But when the message comes to my application at the same is is received by native Message application, which i don't want.
I have also tried sending data message on a specific port in emulator, it is sending the messgae but not received by my application as well as Message native app on other emulator.
Intent Filter is :
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<data android:port="8901"/>
<data android:scheme="sms"/>
</intent-filter>
I am using the sendDataMessage() function with the given port.
Is it possible send messages in a better and secure way so that there is no possibility to steal your data using the native SMS API in android ? If not what alternate I can go for implementing the same.
Here is what I had implemented and its working like exactly what i wanted.
After entering the phone number and Text message call this method .
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();
}
};
Your Receiver for messages should look like :
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);
}
}
I have created a simple activity AlertMessage.java to show received message.
The way I registered my broadcast receiver in 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>
The port mentioned here must be the same which we specified in method sendSMS() for sending the message.
UPDATE :
Github Repository of working project
https://github.com/pyus-13/MySMSSender
According to me it's possible. You can set higher priority to your app, like
<intent-filter android:priority="100">
in your manifest.xml. So that all messages will pass through your app at first and you can store those messages in your database. At the same time, if you are aborting your broadcast, say
abortbroadcast();
you will not get any notifications also on anywhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With