Screen on and off via sms received - android

I am trying to turn screen on and off via sms. here is my code below i don't know what has gone wrong as it is not working at all.Do help me in finding error. I am attaching manifest file too.Thank you in advance.
My java file:
public class MyReceiver extends BroadcastReceiver{
String sender;
#Override
public void onReceive(Context context, Intent intent) {
SmsMessage[] sms = null;
Bundle b = intent.getExtras();
String str = " SMS From : ";
if (b != null) {
Object[] pdus = (Object[]) b.get("pdus");
sms = new SmsMessage[pdus.length];
for (int i = 0; i < sms.length; i++) {
sms[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
if (i == 0) {
str += sms[i].getOriginatingAddress();
str += ":"+sms[i].getMessageBody().toString();
}else if (sms[i].getMessageBody().equals("D")) {
Intent in2= new Intent(Intent.ACTION_SCREEN_OFF);
in2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(in2);
}else if (sms[i].getMessageBody().equals("E")) {
Intent in3= new Intent(Intent.ACTION_SCREEN_ON);
in3.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(in3);
}
}
}
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
Log.d("Receiving", str);
}
}
}
MY manifest file:
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<receiver android:name=".MyReceiver">
<intent-filter android:priority="100">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
<action android:name="android.intent.action.SCREEN_OFF"/>
<action android:name="android.intent.action.SCREEN_ON"/>
</intent-filter>
</receiver>
</application>

