BroadcastReceiver for Android Calendar events (2018) - java

This question is indeed a duplicate to Listen for new calendar events
I have been trying to register the BroadcastReceiver with the way specified in the link, however, my app couldn't receive any broadcast when I modified the phone's calendar.
I also tried to add it through IntentFilter instead of through the AndroidManifest
filter = new IntentFilter();
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
registerReceiver(calendarReceiver,filter);
still no luck getting it to receive the broadcast. Did I miss anything or listening to calendar's changes cannot be done anymore?

You must add the scheme and and authority for calendar events:
filter.addDataScheme("content");
filter.addDataAuthority("com.android.calendar", null);
A complete example of listening for calendar changes would be:
CalendarReceiver.java
public class CalendarReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("example", "Calendar changed (or the phone just booted)");
}
}
Activity.java
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
filter.addDataScheme("content");
filter.addDataAuthority("com.android.calendar", null);
registerReceiver(new CalendarReceiver(), filter);

Related

How to update RecyclerView from BroadcastReceiver?

In AndroidManifest.xml I have a BroadcastReceiver:
<receiver android:name=".SmsMonitor">
<intent-filter android:priority="-100">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
In my MainActivity, I have RecyclerView with a list of received SMS.
My question is - How I can update the RecyclerView from my BroadcastReceiver "SmsMonitor" in case new SMS received when the application is running?
UPD: I mean I need solution for both states - for running application AND for state when application is not running, in one receiver. Because I have to take SMS all time while phone is working. And in case the application is running I want to update RecyclerView.
I tried to do it through the Service, but I did not succeed.
But I found simple solution:
I still have BroadcastReceiver SmsMonitor, registered in AndroidManifest.xml
And in the point where I create instance of my RecyclerAdapter:
mainAdapter = new MainAdapter(this);
After this I register another BroadcastReceviver:
BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
setInitialData();
mainAdapter.notifyDataSetChanged();
}
};
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
this.registerReceiver(br, filter);
And in setInitialData() I recreate all list of data for RecyclerView.
And now I have two independently working BroadcastReceiver. The first working the BroadcastReceiver from the AndroidManifest.xml, and then working the BroadcastReceiver registered in MainActivity.
You need to have the BrodcastReceiver in your MainActivity or Fragment as well which hosts the RecyclerView. So that when the new SMS is received, you can call the notifyDataSetChanged on the adapter of your RecyclerView to update it.
Declare a BroadcastReceiver in your Activity like the following. This can be an inner class of your MainActivity class.
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) {
if (intent.getAction() == SMS_RECEIVED) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
// Update your RecyclerView here
// by calling notifyDataSetChanged on the adapter
}
}
}
}
Now create an instance of this BroadcastReceiver in the onCreate function of your MainActivity and register the receiver.
You need to ask for SMS permission first in your Activity like the following.
if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.RECEIVE_SMS}, 0);
} else {
// register sms receiver
IntentFilter filter = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(smsReceiver, filter);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
} else {
// register sms receiver
IntentFilter filter = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(smsReceiver, filter);
}
}
Do not forget to un-register the receiver in the onDestroy function of your MainActivity.
Hope that helps!
Update
Based on the comment below this answer, you have two cases.
Case 1. The app is running.
Case 2. The app is not running.
For case 1: The local BroadcastReceiver like I shown above, is good enough to update the RecyclerView instantly when a new SMS arrives. As you are handling the BroadcastReceiver from the MainActivity this should not be a problem, as you have the reference to your RecyclerView.
Now for Case 2: If you are able to detect any new SMS arrival, you can save the new SMS received in your local database. You need to have an SQLite database for your application which will store all the SMS and the RecyclerView in your application should populate the data from the database table where the SMS are stored. I hope you get the idea - just store the SMS in your local database associated with your application and when you run the application and launch the MainActivity, read the SMS from your local database and show them in your RecyclerView.

Android Service to check whether the user screen on or off

Is there any way to create a service that runs forever on a background for Android user to check whether their screen on or off, etc?
I'm about to create an analytics, so I need to know when the user turn on or turn off their screen.
Thanks, I will appreciate all the input
You may use Android broadcast receiver to detect screen on and off.
Here is a good example of it
https://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
you may also follow this thread
https://stackoverflow.com/a/9478013/2784838
You need to create broadcast receiver and manage screen on or off status.
Declare receiver in manifest:
<receiver android:name=".DeviceWakeUpReceiver" />
public class DeviceWakeUpReceiver extends BroadcastReceiver {
private static final String TAG = "DeviceWakeUpService";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive() called");
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
//End service when user phone screen off
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
//Start service when user phone screen on
}
}
}
You cannot use a BroadcastReceiver for receiving screen off/on events.
Write a intent service which is started via boot complete listener and register for Intent.ACTION_SCREEN_OFF and Intent.ACTION_SCREEN_ON.
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(new ScreenOffOnReceiver(), filter);
class ScreenOffOnReiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// Screen OFF
else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// Screen ON
}
}
}

