I have implemented a service to run with the alarm manager.
I read this link: Should I use android: process =“:remote” in my receiver?
I thought this would be a nice feature for my app, since i want the service to keep running after my app is down.
But when i add this line of configuration to my receiver on the manifest, my service stops being called.
Any clues?
Here is my receiver declaration:
This works:
<receiver
android:name=".service.MyAlarmReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name=".service.MyAlarmReceiver"></action>
</intent-filter>
</receiver>
This wont'n work:
<receiver
android:name=".service.MyAlarmReceiver"
android:enabled="true"
android:process=":remote"
android:exported="false">
<intent-filter>
<action android:name=".service.MyAlarmReceiver"></action>
</intent-filter>
</receiver>
public class MyAlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Time to start scan service!");
Intent intent = new Intent(context, BeaconFinderService.class);
context.startService(intent);
}
}
This is how i start my alarm manager:
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), MyAlarmReceiver.class);
final PendingIntent pIntent = PendingIntent.getBroadcast(getApplicationContext(), MyAlarmReceiver.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), Constants.BLE_SERVICE_LOOP_TIME, pIntent);
When you configure your service to run in remote mode (android:process=":remote"), you will have to debug the process :remote instead as usual .
Personal bug:
So I was having an exception when trying to access FirebaseUser on the service. When in remote mode, you can't access the FirebaseUser, since your process runs on another context.
I had to pass the user through intent extras when initializing the service.
That was all!
Related
I'm trying to write a service that will run in background until removed by the user, I used this code:
Intent activityIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0,
activityIntent, 0);
Notification notification = new Notification.Builder(this).
setContentTitle(getText(R.string.app_name)).
setContentText("Doing stuff").
setContentInfo("").
setSmallIcon(R.drawable.icon).
setDeleteIntent(createOnDismissedIntent(getBaseContext(), notId)).
setContentIntent(pendingIntent).build();
notificationManager.notify(notId,notification);
return START_REDELIVER_INTENT;
The service is supposed to listen for incoming SMS and then do something once it detects an SMS.
Now it works , But if I wait for a little while and then try sending myself an SMS to see if the service is still up , the service does not do any thing implying that the service is down(I think), So my question is , Why would the service be down if i used 'START_REDELIVER_INTENT'?
-I remove the notification in onDestroy function in the service. So while the service stops working after a while the notification is still there implying that the service has not been destroyed
You need autorestart service after reboot.
Manifest:
<service android:exported="false" android:name=".service.YourService" android:enabled="true"></service>
<receiver android:name=".service.YourBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
Also permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Define receiver:
public class YourBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
Intent serviceIntent = new Intent(arg0, YourService.class);
arg0.startService(serviceIntent);
}
I've an issue with an Alarm Manager. I wan't to execute my service each hour.
Alarm Manager is launched after reboot and work well, even if the app is not open or open and closed (My PhoneStartReceiver call launchBackgroundService one time, after a completed boot).
My problem is when I launch application after installation, without phone reboot. In this case, AlarmManager is killed when application is force closed or destroyed.
Problem is juste between installation, and next reboot. How to maintain AlarmManager enabled until next reboot ?
<receiver
android:name=".helpers.PeriodicalServiceCaller"
android:process=":remote"/>
<receiver
android:name=".helpers.PhoneStartReceiver"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Here is my launchBackgroundServiceMethod, called in the both cases.
public static void launchBackgroundService(){
// Construct an intent that will execute the PeriodicalServiceCalle
Intent intent = new Intent(getApplicationContext(), PeriodicalServiceCaller.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(getApplicationContext(), PeriodicalServiceCaller.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every minute
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, 1000L, pIntent);
}
PeriodicallServiceCaller code
public class PeriodicalServiceCaller extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
// Triggered by the Alarm periodically (starts the service to run task)
#Override
public void onReceive(Context context, Intent intent) {
Log.i("START-SERVICE", "PeriodicalServiceCaller");
Intent i = new Intent(context, MonitorDataService.class);
context.startService(i);
}
EDIT
My launchBackgroundService is launch by an Acitivity if it's after install and by PhoneStartReceiver if it's after a reboot
You need to register a BroadcastReceiver to detect when your are has been updated.
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
Take a look at
How to know my Android application has been upgraded in order to reset an alarm?
Is launchBackgroundService in a service or run from the activity? If it is run from the service please check this answer Background Service getting killed in android
START_STICKY was the thing I missed.
I want to know whether the user allows autostart permissions of the app. I have already tried this:
ComponentName mComponentName = new ComponentName(getPackageName(),".AutoStartReceiver");
int a = getPackageManager().getComponentEnabledSetting(mComponentName);
the autostart permission can be granted and denied by security app,but I don't know how to get the status in my application.
such as the picture
you are probably using this permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
After that, you can implement a BroadcastReceiver:
public class BootUpReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context, MyService.class), PendingIntent.FLAG_UPDATE_CURRENT);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + interval, interval, pi);
}}
And just add the class to your manifest-file:
<receiver android:enabled="true" android:name=".BootUpReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
To check directly, if you have Autostart permissions, use this:
int p = ContextCompat.checkSelfPermission(Activity.this, Manifest.permission.RECEIVE_BOOT_COMPLETED);
if (p == PackageManager.PERMISSION_GRANTED) {
//Yay, you have the receive boot completed (= Autostart) permission!
}
To get a list of receivers, registered for a specific intent, you can use
Use PackageManager and queryBroadcastReceivers().
To get a list for BOOT_COMPLETE, construct an intent with BOOT_COMPLETE action
I want to add reminder functionality to my Application.
I have Activity with a Button "Remind in 5 minutes". When I press this Button method setReminderInMinutes calls and in 5 minutes I will get a Dialog Fragment.
public void setReminderInMinutes(int timeInMinutes){
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override public void onReceive(Context context, Intent intent){
ReasonsNonDeliveryDlgFragment cityDlg = ReasonsNonDeliveryDlgFragment.newinstance();
cityDlg.show(getSupportFragmentManager(), CityDlgFragment.TAG);
((Vibrator)getSystemService(VIBRATOR_SERVICE)).vibrate(800);
context.unregisterReceiver(this);
}
};
this.registerReceiver(receiver, new IntentFilter("somemessage"));
PendingIntent pintent = PendingIntent.getBroadcast( this, 0, new Intent("somemessage"), 0 );
AlarmManager manager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000*60*timeInMinutes, pintent);
}
It works well until I stay on this Activity, but when I press back Button Activity destroys, onReceive method never fire and I receive exception:
" android.app.IntentReceiverLeaked: Activity MyActivity has leaked
IntentReceiver MyActivity$1#42136488 that was originally registered
here. Are you missing a call to unregisterReceiver()?"
So, is there anyway to register BroadcastReceiver outside my Activity?
P.S. I have tried to register it in manifest file:
<receiver android:name=".receivers.ReminderReceiver">
<intent-filter>
<action android:name="name"/>
</intent-filter>
</receiver>
But still nothing works. What am I doing wrong?
In your case it will not work because in manifest file you given the action as "name" but while creating intent you given the action as "somemessage". So how it works. Give the same action name in manifest and intent.
Change your code like below
<receiver android:name=".receivers.ReminderReceiver">
<intent-filter>
<action android:name="some_action"/>
</intent-filter>
</receiver>
And in setReminder() method
PendingIntent pintent = PendingIntent.getBroadcast( this, 0, new Intent("some_action"), 0 );
AlarmManager manager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000*60*timeInMinutes, pintent)
The only way to register reciever outside of Activity - register it inside manifest of application. In you case it should look like following:
<receiver android:name=".receivers.ReminderReceiver" >
<intent-filter>
<action android:name="somemessage" />
</intent-filter>
</receiver>
Important to set name in <intent-filter> same as action of your Intent inside sended broadcast.
Try this out
#Override
public void onResume() {
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));
}
// handler for received Intents for the "my-event" event
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
#Override
protected void onPause() {
// Unregister since the activity is not visible
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
It is not necessary to pass a reference of BroadCastReceiver to pending intent. You can also pass the reference of your activity so that it will be called for you when the pending intent goes of.
If you want to use BroadCastReceiver outside of your activity you can declare it in manifest like this
<receiver android:name=".MyReceiver"
android:exported="true">
</receiver>
Then in your activity do this to register it with alarm manager
PendingIntent pintent = PendingIntent.getBroadcast(this, 0, new Intent(this, MyReceiver.class), 0 );
AlarmManager manager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000*60*timeInMinutes, pintent);
I"m sure this is something that is simple, but I'm not figuring it out. I'm trying to make a simple repeating alarm and it never gets triggered. What I have is:
private void setupAlarms()
{
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, RepeatingAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(HelloAndroid.this, 0, intent, 0);
GregorianCalendar fifteenSeconds = (GregorianCalendar)Calendar.getInstance();
fifteenSeconds.add(Calendar.MINUTE, 0);
fifteenSeconds.set(Calendar.SECOND, 15);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), fifteenSeconds.getTimeInMillis(), pendingIntent);
}
This is called from the main onCreate call.
My alarm receiver:
public class RepeatingAlarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, R.string.hello, Toast.LENGTH_SHORT).show();
}
}
In my manifest, I have added:
<receiver android:name=".RepeatingAlarm" android:process=":remote" />
Any help, much appreciated
Have you added an intent filter to your BroadcastReceiver?
Code might look something like this in your AndroidManifest.xml file:
<receiver android:name=".RepeatingAlarm" android:exported="true">
<intent-filter>
<action android:name="intent id text" />
</intent-filter>
</receiver>
and when creating your intent do something like this:
Intent intent = new Intent("intent id text")
where the "intent id text" can be any string you use to identify your intent. Also Android alarms get reset if you reboot your device so that may be something you need to look into.
Hope this helps.