Unable to catch SMS received with android.provider.Telephony.SMS_RECEIVED - android

I am not able to catch the intent when a SMS is received. Below is my code of the service. I am able to catch the "Intent.ACTION_SCREEN_ON" and "Intent.ACTION_SCREEN_OFF" but I am NOT able to catch the SMS_RECEIVED intent "android.provider.Telephony.SMS_RECEIVED".
Sincerely appreciate any hints on what I am doing wrong here?
public class SmsCatcher extends Service{
BroadcastReceiver myBroadcast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("myBroadcast SmsCatcher", "Entered onReceive method");
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.i("myBroadcast SmsCatcher", "Caught SCREEN_OFF");
}
if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.i("myBroadcast SmsCatcher", "Caught SCREEN_ON");
}
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Log.i("myBroadcast SmsCatcher", "SMS_RECEIVED");
}
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("neil SmsCatcher", "Entered onCreate() in 'SmsCatcher extends Service'");
Toast.makeText(this, "Entered onCreate() in 'SmsCatcher extends Service'", Toast.LENGTH_LONG).show();
registerReceiver(myBroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON));
registerReceiver(myBroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF));
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("neil SmsCatcher", "Entered onDestroy() in 'SmsCatcher extends Service'");
Toast.makeText(this, "Entered onDestroy() in 'SmsCatcher extends Service'", Toast.LENGTH_LONG).show();
}
}
UPDATE 1: Adding some more information from my ongoing debug:
I used the App Internal Broadcasts Monitor to see there is a broadcast when there is a text message received and I dont see anything, very strange. What could be the reason?
I have other SMS apps installed (Hangout, AT&T Messages) - these cant suppress the broadcast can they?
UPDATE 2: FOUND PROBLEM BUT DONT KNOW HOW TO SOLVE
I uninstalled the Google Hangouts (replaces Talk) app and it WORKS!!!
Any solution around this? (should i be opening a separate thread as per stackoverflow rules?)
UPDATE 3: FOUND ROOTCAUSE (with help below of course, thank you)
It turns out that because of the new Google Hangouts App, I needed to setPriority(int). I found the solution at Enabling SMS support in Hangouts 2.0 breaks the BroadcastReceiver of SMS_RECEIVED in my app

You need to register the android.provider.Telephony.SMS_RECEIVED intent filter,only if you have registered it you can able to check the intent in the onRecive like
IntentFilter filter = new IntentFilter(android.provider.Telephony.SMS_RECEIVED);
this.registerReceiver(myBroadcastReceiver, filter);
Update From the question:
It turns out Google Hangouts App aborts the sms broadcast as soon as it receives it,So disabling SMS support in Hangouts 2.0 may fix the issue.

You did not register the intent-filter:
#Override
public void onCreate() {
// ..
registerReceiver(myBroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON));
registerReceiver(myBroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF));
registerReceiver(myBroadcast, new IntentFilter("android.provider.Telephony.SMS_RECEIVED")); // missing in your code
}
And please check your permissions for android.permission.RECEIVE_SMS in AndroidManifest.xml.

Related

Receiving data in activity from a service

I've look at many solutions to other questions with similar issues but I can't figure out what's wrong with my code. I understand that LocalBroadcast is a popular way to do this and I've spent time trying to implement it. At the moment, the receiver isn't declared in my manifest but from what I understand, that's what the register lines are for.
In my activity:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MyActivity", "onReceive");
String action = intent.getAction();
int current = intent.getIntExtra("test", 0);
Toast.makeText(MyActivity.this, current.toString(), Toast.LENGTH_LONG).show();
}
};
#Override
public void onResume() {
super.onResume();
Log.d("MyActivity", "onResume()");
LocalBroadcastManager.getInstance(MyActivity.this).registerReceiver(
mMessageReceiver, new IntentFilter("currentUpdate"));
}
#Override
protected void onPause() {
Log.d("MyActivity", "onPause()");
LocalBroadcastManager.getInstance(MyActivity.this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
In the service I have a method defined:
private void sendNewBroadcast(Intent intent, int current){
intent.putExtra("test", current);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Log.d("MyService", "new Broadcast sent from service");
}
and I use it like this elsewhere in the service:
Intent intent = new Intent("currentUpdate");
sendNewBroadcast(intent, 5);
I've debugged and everything seems to be working except for the 'receiving' part. Am I missing something? The service is started in a different activity and is ongoing.
Firstly, the action String on the broadcast Intent needs to match the action set on the IntentFilter you're registering the Receiver with. Originally, they were different, but it was possibly just a typo.
Secondly, LocalBroadcastManager does not work across processes. The Activity and the Service must be running in the same process to be able to use LocalBroadcastManager. If the Service needs to be in a separate process, you'll have to use some other mechanism; e.g., Intents, broadcasts sent and received on a Context, some event bus implementation that supports IPC, etc.

Uninstall App from device

I want to remove app from device, as i perform uninstall , app must removed from the ArrayList and update the app drawer like wise.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
registerReceiver(new RefreshApps(), filter);
}
public class RefreshApps extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "App Installed/Removed" ,Toast.LENGTH_SHORT).show();
}
}
You can find out that an app is being removed via a BroadcastReceiver listening for ACTION_PACKAGE_REMOVED. You can find out one has been installed by listening for ACTION_PACKAGE_ADDED. Obviously these work for anything except your own app.

