DUE TO COMMENTS, CODE IS UPDATED WITH MORE SPECIFIC INFORMATION.
Manifest.xml
<receiver
android:name="com.x.x.x.MyReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.x.x.x.NOTIFICATION_INTENT_ACTION.TEST" />
</intent-filter>
</receiver>
MyReceiver.java
internal class MyReceiver: BroadcastReceiver() {
companion object {
const val NOT_ID = ".."
const val NOT = ".."
const val NOTIFICATION_INTENT_ACTION = "com.x.x.x.NOTIFICATION_INTENT_ACTION.TEST"
}
override fun onReceive(context: Context, intent: Intent) {
// does not get called
}
}
CreatingIntent.java
Intent intent = new Intent(this, MyReceiver.class);
mPendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
if (mAlarmManager != null) {
mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 60000L, mPendingIntent);
}
Problem: onReceive method inside of NotRec class does not get called. I tried to change Manifest to <receiver android:name="FULL_PATH.receiver.NotRec" /> but it didn't change anything. Any ideas?
Remove
android:exported="false"
from the <receiver> declaration in the manifest.
If you don't "export" your receiver, the AlarmManager cannot trigger it. When you mark a component in the manifest as "not exported", this means that it is "private" and other applications (including system applications like AlarmManager) cannot launch or trigger the component.
Related
I've been stuck on this problem for days. I want to set an alarm and then send a notification when the alarm goes off. works well when the app is open, but it should work when the app is closed too.
here's the code:
Android Manifest:
<receiver android:name=".note.AlertReceiver"
android:enabled="true"
android:exported="true" ></receiver>
<service android:name=".note.AlarmNotificationService"
android:enabled="true"
android:exported="true" ></service>
AlertReceiver:
public class AlertReceiver extends BroadcastReceiver {
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onReceive(Context context, Intent intent) {
Log.d("done", "done");
Intent serviceIntent = new Intent(context,AlarmNotificationService.class);
context.startService(serviceIntent);
}
}
AlarmNotificationService:
public class AlarmNotificationService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("done","done1");
return START_NOT_STICKY;
}
MainActivity:
#RequiresApi(api = Build.VERSION_CODES.N)
private void setAlarm(Calendar calendar){
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this , AlertReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,REQUEST_CODE_alarm,intent,0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),pendingIntent);
}
setAlarm is triggered after TimePicker dialog is closed. I won't add the time picker code because it works with the app open.
when the app is closed. done won't appear in logcat so I'm assuming that there BroadcastReceiver isn't receiving anything
I haven't used AlarmManager with Service therefore it is hard for me to understand why it works only in foreground in your case, but, what I can do is give you a working example that executes in both foreground/background.
From there you should be able to figure out the solution that works for you.
Again, keep in mind that we are not going to use Service class.
AndroidManifest.xml
<receiver
android:name="com.example.name.Receiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
Alarm.kt
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, Receiver::class.java)
// Used for filtering inside Broadcast receiver
intent.action = "MyBroadcastReceiverAction"
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
// In this particular example we are going to set it to trigger after 30 seconds.
// You can work with time later when you know this works for sure.
val msUntilTriggerHour: Long = 30000
val alarmTimeAtUTC: Long = System.currentTimeMillis() + msUntilTriggerHour
// Depending on the version of Android use different function for setting an
// Alarm.
// setAlarmClock() - used for everything lower than Android M
// setExactAndAllowWhileIdle() - used for everything on Android M and higher
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
alarmManager.setAlarmClock(
AlarmManager.AlarmClockInfo(alarmTimeAtUTC, pendingIntent),
pendingIntent
)
} else {
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
alarmTimeAtUTC,
pendingIntent
)
}
BroadcastReceiver.kt
class Receiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// We use this to make sure that we execute code, only when this exact
// Alarm triggered our Broadcast receiver
if (intent?.action == "MyBroadcastReceiverAction") {
Log.d("ALARM", "RECEIVED")
}
}
}
The code is in Kotlin, but you should have no trouble using it in your project or just rewrite to Java.
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!
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.