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>
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'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>
I have this program that will try to monitor incoming SMS messages. But when I tried to run my program in the emulator and I tried to send a SMS message, it works. But when I installed my program in my phone, its not working.
What is the problem?
And I want to run the program at the backend as well. How to do that?
BTW, below are the whole codes for this sample app.
Thanks
RJ
import java.io.BufferedWriter;
import java.io.FileWriter;
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 MySMSMonitor extends BroadcastReceiver
{
private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent)
{
if(intent!=null &&
intent.getAction()!=null &&
ACTION.compareToIgnoreCase(intent.getAction())==0)
{
Object[]pduArray= (Object[]) intent.getExtras().get("pdus");
SmsMessage[] messages = new SmsMessage[pduArray.length];
for (int i = 0; i<pduArray.length; i++) {
messages[i] = SmsMessage.createFromPdu ((byte[])pduArray [i]);
}
Log.d("MySMSMonitor","SMS Message Received.");
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="spy.Frandy.com"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="6" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".TelephonyDemo"
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=".MySMSMonitor"> <intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter>
</receiver>
</application>
</manifest>
import android.app.Activity;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class TelephonyDemo extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button sendBtn = (Button)findViewById(R.id.sendSmsBtn);
sendBtn.setOnClickListener(new OnClickListener(){
#Override public void onClick(View view) {
EditText addrTxt = (EditText)TelephonyDemo.this.findViewById(R.id.addrEditText);
EditText msgTxt = (EditText)TelephonyDemo.this.findViewById(R.id.msgEditText);
try {
sendSmsMessage(
addrTxt.getText().toString(),msgTxt.getText().toString());
Toast.makeText(TelephonyDemo.this, "SMS Sent",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(TelephonyDemo.this, "Failed to send SMS", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}});
}
#Override
protected void onDestroy() {
super.onDestroy();
}
private void sendSmsMessage(String address,String message)throws Exception {
SmsManager smsMgr = SmsManager.getDefault();
smsMgr.sendTextMessage(address, null, message, null, null);
}
}
I would simply insist you to use ContentObserver and register content://sms Uri and fetch the type of the SMS using
cusor.getString(cusor.getColumnIndex("type")); // 1 = SMS Received
// 2 = SMS Sent
Further you can easily get the required data from the cursor that you fetched. Here is a blog for the same.
I'm going to assume with the little detail you have provided that the reason it works on a emulator and not your actual phone; may be another conflicting app intercepting the messages before they are broadcasted to your app.
try adding android:priority="1000" to your intent-filter of your receiver in your apps manifest
(a thousand being whatever number you feel necessary, could be higher if needed)
<intent-filter android:priority="1000" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
more info on - intent-filter priority
Try This:
<receiver android:name=".MySMSMonitor"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="2">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
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.