Pass SMS from BroadcastReceiver to Activity

I am creating an SMS app. I can send messages fine, however I cannot get it to receive. I have successfully implemented the functionality to allow the app to be selected as the default SMS application on the device.
The problem I have is that I cannot pass the SMS from the BroadcastReceiver to the Activity that displays messages. I am aware of the ability to use intent.putExtra() for the message and then startActivity(), but what happens if that activity has already been started when the message is received? I do not want to restart the activity every time a new message is received.
There are few ways to skin that cat, one way is to have a receiver inside the Activity something like this
void onResume(){
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mSmsReceiver, filter);
}
void onPause(){
super.onPause();
unregisterReceiver(mSmsReceiver);
}
private BroadcastReceiver mSmsReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Do you stufff
}
};

Receiving same intent broadcast multiple times but only sending once

I have an intent that gets sent under a certain condition. The logs prove it is only sent ONCE, but the receiver is receiving it multiple times milliseconds apart.
10-01 10:09:59.201: I/System.out(13543): SENDER CHECKPOINT
10-01 10:09:59.211: I/System.out(13543): RECEIVER CHECKPOINT
10-01 10:09:59.291: I/System.out(13543): RECEIVER CHECKPOINT
I have confirmed that there is only ONE registration of the Broadcast Receiver and only ONE action filter used with the registered BR. It is only used in a single activity where a service running in another thread broadcasts the intent. Again, the logs substantiate the ONE broadcast and multiple receipts. What's more, the extras are null in the echo receipt.
How can this be? Is it possible the OS is echoing it?
Code that sends the broadcast:
private void sendBroadcast(boolean status, String message, String action){
System.out.println("SENDER CHECKPOINT");
Intent intent = new Intent(action);
Bundle bundle = new Bundle();
bundle.putBoolean("status", status);
bundle.putString("message", message);
intent.putExtras(bundle);
sendBroadcast(intent);
}
Code that receives the broadcast:
private class displayUpdate extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("RECEIVER CHECKPOINT");
};
}
Registration:
#Override
public void onResume() {
super.onResume();
try {
// just in case onResume is called w/o a pause
try{activity.unregisterReceiver(displayReceiver);}catch(Exception e){}
filterRefreshUI = new IntentFilter(REFRESH_UI);
activity.registerReceiver(displayReceiver, filterRefreshUI);
} catch (Exception e) {
e.printStackTrace();
}
}
Unregistration:
#Override
public void onPause() {
super.onPause();
try{unregisterReceiver(displayReceiver);}catch(Exception e){}
}
REALLY IT'S THAT SIMPLE! Yet the receiver fires TWICE!
In case you were wondering - Registration/Unregistration are handled in the onPause/onResume to prevent leaking memory if the App is killed by the OS.

Dock and screen off broadcast service

First,I have searched for the question and found about 2-3 stackoverflow links but I dont get a definite answer.Basically,my app needs to start a activity when the phone is docked (any type of dock) or when screen is off.I registered a broadcast receiver in manifest:
<receiver android:name=".BootReciever">
<intent-filter >
<action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
<action android:name="android.intent.action.SCREEN_OFF"/>
</intent-filter>
</receiver>
And in my class:
public class BootReciever extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(Intent.ACTION_DOCK_EVENT)){
//work for dock
}
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
//work for screen off
}
}
}
But both doesnt work.My work is not done is both the cases.I read about I have to do it in services but since I have never worked with my own service and I fell android.developers.com is a bit of pro friendly,I have difficulty getting it to work.Can somebody say me how to I achieve the above?And my app has to listen for it as long service.So even when my app isnt in foreground.Thanks for your help.
The SCREEN_OFF has definitely to be registered programatically (see this link for instance, it'a a protected intent):
public class MainActivity extends Activity {
BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG", "on or off");
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
Log.d("TAG", "Register receiver");
registerReceiver(receiver, filter);
} catch (Exception e) {
Log.d("TAG", "Caught: " + e.getStackTrace());
}
}
#Override
public void onDestroy() {
super.onDestroy();
try {
Log.d("TAG", "Unregister receiver");
unregisterReceiver(receiver);
} catch (Exception e) {
Log.d("TAG", "Caught: " + e.getStackTrace());
}
}
}
For the ACTION_DOCK_EVENT I would assume something else being wrong. May be it doesn't work due to the combination with ACTION_SCREEN_OFF, may be it's due to a naming issue (I wouldn't expect a relative path for .BootReciever, for instance; check, if a full qualified class name works).
Hope this helps .... Cheers!
Receivers for these kinds of intents need to be registered dynamically in the code.
this.receiver = new BootReceiver();
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_DOCK_EVENT);
this.registerReceiver(receiver, filter);
You could do this in any activity (register in onStart(), un-register in onStop(), see visible lifetime section) or in you application object.
The problem with dynamic registration though is your application has to be started before BootReceiver can receive intents.

Categories

Resources