Update textview of MainActivity from class that extends Service

I'm trying to create an android app that communicate with Bluetooth low energy module. I am able to connect to module, read data and so on. But the problem is i do not know how to update textview from class that extends Service (the one in which whole connection to BLE is going on). I know there is like BILLION or even more posts like these, but believe me i tried.
Here is MainActivity: http://pastebin.com/6yaP0dYM
and here is a class that extends Service: http://pastebin.com/cYuAUina
If someone could provide me some tips to solve my issue that would be more than great!
Create Broadcast Receiver and broadcast that in Service.
If your Activity is ope, register receiver and in onReceive() update the UI.
The receiver should be in the Activity...
Below is the working code
https://stackoverflow.com/a/14695943/1403112
You can get values through broadcast receiver......as follows, First create your own IntentFilter as,
Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");
Then create inner class BroadcastReceiver as,
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
/** Receives the broadcast that has been fired */
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction()=="YOUR_INTENT_FILTER"){
//HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW///////////
String receivedValue=intent.getStringExtra("KEY");
}
}
};
Now Register your Broadcast receiver in onResume() as,
registerReceiver(broadcastReceiver, intentFilter);
And finally Unregister BroadcastReceiver in onDestroy() as,
unregisterReceiver(broadcastReceiver);
Now the most important part...You need to fire the broadcast from wherever you need to send values..... so do as,
Intent i=new Intent();
i.setAction("YOUR_INTENT_FILTER");
i.putExtra("KEY", "YOUR_VALUE");
sendBroadcast(i);
....cheers :)

Checking for variable change using infinite loop

I need to check when the value of a variable is changed in my activity by a service so that I can then update the UI with the new values. I am currently using an infinite loop to check for this within a new thread, will this be using a lot of resources/is there a more efficient way to do this?
You should use a broadcast from the Service to send the changes in the variable. First of all create a broadcast in your main Activity.
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Broadcast","broadcast received");
String value = intent.getStringExtra("Variable"); // this will get the value
// send from Service
}
};
Next set a intent filter to which the broadcast listens. This you can do in onCreate() of your activity.
IntentFilter intentFilter = new IntentFilter("FROM_SERVICE");
registerReceiver(broadcastReceiver,intentFilter);
then in your service you must send a broadcast. If you want to send some data from Service to Activity then you must replace the above code with below
Intent intent = new Intent("FROM_SERVICE");
intent.putExtra("Variable", "change");
sendBroadcast(intent);

LocationPoller and multiple broadcast receiver

I am using cwac-Location Poller (from here) to constantly poll user location and display location based notifications. This all is working fine but now I am trying to attach another BroadcastReceiver so that if my application is in foreground, instead of displaying notification animate the google map to current user location. But for some reason I can't get it working.
onCreate() method of MapActivity I have following code to start poller:
#Override
public void onCreate(Bundle savedInstanceState) {
.....
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, LocationPoller.class);
Bundle bundle = new Bundle();
LocationPollerParameter parameter = new LocationPollerParameter(bundle);
parameter.setIntentToBroadcastOnCompletion(new Intent(this, LocationReceiver.class));
parameter.setProviders(new String[] {LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER});
parameter.setTimeout(60000);
i.putExtras(bundle);
pendingIntent = PendingIntent.getBroadcast(this, 0, i, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), PERIOD, pendingIntent);
}
in onResume() method I am registering another receiver using registerReceiver() method:
#Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(com.commonsware.cwac.locpoll.LocationPollerParameter.INTENT_TO_BROADCAST_ON_COMPLETION_KEY);
intentFilter.setPriority(1);
registerReceiver(locationReceiver, intentFilter);
}
Where locationReceiver looks like:
private BroadcastReceiver locationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "mapActivity called");
abortBroadcast();
}
};
And in order to send ordered broadcast to multiple receiver I have modified LocationPollerService to use sendOrderedBroadcast instead of sendBroadcast
public void onLocationChanged(Location location) {
handler.removeCallbacks(onTimeout);
Intent toBroadcast = createIntentToBroadcastOnCompletion();
toBroadcast.putExtra(LocationPollerResult.LOCATION_KEY, location);
sendOrderedBroadcast(toBroadcast, null);
quit();
}
Now the problem is my dynamically registered receiver never get called but the one mentioned in AndroidManifest.xml does:
<receiver android:name=".receiver.LocationReceiver" />
<receiver android:name="com.commonsware.cwac.locpoll.LocationPoller" />
<service android:name="com.commonsware.cwac.locpoll.LocationPollerService" />
Your problem is in a disconnect between the IntentFilter you create in Java and your createIntentToBroadcastOnCompletion() implementation, which you did not include in your question. Your IntentFilter is expecting a broadcast with a certain action string -- the Intent you are creating in createIntentToBroadcastOnCompletion() apparently does not include this action string.
BTW, with respect to "And in order to send broadcast to multiple receiver", sendBroadcast() is perfectly capable of sending broadcasts to multiple receivers.

Categories