Ok, first, regarding the receiving of SMS you might want to see my answer to this: communication between two device using sms
It is the most reliable way of receiving SMS that I have found.
Notice that SMS might not be the best option on newer devices from KitKat upwards if you do not want the message to appear on the device Hide sms notifications with a broadcastreceiver in KitKat
You might want to consider switching to push notifications from the internet instead. This is easily done using for instance parse.com
Regarding turning on and off screen I use the following piece of code.
private PowerManager.WakeLock wl;
private PowerManager pm;
public void screenWakeup(Context context, Activity activity) {
try {
pm = (PowerManager) context
.getSystemService(Activity.POWER_SERVICE);
// if (!pm.isScreenOn()) {
if (wl == null) {
wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Turios");
}
if (!wl.isHeld()) {
wl.acquire();
}
final Window win = activity.getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
win.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// }
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
}
public void screenRelease(Activity activity) {
if (releaseWakeLock()) {
activity.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
Notice that it needs access to an activity, so it will not work unless your activity is alive. What I would suggest to do is:
Receive the turn on/off message
Send a new broadcast e.g. sendBroadcast(new Intent("INTENT_TURN_SCREEN_ON_OFF"))
Register a listener for the broadcast inside your activity
// in onCreate
wakeScreenReceiver = new WakeScreenReceiver();
registerReceiver(wakeScreenReceiver, new IntentFilter("INTENT_TURN_SCREEN_ON_OFF"));
// in onDestroy
unregisterReceiver(wakeScreenReceiver);
// WakeScreenReceiver defined somewhere inside the Acitivity
public class WakeScreenReceiver extends BroadcastReceiver {
private static final String TAG = "WakeScreenReceiver";
public RefreshModules() {
}
#Override
public void onReceive(Context context, final Intent intent) {
screenWakeup(MainActivity.this, MainActivity.this);
// or
screenRelease(MainActivity.this);
}
}
This way the app will only ever attempt to turn on/off the screen if the Activity is alive since otherwise the broadcast will simply not be received.

Related

Stay in current activity upon NFC reception

I have an application that seems to work fine and can transmit data via NFC perfectly well. I have a main activity, an activity to transmit the data, and a different activity to receive data.
The sender activity works great, but when the receiver gets the NFC intent, it restarts the app back to the main activity.
I'm not exactly sure why this is. I would like it to decline any pushes unless the user is already in that activity, and if they are, to stay in that activity and handle the NFC intent.
Here is the manifest:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Timer" />
<activity android:name=".AddSlaves"
android:label="Add Slave Devices"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity android:name=".JoinSrv"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Here is the sender class:
public class JoinSrv extends Activity implements NfcAdapter.OnNdefPushCompleteCallback, NfcAdapter.CreateNdefMessageCallback {
//The array lists to hold our messages
private ArrayList<String> messagesToSendArray = new ArrayList<>();
private ArrayList<String> messagesReceivedArray = new ArrayList<>();
//Text boxes to add and display our messages
private NfcAdapter mNfcAdapter;
//Save our Array Lists of Messages for if the user navigates away
#Override
public void onSaveInstanceState(#NonNull Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putStringArrayList("messagesToSend", messagesToSendArray);
savedInstanceState.putStringArrayList("lastMessagesReceived", messagesReceivedArray);
}
//Load our Array Lists of Messages for when the user navigates back
#Override
public void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
messagesToSendArray = savedInstanceState.getStringArrayList("messagesToSend");
messagesReceivedArray = savedInstanceState.getStringArrayList("lastMessagesReceived");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_join_srv);
//Check if NFC is available on device
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
//Handle some NFC initialization here
} else {
Toast.makeText(this, "NFC not available on this device",
Toast.LENGTH_SHORT).show();
}
//Check if NFC is available on device
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
//This will refer back to createNdefMessage for what it will send
mNfcAdapter.setNdefPushMessageCallback(this, this);
//This will be called if the message is sent successfully
mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
}
#Override
public NdefMessage createNdefMessage(NfcEvent event) {
//This will be called when another NFC capable device is detected.
//We'll write the createRecords() method in just a moment
NdefRecord[] recordsToAttach = createRecords();
//When creating an NdefMessage we need to provide an NdefRecord[]
return new NdefMessage(recordsToAttach);
}
#Override
public void onNdefPushComplete(NfcEvent event) {
//This is called when the system detects that our NdefMessage was
//Successfully sent.
messagesToSendArray.clear();
}
public NdefRecord[] createRecords() {
NdefRecord[] records = new NdefRecord[1];
//To Create Messages Manually if API is less than
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
byte[] payload = "192.168.1.100".
getBytes(Charset.forName("UTF-8"));
NdefRecord record = new NdefRecord(
NdefRecord.TNF_WELL_KNOWN, //Our 3-bit Type name format
NdefRecord.RTD_TEXT, //Description of our payload
new byte[0], //The optional id for our Record
payload); //Our payload for the Record
records[1] = record;
}
//Api is high enough that we can use createMime, which is preferred.
else {
byte[] payload = "192.168.1.100".
getBytes(Charset.forName("UTF-8"));
NdefRecord record = NdefRecord.createMime("text/plain",payload);
records[1] = record;
}
records[messagesToSendArray.size()] =
NdefRecord.createApplicationRecord(getPackageName());
return records;
}
private void handleNfcIntent(Intent NfcIntent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(NfcIntent.getAction())) {
Parcelable[] receivedArray =
NfcIntent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (receivedArray != null) {
messagesReceivedArray.clear();
NdefMessage receivedMessage = (NdefMessage) receivedArray[0];
NdefRecord[] attachedRecords = receivedMessage.getRecords();
for (NdefRecord record : attachedRecords) {
String string = new String(record.getPayload());
//Make sure we don't pass along our AAR (Android Application Record)
if (string.equals(getPackageName())) {
continue;
}
messagesReceivedArray.add(string);
}
Toast.makeText(this, "Received " + messagesReceivedArray.size() +
" Messages", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Received Blank Parcel", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onNewIntent(Intent intent) {
handleNfcIntent(intent);
}
#Override
public void onResume() {
super.onResume();
handleNfcIntent(getIntent());
}
}
Here is the receiver class:
public class AddSlaves extends Activity implements NfcAdapter.OnNdefPushCompleteCallback, NfcAdapter.CreateNdefMessageCallback{
//The array lists to hold our messages
private ArrayList<String> messagesToSendArray = new ArrayList<>();
private ArrayList<String> messagesReceivedArray = new ArrayList<>();
//Text boxes to add and display our messages
private EditText txtBoxAddMessage;
private TextView txtReceivedMessages;
private TextView txtMessagesToSend;
private NfcAdapter mNfcAdapter;
private void updateTextViews() {
txtReceivedMessages.setText("Messages Received:\n");
//Populate our list of messages we have received
if (messagesReceivedArray.size() > 0) {
for (int i = 0; i < messagesReceivedArray.size(); i++) {
txtReceivedMessages.append(messagesReceivedArray.get(i));
txtReceivedMessages.append("\n");
}
}
}
//Save our Array Lists of Messages for if the user navigates away
#Override
public void onSaveInstanceState(#NonNull Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putStringArrayList("lastMessagesReceived",messagesReceivedArray);
}
//Load our Array Lists of Messages for when the user navigates back
#Override
public void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
messagesReceivedArray = savedInstanceState.getStringArrayList("lastMessagesReceived");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_slaves);
txtReceivedMessages = (TextView) findViewById(R.id.txtMessagesReceived);
Button btnAddMessage = (Button) findViewById(R.id.buttonAddMessage);
//Check if NFC is available on device
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter != null) {
//Handle some NFC initialization here
}
else {
Toast.makeText(this, "NFC not available on this device",
Toast.LENGTH_SHORT).show();
}
//Check if NFC is available on device
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter != null) {
//This will refer back to createNdefMessage for what it will send
mNfcAdapter.setNdefPushMessageCallback(this, this);
//This will be called if the message is sent successfully
mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
}
#Override
public NdefMessage createNdefMessage(NfcEvent event) {
//This will be called when another NFC capable device is detected.
return null;
}
#Override
public void onNdefPushComplete(NfcEvent event) {
//This is called when the system detects that our NdefMessage was
//Successfully sent.
messagesToSendArray.clear();
}
private void handleNfcIntent(Intent NfcIntent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(NfcIntent.getAction())) {
Parcelable[] receivedArray =
NfcIntent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if(receivedArray != null) {
messagesReceivedArray.clear();
NdefMessage receivedMessage = (NdefMessage) receivedArray[0];
NdefRecord[] attachedRecords = receivedMessage.getRecords();
for (NdefRecord record:attachedRecords) {
String string = new String(record.getPayload());
//Make sure we don't pass along our AAR (Android Application Record)
if (string.equals(getPackageName())) { continue; }
messagesReceivedArray.add(string);
}
Toast.makeText(this, "Received " + messagesReceivedArray.size() +
" Messages", Toast.LENGTH_LONG).show();
updateTextViews();
}
else {
Toast.makeText(this, "Received Blank Parcel", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onNewIntent(Intent intent) {
handleNfcIntent(intent);
}
#Override
public void onResume() {
super.onResume();
updateTextViews();
handleNfcIntent(getIntent());
}
}
You have qute a few issues in your code of the sender activity:
You store messagesToSendArray, but you never actually fill this array list with data (i.e. messagesToSendArray.size() is always 0). Since you freshly create the NDEF message whenever createNdefMessage() is invoked, there is no need to save and restore messagesToSendArray.
You wrote that you want to send NDEF messages in one activity, but you want to receive NFC events in another activity. However, you registered your sender activity to receive NDEF_DISCOVERED events in the manifest. There is no need for the NDEF_DISCOVERED intent filter in the manifest if you do not want to receive and process these events.
Moreover, there is no need to handle the NDEF_DISCOVERED intent in your sender activity (i.e. you can safely remove the methods onNewIntent() and handleNfcIntent()).
On Android versions below Jelly Bean you create an NFC Forum Text record with an invalid structure. The Text RTD requres a payload that is encoded in the form (also see this post)
+----------+---------------+--------------------------------------+
| Status | Language Code | Text |
| (1 byte) | (n bytes) | (m bytes) |
+----------+---------------+--------------------------------------+
where Status equals to the length n of the Language Code if the Text is UTF-8 encoded and Language Code is an IANA language code (e.g. "en" for English). Consequently, the proper way to encode that record would be:
public static NdefRecord createTextRecord(String language, String text) {
byte[] languageBytes;
byte[] textBytes;
try {
languageBytes = language.getBytes("US-ASCII");
textBytes = text.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
byte[] recordPayload = new byte[1 + (languageBytes.length & 0x03F) + textBytes.length];
recordPayload[0] = (byte)(languageBytes.length & 0x03F);
System.arraycopy(languageBytes, 0, recordPayload, 1, languageBytes.length & 0x03F);
System.arraycopy(textBytes, 0, recordPayload, 1 + (languageBytes.length & 0x03F), textBytes.length);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, null, recordPayload);
}
It's unclear to me why you create an NFC Forum Text record on Android versions below Jelly Bean while you create a MIME type record on Jelly Bean and above. You should be consistent and create the same record type on all platforms (see Method NdefRecord.createTextRecord("en" , "string") not working below API level 21):
String text = "192.168.1.100";
String language = "en";
NdefRecord record;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
record = NdefRecord.createTextRecord(language, text);
} else {
record = createTextRecord(language, text);
}
Finally, in createRecords() you create the array records as
NdefRecord[] records = new NdefRecord[1];
Consequently, the array has one element accessible at index 0. Hoever, you try to access element 1 later on:
records[1] = record;
This results in an IndexOutOfBounds exception. Since createRecords() is called by Android through the createNdefMessage() callback, the callback fails (due to the runtime exception) and Android will not use your NDEF message. Instead, Android will use a default NDEF message for your app. This default NDEF message contains an Android Application record that will cause your main activity to be called (since none of your other activities are registered to be started for the specific contents of the default NDEF message); see NFC tag detection is not calling onNewIntent and it's Launching From Main Activity. Consequently, you need to change the offset in records where you store your newly created NDEF record to 0:
records[0] = record;
Moreover, you need to remove the line
records[messagesToSendArray.size()] =
NdefRecord.createApplicationRecord(getPackageName());
since this would then overwrite the previously stored NDEF record at index 0 (messagesToSendArray.size() is 0) with an Android Application record. Again, this would cause your main activity to be started since you did not register for that specific record type in your manifest.
Finally, if you want to decline pushes unless the user is inside the receiver activity, you should consider using the foreground dispatch system. In that case, you would complete remove all NDEF_DISCOVERED intent filters from your manifest and instead register each activity (receiver, sender, and main) with the foreground dispatch system. In the receiver, you would then receive the NDEF messages through onNewIntent(). In the sender and in the main activity, you would simply ignore and drop any received NDEF message. See Android app enable NFC only for one Activity for an example.

Send data to BroadcastReceiver (CONNECTIVITY_CHANGE) to access to database from it

I am programming a Geofence app. When user arrives at some point, geofence triggers, and sends a Mail.
This works just perfect. But I need to control the case in which there is no connectivity so that the app sends the mail when connectivity becomes available.
I achieved this, with a Broadcast Receiver, which listens for CONNECTIVITY_CHANGE.
My problem is that I need to retrieve from database the details (receiver of the mail and text), and for that I need an "ID", but I can't find the way to pass this ID to the BroadcastReceiver.
This is my code:
I've an Intent that detects the Geofence, and if there is no Internet, activates the BroacasReceiver:
public class GeofenceIntentService extends IntentService implements com.google.android.gms.location.LocationListener {
[...]
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
extras = intent.getExtras();
Log.e(TAG, String.valueOf(extras.getLong("id")));
ID = extras.getLong("id");
sendMail(ID);
}
}
[...]
private void sendMail(long ID) {
dbHelper = new DBHelper(context);
dbHelper.getWritableDatabase();
cursor = dbHelper.getRegister(ID);
dbHelper.close();
tomail = cursor.getString(cursor.getColumnIndex("tomail"));
where = cursor.getString(cursor.getColumnIndex("where"));
texttosend = cursor.getString(cursor.getColumnIndex("texttosend"));
if (getConnectivityStatus(context) == 1 || getConnectivityStatus(context) == 2) {
Mail m = new Mail("***", "****");
String[] toArr = {tomail};
m.setTo(toArr);
m.setFrom("*****");
m.setSubject(getString(R.string.justtrying));
m.setBody(texttosend);
try {
if (m.send()) {
Log.v(TAG, "Email was sent successfully.");
} else {
Log.v(TAG, "Email was not sent.");
}
} catch (Exception e) {
Log.e("MailApp", "Could not send email", e);
}
} else {
Log.v(TAG, "Waiting for Internet Connection.");
registerForBroadcasts(context);
}
}
public void registerForBroadcasts(Context context) {
ComponentName component = new ComponentName(context, NetworkChangeReceiver.class);
PackageManager pm1 = context.getPackageManager();
pm1.setComponentEnabledSetting(
component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
An then the receiver on the manifest:
<receiver
android:name=".NetworkChangeReceiver"
android:enabled="false"
android:label="NetworkChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
As I said, this works, but then onReceive, I need to know the ID to get the contact info to send the mail. The Broadcast as an Intent variable, but I don't know how to edit it. This would be the idea:
#Override
public void onReceive(final Context context, final Intent intent) {
final Context mContext = context;
String action = intent.getAction();
extras = intent.getExtras();
ID = extras.getLong("id");
Any ideas? The only alternative I can find is to keep checking for connectivity every 30secs, from the GeofenceIntent, but I think it would be much more effective to listen to Connectivity Change.
EDIT:
Finaly I solved this situation, by adding a "pending" column, on database, and from BroadcastReceiver checking all registers, where Pending = true.
Anyway I still have the doubt if there were any other way.

passing a variable from a service to a broadcast receiver

Hello guys i am trying to send two variables from an android service to a broadcast receiver, and i need help here..
i am setting up two var's in the oncreate method of the service class here..
#Override
public void onCreate() {
super.onCreate();
Intent eSendIntent = new Intent(getApplicationContext(), OutgoingCallReceiver.class);
eSendIntent.putStringArrayListExtra("BlockArray", contactsListB);
eSendIntent.putExtra("BlockBool", checkB);
getApplicationContext().sendOrderedBroadcast(eSendIntent, null);//Call receiver
}
and in my receiver class...
onReceive(Context context, Intent intent){
Bundle bundle = intent.getExtras();
if(bundle == null)
return;
boolean cb = bundle.getBooleanExtra("BlockBool", true);
ArrayList<String> ab = bundle.getStringArrayListExtra("BlockArray");
//disconnecting
try{
if(cb==false){
for(int ij = 0; ij < ab.size(); ij++){
if(ab.get(ij).contains(phonenumber)){
tempBoolean = true;
//Log.e("OutgoingCallReceiver", SmsBlockerService.contactsListB.get(ij));
}
}//for loop
if(tempBoolean==true){
setResultData(null);
Toast.makeText(context, phonenumber + " is Blocked", Toast.LENGTH_SHORT).show();
}
}else{
setResultData(null);
Toast.makeText(context, "All Out-Going Calls are Blocked", Toast.LENGTH_SHORT).show();
}//end of main if
} catch(Exception e){
Toast.makeText(context, "Detect Calls sample application Failed: ", Toast.LENGTH_LONG).show();
}
}
logcat:
E/BroadcastReceiver(1459): BroadcastReceiver trying to return result during a non-ordered broadcast
set this in your broadcast intent
i.setAction("MYACTION");
than set this in your manifest
<receiver android:name=".BroadcastClass" >
<intent-filter>
<action android:name="MYACTION" />
</intent-filter>
</receiver>
may be this should helpful
Assuming that you registered the receiver.Now try to make a small change:
boolean cb = bundle.getBooleanExtra("BlockBool", true);
ArrayList<String> ab = bundle.getStringArrayListExtra("BlockArray");
Update:
In the on create... call the broadcast like...
sendOrderedBroadcast(eSendIntent);
You are facing that error because , setResultData() function works only with OrderedBroadcast.
From Android Documentation:
public final void setResultCode (int code)
Added in API level 1
Change the current result code of this broadcast; only works with broadcasts sent
through Context.sendOrderedBroadcast. Often uses the Activity RESULT_CANCELED and
RESULT_OK constants, though the actual meaning of this value is ultimately up to the
broadcaster.
This method does not work with non-ordered broadcasts such as those sent with
Context.sendBroadcast.
for broadcast receiver to work the activity/screen in which it is written should be up & running. so that receiver can receives the passed intent & it's value.

Broadcast Receiver does not trigger when Mobile Screen Locks

When I install the app everything works fine. I am able to print Message body every time I send a message until I lock mobile screen. After that, the app stops printing incoming messages. I tried many ways to overcome this problem but with no luck. Please help me...
public class SmsReceiveActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED)) {
Object[] pdus = (Object[]) bundle.get("pdus");
final android.telephony.SmsMessage[] messages = new android.telephony.SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = android.telephony.SmsMessage.createFromPdu((byte[]) pdus[i]);
incomingMsgString += messages[i].getMessageBody().toString();
}
// Print Incoming message Body
}
}
}
getApplication().registerReceiver(receiver, new IntentFilter(SMS_RECEIVED));
}
}
Per the BroadcastReceiver docs, when you register a receiver with registerReceiver(), "You won't receive intents when paused". If you want a receiver that is independent of your activity, you should implement it as a named class and publish it in your manifest. For example, create a named class with your anonymous BroadcastReceiver,
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED)) {
Object[] pdus = (Object[]) bundle.get("pdus");
final android.telephony.SmsMessage[] messages = new android.telephony.SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = android.telephony.SmsMessage.createFromPdu((byte[]) pdus[i]);
incomingMsgString += messages[i].getMessageBody().toString();
}
// Print Incoming message Body
}
}
}
And in your manifest add the receiver inside your application tag
<receiver android:name=".MyReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/ >
</intent-filter>
</receiver>
Then when an SMS message is received your onReceive method will be invoked. There you can package up the information you need and launch an intent to your Activity or Service for further processing.
Create your broadcast as static inner class and register it in manifest. Try this link. Receiver as inner class in Android

