Repeating actions using Alarm in Android background service - java

I wrote this code in MainService.java that is called in foreground by using startForeground method. I want to make a toast message in every 10 seconds but it doesn't work. How can I fix it??
public void Alarm(){
Intent intent = new Intent("AlarmService");
PendingIntent sender = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
long firstTime = SystemClock.elapsedRealtime() + 10 * 1000;
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, sender) ;
} else {
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, sender);
}
} else {
am.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, sender);
}
}
BroadcastReceiver alarmReceiver;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
alarmReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub\
count++;
Toast.makeText(getApplicationContext(),count+"times",Toast.LENGTH_LONG);
Alarm();
}
};
registerReceiver(alarmReceiver, new IntentFilter("AlarmService"));
}

Take a look at https://developer.android.com/topic/libraries/architecture/workmanager to do Background tasks

Related

Timer in the Service

I have an app that records the time of the job, i mean that calculates the job time for that purpose i used chronometer to run the time. Since the job is 9 hours long so user can't open the app for that long. For that purpose i am using the Service which indicate the time. Since i cannot use Chronometer because
Chronometer is a UI widget (actually a TextView) in Android. So, i can't use it for non-UI purposes. So i have to use timer to do the job. But i do not know how can i achieve this. Any code or help is appreciated. Thanks
When i hit the start button the chronometer starts like this
and my service also started but i get the time as 00:00:00 like this
i just want that timer should run in the service and i can see the time in service and i do not want to deal or use the time that is running in service, the time in service will show user that how much time they spend on job.
Service Class
public class ServiceTimer extends Service {
// Chronometer chronometer ;
//String valueOfTime ;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
// chronometer = new Chronometer(this);
//chronometer.setText("00:00:00");
//chronometer.setOnChronometerTickListener(new //Chronometer.OnChronometerTickListener() {
// #Override
// public void onChronometerTick(Chronometer chronometer) {
// CharSequence text = chronometer.getText();
// if (text.length() == 5) {
// chronometer.setText("00:"+text);
// } else if (text.length() == 7) {
// chronometer.setText("0"+text);
// }
//}
// });
// chronometer.start();
//before i know about chronometer that i cannot use it in service
// this is what i have so for with chronometer to achieve
// but failed ...
Intent notificationIntent = new Intent(this, Timer_FullTime.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(chronometer.getText().toString())
.setSmallIcon(R.mipmap.logoback)
.setContentText(input)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
//do heavy work on a background thread
//stopSelf();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
UPDATE this is how i get what i wanted or asked in the question
public class ServiceTimer extends Service {
private int THE_ID_TO_UPDATE = 1;
private static Timer timer = new Timer();
private Context ctx;
private int second = 0 ;
NotificationManager notificationManager ;
private int minute = 0 ;
private int hour = 0 ;
//we are going to use a handler to be able to run in our TimerTask
final Handler handler = new Handler();
NotificationCompat.Builder notification ;
#Override
public void onCreate() {
super.onCreate();
super.onCreate();
ctx = this;
}
private class mainTask extends TimerTask
{
public void run()
{
second = second + 1 ;
if (second == 60){
minute++ ;
second = 0 ;
}
if (minute == 60){
hour++;
minute = 0 ;
second = 0 ;
}
notification.setContentText( hour + "h " + minute + "m " + second+"s");
notificationManager.notify(THE_ID_TO_UPDATE , notification.build());
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
Intent notificationIntent = new Intent(this, Timer_FullTime.class) ;
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0) ;
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notification = new NotificationCompat.Builder(this, CHANNEL_ID);
notification.setContentTitle(input);
notification.setSmallIcon(R.mipmap.logoback);
notification.setOnlyAlertOnce(true);
notification.setWhen(System.currentTimeMillis());
notification.setContentIntent(pendingIntent);
notification.setLights(Color.RED, 1000, 1000);
notification.setVibrate(new long[]{0, 400, 250, 400});
notification.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
notification.build();
notificationManager.notify(THE_ID_TO_UPDATE , notification.build());
startForeground(THE_ID_TO_UPDATE, notification.build());
timer.scheduleAtFixedRate(new mainTask(), 0, 1000);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
You could try to use a Timer with a TimerTask:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Update your counter/notification each second
}
}, 0, 1000);
Link to official documentation: https://developer.android.com/reference/java/util/Timer

Android How to keep Running the background service when app is killed by user?

I want a background service that keeps running always in a background? It is running on some phone but not running on customised OS phones like VIVO, OPPO MIUI etc? Service is Killed on these customised OS phone.
My Code is given below --
public class MyService extends Service
{
private static final String TAG = "MyService";
#Override
public void onStart(Intent intent, int startId)
{
// TODO Auto-generated method stub
super.onStart(intent, startId);
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
#Override
public void onCreate()
{
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
//call to onTaskRemoved
onTaskRemoved(intent);
//return super.onStartCommand(intent, flags, startId);
Toast.makeText(this, "Service Started!", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onDestroy()
{
super.onDestroy();
int i = 1;
Intent intent = new Intent(this, MyBroadCastReceiver.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), 234324243, intent, 0);
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 5);
if (alarmManager != null)
{
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
60000,
pendingIntent);
}
}
#Override public void onTaskRemoved(Intent rootIntent)
{
Log.e("onTaskRemoved", "Called!");
int i = 1;
Intent intent = new Intent(this, MyBroadCastReceiver.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), 234324243, intent, 0);
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 5);
if (alarmManager != null)
{
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES,
pendingIntent);
}
super.onTaskRemoved(rootIntent);
}}
I have written a Broadcast Receiver that wake ups my service for every second but it is not working. My Broadcast Receiver as follows-
public class MyBroadCastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.e("MyBroadCastReceiver", "onReceive");
//if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction()))
{
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O)
{
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("myFCMJob")
.build();
dispatcher.mustSchedule(myJob);
}
else
{
Intent service = new Intent(context, MyService.class);
context.startService(service);
}
}
}}
I have started my service using Alarm Manager and have set the Alarm for every 5 seconds, my MainActivity.java file code is as below ---
public class MainActivity extends AppCompatActivity
{
Button btnStopService;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStopService = findViewById(R.id.btnStopService);
//get FirebaseToken
getToken();
//start Service
startService();
//setReceiver();
btnStopService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
}
});
}
private void getToken()
{
FirebaseId firebaseId=new FirebaseId();
String token_firebase=firebaseId.getFireBaseToken();
}
private void startService()
{
Intent myIntent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, myIntent, 0);
Log.e("TAG", "++++++++++222222++++++++");
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
//Calendar calendar = Calendar.getInstance();
// calendar.setTimeInMillis(System.currentTimeMillis());
//calendar.add(Calendar.SECOND, 10);
Calendar alarmStartTime = Calendar.getInstance();
Calendar now = Calendar.getInstance();
alarmStartTime.set(Calendar.HOUR_OF_DAY, 0);
alarmStartTime.set(Calendar.MINUTE, 0);
alarmStartTime.set(Calendar.SECOND, 5);
if (now.after(alarmStartTime)) {
Log.d("Hey","Added a day");
//alarmStartTime.add(Calendar.DATE, 1);
}
if (alarmManager != null) {
alarmManager.set(
AlarmManager.RTC_WAKEUP,
alarmStartTime.getTimeInMillis(),
pendingIntent);
}
Toast.makeText(this, "Start Alarm", Toast.LENGTH_LONG).show();
}}
Thanks in Advance.
To keep your service and all your application running even if the phone goes into sleep mode, your service has to call startForeground() and show a non dismissable notification.
It is also convenient to acquire a partial WAKE LOCK.
on your onStartCommand()
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, Constants.CHANNEL_NOTIFY_ID)
.setContentTitle("the content title")
.setContentText("the content text")
.setSmallIcon(R.drawable.myicon)
.setOngoing(true);
// you can add other options Builder has
startForeground(1234, mBuilder.build());

