I have read many similar questions that usually results in an answer about priority. The reason I don't think this is true in my case is that other SMS readers on my phone (like automation apps) receive the broadcasts just fine. I would like to post the process of what I'm doing currently and make triple sure that I'm not doing something wrong in my code that would cause this to fail. Thanks for any tips you can give!
Note: I've tried with the highest integer priority, priority 99, 100, 0, or none set at all. They all don't work.
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hennessylabs.appname" >
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.hennessylabs.drivercompanion.ProcessTextMessage" android:exported="true">
<intent-filter android:priority="999" android:permission="android.permission.BROADCAST_SMS">
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
</application>
</manifest>
BroadcastReceiver:
package com.hennessylabs.appname;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Telephony;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
/**
* Created by kyleC on 11/15/2015.
*/
public class ProcessTextMessage extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
final SmsManager sms = SmsManager.getDefault();
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Entered onReceive", Toast.LENGTH_LONG).show();
// Retrieves a map of extended data from the intent.
final Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
final Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
String phoneNumber = currentMessage.getDisplayOriginatingAddress();
String senderNum = phoneNumber;
String message = currentMessage.getDisplayMessageBody();
Log.i("SmsReceiver", "senderNum: "+ senderNum + "; message: " + message);
// Show alert
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, "senderNum: " + senderNum + ", message: " + message, duration);
toast.show();
} // end for loop
} // bundle is null
} catch (Exception e) {
Log.e("SmsReceiver", "Exception smsReceiver" +e);
}
}
}
Expected Result:
The expected result is that when an SMS arrives, the screen would first show a Toast that it entered the OnReceive method. Then it would log and Toast the contents of the SMS.
Actual Result:
Nothing from the expected result happens. In fact even while connected to USB and in debug mode it never seems to enter that class at all. So maybe I have my manifest set up wrong?
Provided everything else is correct, it looks like you're just missing the RECEIVE_SMS permission.
<uses-permission android:name="android.permission.RECEIVE_SMS" />
You are missing some things from the manifest declaration of your receiver. You must declare exported=true and you must require the BROADCAST_SMS permission. See working example:
<receiver android:name=".sms.IncomingSmsReceiver" android:exported="true">
<intent-filter android:priority="999" android:permission="android.permission.BROADCAST_SMS">
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
So what is the version of the device your app is running on?
Begins in Android 4.4, only the default sms app can receive the SMS_DELIVER_ACTION broadcast.
more information: http://android-developers.blogspot.sg/2013/10/getting-your-sms-apps-ready-for-kitkat.html
Related
I am working on an app that will use a BroadcastReceiver to pick up certain SMS messages that meet certain criteria. It's a long way short of finished, mainly because it seems that the BroadcastReceiver isn't working. I've tried to use a toast to check if it's working but I get no result. So either:
The BroadcastReceiver is not working
My method of testing is wrong
Or both
The AndroidManifest.xml file is
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.alert6">
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Alert6">
<activity
android:name=".SendResponseActivity"
android:parentActivityName=".ReceiveAlertActivity">
</activity>
<activity
android:name=".ReceiveAlertActivity"
android:parentActivityName=".MainActivity">
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SmsBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="999" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
And this is the SmsBroadcastReceiver java file
package com.example.alert6;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.provider.Telephony;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"SMS Is Being Received",Toast.LENGTH_LONG).show();
if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
String smsSender = "";
String smsBody = "";
for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
smsSender = smsMessage.getOriginatingAddress();
smsBody = smsMessage.getMessageBody();
}
if (smsSender.equals("+420775367297")) {
if (smsBody.contains("Test")) {
// I haven't done this bit yet
}
}
}
}
}
When I send a SMS to the test device I would expect a toast message saying "SMS Is Being Received". Instead the app disappears from the screen and my default SMS app appears instead. What am I doing wrong?
Since Android API 23 you need set permission not only in manifest class, but also set permisson manually. You should set it in app's settings, or you should make permission reqeust from your code. This is what you need add in your main activity's file:
// constant for request code
private final int MY_PERMISSIONS_REQUEST_SMS_RECEIVE = 10; // any number which you want
//function for permission request
#RequiresApi(api = Build.VERSION_CODES.M)
public void checkPermission() {
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED)) {
requestPermissions(new String[]{Manifest.permission.RECEIVE_SMS}, MY_PERMISSIONS_REQUEST_SMS_RECEIVE);
}
}
Also you need call this function somewhere. For example you can make it in onCreate().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkPermission();
}
//do something else
}
After a huge amount of fiddling and testing, I came to the conclusion that the broadcast receiver is not working. Probably due to Android's limitations on "dangerous" permissions. I don't think this thread has any life left in it, but I will continue to try to persuade my Android app to work with the necessary permissions.
I'm trying to write an appication used to block sms/call from: sender in contact, filtering by number, content. I'm using receiver to handle it.
1. About block call function: What i did below:
#Override
public void onReceive(Context context, Intent intent) {
// get incomingNumber, ...etc
...
// check if need to block this call, if yes: drop call then clear log
if(isNeedToBlock(incomingNumber)) {
abortBroadcast();
telephonyService.endCall();
Utils.deleteLogFromNumber(incomingNumber);
}
}
public static void deleteLogFromNumber(String number) {
String queryString="NUMBER="+number;
context.getContentResolver().delete(CallLog.Calls.CONTENT_URI,queryString,null);
}
By this way, i can block a call now, but there are two issues:
i can't delete the call logs. -> what im i doing wrong please?
Some time, when receving a call (that should be blocked) screen will be turned on, even display the call for a short moment then drop. -> do we have any solution/suggestion?
2. About block sms function: As the code below:
public void onReceive(Context context, Intent intent) { // in SMS Receiver
this.context = context;
final Bundle extras = intent.getExtras();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
long _id = 0;
String address ="";
String messages = "";
// Get received SMS array
Object[] smsExtra = (Object[]) extras.get(SMS_EXTRA_NAME);
for (int i = 0; i < smsExtra.length; ++i) {
SmsMessage sms = SmsMessage.createFromPdu((byte[]) smsExtra[i]);
_id = sms.getIndexOnIcc(); // can't get sms id
address = sms.getOriginatingAddress();
messages += sms.getMessageBody().toString();
}
if (isNeedToBlock(address)) { // need to block
abortBroadcast();
deleteSms(address);
//markAsRead(address);
}
}
}, 2000); // delay 2s to make sure that sms was saved
}
I can delete this sms, but:
Still an pop-up display this sms on screen (the popup from default sms composer on device)
Can't get sms _id for deleting, i have to delete by "address" + some other condition to make sure that my app will not delete some old sms from the "address". (I have to delete the current one only)
One more, i intend to create a option that make all blocked sms as read (don't delete), but i don't know where to start.
=> please give some hint on that.
To be more clearly, the manifest below:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<receiver android:name=".CallReceiver" >
<intent-filter android:priority="2147483647" >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<receiver android:name=".SmsReceiver" android:enabled="true">
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Please help me to give some hint, idea, solution, suggestion... for all of them.
Many thanks!
Hi everyone .
i send message to one device and receive this sms in another device's application.I used Broascast receiver to listen sms body or number .I have taken all permission in manifest but my reciver not call.I have used many thing in 2 days related to manifest like android:priority,android:enabled="true", android:exporte but stiil receiver not working.
/* final SmsManager sms = SmsManager.getDefault();*/
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "in receiver", Toast.LENGTH_SHORT).show();
// TODO Auto-generated method stub
Log.e("out", "out");
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
String msg_from;
Toast.makeText(context, "broad cast reciver", Toast.LENGTH_SHORT).show();
if (bundle != null){
//---retrieve the SMS message received---
try{
Log.e("in", "in");
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]);
msg_from = msgs[i].getOriginatingAddress();
String msgBody = msgs[i].getMessageBody();
}
}catch(Exception e){
// Log.d("Exception caught",e.getMessage());
}
}
}
}
manifest....
<
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_SMS" />
<application android:icon="#drawable/ic_launcher">
<activity android:name=".MainActivity" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".SmsListener" android:enabled="true" android:exported="true" android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
Have your SmsListener extend BroadcastReceiver:
public class SmsListener extends BroadcastReceiver {
public SmsListener() {
}
#Override
public void onReceive(Context context, Intent intent) {
//you code here
}
}
And now you can register your receiver in your main activity:
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
SmsListener smsListener = new SmsListener();
registerReceiver(smsListener, new IntentFilter(SMS_RECEIVED));
Remember to unregister it at the end.
When i uninstalled other application in my device it have also same functionality like my application for example hello application (check out at play store).Then i installed my application it work great.I think another application set priority or other thing in manifest for new incoming sms.So due to this reason our application broadcast receiver not called
Changing the Priority to 1 made it work for me. It defaulted to 1000.
I also had to change the name from .SmsListener to .MainActivity$SmsListener but that would probably depend on where you defined the class (in my case it was within the MainActivity).
<receiver android:name=".MainActivity$SmsListener"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="1">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
I have Read Incoming SMS Content and Blocked the same before entering in to the inbox. The code is Given below:
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 BroadCastReceiver extends BroadcastReceiver
{
/** Called when the activity is first created. */
private static final String ACTION = "android.provider.Telephony.SEND_SMS";
public static int MSG_TPE=0;
public void onReceive(Context context, Intent intent)
{
String MSG_TYPE=intent.getAction();
if(MSG_TYPE.equals("android.provider.Telephony.SMS_RECEIVED"))
{
// Toast toast = Toast.makeText(context,"SMS Received: "+MSG_TYPE , Toast.LENGTH_LONG);
// toast.show();
Bundle bundle = intent.getExtras();
Object messages[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[messages.length];
for (int n = 0; n < messages.length; n++)
{
smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
}
// show first message
Toast toast = Toast.makeText(context,"BLOCKED Received SMS: " + smsMessage[0].getMessageBody(), Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
for(int i=0;i<8;i++)
{
System.out.println("Blocking SMS **********************");
}
}
else if(MSG_TYPE.equals("android.provider.Telephony.SEND_SMS"))
{
Toast toast = Toast.makeText(context,"SMS SENT: "+MSG_TYPE , Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
for(int i=0;i<8;i++)
{
System.out.println("Blocking SMS **********************");
}
}
else
{
Toast toast = Toast.makeText(context,"SIN ELSE: "+MSG_TYPE , Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
for(int i=0;i<8;i++)
{
System.out.println("Blocking SMS **********************");
}
}
}
}
The code works fine on Incoming SMS. Shows the Sms pdu on Toast and blocks the SMS to enter in to Inbox.
But my problem is that same Code is not working for Outgoing SMS. It doesnt blocks the Outgoing SMS. I have registered BroadcastReceiver in the AndroidManifest as follows.
<service android:name=".MyService" android:enabled="true"/>
<receiver android:name="BroadCastReceiver">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_SENT"/>
</intent-filter>
</receiver>
<service android:name=".MyServiceSentReceived" android:enabled="true"/>
<receiver android:name="BroadCastReceiver">
<intent-filter android:priority="2147483645">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<intent-filter>
<action android:name="android.intent.action.SENDTO"></action>
<data android:scheme="smsto"></data>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
and Permissions Like:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
Can anyone please help me What is going wrong and why i am not able to block outgoing SMS. Thanks
Your receiver is invoked only, when action android.provider.Telephony.SMS_RECEIVED is fired. Thus it doesn't react, when SMS is sent.
I am far from being expert, but I think, there is no possibility, to block outgoing messages. The default SMS Application uses android.telephony.SmsManager's method SendDataMessage() that doesn't send any broadcast.
I captured the event while sending the sms , i use an observer on "content://sms/" , i make a query and i get the last sent sms then i delete it : getContentResolver().delete("content://sms/","_id=?",new String[] { message_id});
My problem that this idea work perfectly on Emulator but not on real device.
I would like to retrieve the incoming call's phonenumber and do something with it like the do
in http://blog.whitepages.com/2009/02/27/caller-id-by-whitepages-a-new-android-app-that-puts-telemarketers-on-alert/
Could you please help me because I can't find any information about this.
Where do i start and how do i get hold of the phonenumber?
Ok so currently my code looks like below. When I place the call the CustomBroadcastReceiver catches it and the log message is printed out. I can retrieve the telephone number from the bundle. But! I can't get hte CustomPhoneStateListener to work. As you can see I have registered my customPhoneState listener to the receiver but the log message never get's printed out from the CustomPhoneStateListener class. What am I my missing here?
Is my thinking correct?
<receiver android:name=".CustomBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="5" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
public class CustomPhoneStateListener extends PhoneStateListener {
private static final String TAG = "CustomPhoneStateListener";
public void onCallStateChange(int state, String incomingNumber){
Log.v(TAG, "WE ARE INSIDE!!!!!!!!!!!");
Log.v(TAG, incomingNumber);
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "RINGING");
break;
}
}
public class CustomBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CustomBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "WE ARE INSIDE!!!!!!!!!!!");
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Bundle bundle = intent.getExtras();
String phoneNr= bundle.getString("incoming_number");
Log.v(TAG, "phoneNr: "+phoneNr);
}
Use PhoneStateListener. It has an onCallStateChanged handler; one of the supplied arguments you'll get is a String containing the incoming phone number.
Your overridden method in CustomPhoneStateListener should be called onCallStateChanged() (and not onCallStateChange()).
This would have been spotted by the Java compiler if you would have had the #Override annotation, like you have for onReceive().
The above answers are out-od-dated now. There are valid for Android 7 and lower.
For android 9 and higher you have to add another permission in the Androidmanifest.xml with the permission
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
without the phone number will be null. For Android 8 I am not sure.
PhoneStateReciever.java
package com.incomingcalls;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
public class PhoneStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.e("Incoming Number", "Number is ," + incomingNumber);
Log.e("State", "State is ," + state);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
Toast.makeText(context,"Incoming Call State",Toast.LENGTH_SHORT).show();
Toast.makeText(context,"Ringing State Number is -"+incomingNumber,Toast.LENGTH_SHORT).show();
}
if ((state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))){
Toast.makeText(context,"Call Received State",Toast.LENGTH_SHORT).show();
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context,"Call Idle State",Toast.LENGTH_SHORT).show();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
AnroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.incomingcalls">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".PhoneStateReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>