I wanted to write an app to encrypt all incoming Messages. So I received SMS and after encryption I put encrypted SMS on Messages inbox without any problem:
package org.appsroid.smsmodifier;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.SmsMessage;
public class SmsReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
String address = msgs[i].getOriginatingAddress();
String body = msgs[i].getMessageBody().toString();
/*
* Some codes to encrypt body ...
*/
/*
* Add Encrypted SMS to Messages inbox
*/
}
// Delete plain SMS
abortBroadcast();
}
}
}
Now, I need to add a custom content menu to built-in Android Messages context menu to let user to decrypt message body. Any Suggestion?
First, there is no single "built-in Android Messages" app. There dozens, perhaps hundreds, across different device models. Few will have a context menu, fewer still will offer any means for you to modify it. Beyond that, there are many more SMS client apps available on the Play Store and elsewhere that the user may already be using.
Second, your "put encrypted SMS on Messages inbox" code will not work on Android 4.4+, unless you write a complete SMS client, as only the SMS client can write to the SMS ContentProvider.
Hence, you will need to write your own SMS client, both to be able to decrypt your messages and to be able to have it work at all on Android 4.4 and higher. Then, you will need to convince people that your SMS client, given its encryption capabilities, is worth using instead of their current SMS client.
Related
I want to open incoming sms from notification directly to my application's intent , Please help I tried following code to read sms from inbox
public class SmsReceiver extends BroadcastReceiver
{
public static String BODY = "Test";
public static String ADDRESS = "5556";
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
ADDRESS=msgs[i].getOriginatingAddress();
BODY=str;
}
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
When a new SMS is received by your device, the android creates a intent and broadcasts the SMS_RECEIVED_ACTION. What you are going to do is create an Intent Filter for the activity of your application that handles the SMS that the phone receives.
When the phone gets a new SMS message and the user clicks on the notification, she is presented with a dialog of apps that can handle this action*****. Your app should be there, and when she decides that she wants your app to handle the incoming message then you can use the getMessagesFromIntent method in order to extract the message (you use that method inside your app).
PS: You cannot set your app as the default message app, which you probably need to do. The user has to explicitly choose your app to open the message, and if she wants it to be the default messaging app (by ticking the set as default checkbox).
Note: It looks like you have to create a broadcast receiver that receives the SMS_RECEIVED_ACTION which you can use prior to API 19 as a constant at android.provider.Telephony.SMS_RECEIVED and launch your own notifications in which you direct the user directly to the application of yours. Unfortunately it seems that the default messaging app will still issue notifications.
Credit: #Mike M.
I am sure I must just be missing something obvious but this is currently baffling me.
I have a class which extends BroadcastReceiver this class is setup as a receiver int he manifest and it does correctly capture the sms received intent.
package gull.sana.textit;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("SMSReceiver", "Intent received");
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
}
Log.d("SMS", str);
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}
Now when I send in an SMS message I always get the first log message Log.d("SMSReceiver", "Intent received"); and I always get the Toast as I would expect, however, I never get the Log.d("SMS", str);
Am I doing something wrong? Why does the Toast appear yet the log on the line before never does?
It turns out that there are several buffers for log messages. The tags decide which buffer these logs go into. According to this https://stackoverflow.com/a/9011945/1475461 SMS is one of those tags that gets put into a different buffer.
The other buffer can be viewed with the following command
adb logcat -b radio
Thanks to #nKn for getting me along the right tracks.
This seems to be an old known issue when you use Log.* in combination with a tag called SMS. There seems not logical explaination to this but your code is working accordingly, it's just the Log.d() line that is not working correctly.
You should replace the tag SMS with some other, in that case it should work as expected (in this case, avoiding the bug).
I want my program to be able to receive sms from a special number("+9856874236"). But, if the SMS is from any other number, it should go to the phone's message inbox and not to my application.
please help me my dears
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
public class receiver extends BroadcastReceiver {
public String str = "";
#Override
public void onReceive(Context context, Intent intent) {
// ---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++)
{
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
//for get sms from special number===============================
String msg_from = msgs[i].getOriginatingAddress();
Log.v("msg_from >>",msg_from);
if(msg_from.equals("+9830007546"))
{
//===============================
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
Intent act = new Intent(context, ReceiveSMS.class);
act.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
act.putExtra("message", str);
context.startActivity(act);
this.abortBroadcast();
}
}
// ---display the new SMS message---
// Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}
main class :
private TextView showSms;
private String ReceivedSms;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//this.setContentView(R.layout.receivesms);
/*Removing system bar from screen*/
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.receivesms);
Intent act = getIntent();
ReceivedSms = act.getStringExtra("message");
showSms = (TextView) this.findViewById(R.id.textView2);
showSms.setText(ReceivedSms);
Give your BroadcastReceiver a high priority in your AndroidManifest. This will put your receiver first in line to process the broadcast.
<receiver
android:name=".SmsReceiver">
<intent-filter
android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Inside your BroadcastReceiver, check if the number of the incoming sms equals your given number. If true, then cancel the broadcast with abortBroadcast().
Edit
There are a couple of things to watch out for:
When you do the number matching, be aware of phone number formatting. If the incoming number is 0123456789 and you use String.equals('+XX0123456789'), then your check will fail, even though its technically correct. Have a look at PhoneNumberUtils to find a solution for this.
If I recall correctly, some device manufacturers have given the default SMS application priority one on processing sms broadcasts. This will mess with your application. Be sure to test this out ;)
Assuming you meant to say that your special number should not show up in the inbox...
You cannot re-route the message being received by the phone. So instead you have to upon receiving that message then look it up in the MMS database and delete it, there is no other way.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can we delete an SMS in Android before it reaches the inbox?
I've already gotten receive SMS code running successfully. What I cannot determine is a way (or if it's possible) to process messages sent from specific phone numbers within my app without them being made visible to the user. All other SMS's sent from other phone number would be handled by the normal Android SMS processing. I.e., SMS's from selected numbers should not be visible to the phone user and the rest should. Any suggestions?
Here's the SMSReceiver code (taken straight from Wei-Meng Lee's book):
public class SMSReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//get the received SMS message
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null) {
// retrieve the SMS message
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += "\nMessage Text:\n";
str += msgs[i].getMessageBody().toString();
str += "\nLength="+msgs[i].getMessageBody().toString().length()+"\n";
} // [END FOR]
// display the new SMS message
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
// 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);
} // [END IF]
} // [END onReceive]
} // [END SMSReceiver]
well if you put an if before you start concatenating str, you can check the originating address, and compare it to your blacklist of addresses, if its on the list, then simply use the continue to skip the concatenations
I want to read sms sent by user in my application before it sent. Is there any way to accomplish this?
This is not possible. Any application can use SmsManager to send an SMS, and such messages cannot be intercepted, except perhaps by custom firmware.
You cant block an outgoing sms.You can find out about it only after it has been sent. And you can do it by registering a content observer for sms, when the sms comes to sent box.
You may intercept incoming messages if you want.
Here is an example of a SMS interceptor that "cancels" the SMS if it contains some custom defined data:
For your application to receive the message before it shows up in the phone you will have to define a receiver in the manifest with a high priority. Example:
<receiver android:name=".SMSReceiver">
<intent-filter android:priority="9999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Then, create the receiver:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver{
private static final String CRITICAL_MESSAGE = "critical";
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null){
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
if (msgs[i].getMessageBody().toString().equals(CRITICAL_MESSAGE)){
str = "Critical msg from " + msgs[i].getOriginatingAddress() + " !";
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
abortBroadcast();
}
}
}
}
}
The above receiver cancels the SMS (aborts broadcast) if critical string is received.