I am try to set a alarm to restart app on 8:30.am in every day , so I design service and receiver,
<receiver android:name=".AlarmReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
</receiver>
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_ON.equals(action)){ //not working ?
Log.d("BootReceiver", "screen on completed");
Intent Alarm = new Intent(context,LongRunningService.class); //start Service
context.startService(Alarm);
}
if (Intent.ACTION_BOOT_COMPLETED.equals(action)){ //not working ?
Log.d("BootReceiver", "system boot completed");
Intent Alarm = new Intent(context,LongRunningService.class); //start Service
context.startService(Alarm);
}
if ("startAlarm".equals(intent.getAction())){
Intent home = new Intent(context, MainActivity.class);
home.putExtra("RELOAD",1);
home.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(home);
}
LongRunningService.java
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable(){
#Override
public void run() {
Log.i(TAG, "run: executed at "+ new Date().toString()); //not working?
}
}).start();
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 00);
}
In fact , I start service in MainActivity , but I don't want to start service
onCrate in MainActivity , because My alarm set 8:30 to restart MainActivity,
that will be problem , 8:30:00 ~ 8:30:30 will repeat restart my app....
According to docs
Apps that target Android 8.0 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest. An implicit broadcast is a broadcast that does not target that app specifically
So, if you want receive this broadcast you need to register them during app run (and it will work only if you app not destroyed).
JobScheduler will better fit your needs, i think.
Related
I'm attempting to make it so my app runs some code once per day at 6AM. This works just fine when the app is open and in the foreground, but if the app is closed by swiping it away, the code is never called at the appropriate time.
AlarmReceiver.java (For testing purposes, I have it just trying to display a Toast to verify it runs)
public class AlarmReceiver extends BroadcastReceiver {
public static final String intentAction = "com.mpagliaro98.action.NOTIFICATIONS";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(intentAction)) {
Toast.makeText(context, "RECEIVER CALLED", Toast.LENGTH_LONG).show();
}
}
}
MainActivity.java (Where the alarm is being set)
public class MainActivity extends AppCompatActivity {
...
private void setRecurringAlarm() {
// Set this to run at 6am
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getDefault());
updateTime.set(Calendar.HOUR_OF_DAY, 6);
updateTime.set(Calendar.MINUTE, 0);
updateTime.set(Calendar.SECOND, 0);
updateTime.set(Calendar.MILLISECOND, 0);
// Build the pending intent and set the alarm
Intent i = new Intent(AlarmReceiver.intentAction);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(),
0, i, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
assert am != null;
am.setRepeating(AlarmManager.RTC, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
}
}
AndroidManifest.xml (Just the relevant parts)
<uses-permission android:name="android.permission.SET_ALARM" />
<receiver
android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.mpagliaro98.action.NOTIFICATIONS" />
</intent-filter>
</receiver>
I've read through dozens of similar problems to this on this site and elsewhere and I'm seriously at a loss for why this won't work. Any help would be appreciated.
Try changing receiver to
<receiver android:process=":remote" android:name="AlarmReceiver"></receiver>
Should I use android: process =":remote" in my receiver?
I want to start ScheduledExecutorService exactly on 12 AM daily, but in my code schedule is not started. Can any one tell me Whether my code is Correct or not? If any other way available that would also helpful
public class MainActivity extends AppCompatActivity{
ScheduledExecutorService scheduler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scheduler = Executors.newScheduledThreadPool(1);
scheduleTask();
}
public void scheduleTask() {
final Runnable beeper = new Runnable() {
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(),"SCHEDULE STARTED",Toast.LENGTH_LONG).show();
}
}
}
}, 1500);
}
});
}
};
Calendar midnight = Calendar.getInstance();
midnight.set(Calendar.HOUR_OF_DAY, 0);
midnight.set(Calendar.MINUTE, 0);
midnight.set(Calendar.SECOND, 0);
midnight.set(Calendar.MILLISECOND, 1);
midnight.set(Calendar.DAY_OF_YEAR, midnight.get(Calendar.DAY_OF_YEAR) + 1);
long tillMidnight = midnight.getTimeInMillis() - System.currentTimeMillis() - 1;
long ticksTillMidnight = tillMidnight / 50;
final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper, ticksTillMidnight,20*60*60*24, TimeUnit.MILLISECONDS
);
scheduler.schedule(new Runnable() {
public void run() {
beeperHandle.cancel(true);
}
}, 6*6, TimeUnit.MILLISECONDS
);
}}
The answer is quite simple. In your case, a ScheduledExecutorService is bound to the lifetime of your process. If your process gets killed, then the ScheduledExecutorService will get killed along with it. Instead use an AlarmManager
Here are 3 steps
Create the Alarm
Create the BroadcastReceiver
Register the Receiver in the App Manifest
1. Create the Alarm
public void createAlarm() {
//System request code
int DATA_FETCHER_RC = 123;
//Create an alarm manager
AlarmManager mAlarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
//Create the time of day you would like it to go off. Use a calendar
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
//Create an intent that points to the receiver. The system will notify the app about the current time, and send a broadcast to the app
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, DATA_FETCHER_RC,intent, PendingIntent.FLAG_UPDATE_CURRENT);
//initialize the alarm by using inexactrepeating. This allows the system to scheduler your alarm at the most efficient time around your
//set time, it is usually a few seconds off your requested time.
// you can also use setExact however this is not recommended. Use this only if it must be done then.
//Also set the interval using the AlarmManager constants
mAlarmManager.setInexactRepeating(AlarmManager.RTC,calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntent);
}
2. Create the BroadcastReceiver
//This is the broadcast receiver you create where you place your logic once the alarm is run. Once the system realizes your alarm should be run, it will communicate to your app via the BroadcastReceiver. You must implement onReceive.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Your code once the alarm is set off goes here
//You can use an intent filter to filter the specified intent
}
}
3. In your app manifest register the receiver
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package">
//This is a useful permission as it allows your apps alarm to still be active once a reboot takes place
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MainActivity$AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
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 set One time alarm for certain Date and time. And i also set this by using alarm manager. But My problem is when device switch off and switch on then alarm is not wake up.
My code ::
public void setAlarm(String initialTime, String diffTime) throws ParseException {
Calendar cal = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
cal.set(Calendar.DATE,date);
cal.set(Calendar.MONTH,month-1);
cal.set(Calendar.YEAR,year);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ChatScreen.this, AlarmNotificationReceiver.class);
i.putExtra("CoId", coId);
i.putExtra("DeptId", deptNo);
i.putExtra("CoName", companyName);
i.putExtra("DpLogo", dpLogo);
i.putExtra("DeptName",deptName);
i.setAction("isFromAlram");
PendingIntent pi = PendingIntent.getBroadcast(ChatScreen.this,0, i, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),pi);
}
My AlarmReceiverclass :::
public class AlarmNotificationReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e("AlarmReceiver",action);
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
Toast.makeText(context, "ALARM_BOOT_COMPLETED", Toast.LENGTH_LONG).show();
} else if (action.equals("isFromAlram")) {
Logger.errorLog("From Service", "yes");
}
}
}
and also give permission in menifest file android:name="android.permission.RECEIVE_BOOT_COMPLETED"
receiver
android:name="com.chatapi.ChatApi.MyBroadcastReceiver"
android:enabled="true"
EDIT Here the complete manifest entry for the receiver
<receiver android:name=".AlarmNotificationReceiver"
android:enabled="true"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="isFromAlram" > </action>
</intent-filter>
</receiver>
You should add logging to see if your BroadcastReceiver is being called on device boot. Using Toast for this is a bad idea, you may never get to see it. Use logging and check your logcat.
Alarms are not preserved over device boots. When the device boots, your BroadcastReceiver should get called. You then need to set the alarm again.
Background and issue
I have checked dozens of tutorial, examples and questions here on stackoverflow which are related to the issue that services don't get registered after the phone is switched off.
My issue is almost similar with a little difference: I use an IntentService (I need to collect data from an external database and show it as a notification) and the service runs without any problem every 30 seconds until I switch the phone off.
The interesting part
Here comes the weird behaviour! I turn my phone back and the IntentService is registered ONLY ONCE. After booting up, I get my notification (in the example i use only logs for the sake of simplicity) only once, then never again.
part of Activity code (where I can set the service)
private void setRecurringAlarm(Context context) {
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, BackgroundDataServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 30);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), 30*1000, pending);
}
IntentService
public class BackgroundDataService extends IntentService {
....
#Override
protected void onHandleIntent(Intent intent) {
Log.i("BACKGROUNDDATASERVICE STATUS", "running");
}
}
BroadcastReceiver
public class BackgroundDataServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent dailyUpdater = new Intent(context, BackgroundDataService.class);
context.startService(dailyUpdater);
}
}
Manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
...
<service android:name="com.example.blgui3.BackgroundDataService" >
</service>
<receiver android:name="com.example.blgui3.BackgroundDataServiceReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
...
</application>
As far as I know if my service needs to do background tasks e.g. fetch data from external database with AsyncTask then it is recommended to use IntentService. Even if I launch the app after the boot, the service still runs only once, so it simply does not register the BOOT_COMPLETE action. After struggling for hours with this I have absolutely no clue where I go wrong.
The service is started after boot with BOOT_COMPLETED but that does not start any activity and it seems it is only activity that sets the alarm.