Error notification when i close my app

i am doing an application that will notify the user after 2 weeks. but i set the timer in 2 mins so i could test if my application will notify the user. my problem is when i turn on the notification and close my app. i will get an error in 2 minutes no notification but when my app is running the notification is working fine. In the logcat my error is in Bundle showData = i.getExtras(); i think the problem is when i closed my app, the Bundle passData is getting null?
PhoneInformation.java
case R.id.bTurnOn:
Bundle passData = new Bundle();
Intent intent = new Intent(PhoneInformation.this,NotificationService.class);
passData.putInt("keyid", rowId);
intent.putExtras(passData);
startService(intent);
break;
NotificationService.java
public class NotificationService extends Service{
int rowId;
private Timer timer = new Timer();
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Toast.makeText(this, "OnCreate()", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "OnDestroy()", Toast.LENGTH_SHORT).show();
}
#Override
#Deprecated
public void onStart(final Intent i, int startId) {
// TODO Auto-generated method stub
super.onStart(i, startId);
final Handler handler = new Handler();
Timer timer;
TimerTask timertask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#SuppressWarnings("deprecation")
public void run() {
Bundle showData = i.getExtras();
rowId = showData.getInt("keyid");
Bundle passData = new Bundle();
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(NotificationService.this,SMSPhoneMessage.class);
passData.putInt("keyid", rowId);
notificationIntent.putExtras(passData);
PendingIntent pendingIntent = PendingIntent.getActivity(NotificationService.this, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification = new Notification(R.drawable.ic_launcher, "New Message", System.currentTimeMillis());
notification.setLatestEventInfo(NotificationService.this, "New Message", "Please come to me immediately", pendingIntent);
nm.notify(123, notification);
}
});
}
};
timer = new Timer();
timer.schedule(timertask, 10000);
}
}

