I am trying to make a simple app that will forward all messages with particular body to another number.
Broadcast receiver in my class is not being called. Any leads will be appreciated
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Settings.Applog("App started !!");
Intent intent = new Intent(this, SMSService.class);
startService(intent);
}
SMSService.java
public class SMSService extends Service {
private IntentFilter mIntentFilter;
private SMSreceiver mSMSreceiver;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate()
{
super.onCreate();
Settings.Applog("Service started !!");
//SMS event receiver
mSMSreceiver = new SMSreceiver();
mIntentFilter = new IntentFilter();
mIntentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mSMSreceiver, mIntentFilter);
}
#Override
public void onDestroy()
{
super.onDestroy();
// Unregister the SMS receiver
unregisterReceiver(mSMSreceiver);
}
private String ConvertNumber(String from){
return from;
}
public class SMSreceiver extends BroadcastReceiver
{
private final String TAG = this.getClass().getSimpleName();
#Override
public void onReceive(Context context, Intent intent)
{
Bundle bundle = intent.getExtras();
String strMessage = "";
Settings.Applog("Got a message!!");
if ( bundle != null )
{
try{
Object[] pdus = (Object[]) bundle.get("pdus");
SmsMessage[] msgs = new SmsMessage[pdus.length];
for(int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
String msg_from = msgs[i].getOriginatingAddress();
String msgBody = msgs[i].getMessageBody();
Settings.Applog("Message body ::"+msgBody);
}
}catch(Exception e){
//Log.d("Exception caught",e.getMessage());
}
}
}
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="mypackage">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".SMSService"
android:exported="false">
</service>
</application>
</manifest>
You have to register the Broadcast Receiver for receiving SMS in the manifest file.
Just the permission will not work.
Inside the application tag it would look something like:
<application android:icon="#drawable/icon" android:label="#string/app_name" android:debuggable="true" >
<receiver android:name=".SMSBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
</application>
Use this as an example for receiving the SMS message. It should be a good starting point.
http://javapapers.com/android/android-receive-sms-tutorial/
Related
I can't seem to get a basic sms reading app to work on android. Not sure what am I missing here. I think I have all the basic minimum specified in the code, despite that it seems to be not working. The onReceive() of SmsReceiver is never invoked. All the required permissions are set.
Here are my files.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
//...
//...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestReadAndSendSmsPermission();
smsReceiver = new SmsReceiver() {
#Override
protected void onData(String data) {
//handle
}
};
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
//intentFilter.setPriority(999);
registerReceiver(smsReceiver, intentFilter);
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(smsReceiver);
}
private void requestReadAndSendSmsPermission() {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_SMS},1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS},1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.SEND_RESPOND_VIA_MESSAGE}, 1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.SEND_SMS}, 1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_NETWORK_STATE}, 1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CHANGE_NETWORK_STATE}, 1);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.INTERNET}, 1);
}
//...
//...
}
SmsReceiver.java
public abstract class SmsReceiver extends BroadcastReceiver {
private static final String TAG = "SmsReceiver";
#Override
public void onReceive(Context context, Intent intent) {
if (context == null || intent == null) {
return;
}
String action = intent.getAction();
if (!action.equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
return;
}
//read sms
onData("sms received");
}
protected abstract void onData(String data);
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mysmsapp">
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<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.MySMSApp">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
You are missing defining the receiver entry in AndroidManifest.xml file for your BroadcastReceiver named SmsReceiver please make the entry for it else OS will not know if you have a broadcast receiver waiting to be triggered.
Depending upon what is your use case it might be something like
<receiver
android:name=".SmsReceiver"
android:exported="true"
android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
</intent-filter>
</receiver>
Or
<receiver
android:name=". SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Note: These receiver are sample receiver please use the correct one as per your use case, the main point is you are missing receiver entry in your manifest file
i use this code to read incoming message
public class SmsReceiver extends BroadcastReceiver {
private static final Uri smsuri = Apconsts.smsuri;
private static final String pdu_type = "pdus";
#Override
public void onReceive(Context context, Intent intent){
// Get the SMS message.
Bundle bundle = intent.getExtras();
SmsMessage[] msgs;
String format = bundle.getString("format");
// Retrieve the SMS message received.
Object[] pdus = (Object[]) bundle.get(pdu_type);
String body="";String adrs="";
if (pdus != null) {
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++){
if(Build.VERSION.SDK_INT < 23){ msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); }
else{ msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format); }
adrs=msgs[i].getOriginatingAddress();
body += ""+msgs[i].getMessageBody();
}
Toast.makeText(getApplicationContext(), "The message Body: "+body+"\nThe address: "+adrs, Toast.LENGTH_LONG).show();
}
}
}
and this receiver in manifest
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
I'm currently working on a simple android app. The idea is, it changes the wallpaper automatically after 12 A.M or when the date is changed. It's working on android Oreo and lower versions, however, it doesn't work on android 9(Pie). However, if I change the date manually from the setting of the phone, it calls the broadcast. I have googled a lot, and some suggested to register the broadcast on your java codes instead of Manifest. Unfortunately, it didn't work.
I have tested this question in Stackoverflow.
First of all, changing the date is not part of implicit broadcasts, secondly, I assumed it is. then I changed the codes but it didn't work.
Now I'm gonna provide some codes of my broadcast:
DailyBroadcastReceiverService
public class DailyBroadcastReceiverService extends Service {
private BroadcastReceiver dailyZekrBr;
private Context context;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
registerDailyZekrReceiver();
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(dailyZekrBr);
dailyZekrBr = null;
}
private void registerDailyZekrReceiver() {
context= this.getApplicationContext();
Log.d("Register", "onStart: Now gonna register the broadcast receiver on Daily Boadcast receiver");
dailyZekrBr = new DailyZekrBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addCategory(Intent.CATEGORY_DEFAULT);
filter.addAction("android.intent.action.ACTION_TIME_CHANGED");
filter.addAction("android.intent.action.TIME_SET");
filter.addAction("android.intent.action.DATE_CHANGED");
filter.addAction("android.intent.action.TIMEZONE_CHANGED");
this.registerReceiver(dailyZekrBr, filter);
}
}
DailyZekrBroadcastReceiver
public class DailyZekrBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("DailyZekrBroadcast", "onReceive:The broadcast is called ");
DailyZekrHandler.setTodayImage(context);
}
}
setTodayImage
public static void setTodayImage(Context context) {
int todayImage = DailyZekrHandler.nameOfTheWeek();
DisplayMetrics metrics = new DisplayMetrics();
WindowManager window = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
window.getDefaultDisplay().getMetrics(metrics);
Log.d("DailyZekrBroadCast", "trying to change imge: " + todayImage);
if(todayImage != DailyZekrHandler.getTodayImage(context)) {
DailyZekrHandler.storeTodayImage(context);
Bitmap tempbitMap = BitmapFactory.decodeResource(context.getResources(), todayImage);
Bitmap bitmap = Bitmap.createScaledBitmap(tempbitMap, metrics.widthPixels, metrics.heightPixels, true);
WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
wallpaperManager.setWallpaperOffsetSteps(1, 1);
wallpaperManager.suggestDesiredDimensions(metrics.widthPixels, metrics.heightPixels);
try {
wallpaperManager.setBitmap(bitmap);
Log.d("DailyZekrBroadCast", "today_image: " + todayImage);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ellia.dailyzekr">
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-9778979220370457~9773548477"/>
<receiver android:name=".core.DailyZekrBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_TIME_CHANGED"/>
<action android:name="android.intent.action.TIME_SET"/>
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
</intent-filter>
</receiver>
<service android:name=".core.DailyBroadcastReceiverService"/>
<activity android:name=".SplashActivity" android:theme="#style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
</activity>
</application>
</manifest>
I want to monitor an incoming sms in a phone by making a Toast message pop up when a sms is received. However, with the following code, I don't receive the Toast message even when a sms is received. Why is that so? I'm using Android Studio 3.0.1 and there are no errors when I run the code.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mapp.com.sg.broadcastreceiver">
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
<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">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
public class MainActivity extends Activity {
private static final int NOTIFY_ME_ID = 1337;
private BroadcastReceiver the_receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, "SMS Message Received!", duration);
toast.show();
}
};
private IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
// Register receiver if activity is in front
this.registerReceiver(the_receiver, filter);
super.onResume();
}
#Override
protected void onPause() {
// Unregister receiver if activity is not in front
this.unregisterReceiver(the_receiver);
super.onPause();
}
}
Do as following by adding the receiver in the manifest file
<receiver
android:name=".receivers.SMSReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
and then create SMSReceiver class
public class SMSReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle myBundle = intent.getExtras();
SmsMessage[] messages;
if (myBundle != null) {
Toast toast = Toast.makeText(context, "SMS Message Received!",duration);
}
}
}
I want to handle received SMS using BroadcastReceiver. If new sms arrives, new activity will be shown. This is my effort:
public class SMSReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
StringBuilder sb = new StringBuilder();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdus.length; i++) {
//yes, I need PDU
sb.append(pdus[i]);
}
}
Intent result = new Intent(context, MainActivity.class);
result.putExtra(Mapping.PDU_TEXT, sb.toString());
result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(result);
}
And activity:
public class MainActivity extends Activity {
private TextView mPDUTextView;
private String pduText;
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(Mapping.PDU_TEXT, pduText);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
pduText = savedInstanceState.getString(Mapping.PDU_TEXT);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
if (getIntent().getExtras() != null) {
pduText = this.getIntent().getExtras()
.getString(Mapping.PDU_TEXT);
}
}
mPDUTextView = (TextView) this.findViewById(R.id.pduTextView);
mPDUTextView.setText(pduText);
}
}
Also take a look at the manifest:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.BROADCAST_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name="ru.tenet.pdureceiver.SMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<data android:scheme="sms" />
<data android:port="8998" />
</intent-filter>
</receiver>
<activity
android:name="ru.tenet.pdureceiver.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>
</application>
I've installed my app at real device. If I send message, no activity will run. What is wrong?
Just try this instead:
<intent-filter android:priority="1" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
I am new to android and I am trying to learn by doing some basics projects. The current app I am working on requires me to use BroadcastReceiver, but I need it to run when the phone starts and when the app closes.
I need it to receive all the incoming SMS, even when the app is not running.
Currently I have a startForeground which uses a notification to run. Is there a way to make the app run without the notification?
Please help. Here is my code:
public class IncomingSMS extends Service {
// Get the object of SmsManager
final SmsManager sms = SmsManager.getDefault();
//get audioManager
AudioManager aud;
public void onCreate(){
Log.i("MyActivity", "aaa");
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
registerReceiver(receiver, filter);
registerReceiver(receiver, filter);
Notification notification= new Notification();
startForeground(1, notification);
}
public void onDestroy(){
unregisterReceiver(receiver);
Log.i("MyActivity", "Destroyed");
}
public int onStartCommand(Intent intent, int flags, int startId){
return START_STICKY;
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Retrieves a map of extended data from the intent.
Log.i("MyActivity", "aaa");
final Bundle bundle = intent.getExtras();
aud = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
try {
if (bundle != null) {
Log.i("MyActivity", "Bundle");
final Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
String message = currentMessage.getDisplayMessageBody();
Log.i("MyActivity", message);
//Some Code
} // end for loop
} // bundle is null
}catch (Exception e) {
Log.e("SmsReceiver", "Exception smsReceiver" + e);
Log.i("MyActivity", "bbb");
}
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
And AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pi.sum.nesbtesh.SARA" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="......"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="......">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</service>
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="#android:style/Theme.Translucent" />
</application>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>
What you want is a BroadcastRceiever to run on phone startup, here you go. Basically you start your service in its callback.
For when the app closes, I wouldn't say that's quite possible because most of the times when you close an app, it just stats in Stopped but isn't destroyed. So I'd suggest you create a BaseActivity which is an Activity subclass that override onStop() or onPause() and start your service in this method.
Then every other Activity in your app are subclass of BaseActivity