How to ensure alarm fires even if app killed by system - java

I have application whose major functionality depend on alarm but alarm sometimes fired sometimes not, i red about it its says because system kills your app before alarm fires, how can i ensure alarm should fire even after application killed, here is how I'm setting alarm
public static void setEndAlarm(){
AlarmManager alarmManager = (AlarmManager) MyApplication.getContext().getSystemService(Context.ALARM_SERVICE);
Calendar time = Calendar.getInstance();
time.setTimeInMillis(System.currentTimeMillis());
time.set(Calendar.HOUR_OF_DAY, SharedPrefUtils.getEndHour(MyApplication.getContext()));
time.set(Calendar.MINUTE, SharedPrefUtils.getEndMin(MyApplication.getContext()));
time.set(Calendar.SECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), endPendingIntent(MyApplication.getContext()));
}
private static PendingIntent endPendingIntent(Context context){
Intent intent = new Intent(context, ClsEndBroadcastReciever.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 02, intent, PendingIntent.FLAG_ONE_SHOT);
return pendingIntent;
}
and the getting context like this:
public class MyApplication extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static Context getContext() {
return mContext;
}
}
Broadcast Receiver:
public class ClsEndBroadcastReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
FirebaseJobDispatcher dispatcher = new
FirebaseJobDispatcher(new GooglePlayDriver(context));
dispatcher.cancel("notification");
Toast.makeText(context, "End Time", Toast.LENGTH_SHORT).show();
}
}

I don't think you can reliably do this without system permissions.
Trying using IntentService and START_STICKY (https://developer.android.com/reference/android/app/Service.html) to ensure that the app does not get killed.

If you specify your BroadcastReceiver in Manifest then it will be called even if your app is not active write now.
Manifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<!-- Activities and Services -->
<receiver android:name=".AlarmBroadcastReceiver"/>
</application>
AlarmBroadcastReceiver
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// do what you want to do here.
// if the work load is heavy then launch service for it here
}
}

Related

App is not running in Background (Android Studio java)

I am working on an Android app and I want to activate a daily Alarm (I used 5 min interval just as an example to test).
I used a Brodacast receiver (Static one declared in the manifest file),
but the app still doesn't work. Here's my code:
The Manifest file:
</activity> <receiver android:name=".ExecutableService" android:enabled="true" ></receiver </application>
The AlarmHandler class:
public class AlarmHandler {
private Context context;
public AlarmHandler(Context context) {
this.context = context;
}
//This will active the alarm
public void setAlarmManager(){
Intent intent = new Intent(context,ExecutableService.class);
PendingIntent sender = PendingIntent.getBroadcast(context ,2,intent,0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
long triggerAfter=60*5*1000;//this will trigger the service after 5 min
long triggerEvery=60*5*1000;//this will repeat alarm every 5 min after that
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,triggerAfter,triggerEvery,sender);
}
}
//This will cancel the alarm
public void cancelAlarm (){
Intent intent = new Intent(context,ExecutableService.class);
PendingIntent sender = PendingIntent.getBroadcast(context,2,intent,0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.cancel(sender);
}
}
}
This is the Broadcast receiver:
import ...
public class ExecutableService extends BroadcastReceiver {
private static final String TAG="Executable Service";
#Override
public void onReceive(Context context, Intent intent) {
//this will be executed at selected interval Notification show
Toast.makeText(context, "Hello World 2! ", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onReceive: it worked ");
Vibrator v=(Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
//deprecated in API 26
v.vibrate(500);
}}}
And this is the MainActivty where I activate the alarm:
public class MainActivity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
AlarmHandler alarmHandler = new AlarmHandler(this);
//cancel the previous scheduled alarm
alarmHandler.cancelAlarm();
//set the new alarm after one hour
alarmHandler.setAlarmManager();
Toast.makeText(this, "Alarm Set ! ", Toast.LENGTH_SHORT).show();
}
If this is not the way that I should use to run the app in the background and push a notification (or a simple toast at a specific time), what is the best way to do it?
I tried also jobscheduler services.
you set the alarm start time to long triggerAfter=60*5*1000;
I suggest changing this to
long triggerAfter =60*5*1000+ System.currentTimeMillis()

Repetitive alarm not working in actual devices but working in emulator