Android Kitkat how to fix return_sticky bug in service

I found several posts regarding the return_sticky problem when using KitKat.
It seems like that the service can be killed and don't come back even when return_sticky.
I'm talking about a background service, not a foreground service.
I've tried several approaches but everything seems to fail. Heres a bit of code for demonstrating. After a while it gets killed and it won't come back:
public class RestPushService extends Service {
#Override
public void onDestroy() {
MainApplication.getDevice().writeBoolean("REST_PUSHSERVICE_RUNNING", false);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if ((intent != null) && (intent.getBooleanExtra("ALARM_RESTART_SERVICE_DIED", false))) {
if (MainApplication.getDevice().readBoolean("REST_PUSHSERVICE_RUNNING", false)){
ensureServiceStaysRunning();
return START_STICKY;
}
}
MainApplication.getDevice().writeBoolean("REST_PUSHSERVICE_RUNNING", true);
/** doing other stuff like creating a thread **/
return START_STICKY;
}
private void ensureServiceStaysRunning() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final int restartAlarmInterval = 20 * 60 * 1000;
final int resetAlarmTimer = 2 * 60 * 1000;
final Intent restartIntent = new Intent(this, RestPushService.class);
restartIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
restartIntent.putExtra("ALARM_RESTART_SERVICE_DIED", true);
final AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Handler restartServiceHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 0, restartIntent, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + restartAlarmInterval, pintent);
sendEmptyMessageDelayed(0, resetAlarmTimer);
}
};
restartServiceHandler.sendEmptyMessageDelayed(0, 0);
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartService = new Intent(getApplicationContext(), this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartServicePI = PendingIntent.getService(getApplicationContext(), 1, restartService, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePI);
}
}
Now another receiver which gets called when the device starts.
public class myReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == null || action.equals("com.myapp.START_ALARM")) {
if (MainApplication.getDevice().hasInternet()) {
if (!MainApplication.getDevice().hasServiceRunning(RestPushService.class)) {
context.startService(new Intent(context, RestPushService.class));
} else {
Log.d(TAG, "RestPushService was aready running. Do nothing");
}
}
}
}
public void startRepeating(Context context) {
if (alarmManager == null) alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent("com.myapp.START_ALARM");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 30, pi); // Millisec * Second * Minute
}
public void stopRepeating(Context context) {
Intent intent = new Intent("com.myapp.START_ALARM");
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.cancel(sender);
}
}
I've truncated much code because I think it is not relevant. I removed all try catches and null initializations to make sure it's easily readable. So what may be caused the "don't come back" crap?
I refer also to START_STICKY does not work on Android KitKat

Alarm During Specific time Android Application

Can anyone inform me how can I create an alarm in android application that starts from current time and it'll be repeated for each 10 minutes during specific time?
For example, depending on different cases the time that the alarm should repeate is during 2 hours, another case it might be just 1:30 hour and so on.
Is there any way to do that?
Actually I used a code I took it from the web, as shown below:
public class MyAlarmService extends Service {
#Override
public void onCreate() {
// TODO Auto-generated method stub
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "MyAlarmService.onBind()", Toast.LENGTH_LONG)
.show();
return null;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "MyAlarmService.onDestroy()", Toast.LENGTH_LONG)
.show();
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Toast.makeText(this, "...", Toast.LENGTH_LONG)
.show();
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(this, "MyAlarmService.onUnbind()", Toast.LENGTH_LONG)
.show();
return super.onUnbind(intent);
}
}
You can use a BroadcastReceiver and an PendingIntent. First you declare an BroadcastReceiver:
public class EventAlarmReceiver extends BroadcastReceiver {
private long alarmTime;
#Override
public void onReceive(Context context, Intent intent1) {
//declare the new time for the alarm, you can use a time stamp, for example in the next hour
alarmTime = Calendar.getInstance().getTimeInMillis()+(60*60000);
//set an intent to the Receiver
Intent intent = new Intent(context, EventAlarmReceiver.class);
//set an PendingIntent to the Intent
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 234324243, intent, 0);
//add to the System Alarm Manager
AlarmManager alarmManager = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, alarmTime, pendingIntent);
}
}
and start the alarm in the Activity:
Intent intent = new Intent(context, EventAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 234324243, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, time, pendingIntent);

Categories