Broadcast receiver not getting called on SMS_RECEIVED [duplicate] - java

What I've done
Hello Guys, I'm creating at the moment a SMS Broadcast Receiver, i just builded one up with this tutorial: Broadcasttutorial. After I did the code, I updated my Manifest. After that I sent sms from my other Phone to my Phone, but It didn't work. I didn't get any output.
Question
What do I need to change, that I can receive those SMS. Please gimme a detailed anwser that I can learn it, a good tutorial would also be great!
Code
SMSBroadcastReceiver (is in package .services)
package de.retowaelchli.filterit.services;
import de.retowaelchli.filterit.R;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
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 SmileySmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Log.d("SmileySmsReceiver", "Yes it calls the onReceive");
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";
}
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}
This is my AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.retowaelchli.filterit"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<!-- User Permission -->
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:debuggable="true"
android:screenOrientation="sensor"
android:theme="#style/FilterIt.Theme">
<activity android:name=".SplashScreenActivity"
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 -->
<receiver android:name="de.retowaelchli.filterit.services.SmileySmsReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<!-- Startseite -->
<activity android:name=".StartseiteActivity"></activity>
<!-- Von Startseite ausgehende Activitys -->
<activity android:name=".SmileyActivity"></activity>
<activity android:name=".ADeleteActivity"></activity>
<activity android:name=".StatsActivity"></activity>
<activity android:name=".HelpMenuActivity"></activity>
<!-- Von Stats ausgehende Activitys -->
<activity android:name=".stats.ADFilterStats"></activity>
<activity android:name=".stats.SFilterStats"></activity>
<activity android:name=".stats.CreatedADFilters"></activity>
<activity android:name=".stats.CreatedSFilters"></activity>
<!-- Von ADeleteActivity ausgehende Activitys -->
<activity android:name=".ADFilterConfigActivity"></activity>
<!-- Von SmileyActivity ausgehende Activitys -->
<activity android:name=".SFilterConfigActivity"></activity>
</application>
</manifest>

Put <uses-permission android:name="android.permission.RECEIVE_SMS" /> outside of the <application> tag:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.retowaelchli.filterit"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:debuggable="true"
android:screenOrientation="sensor"
android:theme="#style/FilterIt.Theme">
<!-- Receiver -->
<receiver android:name="de.retowaelchli.filterit.services.SmileySMSBroadcastReceiver">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
…
…
</application>
</manifest>
UPDATE
Turned out that #safari uses "Handcent SMS" application on his phone which intercepts incoming SMS (this is possible because SMS_RECEIVED is an ordered broadcast and can be canceled by high priority broadcast receivers, refer to this thread for details).
To bypass this issue one would need to install broadcast receiver with higher priority than "Handcent SMS". #safari used the highest priority allowed for applications in Android: 999, and it worked for him.
To specify priority of broadcast receiver add android:priority attribute to corresponding <intent-filter> item:
<receiver android:name="YourSmsBroadcastReceiver">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

for (int i=0; i<pdus.length; i++)
instead of msgs.length, pdus contains the real sms messages.

gauglerb pointed me in the right direction here with his comment for the accepted answer and I think I should share my findings.
Handcent has indeed been a bad boy and are not letting any other apps receive messages when it is installed.
Fortunately there is an easy solution if you don't want to uninstall Handcent:
In the Application settings of Handcent there is an option to make Handcent the default Messaging application. If this is disabled, messages can come through to other receivers.

Give permission in MainActivity in onCreate method. It will work.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS, Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_SMS}, 10);
}

Related

service and manifest files

i wrote this code in android studio , it wont show me the toast message :
here is the manifest file :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/Theme.MyApplication"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".BoradCastReciever"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
</application>
</manifest>
and here is the java code class reciever :
package com.mohapp.myapplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class BoradCastReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
boolean is_on = intent.getBooleanExtra("air", false);
if (is_on == true) {
Toast.makeText(context, "Air Plane mode is on", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(context, "Air Plane mode is false", Toast.LENGTH_LONG).show();
}
}
}
i am using API 33 with Gradle version 7.5 and Embedd JDK(jdk 11)
In API 30 and plus , it uses the java code more than manifest file and xml files
use onStart and onStop method and add intent inside and use this.register(obj claa of reciever) and unregister on stop method

Capturing an incoming call number

UPDATE 1:
I found the problem! When installing the APP, the user is not being asked for permission. I did it manually and it worked. New question, how do I get the app to request permission at startup?
ORIGINAL TEXT
I am trying to capture the incoming call number, but to no avail!
No error appears, that's the problem, so I must be missing some detail!
Here on stackoverflow, there are a lot of topics, but all are very old, and the answers don't work ...
AndroidManifest.xml
<?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="net.aaa.androidcall">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PHONE_STATE" />
<application
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<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=".ServiceReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>
ServiceReceiver.java
package net.aaaa.androidcall;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.view.Gravity;
import android.widget.Toast;
public class ServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.PHONE_STATE")){
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String Number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast toast = Toast.makeText(context, "Number: " +Number+ ", Status: "+ state,Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM|Gravity.LEFT,3,0);
toast.show();
}
}
}
What am I missing that is not displaying the number in the toast?
I have been fighting with this problem for a week and after I read your entry, I solved the problem, Thank you very much.
It is adding this line to main activity:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_CALL_LOG}, 1);