Listening to incoming SMS after broadcast is unregistered: nice feature or broadcastreciever's bug?

I have an application which should watching incoming SMS (scan SMS text and show toast messages based on content) , even after my application is closed. The desired functionality is app watching all incoming SMS until app will not moved from device, and now it works like this. But I think, if I will need soon, to "switch of" this "watching eye", how I could to do this?
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;
if (bundle != null)
{
//do some action
}
}
BroadcastReceiver's code is a separate unit SMSReceiver.java. From main Activity I do not call this receiver, do not register and do not unregister. It's just working independently. Amazing.
So.. how I can ti stop this receiver??
The most common way to register/unregister BroadcastReceivers is to use the onResume() and onPause() methods of your Activity.
Firstly remove the <intent-filter> from your manifest, i.e., delete this section......
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECIEVED"></action>
</intent-filter>
Then add something like this to your Activity....
public class MyActivity extends Activity {
private final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private SMSReceiver smsReceiver = null;
private Boolean isReceiverRegistered = false;
#Override
protected void onResume() {
if (!isReceiverRegistered) {
registerReceiver(smsReceiver, new IntentFilter(ACTION_SMS_RECEIVED));
isReceiverRegistered = true;
}
}
#Override
protected void onPause() {
if (isReceiverRegistered) {
unregisterReceiver(smsReceiver);
isReceiverRegistered = false;
}
}
}
You'll have to take the BroadcastReceiver out of your Manifest to control it such as using it in a Service or Activity. When its in the Manifest its always on.

Categories

Resources