I know this is duplicate question but I have tried all the solution available on the Internet but not able to find the solution.
manifest file
<receiver android:name=".UpdateTables"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
calling this method in onCreate() of mainActivity.java and I also tried to call the method from application class.
private void setTheTimeToUpdateTables(Context context) {
Log.i("Update table function","Yes");
AlarmManager alarmManager=(AlarmManager) getSystemService(ALARM_SERVICE);
Intent alarmIntent=new Intent(context,UpdateTables.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(context,0,alarmIntent,PendingIntent.FLAG_UPDATE_CURRENT);
//alarmManager.cancel(pendingIntent);
Calendar alarmStartTime = Calendar.getInstance();
alarmStartTime.setTimeInMillis(System.currentTimeMillis());
//midnight
alarmStartTime.set(Calendar.HOUR_OF_DAY, 0);
alarmStartTime.set(Calendar.MINUTE, 1);
alarmStartTime.set(Calendar.SECOND, 0);
if(Calendar.getInstance().getTimeInMillis()>alarmStartTime.getTimeInMillis())
{
alarmStartTime.add(Calendar.DATE,1);
}
Log.i("TIME IS ",Long.toString(alarmStartTime.getTimeInMillis()));
System.out.println("Updating table time "+alarmStartTime);
System.out.println("Time in millseconds "+alarmStartTime.getTimeInMillis());
alarmManager.setInexactRepeating(AlarmManager.RTC,alarmStartTime.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);
Log.d("Alarm","Set for midnight");
}
public class UpdateTables extends BroadcastReceiver {
//midnight saga
DbHelper dbHelper;
ArrayList<ListMedicine> reminderInfo;
private SharedPreferences sharedPreferences;
private static AlarmManager alarmManager;
private static void init(Context ctx){
if (alarmManager==null)
alarmManager=(AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE);
}
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Update tables","yes");
}
When app is closed than it the updatetables broadcast receiver will not call.
output of ./adb shell dumpsys alarm before the app closed.
RTC #5: Alarm{28e47fec type 1 when 1487010660087 user.com.hlthee}
tag=*alarm*:user.com.hlthee/.UpdateTables
type=1 whenElapsed=+23h48m35s946ms when=2017-02-14 00:01:00
window=-1 repeatInterval=86400000 count=0
operation=PendingIntent{24cc8fb5: PendingIntentRecord{19e0864a user.com.hlthee broadcastIntent}}
But when the app is closed from recent activity then this entry is also delete. Why?
thats why no alarm is rang when app is closed.
Any help would be appreciated.
define a custom action name, such as:
public static final String MY_ACTION = "com.sample.myaction"
create a BroadcastReceiver:
public class MyAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MY_ACTION)) {
// Do something here
}
}
}
Register the receiver on your AndroidManifest.xml:
<receiver android:name="com.sample.MyAlarmReceiver">
<intent-filter>
<action android:name="com.sample.myaction"/>
</intent-filter>
setup the alarm, use the following PendingIntent:
Intent i = new Intent(MY_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);

Android not recreating service even when using START_STICKY

I am trying to create a service and set an alarm through it. I need to run the service in background to keep the broadcaster reciever running even if the app is closed. I tried using START_STICKY, running service in a separate child process as well as a global process, all in vain. What should I do ?
Alarm.java
package com.simpleapps.simpleweather;
import ...
public class Alarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
ToneGenerator toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP,150);
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show();
}
public void setAlarm(Context context)
{
Log.d("Alarm","Started");
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60, pi); // Millisec * Second * Minute
}
public void cancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
HelloService.java
package com.simpleapps.simpleweather;
import ...
public class HelloService extends Service
{
Alarm alarm = new Alarm();
public void onCreate()
{
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("Alarm","New Service");
alarm.setAlarm(this);
return START_STICKY;
}
#Override
public void onStart(Intent intent, int startId)
{
alarm.setAlarm(this);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.simpleapps.simpleweather">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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>
<activity android:name=".today_details" />
<activity android:name=".forecast_details"/>
<receiver android:process=":remote" android:name=".Alarm" android:exported="true">
</receiver>
<service
android:name=".HelloService"
android:enabled="true">
</service>
</application>
</manifest>
Starting Service -
Intent intent = new Intent(this, HelloService.class);
startService(intent);
Update : It is working on every device except my Lollipop 5.0 device AsusZenfone2
I've tried your code and it's working ok on the emulator. One thing I've notice is that:
* setRepeating
* <b>Note:</b> Beginning in API 19, the trigger time passed to this method
* is treated as inexact: the alarm will not be delivered before this time, but
* may be deferred and delivered some time later. The OS will use
* this policy in order to "batch" alarms together across the entire system,
* minimizing the number of times the device needs to "wake up" and minimizing
* battery use. In general, alarms scheduled in the near future will not
* be deferred as long as alarms scheduled far in the future.
So I've change the Alarm to look like so (It's just illustration, you could do it without static fields):
public class Alarm extends BroadcastReceiver
{
private static boolean sAlarmCanceled = false;
#Override
public void onReceive(Context context, Intent intent)
{
if (sAlarmCanceled)
return;
ToneGenerator toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
toneGen1.startTone(ToneGenerator.TONE_CDMA_PIP,150);
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_SHORT).show();
scheduleNextAlarm(context);
}
public static void enableAlarm(Context context) {
sAlarmCanceled = false;
scheduleNextAlarm(context);
}
public static void disableAlarm() {
sAlarmCanceled = true;
}
private static void scheduleNextAlarm(Context context)
{
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_ONE_SHOT);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, pi);
}
}
And now it get executed precisely every 10 sec. Service runs normal and I was able to remove Application task and see the alarm anyway.

