i followed a tutorial to receive SMS on my application and read it to pass the SMSbody to Toast.
that is the Receiver class.
public class SmsReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
Bundle bundle= intent.getExtras();
SmsMessage[] msgs= null;
String str="";
if(bundle != null ){
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+= msgs[i].getMessageBody();
}
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
}
}
}
the manifest file
<receiver android:name="com.msoft.masrooq.SmsReciever">
<intent-filter>
<action android:name="android.provider.telephony.SMS_RECIEVED"></action>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS" />
the app starts fine but it doesn't response to receiving sms
it doesn't do anything.
Here is my implementation of receiving sms messages. Sms message may be broken into many, notice how it is treated. Also check the android:priority attribute.
public class SmsReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
// get sms objects
Object[] pdus = (Object[]) bundle.get("pdus");
if (pdus.length == 0) {
return;
}
// large message might be broken into many
SmsMessage[] messages = new SmsMessage[pdus.length];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
sb.append(messages[i].getMessageBody());
}
String sender = messages[0].getOriginatingAddress();
String message = sb.toString();
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
// prevent any other broadcast receivers from receiving broadcast
// abortBroadcast();
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smsreceiver"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity
android:name=".SmsLoggerActivity"
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="com.example.smsreceiver.SmsReceiver" android:enabled="true">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Few notes:
If you declare your receiver in xml than system can use your receiver regardless of your application was ever launched.
Since Android 1.6 notifications about received sms messages are delivered as ordered broadcasts, you can use android:priority attribute of <intent-filter> to tell the system send the sms first to your application (you can also call abortBroadcast() so other applications won't receive the sms, e.g. the native sms app). Don't forget broadcast receiver has about 10 seconds for executing its operation, otherwise it can be prematurely terminated before finishing its job.
Note: That on some devices your code wont work without android:priority="100" in intent filter:
<application
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
...
<receiver
android:name=".SMSReceiver">
<intent-filter android:priority="100">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
...
</application>
And here Java code :
public class SMSReceiver extends BroadcastReceiver {
public static final String ACTION ="android.provider.Telephony.SMS_RECEIVED";
private static final String SMS_SENDER="123456789";
#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]);
}
// SMS Sender, example: 123456789
String sms_from = messages[0].getDisplayOriginatingAddress();
//Lets check if SMS sender is 123456789
if (sms_from.equalsIgnoreCase(SMS_SENDER)) {
StringBuilder bodyText = new StringBuilder();
// If SMS has several parts, lets combine it :)
for (int i = 0; i < messages.length; i++) {
bodyText.append(messages[i].getMessageBody());
}
//SMS Body
String body = bodyText.toString();
// Lets get SMS Code
String code = body.replaceAll("[^0-9]", "");
}
}
}
Broadcasts are case-sensitive. Use android.provider.Telephony.SMS_RECEIVED not android.provider.telephony.SMS_RECEIVED.
Also, I also have a category set, but I'm not sure it's mandatory:
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
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 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/
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
I've searched a lot on web and on SO I couldn't find an answer to my case or a straightforward tutorial, I was following this my problem is that the constructor doesn't get call nor onReceive().
public class Smsreceiver extends BroadcastReceiver
{
public Smsreceiver()
{
Log.v("constructing", "constructing");
}
#Override
public void onReceive(Context context, Intent intent)
{
Log.v("received", "received");
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_LONG).show();
}
}
}
and manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dwaik.testreceivesms"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_SMS" >
</uses-permission>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<receiver
android:name=".SmsReceiver"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
I'm building against api-level 15 (4.0.3) and running on xperia neo v (4.0.3), what am I missing? or shall I do anything special beside run to get my service to run?
EDIT
I can't find my service between running apps menu, though it does exist on installed apps menu
Register your receiver in your main activity:
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
SmsReceiver smsReceiver = new SmsReceiver();
registerReceiver(smsReceiver, new IntentFilter(SMS_RECEIVED));
Remember to unregister it at the end.
It works if you put the correct name of your class in the manifest.xml.
In fact you called: "Smsreceiver" your java class and you try to register a service in the manifest that is called SmsReceiver.
Change the name of the class or into the manifest.
<receiver android:name="com.example.package_name.HERE YOUR SMS RECEIVER">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
I am writing an sms receiver android code but it is not working.
It compiles will but when I get an sms it did not displayed as supposed to be when using Toast.
This is my code:
package com.example.homecontrolingbysms;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String messageReceived = "";
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]);
messageReceived +="From "+ msgs[i].getOriginatingAddress();
messageReceived+=" : ";
messageReceived += msgs[i].getMessageBody().toString();
messageReceived += "\n";
}
//---display the new SMS message---
Toast.makeText(context, messageReceived, Toast.LENGTH_SHORT).show();
}
}
}
I also posted manifest to make sure all important parts of code are available
manifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.homecontrolingbysms"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.homecontrolingbysms.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>
<activity
android:name="com.example.homecontrolingbysms.Door"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.example.homecontrolingbysms.Window"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.example.homecontrolingbysms.Light"
android:label="#string/app_name" >
</activity>
</application>
</manifest>
Register smsreceiver by adding below code in menifest file
<receiver android:name="com.shreymalhotra.smsreceiver.SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
This links may help you.
Receiving SMS on Android App
http://shreymalhotra.me/blog/tutorial/receive-sms-using-android-broadcastreceiver-inside-an-activity/
Please check it.
if you want to receive some broadcasts , blew things must be done.
1. In the manifest.xml ,you must declare your receiver with the intent filter
exp:
2. if the broadcast that you want to receive is ordered, you must make sure your priority.
android:priority="1000"
I think your manifest looks okay; the problem is with the line:
Mistake is in this part I think can you change this
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String messageReceived = "";
if (bundle != null)
to something like this
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Intent recieved: " + intent.getAction());
intent.getAction().equals(ACTION) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
(you need to do an object comparison on the action string, or just do no comparison), in your manifest file you have misspelled SMS_RECEIVED.