I have an app that tries to catch SMS messsages from a specific sender and then starts a new activity. When running in Eclipse using Debug As and using emulator my BroadcastReceiver it works great, it hits the breakpoints as expected. When I use Run As in Eclipse to launch in the emulator the SMS messages never get caught. It appears the BroadcastReceiver is never called based on the lack of Log outputs. The SMSes also do not get caught when running on my phone. Any ideas why it works one way but not another?
I have very few apps on my phone and the only one I know of that catches text messages is the built-in messenger one.
<receiver android:name=".sms.ConfirmationResponder">
<intent-filter android:priority="100">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
...
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
The receiver:
public class ConfirmationResponder extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.i("SMS", "############################ Confirmation being read");
// More stuff after this but I don't even get the log message
}
}
Here is my program:
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 SMSBroadcastReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String TAG = "SMSBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Intent recieved: " + intent.getAction());
if (intent.getAction() == SMS_RECEIVED) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
if (messages.length > -1) {
Log.i(TAG, "Message recieved: " + messages[0].getMessageBody());
}
}
}
}
}
And the manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="Technicaljar.SMSBroadcastReceiver"
android:versionCode="1"
android:versionName="1.0">
<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>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
</manifest>
Hope it Helps
I think it works but eclipse is not attached to device when "Run as" mode and do not show logcat info.
Related
I am testing on Xiaomi Redmi Note 3 and what I need is very simple:
* Register broadcast receiver for incoming text messages
* Once message comes in, just read it
It looks like I can not get receiver register no matter what I try.
From the google docs, since 4.4 there should be no way for any app to swallow the event and every app listening should get a chance to get the event.
I have tried all kind of combinations and googled pretty much everything. Could it be the Xiaomi phone issue?
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.com.dimitar.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="21" />
<uses-permission
android:name="android.permission.RECEIVE_SMS"
android:protectionLevel="dangerous" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name="com.example.com.dimitar.test.SmsListener"
android:enabled="true" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<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>
</application>
</manifest>
Java code:
package com.example.com.dimitar.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsListener extends BroadcastReceiver{
private SharedPreferences preferences;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle bundle = intent.getExtras();
Toast toast = Toast.makeText(context, "poruka: ", Toast.LENGTH_SHORT);
toast.show();
if(bundle != null){
//---get the SMS message passed in---
SmsMessage[] msgs = null;
String msg_from;
if (bundle != null){
//---retrieve the SMS message received---
try{
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();
Toast toast1 = Toast.makeText(context, "poruka: " + msgBody, Toast.LENGTH_SHORT);
toast1.show();
}
}catch(Exception e){
// Log.d("Exception caught",e.getMessage());
}
}
}
}
}
Looks like Xiaomi has a Security application that controls pretty much everything. See another question and answer here
Steps:
go to settings > installed apps
find the app > tap it
go to permissions manager and enable permission you need
Or:
go to Security app
tap Permissions
Choose Autostart or Permissions and enable whatever you need for your app
I know from KitKat onward we need to make out app as default SMS app to be able to modify the SMS database.
But I don't want that. I only need to get notification of incoming SMS and display as toasts, and also send SMS.
Do I need to make my app default for that?
Edit 1:
Here is my manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rtrgroup.sms_to_neta_server"
android:installLocation="preferExternal">
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true">
<activity
android:name=".SplashScreen"
android:label="#string/app_name"
android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".LoginScreen" android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen"/>
<activity android:name=".MainScreen" android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen">
</activity>
<service android:name=".MainService"
android:exported="true">
</service>
<receiver android:name=".MainReceiver"
android:exported="true"
android:enabled="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Here is my BroadcastReceiver:
package com.rtrgroup.sms_to_neta_server;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Telephony;
import android.widget.Toast;
import android.telephony.*;
public class MainReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage;
if (Build.VERSION.SDK_INT >= 19) { //For ver. >= KitKat
SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent);
currentMessage = msgs[0];
} else {
Object pdus[] = (Object[]) bundle.get("pdus");
currentMessage = SmsMessage.createFromPdu((byte[]) pdus[0]);
}
String phoneNumber = currentMessage.getDisplayOriginatingAddress();
String senderNum = phoneNumber;
String messageB1 = currentMessage.getDisplayMessageBody();
String msg = currentMessage.getMessageBody();
String address = currentMessage.getOriginatingAddress();
Toast.makeText(context, senderNum + ": " + msg, Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
}
}
}
}
You don't need to be the default SMS app to send SMS. SmsManager.sendTextMessage() still works as long as you have the android.permission.SEND_SMS permission.
To receive SMSs, you can monitor the android.provider.Telephony.SMS_RECEIVED broadcast, with android.permission.RECEIVE_SMS permission.
Ref. http://android-developers.blogspot.fi/2013/10/getting-your-sms-apps-ready-for-kitkat.html
I have an app with the following manifest entries.
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" android:windowSoftInputMode="adjustPan" package="com.example.app" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />
<application android:allowBackup="true" android:hardwareAccelerated="true" android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="#string/app_name" android:name="TestSmsApp" android:theme="#android:style/Theme.Black.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="com.applegrew.cordova.android.plugin.SmsReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
When my app is stopped and a new SMS is received, I see the following in logcat.
I/ActivityManager( 540): Start proc com.example.app for broadcast com.example.app/com.applegrew.cordova.android.plugin.SmsReceiver: pid=25457 uid=10095 gids={50095, 1028}
E/Trace (25457): error opening trace file: No such file or directory (2)
After that I see no more activity from my receiver. I also have a logger to print messages at the start of onReceive() but I guess that was never invoked. My receiver's code is as below.
package com.applegrew.cordova.android.plugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.LOG;
import org.apache.cordova.PluginResult;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
public class SmsReceiver extends BroadcastReceiver {
public static final String SMS_EXTRA_NAME = "pdus";
private CallbackContext callback_receive;
private boolean isReceiving = true;
// This broadcast boolean is used to continue or not the message broadcast
// to the other BroadcastReceivers waiting for an incoming SMS (like the native SMS app)
private boolean broadcast = true;
#Override
public void onReceive(Context ctx, Intent intent) {
LOG.v("com.example.app", ">>>>>>>>>>>>>>>>>onReceive called!!!!");
// Get the SMS map from Intent
Bundle extras = intent.getExtras();
if (extras != null)
{
// 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]);
if(this.isReceiving && this.callback_receive != null) {
JSONObject obj = new JSONObject();
try {
obj.put(SMS.ADDRESS, sms.getOriginatingAddress());
obj.put(SMS.BODY, sms.getMessageBody());
LOG.v("com.example.app", ">>>>>>>>>>>>>>>>>with value" + sms.getOriginatingAddress() + ";; " + sms.getMessageBody());
PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
result.setKeepCallback(true);
callback_receive.sendPluginResult(result);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
// If the plugin is active and we don't want to broadcast to other receivers
// Also we cannot abort a broadcast which is not ordered.
if (this.isReceiving && !broadcast && isOrderedBroadcast()) {
this.abortBroadcast();
}
}
}
public void broadcast(boolean v) {
this.broadcast = v;
}
public void startReceiving(CallbackContext ctx) {
this.callback_receive = ctx;
this.isReceiving = true;
}
public void stopReceiving() {
this.callback_receive = null;
this.isReceiving = false;
}
}
I have just tried your code. It works well. onReceive() gets called, but the Application column is not filled in the LogCat. If you have filter set, you won't see the message. Please replace application filter with "tag:pdus" (or completely remove the filter) and you will see the output. Also use "Stop process" button in "Devices" view of Eclipse to stop the app.
I am trying to do a lockNow() on receive a specified command from SMS. I have tested and it is working fine on my emulator (4.0.3) but when I tested on my actual device (4.2.2) and (4.1.2) and emulator of (4.2.2), it is not working.
It seem like it is not even receiving on on BroadcastReceiver for SMS.
Edit: It is working for my emulator (4.2.2) now, I actually forgot about RECEIVE_SMS permission in manifest earlier on when I pushed to 4.2.2 AVD. but it is still not working on my device.
Edit 2: I think that it might be due to 3rd party SMS application (e.g. GO SMS) which prevent my Broadcast from receiving the SMS first. I will probably try to uninstall GO SMS and see if it works.
Edit 3: It's really GO SMS. After hours of searching around, I just need to disable one of the settings in GO SMS. "Open Go SMS, hit 'Menu' and click 'Settings', click on 'Receive Settings', then uncheck the 'Disable other message notifications". And it works now! phew!
Hope it helps others in future.
This is my class for receiving the SMS and doing the lock action.
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class RemoteWipeSMS extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String TAG = "SMSBroadcastReceiver";
static final int WIPE_EXTERNAL_STORAGE = 1;
DevicePolicyManager devicePolicyManager;
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Test get SMS");
Log.i(TAG, "not getting sms");
Log.i(TAG, "Intent recieved: " + intent.getAction());
devicePolicyManager = (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (intent.getAction().equals(SMS_RECEIVED)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
if (messages.length > -1) {
Log.i(TAG, "Message recieved: " + messages[0].getMessageBody());
Toast.makeText(context, "SMS Received : "+messages[0].getMessageBody(),
Toast.LENGTH_LONG).show();
if (messages[0].getMessageBody().equalsIgnoreCase("Lock")) {
Toast.makeText(context, "SMS Action : To LOCKED",
Toast.LENGTH_LONG).show();
try {
devicePolicyManager.lockNow();
} catch (Exception e) {
Log.e("Locked", "Lock error");
}
} else if (messages[0].getMessageBody().equalsIgnoreCase("Reset")) {
Toast.makeText(context, "SMS Action : To Reset",
Toast.LENGTH_LONG).show();
try {
devicePolicyManager.wipeData(WIPE_EXTERNAL_STORAGE);
} catch (Exception e) {
Log.e("Locked", "Reset error");
}
}
}
}
}
}
}
Part of my manifest.
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application
android:allowBackup="true"
android:icon="#drawable/app_icon"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo" >
<service
android:name="TestService">
</service>
<receiver
android:name="com.my.test.RemoteWipeSMS"
android:exported="true" >
<intent-filter
android:priority="999" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<!-- This is where we register our receiver -->
<receiver
android:name="com.my.test.DeviceAdminDetect"
android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<!-- This action is required -->
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
<!-- This is required this receiver to become device admin component. -->
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/device_admin" />
</receiver>
<activity
android:name="com.my.test.Main"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I'm trying to listen for received SMS messages, but onReceive method is never called.
The program is built for 1.6 version of android, and it runs without errors with 2.3.7 version, but the event I said before doesn't fire.
Any tip?
// SMSListener CODE
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SMSListener extends BroadcastReceiver {
protected String smsBody = "";
public static final String SMS_EXTRA_NAME = "pdus";
protected SQLEventDataSource events;
#Override
public void onReceive(Context context, Intent intent) {
// Get SMS map from Intent
Bundle extras = intent.getExtras();
Toast.makeText( context, "O evento onReceive foi lançado", Toast.LENGTH_SHORT ).show();
String messages = "";
if ( extras != null )
{
// 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]);
String body = sms.getMessageBody().toString();
// check if it's a configuration message
if (body.substring(0, 5) == "SMED#") {
String[] configs = body.split("#");
events.addEventConfiguration(configs[1], configs[2], configs[3]);
}
}
// Display SMS message
Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
}
}
private void setSmsBody(String smsBody) {
this.smsBody = smsBody;
}
public String getSMSBody() {
// TODO Auto-generated method stub
return this.smsBody;
}
}
// AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pt.ipbeja.estig.smed"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="1" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.provider.Telephony.SMS_RECEIVED" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name" >
<activity
android:name=".SMEDGPSActivity"
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:exported="true" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Assuming you literally pasted your manifest, it contains a typo in the required permissions. It currently incorrectly lists the action filter string (android.provider.Telephony.SMS_RECEIVED) as opposed to the actual permission:
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>