AlarmManager reset on reboot

I've an alarm which opens an activity at a time chosen by the user. If the user hits the start button, the alarm goes fine but it gets cancelled after reboot. I've looked everywhere and it says that I should use a service. Is it possible to keep the alarms on after the reboot without using service? I'm new to coding so can you please breakdown what I need to do. Thank you
public class MainActivity extends AppCompatActivity {
Button disable;
Button start;
TimePicker timePicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timePicker = (TimePicker) findViewById(R.id.timePicker);
disable = (Button) findViewById(R.id.disable_alarm);
start = (Button) findViewById(R.id.button);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, timePicker.getHour());
calendar.set(Calendar.MINUTE, timePicker.getMinute());
Intent intent = new Intent(getApplicationContext(),notification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 120*1000, pendingIntent);
}
});
disable.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(),notification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
});
and Broadcast Receiver is
public class notification extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent scheduledIntent = new Intent(context, pop_up2.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);}}
Thanks
All of the active alarms are cancelled after phone is shutdown. In order to reset the alarms you need to use a separate broadcast receiver that will receive only boot completed action. The receiver then starts service that will reset all your alarms in background. Best one for you is IntentService, because it ends itself when the work is done. Of course you need to store the information about alarms somewhere in order to remember which ones to reset. You can use, for example, SQLite to store them.
In your manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
and
<receiver android:name="developer.marat.apps.days.Alarms.BootCompletedReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name="developer.marat.apps.days.Alarms.RestartAlarmsService"/>
Special receiver:
public class BootCompletedReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent i = new Intent(context, RestartAlarmsService.class);
ComponentName service = context.startService(i);
}
}
}
RestartAlarms:
public class RestartAlarmsService extends IntentService{
public RestartAlarmsService() {
super("RestartAlarmsService");
}
#Override
protected void onHandleIntent(Intent intent) {
// Restart your alarms here.
// open database, iterate through every alarm and set them again
}
}

How can i keep a thread in android app forever?

I'm building an enterprise application that needs to get some information about the employees' rooted phones to do corporate management.
This thread needs to run each five minutes.
I'm using an Activity that is started by a broadcast(BOOT_COMPLETED) when the android boots up, and it starts an infinite thread to send this information to server.
My current problem is my application is being killed by android after the user opens a lot of others apps.
What would be the better way to keep a thread running in background to send this information to server?
Main Application Class
public static void startService(Context mContext){
try{
//Schedule Service.
scheduleService(mContext);
//Call onUpdate.
onUpdate();
}catch (Exception o){
Utilities.log(o.toString());
}
}
public static void scheduleService(Context mContext){
try{
final int NOTIFICATION_INTERVAL = 5 * 60 * 1000;
Intent mIntent = new Intent(mContext, ServiceReceiver.class);
AlarmManager mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
PendingIntent mPendingIntent = PendingIntent.getBroadcast(mContext, 1, mIntent, 0);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), NOTIFICATION_INTERVAL, mPendingIntent);
}catch (Exception o){
Utilities.log(o.toString());
}
}
ServiceReceiver
public class ServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context mContext, Intent intent) {
Utilities.log("Service Received");
//Start Service.
MyApplication.startService(mContext);
}
}
AndroidManifest
<receiver
android:name=".BootUpReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.REBOOT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver android:name=".ServiceReceiver"/>
BootUpReceiver
public class BootUpReceiver extends BroadcastReceiver
{
public void onReceive(Context mContext, Intent mIntent){
Utilities.log("BootUp Received.");
//Start Service.
MyApplication.startService(mContext);
}
}
create a static broadcast receiver for Repeating Alarms and start Intent Service from broadcast don't use infinite Thread
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationStatus.setupNotification(context); // if you restart your phone
}
}
class NotificationStatus{
//Call only one time from app from any activity
public static void setupNotification(Context context) {
final int NOTIFICATION_INTERVAL = 5 * 60 * 1000;
Intent myIntent1 = new Intent(context, NotificationReceiver.class);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 1, myIntent1, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), NOTIFICATION_INTERVAL, pendingIntent1);
}
}
public class NotificationReceiver extends BroadcastReceiver {
private static final int mNotificationId = 0;
#Override
public void onReceive(Context context, Intent intent) {
//start your services here for sending data
Intent intent1 = new Intent(context, SyncService.class);
context.startService(intent1);
}
}
public class SyncService extends IntentService {
public SyncService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
//Write code here for sending data to server
}
}
AndroidManifest
<receiver android:name="NotificationReceiver" />
<receiver android:name="BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
Define Service in Manifest
<service android:name=".SyncService"/>
You need to make your application an Android service.

Categories

Resources