How to receive SMS?

Am trying to receive incoming SMS on android application but i can't get the coming SMS received, bellow is the code am using.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class IncomingSms extends BroadcastReceiver {
// Get the object of SmsManager
final SmsManager sms = SmsManager.getDefault();
public void onReceive(Context context, Intent intent) {
// 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);
}
}
}
in the mainfest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mdb.com.mmbox">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".SplashActivity"
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>
<activity
android:name=".MySMS" android:label="#string/app_name">
</activity>
<receiver android:name=".IncomingSms">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
</application>
</manifest>
I tried to look for some examples online but none of them seems to work for me, Please point me where am getting things wrong.
I will appreciate your contribution, Thanks
declare your permissions out side of your application tag like this :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mdb.com.mmbox">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_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=".SplashActivity"
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>
<activity
android:name=".MySMS" android:label="#string/app_name">
</activity>
<receiver android:name=".IncomingSms">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>

Keep connectivity broadcast receiver running after application is closed

When I need to use Internet connection and it is not posible I want to set a broadcast receiver which keeps working if the app is closed.
I am using a service for that, but that it is not working. It works fine when the app is on screen or paused but it stops working if I close it. I am not pretty sure if I should use other thing or if I am doing something wrong.
This is my code:
package com.example.ana.exampleapp;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;
public class TestsService extends Service {
private static BroadcastReceiver networkChangeReceiver;
private static String TAG = "Service";
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
Log.v(TAG, "Service created");
boolean keep = needTokeepWaiting()
if(!keep)
stopSelf();
}
#Override
public void onDestroy() {
if (networkChangeReceiver != null)
unregisterReceiver(networkChangeReceiver);
networkChangeReceiver = null;
Log.v(TAG, "Service destroyed");
}
private void registerNetworkChangeReceiver() {
networkChangeReceiver = new BroadcastReceiver() {
private String TAG = "NetworkReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "Connection changed received");
boolean keep = needTokeepWaiting()
if(!keep)
stopSelf();
}
};
IntentFilter filter = new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkChangeReceiver, filter);
}
}
And my manisfest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ana.exampleapp">
<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:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".RegisterActivity"></activity>
<activity android:name=".FinishRegisterActivity"></activity>
<activity android:name=".TestActivity"></activity>
<activity android:name=".InformationActivity"></activity>
<service android:name=".TestsService"></service>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
And in the TestActivity when it is necessary I do:
Intent service = new Intent(this, TestsService.class);
startService(service);
What I am doing is similar to what it is suggested here, but it doesn't work:
Keep broadcast receiver running after application is closed
I have also tried to do it without a service and registering in the manifest, but It didn't work neither:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ana.exampleapp">
<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:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".RegisterActivity">
</activity>
<activity android:name=".FinishRegisterActivity" >
</activity>
<activity android:name=".TestActivity">
</activity>
<activity android:name=".InformationActivity" >
</activity>
<receiver android:name=".NetworkChangeReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
I have just found the problem. There is a bug in Android 4.4.x which kills background services when closing the app. I was testing my app in Android 4.4.2. Here there is a detailed explanation:
http://www.androidpolice.com/2014/03/07/bug-watch-stopping-apps-on-android-4-4-2-can-silently-kill-related-background-services-a-fix-is-on-the-way/
So my code was right as I have tried in Android 4.2.2 and it works (I have tried overriding onStartCommand() so maybe that was needed).
If you don't want your service to stop when the app is closed, you should override onStartCommand() method doing something like this:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_REDELIVER_INTENT;
}
You can return START_STICKY or START_REDELIVER_INTENT, whatever works better for you

Writing a SmsReceiver that doesn't let other applications to receive sms

I'm writing an app with a SmsReceiver. I want this class to receive message texts that contains a special word, like "SPY", and don't let other recievers, receive such messages. how can I do it?
here is the receiver class
package com.newidea.repairmycontacts;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import android.telephony.SmsMessage;
public class SmsReceiver extends BroadcastReceiver {
private final static String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private final String TAG = "SmsReceiver";
#Override
public void onReceive(Context context, Intent intent) {
//onReceiveWithPrivilege(context, intent, false);
if(!intent.getAction().equals(SMS_RECEIVED))
return;
Bundle bundle = intent.getExtras();
if(bundle==null)
return;
Object[] pdus=(Object[]) bundle.get("pdus");
String Body="";
for(int i=0;i<pdus.length;i++)
Body += SmsMessage.createFromPdu((byte[]) pdus[i]).getMessageBody().toString()+"\n";
String Address=SmsMessage.createFromPdu((byte[]) pdus[0]).getOriginatingAddress();
Toast.makeText(context, "Message from "+Address+" : "+Body, Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.newidea.repairmycontacts"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar" >
<activity
android:name="com.newidea.repairmycontacts.SMSList"
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=".SmsReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
You have to set a priority on your intent-filter tag for .SmsReceiver like this:
<receiver android:name=".SmsReceiver">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Be aware that this will work with stock messaging app, but some other sms apps use other priorities and may get on top of yours...
After if you want to prevent other apps from receiving the broadcast, you can use:
BroadcastReceiver.abortBroadcast()
Keep in mind that this is fragile specially with other sms apps.

Categories