create service with CountDownTimer in android - android

I am starter in android. I want to create a Service.java from this Activity.class.
In my MainActivity I have 2 buttons(aBTN and bBTN). with clicking on each of them Adult1Activity with timer starts. this timer controls with PlayBTN and StopBTN. Also, I want to show timer in notification. I want to use 2 other buttons "RestoreBTN" and "CloseBTN" for connecting between activity and notification.
I use CountDownTimer class for timer. but I don't know how I write
Textview
RestoreBTN
Note: "aBTN" and "bBTN" have different times. "aBTN" is 10 minutes and "bBTN" is 5 min.
This code is the first one.
public class Adult1Activity extends AppCompatActivity implements View.OnClickListener{
private Button playBTN,stopBTN ; // contoroll buttons
private Button OnStop;
private TextView tv ;
private Toolbar toolbar;
private CountDownTimer countDownTimer;
private int total;
private long timeBlinkInMilliseconds ; // start time of start blinking
private boolean blink; // controls the blinking .. on and off
public CustomDialogClass cdd; // back dialog
private boolean isRunning = false;
public String timeString;
public NotificationManager notificationManager;
public NotificationCompat.Builder notificationBuilder;
public final int notification_id=01;
private static final String EXTRA_NOTE = "NOTE";
private static final String NOTE_RESTORE = "restore";
private static final String NOTE_CLOSE = "close";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_adult1);
//define toolbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
playBTN = (Button) findViewById(R.id.play);
stopBTN = (Button) findViewById(R.id.stop);
tv = (TextView) findViewById(R.id.TimeCount);
playBTN.setOnClickListener(this);
stopBTN.setOnClickListener(this);
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
handleIntent(getIntent());
}
#Override
public void onClick(View v) {
switch(v.getId())
{ case R.id.play:
tv.setTextAppearance(getApplicationContext(),
R.style.normalText);
setTimer();
stopBTN.setVisibility(View.VISIBLE);
playBTN.setVisibility(View.GONE);
startTimer(total);
break;
case R.id.stop :
countDownTimer.cancel();
Intent reloadIntent = new Intent(Adult1Activity.this, Adult1Activity.class);
startActivity(reloadIntent); // refresh activity
finish();
isRunning = false;
notificationManager.cancel(notification_id);
break;
}
}
//------------------------------------------------
private void setTimer() {
int time=30;
total = time*60 * 1000; // 30*60 aeconds
timeBlinkInMilliseconds = 10 * 1000;
}
private void startTimer(long enter) {
countDownTimer = new CountDownTimer(enter, 500) {
// 500 means, onTick function will be called at every 500
// milliseconds
#Override
public void onTick(long leftTimeInMilliseconds) {
final long seconds = leftTimeInMilliseconds / 1000;
long save = leftTimeInMilliseconds / 1000;
if (leftTimeInMilliseconds < timeBlinkInMilliseconds) {
tv.setTextAppearance(getApplicationContext(),
R.style.blinkText);
// change the style of the textview .. giving a red
// alert style
if (blink) {
tv.setVisibility(View.VISIBLE);
// if blink is true, textview will be visible
} else {
tv.setVisibility(View.INVISIBLE);
}
blink = !blink; // toggle the value of blink
}
// format the textview to show the easily readable format
timeString = String.format("%02d", seconds / 60)
+ ":" + String.format("%02d", seconds % 60);
tv.setText(timeString);
ExtendedNotification(timeString);
}
#Override
public void onFinish() {
Adult1Activity.this.finish();
vibrate(1000);
notificationManager.cancel(notification_id);
// turn on screen
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
wakeLock.acquire();
// *********** notification
PendingIntent i = PendingIntent.getActivity(getBaseContext(), 0,
new Intent(getBaseContext(), Sport2Activity.class),0);
finish();
}
}.start();
}
//----------------------------------------------------------
public void onFinish() {
moveTaskToBack(true);
}
//-------------vibrate---------------------------------------------
public void vibrate(int duration) {
Vibrator vibs = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibs.vibrate(duration);
}
//****************************************************
//alert dialog for back btn
public void onBackPressed () {
cdd = new CustomDialogClass(Adult1Activity.this);
cdd.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
cdd.show();
}
public class CustomDialogClass extends Dialog {
public Activity c;
public Button minimizeBTN, exitBTN;
public CustomDialogClass(Activity a) {
super(a);
this.c = a;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.back_btn);
minimizeBTN = (Button) findViewById(R.id.minimizing_app);
exitBTN = (Button) findViewById(R.id.exit_completely);
minimizeBTN.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
MinimizeApp();
isRunning = true;
ExtendedNotification(timeString);
cdd.dismiss();
// notificationManager.notify(notification_id,notificationBuilder.build());
}
});
exitBTN.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
CloseApp();
}
});
}
}
//*****************Notification class******
private void ExtendedNotification(String time) {
final Intent resultIntentRestore = new Intent(this, Adult1Activity.class);
resultIntentRestore.putExtra(EXTRA_NOTE,NOTE_RESTORE);
resultIntentRestore.putExtra(time,NOTE_RESTORE);
PendingIntent restoreIntent = PendingIntent.getActivity(Adult1Activity.this,
0, resultIntentRestore, PendingIntent.FLAG_UPDATE_CURRENT);
final Intent resultIntentClose = new Intent(this, Adult1Activity.class);
resultIntentClose.putExtra(EXTRA_NOTE, NOTE_CLOSE);
PendingIntent closeIntent = PendingIntent.getActivity(Adult1Activity.this,
1, resultIntentClose, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder = new NotificationCompat.Builder(Adult1Activity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Stand Up!")
.setContentText(time)
.setAutoCancel(true)
.addAction(new NotificationCompat.Action(R.drawable.ic_note_restore, "Restore", restoreIntent))
.addAction(new NotificationCompat.Action(R.drawable.ic_note_close, "Close", closeIntent))
.setContentIntent(restoreIntent);
//final Notification notification = notificationBuilder.build();
//notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
notificationManager.notify(notification_id,notificationBuilder.build());
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); // Make sure to call super
handleIntent(intent);
}
private void handleIntent(Intent intent) {
final String a = intent.getStringExtra(EXTRA_NOTE);
if (a != null) {
switch (a) {
case NOTE_RESTORE:
tv.setText(timeString);
// tv.setText(intent.getStringExtra(timeString));
notificationManager.cancel(notification_id);
break;
case NOTE_CLOSE:
countDownTimer.cancel();
isRunning = false;
notificationManager.cancel(notification_id);
// Adult1Activity.this.finish();
break;
}
}
}
//**********************App statuse********************
public void MinimizeApp(){
moveTaskToBack(true); //hide
}
private void CloseApp(){
android.os.Process.killProcess(android.os.Process.myPid());// exit
notificationManager.cancel(notification_id);
}
}
this is my ForgroundService that I has written till now.
public class TimerService extends Service {
public CountingDownTimer countingDownTimer;
public static String total_time_string;
public static int totalSeconds;
public NotificationManager notificationManager;
public NotificationCompat.Builder notificationBuilder;
public final int notification_id=01;
private static final String EXTRA_NOTE = "NOTE";
private static final String NOTE_RESTORE = "restore";
private static final String NOTE_CLOSE = "close";
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
countingDownTimer = new CountingDownTimer(totalSeconds,500); //milliseconds , (500 means) onTick function will be called at every 500
//countingDownTimer = new CountingDownTimer(intent.getExtras().getInt(total_time_string),500); //milliseconds , (500 means) onTick function will be called at every 500
countingDownTimer.start();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
setupNotification();
return super.onStartCommand(intent, flags, startId);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
countingDownTimer.cancel();
notificationManager.cancel(notification_id);
}
//******************************************************************
public class CountingDownTimer extends CountDownTimer{
final String timeString;
/**
* #param millisInFuture The number of millis in the future from the call
* to {#link #start()} until the countdown is done and {#link #onFinish()}
* is called.
* #param countDownInterval The interval along the way to receive
* {#link #onTick(long)} callbacks.
*/
public CountingDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
timeString = null;
}
#Override
public void onTick(long leftTimeInMilliseconds) {
// format the textview to show the easily readable format
final long seconds = leftTimeInMilliseconds / 1000;
timeString = String.format("%02d", seconds / 60)
+ ":" + String.format("%02d", seconds % 60);
Adult1Activity.tv.setText(timeString);
// ExtendedNotification(timeString);
}
#Override
public void onFinish() {
startActivity(new Intent(this,Sport2Activity.class));
vibrate(1000);
// turn on screen
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
wakeLock.acquire();
}
}
public void vibrate(int duration) {
Vibrator vibs = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibs.vibrate(duration);
}
//****************Notification ********************
private void setupNotification() {
Intent notificationIntent_Restore = new Intent(this,Adult1Activity.class);
notificationIntent_Restore.putExtra(EXTRA_NOTE,NOTE_RESTORE);
notificationIntent_Restore.putExtra(countingDownTimer.timeString,NOTE_RESTORE);
PendingIntent restoreIntent = PendingIntent.getActivity(this,
0, notificationIntent_Restore, PendingIntent.FLAG_UPDATE_CURRENT);
final Intent notificationIntent_Close = new Intent(this, Adult1Activity.class);
notificationIntent_Close.putExtra(EXTRA_NOTE, NOTE_CLOSE);
PendingIntent closeIntent = PendingIntent.getActivity(this,
1, notificationIntent_Close, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Stand Up!")
.setContentText(countingDownTimer.timeString)
.setAutoCancel(true)
.addAction(new NotificationCompat.Action(R.drawable.ic_note_restore, "Restore", restoreIntent))
.addAction(new NotificationCompat.Action(R.drawable.ic_note_close, "Close", closeIntent))
.setContentIntent(restoreIntent);
startForeground(notification_id,notificationBuilder);
//final Notification notification = notificationBuilder.build();
//notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
// notificationManager.notify(notification_id,notificationBuilder.build());
}

private class OTPCountdown extends CountDownTimer {
/**
* #param millisInFuture The number of millis in the future from the call
* to {#link #start()} until the countdown is done and {#link #onFinish()}
* is called.
* #param countDownInterval The interval along the way to receive
* {#link #onTick(long)} callbacks.
*/
public OTPCountdown(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
tvOTPCountdown.setText(getString(R.string.otp_expiration_msg, millisUntilFinished / 1000));
}
#Override
public void onFinish() {
showManualWrap();
}
}
// use like this
otpCountdown = new OTPCountdown(60000, 1000);
otpCountdown.start();

Just because you are starter in Android and someone didnt get time to answer your question doesn't mean you would downvote their accepted answer and boss over them. If you are not able to figure out whats going on with your code. Give time to other developers to see it again.
Moderator please look at this thread: How to set Service/StartForeground to work CountDownTimer properly

Related

how to pass a string data to my activity from a service

I have an activity that runs a timer and I want to broadcast that timer and set a receiver to my activity and display the timer. I know that it can be done using a broadcast and receiving that broadcast intent but I don't know how to do it.
here are my codes
public class MyService extends Service {
private Vibrator v;
NotificationCompat.Builder notification;
private static final int uniqueID = 71399;
#Override
public void onCreate() {
super.onCreate();
notification = new NotificationCompat.Builder(this);
notification.setAutoCancel(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences sharedPreferences = getSharedPreferences("Timer", Context.MODE_PRIVATE);
int dur = sharedPreferences.getInt("duration", 0);
//background timer
CountDownTimer countDownTimer = new CountDownTimer(dur, 1000) {
#Override
public void onTick(long dur) {
long millis= dur;
String hms= String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
//seconds
,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
startnotif(hms);
startBroadcast(hms);
}
#Override
public void onFinish() {
long n[] = {1,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000};
v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(n, -1);
endnotif();
onDestroy();
}
};
countDownTimer.start();
return START_STICKY;
}
public void onDestroy() {
stopSelf();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
//notification
public void startnotif(String hms)
{
String noT = hms;
notification.setSmallIcon(R.mipmap.ic_launcher);
notification.setTicker("apps are blocked!");
notification.setWhen(System.currentTimeMillis());
notification.setContentTitle("Be productive!");
notification.setContentText(hms);
ClickNotif();
}
public void endnotif(){
notification.setContentText("00:00");
notification.setTicker("apps are now unblocked!");
notification.setWhen(System.currentTimeMillis());
notification.setContentTitle("You survived!");
notification.setContentText("Apps are now unblocked!");
ClickNotif();
}
//other parts of notif
public void ClickNotif(){
Intent intent1 = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setContentIntent(pendingIntent);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(uniqueID, notification.build());
}
The Target activity
public class Main2Activity extends AppCompatActivity {
private Button btntest;
private TextView timer;
private Spinner spinner, spinner2;
public int hours, mins, duration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
btntest = (Button) findViewById(R.id.startbtn);
timer = (TextView) findViewById(R.id.Timertxt);
//setting up 2 spinners
spinner = (Spinner) findViewById(R.id.hrspinner);
String [] values = {"00","01","02","03","04","05","06"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, values);
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
spinner.setAdapter(adapter);
spinner2 = (Spinner) findViewById(R.id.minspinner);
String [] values2 = {"00","01","10","20","30","40","50","60"};
ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, values2);
adapter2.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
spinner2.setAdapter(adapter2);
//button start
btntest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String spin=spinner.getSelectedItem().toString();
hours = Integer.parseInt(spin);
hours = hours*3600000;
String spin2=spinner2.getSelectedItem().toString();
mins = Integer.parseInt(spin2);
mins = mins*60000;
duration = hours+mins;
setParam(duration);
startService(duration);
}
});
}
/*timer part
public void setParam(int param){
CountDownTimer countDownTimer = new CountDownTimer(param, 1000) {
#Override
public void onTick(long param) {
long millis= param;
String hms= String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
//seconds
,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
timer.setText(hms);
}
#Override
public void onFinish() {
timer.setText("00:00");
}
};
countDownTimer.start();
}*/
//saving data and passing intent to service
public void startService(int duration)
{
int d = duration;
SharedPreferences sharedPreferences = getSharedPreferences("Timer", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("duration", d);
editor.apply();
Intent intent = new Intent(this,MyService.class);
startService(intent);
}
}
how can I show that timer to my text field? Please help!
you can use LocalBroadcastManager like this :
in your service
private LocalBroadcastManager broadcaster;
#Override
public void onCreate() {
broadcaster = LocalBroadcastManager.getInstance(this);
}
private void sendData(){
Intent intent = new Intent("MyData");
broadcaster.sendBroadcast(intent);
}
and call sendData() wherever you want, and in your activity write
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
/*
this called when app receive notification and MainActivity is opened
* see FcmMessagingService.class to see where it called
*/
#Override
public void onReceive(Context context, Intent intent) {
// Log.d("broadcaster", "onReceive BaseActivity");
// write whatever you want and you cant use intent.getString("key");
}
};
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver((mMessageReceiver), new IntentFilter("MyData"));
}

How can I pass a String data from my service to my fragment?

I have a service that runs a timer on the background and I want that data to be passed to my fragment to show the timer there too. If i closed my app and open it again i want to see my edittext to show the timer. Any answer would be appreciated.
this is my service
public class MyService extends Service {
private Vibrator v;
//private static Timer timer = new Timer();
NotificationCompat.Builder notification;
private static final int uniqueID = 71399;
#Override
public void onCreate() {
super.onCreate();
notification = new NotificationCompat.Builder(this);
notification.setAutoCancel(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences sharedPreferences = getSharedPreferences("Timer", Context.MODE_PRIVATE);
int dur = sharedPreferences.getInt("duration", 0);
//background timer
CountDownTimer countDownTimer = new CountDownTimer(dur, 1000) {
#Override
public void onTick(long dur) {
long millis= dur;
String hms= String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
//seconds
,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
startnotif(hms);
}
#Override
public void onFinish() {
long n[] = {1,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000,500,1000};
v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(n, -1);
endnotif();
onDestroy();
}
};
countDownTimer.start();
return START_STICKY;
}
public void onDestroy() {
stopSelf();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
//notification
public void startnotif(String hms)
{
String noT = hms;
notification.setSmallIcon(R.mipmap.ic_launcher);
notification.setTicker("apps are blocked!");
notification.setWhen(System.currentTimeMillis());
notification.setContentTitle("Be productive!");
notification.setContentText(hms);
ClickNotif();
}
public void endnotif(){
notification.setContentText("00:00");
notification.setTicker("apps are now unblocked!");
notification.setWhen(System.currentTimeMillis());
notification.setContentTitle("You survived!");
notification.setContentText("Apps are now unblocked!");
ClickNotif();
}
public void ClickNotif(){
Intent intent1 = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setContentIntent(pendingIntent);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(uniqueID, notification.build());
}
}
and here is the fragment. I'm planning on removing the countdown timer on this fragment since I'm going use the timer on the service.
public class page2 extends Fragment {
private static final String TAG = "page2";
private Button btntest;
private TextView timer,tv;
private Spinner spinner, spinner2;
public int hours, mins, duration;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.page2_fragment,container,false);
btntest = (Button) view.findViewById(R.id.button2);
timer = (TextView) view.findViewById(R.id.Timer);
tv = (TextView) view.findViewById(R.id.textView3);
//setting up 2 spinners
spinner = (Spinner) view.findViewById(R.id.spinner1);
String [] values = {"00","01","02","03","04","05","06"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getActivity(), android.R.layout.simple_spinner_item, values);
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
spinner.setAdapter(adapter);
spinner2 = (Spinner) view.findViewById(R.id.spinner2);
String [] values2 = {"00","01","10","20","30","40","50","60"};
ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this.getActivity(), android.R.layout.simple_spinner_item, values2);
adapter2.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
spinner2.setAdapter(adapter2);
//button start
btntest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String spin=spinner.getSelectedItem().toString();
hours = Integer.parseInt(spin);
hours = hours*3600000;
String spin2=spinner2.getSelectedItem().toString();
mins = Integer.parseInt(spin2);
mins = mins*60000;
duration = hours+mins;
setParam(duration);
startService(duration);
}
});
return view;
}
//timer part
public void setParam(int param){
CountDownTimer countDownTimer = new CountDownTimer(param, 1000) {
#Override
public void onTick(long param) {
long millis= param;
String hms= String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
//seconds
,TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
timer.setText(hms);
}
#Override
public void onFinish() {
timer.setText("00:00");
}
};
countDownTimer.start();
}
//saving data and passing intent to service
public void startService(int duration)
{
int d = duration;
SharedPreferences sharedPreferences = getActivity().getSharedPreferences("Timer", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("duration", d);
editor.apply();
Intent intent = new Intent(getActivity(),MyService.class);
getActivity().startService(intent);
Toast.makeText(getActivity(), "Intent passed and preferences saved!"+d,Toast.LENGTH_SHORT).show();
}
}
Thanks in advance.
Try EventBus library, you can send message as normal or stick event, maybe it can solve your problem :)
There are many ways you can update editText in your case.
When you open your application you can bind to your already running service. After binding you can call methods in service to get the results. For simple bind service refer bind service
You can keep a shared preference and continue updating it every countdown. Whenever app opens read the shared preference and update your edittext.

Using service to continue timer outside of application lifecycle

Edit: Thanks for the replies. I ended up figuring out a nice solution (which I posted below) that uses a foreground service and broadcast receivers for those interested.
Original Question:
I have a simple count up timer using a handler which updates a textview. What Im trying to achieve is to
Continue the timer even if the app closes
Put out a notification and wake up the phone(if asleep) when the timer reaches its duration
I've read about using a service as it operates separate from the activity however all the examples I found seem more complicated for what I'm trying to do.
For reference heres my timer class
public class MyTimer implements Runnable {
MainActivity activity;
Handler handler;
TextView timerView;
long current_time,duration;
public MyTimer(MainActivity activity){
this.activity = activity;
this.handler = new Handler();
this.current_time = 0L;
timerView = (TextView) activity.findViewById(R.id.timerValue);
}
public MyTimer startTimer(int duration){
this.duration = duration;
handler.postDelayed(this,1000);
return this;
}
public MyTimer resetTimer(){
timerView.setText("0:00");
handler.removeCallbacks(this);
return this;
}
#Override
public void run() {
if(current_time == duration){
Toast.makeText(activity,"Timer is done",Toast.LENGTH_SHORT).show();
resetTimer();
return;
}
current_time += 1000;
int secs = (int) (current_time / 1000);
int minutes = secs / 60;
timerView.setText(Integer.toString(minutes) + ":" + String.format("%02d", secs%60));
handler.postDelayed(this, 1000);
}
}
timerView and two buttons for start/stop
I was also thinking of just storing the timer in a database during onStop/onDestroy and using the system time and its difference between the saved time to just update the timer that way. But that wouldn't solve the issue of issuing a notification and/or waking up the phone.
The examples that you find are not too complicated - in order to achieve what you want you'll need:
Bound Service which will keep track of elapsed time and will register alarm with AlarmManager
Fragment/Activity that can bind the above Service and execute methods like resetTimer(), startTimer(), getElapsedTime(). You need to perform a query to getElapsedTime() using a Handler, but 1 second timeout is too long (I'd use 0.1 second or similar).
Last note: you can't use the timeout that you set on postDelayed() in order to increment the timer. Better use something like this:
public void startTimer(long duration) {
mStartTime = System.currentTimeMillis();
mDuration = duration;
// register alarm with AlarmManager here
}
public long getElapsedTime() {
return System.currentTimeMillis() - mStartTime;
}
For those out there who might need an answer to this, after some research I decided the best approach was to use a foreground service and a handler because an alarm manager would be inefficient for such a short and constant timer.
So in Summary
In Service Class
Broadcasts the timer to main activity in which the MainActivity will receive it using a broadcastreceiver and updates the UI
Service class uses its own broadcast receiver to check if phone screen is on/off and updates the timer when it returns from sleep.
In Main Activity class
Receive the broadcast sent from the timer service and update the UI
Other logistics such as when to register/unregister broadcast receiver and sending actions to the service to either stop/start
Service Class:
//Timer service which uses a handler to monitor tick rate. Also uses a broadcast receiver
//to update the timer if the device was in sleep mode.
public class TimerService extends Service{
Intent intent;
public static final String TAG = TimerService.class.getSimpleName();
private final Handler handler = new Handler();
long currentTime, duration;
long timeSinceLastOn, elapsedTimeSinceOff;
#Override
public void onCreate() {
super.onCreate();
currentTime = duration = elapsedTimeSinceOff = 0L;
timeSinceLastOn = SystemClock.elapsedRealtime();
intent = new Intent(Constants.ACTION.BROADCAST_ACTION);
/**Starting Timer here**/
handler.removeCallbacks(timerThread);
handler.postDelayed(timerThread,0);
/**********************/
/**Broadcast receiver to check if the screen is on **/
IntentFilter screenStateFilter = new IntentFilter();
screenStateFilter.addAction(Intent.ACTION_SCREEN_ON);
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(broadcastReceiver, screenStateFilter);
/***************************************************/
}
#Override
/**Depending on action issued by MainActivity either puts service in
*foreground with duration or destroys the service**/
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null) {
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
if (intent.hasExtra(Constants.TIMER.DURATION))
duration = intent.getLongExtra(Constants.TIMER.DURATION, 0);
startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE, createTimerNotification());
} else if (intent.getAction().equals(Constants.ACTION.STOPFOREGROUND_ACTION)) {
stopForeground(true);
stopSelf();
}
}
return START_STICKY;
}
/**Thread the handler uses to push to message queue. This creates a timer effect.**/
private Runnable timerThread = new Runnable() {
#Override
public void run() {
if(currentTime == duration){
stopSelf();
return;
}
currentTime += 1000;
sendTimerInfo();
handler.postDelayed(this,1000);
}
};
/**Broadcasts the timer in which the MainActivity will receive it and update the UI**/
private void sendTimerInfo(){
Log.d(TAG, "timer running: tick is " + currentTime);
intent.putExtra(Constants.TIMER.CURRENT_TIME, currentTime);
sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG,"timer service finished");
unregisterReceiver(broadcastReceiver);
handler.removeCallbacks(timerThread);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
/******************** Broadcast Receiver To Check if Screen is on**************************************/
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
handler.removeCallbacks(timerThread);
/**If the screen is back on then update the timer and start it again**/
if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
Log.d(TAG,"Screen is turned on");
elapsedTimeSinceOff = SystemClock.elapsedRealtime() - timeSinceLastOn;
Log.d(TAG," screen was off and updating current time by"+elapsedTimeSinceOff);
currentTime += elapsedTimeSinceOff;
handler.postDelayed(timerThread,0);
}
/**Turns off the timer when the screen is off**/
else if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
Log.d(TAG,"Screen is turned off");
timeSinceLastOn = SystemClock.elapsedRealtime();
}
}
};
/**Since this is foreground service it must have a notification**/
private Notification createTimerNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent,0);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Service Timer")
.setTicker("Count up timer")
.setContentText("timer")
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
return notification;
}
}
MainActivity:
public class MainActivity extends Activity {
TextView timerView;
Intent timerService;
//Example duration of 3minutes
long currentTime, duration = 180000;
#Override
protected void onStart() {
super.onStart();
timerService = new Intent(this, TimerService.class);
//Register broadcast if service is already running
if(isMyServiceRunning(TimerService.class)){
registerReceiver(broadcastReceiver, new IntentFilter(Constants.ACTION.BROADCAST_ACTION));
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton, stopButton;
timerView = (TextView) findViewById(R.id.timerValue);
startButton = (Button) findViewById(R.id.startButton);
stopButton = (Button) findViewById(R.id.stopButton);
//Button to Start the service when pushed
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if(!isMyServiceRunning(TimerService.class)) {
timerService.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
timerService.putExtra(Constants.TIMER.DURATION,duration);
startService(timerService);
registerReceiver(broadcastReceiver, new IntentFilter(Constants.ACTION.BROADCAST_ACTION));
}
}
});
//Button to stop the service when pushed
stopButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if(isMyServiceRunning(TimerService.class)) {
timerView.setText("0:00");
timerService.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
startService(timerService);
unregisterReceiver(broadcastReceiver);
}
}
});
}
#Override
protected void onResume() {
super.onResume();
if(!isMyServiceRunning(TimerService.class)) {
//Resets timer if no service is running
timerView.setText("0:00");
}
}
#Override
protected void onStop() {
super.onStop();
if(isMyServiceRunning(TimerService.class)) {
unregisterReceiver(broadcastReceiver);
Log.d(MainActivity.class.getSimpleName(), "unregistered broadcast");
}
}
/******************** Broadcast Receiver **************************************/
//Receives the broadcast sent out by the service and updates the UI accordingly.
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(!updateUI(intent)){
if(!updateUI(timerService)){
timerService.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
startService(timerService);
showTimerCompleteNotification();
}
}
}
};
//Receives the timer from the service and updates the UI
public boolean updateUI(Intent intent){
if(!intent.hasExtra(Constants.TIMER.CURRENT_TIME)) return false;
this.currentTime = intent.getLongExtra(Constants.TIMER.CURRENT_TIME, 0L);
if(this.currentTime == duration){
timerView.setText("0:00");
Toast.makeText(this,"Timer done",Toast.LENGTH_SHORT).show();
return false;
}
int secs = (int) (currentTime / 1000);
int minutes = secs / 60;
timerView.setText(Integer.toString(minutes) + ":" + String.format("%02d", secs%60));
return true;
}
/******************************************************************************************/
/************* Helper Methods ****************************/
private void showTimerCompleteNotification() {
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Timer Done!")
.setContentText("Congrats")
.setContentIntent(resultPendingIntent)
.setColor(Color.BLACK)
.setLights(Color.BLUE, 500, 500)
.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
.setDefaults(NotificationCompat.DEFAULT_SOUND)
.setStyle(new NotificationCompat.InboxStyle());
// Gets an instance of the NotificationManager service
final NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
mNotifyMgr.notify(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE, mBuilder.build());
//Cancel the notification after a little while
Handler h = new Handler();
long delayInMilliseconds = 5000;
h.postDelayed(new Runnable() {
public void run() {
mNotifyMgr.cancel(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE);
}
}, delayInMilliseconds);
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
Constants class:
package com.example.admin.servicetimer.service;
public class Constants {
public interface ACTION {
public static String MAIN_ACTION = "com.fahadhd.foregroundservice.action.main";
public static final String STARTFOREGROUND_ACTION = "com.fahadhd.foregroundservice.action.startforeground";
public static final String STOPFOREGROUND_ACTION = "com.fahadhd.foregroundservice.action.stopforeground";
public static final String BROADCAST_ACTION = "com.fahadhd.foregroundservice.action.broadcast";
}
public interface TIMER {
public static final String CURRENT_TIME = "com.fahadhd.foregroundservice.timer.current_time";
public static final String DURATION = "com.fahadhd.foregroundservice.timer.duration";
}
public interface NOTIFICATION_ID {
public static int FOREGROUND_SERVICE = 1;
}
}

How to create an alarm wake screen in android and disable default back button?

Hello every one I request you to please give me the solution of this question .
I have created a alarm wake up screen when alarm started it has two buttons snooze and dismiss and it work fine .
But the problem is started when user press the back button on phone it disappears from the screen
and sound is still playing. If anyone have solution please provide me.
Thank you
This is AlarmService class
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class AlarmService extends Service {
public static String TAG = AlarmService.class.getSimpleName();
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent alarmIntent = new Intent(getBaseContext(), AlarmScreen.class);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try{
alarmIntent.putExtras(intent);
getApplication().startActivity(alarmIntent);
AlarmManagerHelper.setAlarms(this);
}catch(Exception e)
{
e.printStackTrace();
System.out.println(" May be null intent found if not snooz or dismiss the button by user on alarm screen");
}
return super.onStartCommand(intent, flags, startId);
}
}
and this one is receiver class that create an alarm screen
public class AlarmScreen extends Activity{
public final String TAG = this.getClass().getSimpleName();
private WakeLock mWakeLock;
private MediaPlayer mPlayer;
public static final String ID = "id";
public static final String NAME = "name";
public static final String TIME_HOUR = "timeHour";
public static final String TIME_MINUTE = "timeMinute";
public static final String TONE = "alarmTone";
public static final String NOTE = "note";
public static final String USER = "user";
static String name;
static String note;
static String userName;
static String tone;
static int timeHour;
static int timeMinute;
private static final int WAKELOCK_TIMEOUT = 60 * 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setup layout
this.setContentView(R.layout.activity_alarm_screen);
/*parentView.getBackground().setAlpha(128);*/
name = getIntent().getStringExtra(AlarmManagerHelper.NAME);
note = getIntent().getStringExtra(AlarmManagerHelper.NOTE);
userName = getIntent().getStringExtra(AlarmManagerHelper.USER);
timeHour = getIntent().getIntExtra(AlarmManagerHelper.TIME_HOUR, 0);
timeMinute = getIntent().getIntExtra(AlarmManagerHelper.TIME_MINUTE, 0);
tone = getIntent().getStringExtra(AlarmManagerHelper.TONE);
TextView tvName = (TextView) findViewById(R.id.alarm_screen_name);
TextView tvNote = (TextView) findViewById(R.id.alarm_screen_note);
TextView tvUser = (TextView) findViewById(R.id.txt_nameUser);
tvName.setText(name);
tvNote.setText(note);
tvUser.setText(userName);
TextView tvTime = (TextView) findViewById(R.id.alarm_screen_time);
tvTime.setText(String.format("%02d : %02d", timeHour, timeMinute));
DisplayMetrics metrics = getResources().getDisplayMetrics();
final int screenWidth = (int) (metrics.widthPixels * 0.50);
final int screenHeight = (int) (metrics.heightPixels * 0.50);
// Get instance of Vibrator from current Context
final Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Start without a delay
// Each element then alternates between vibrate, sleep, vibrate, sleep...
long[] pattern = {0,800,200,1000,300,1000,200,4000};
if (v.hasVibrator()) {
Log.v("Can Vibrate", "YES");
} else {
Log.v("Can Vibrate", "NO");
}
Button dismissButton = (Button) findViewById(R.id.alarm_screen_button);
dismissButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
mPlayer.stop();
v.cancel();
finish();
}
});
//adding snooz button
Button btn_snooz = (Button) findViewById(R.id.btn_snooz);
btn_snooz.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
mPlayer.stop();
v.cancel();
sooz_activity();
System.out.println("Snooz Activity Started");
finish();
}
});
//Play alarm tone
mPlayer = new MediaPlayer();
try {
if (tone != null && !tone.equals("")) {
Uri toneUri = Uri.parse(tone);
if (toneUri != null) {
mPlayer.setDataSource(this, toneUri);
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mPlayer.setLooping(true);
mPlayer.prepare();
mPlayer.start();
v.vibrate(pattern, 0);
}
}
} catch (Exception e) {
e.printStackTrace();
}
//Ensure wakelock release
Runnable releaseWakelock = new Runnable() {
#Override
public void run() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
// getWindow().setLayout(screenWidth, screenHeight);
/* getWindow().setFlags(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);*/
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
}
}
};
new Handler().postDelayed(releaseWakelock, WAKELOCK_TIMEOUT);
}
#SuppressWarnings("deprecation")
#Override
protected void onResume() {
super.onResume();
// Set the window to keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
// getWindow().setLayout(screenWidth, screenHeight);
// Acquire wakelock
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
if (mWakeLock == null) {
mWakeLock = pm.newWakeLock((PowerManager.FULL_WAKE_LOCK | PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), TAG);
}
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
Log.i(TAG, "Wakelock aquired!!");
}
}
#Override
protected void onPause() {
super.onPause();
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
}
}
public void sooz_activity(){
PendingIntent pIntent = createPendingIntent(this);
long currentTimeMillis = System.currentTimeMillis();
long nextUpdateTimeMillis = currentTimeMillis + 5 * DateUtils.MINUTE_IN_MILLIS;
Time nextUpdateTime = new Time();
nextUpdateTime.set(nextUpdateTimeMillis);
setAlarm(this, nextUpdateTimeMillis, pIntent);
}
private static PendingIntent createPendingIntent(Context context) {
Intent intent = new Intent(context, AlarmService.class);
//intent.putExtra(ID, model.id);
intent.putExtra(NAME,name);
intent.putExtra(TIME_HOUR,timeHour);
intent.putExtra(TIME_MINUTE,timeMinute);
intent.putExtra(TONE,tone);
intent.putExtra(NOTE,note);
intent.putExtra(USER,userName);
return PendingIntent.getService(context,1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
#SuppressLint("NewApi")
private static void setAlarm(Context context, long nextUpdateTimeMillis, PendingIntent pIntent) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextUpdateTimeMillis, pIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, nextUpdateTimeMillis, pIntent);
}
}
}
and it works fine but when alarm screen appears on the phone main screen and user just pressed the default phone back button it disappear from the main screen and the sound and vibration continue until i go to stop running task.
All you got to do is override onBackPressed().
Android studio autocompletes this code as you type onBackPressed().
#Override
public void onBackPressed() // Declare in the activity showing the alarm screen
{
// code here what should be done at back button press
super.onBackPressed(); // This line handles the default action of back button
}
Before super.onBackPressed(), you may do something like snooze or something.
Also you can use onPause() or similar ones as the other guy said. (Refer Activity lifecycle)
Hope I cleared your doubt. Let me know if you got further doubts.
I think "The New Boston" has a great video to help with understanding what is going on here.
https://www.youtube.com/watch?v=-G91Hp3t6sg
you might be looking for onPause() to stop the sound.
I think the video would be a good starting point for monitoring how your app is behaving in different states.

Android - Multiple services don't run as expected

I have this service:
public class AAAService extends Service {
private Intent requestService;
private Intent calendarService;
private SharedPreferences servicePreferences;
private static final String REQUEST_DELAY = "request_interval";
private static final int REQUEST_DELAY_DEFAULT = 900000;
private static final String SERVICE = "service";
private static final String SOUND = "sound";
private static final String VIBRATE = "vibrate";
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
Log.i("daim", "AAAService has started ...");
requestService = new Intent(this, RequestService.class);
calendarService = new Intent(this, CalendarService.class);
servicePreferences = getSharedPreferences(SERVICE, MODE_PRIVATE);
long delay = Long.valueOf(servicePreferences.getInt(REQUEST_DELAY, REQUEST_DELAY_DEFAULT));
if(delay > 0){
startRequestService();
}
startCalendarService();
}
#Override
public void onDestroy(){
super.onDestroy();
Log.i("daim", "AAAService has stopped ...");
stopRequestService();
stopCalendarService();
}
public void startRequestService(){
startService(requestService);
}
public void stopRequestService(){
stopService(requestService);
}
public void startCalendarService(){
startService(calendarService);
}
public void stopCalendarService(){
stopService(calendarService);
}
}
And this two other Services:
public class RequestService extends AAAService
public class CalendarService extends AAAService
Both these has onCreate and onDestroy method, in order to start and stop the service.
The problem I'm facing here, is that when I start my AAAService from the an Activity it gets started, and yes it starts the other two services, but right after that it get stopped (onDestroy method), and I don't know why!
This is what I do from my Activity:
Intent service = new Intent(this, AAAService.class);
startService(service);
Any help is appreciated!
Thanks.
My two other services:
public class CalendarService extends AAAService{
private CalendarApi calendarApi;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("daim", "CalendarService has started ...");
calendarApi = AAALifestyleApplication.calendarApi;
startService();
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("daim", "CalendarService has stopped ...");
}
public void startService(){
Log.d("daim", "UPDATING EVENTS FROM CALENDAR SERVICE!!!");
ArrayList<Long> dates = new ArrayList<Long>();
dates.add(0L);
dates.add(System.currentTimeMillis() * 2);
calendarApi.getEventsFromDrupal(dates, this, null);
stopSelf();
}
}
public class RequestService extends AAAService implements RequestListener{
private Timer timer;
private CommonApi commonApi;
private NotificationManager nManager;
private Notification notification;
private PendingIntent pIntent;
private Intent intent;
private Context context;
private SharedPreferences sharedPref;
private long delay;
private boolean sound, vibrate;
private static final int INTERVAL_DEFAULT = 900000;
private static final String SERVICE_NAME = "service";
private static final String INTERVAL_KEY = "request_interval";
private static final String SOUND = "sound";
private static final String VIBRATE = "vibrate";
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("daim", "RequestService has started ...");
sharedPref = getSharedPreferences(SERVICE_NAME, MODE_PRIVATE);
startService();
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("daim", "RequestService has stopped ...");
if(timer != null){
timer.cancel();
}
}
public void startService(){
Log.d("daim", "UPDATING REQUESTS FROM REQUEST SERVICE!!!");
int intervalInteger = sharedPref.getInt(INTERVAL_KEY, INTERVAL_DEFAULT);
delay = Long.valueOf(intervalInteger);
sound = sharedPref.getBoolean(SOUND, true);
vibrate = sharedPref.getBoolean(VIBRATE, true);
Log.d("daim", "sound: " + sound);
Log.d("daim", "vibrate: " + vibrate);
Log.d("daim", "delay: " + delay);
commonApi = AAALifestyleApplication.commonApi;
timer = new Timer();
if(delay > 0){
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(commonApi.isLoggedIn()){
commonApi.getRequests(RequestService.this, false);
}
}
}, 0, delay);
}
}
#Override
public void onRequestResult(ArrayList<Request> requests) {
for(Request r : requests){
if(!commonApi.hasRequest(r)){
sendNotification();
}
}
}
#Override
public void onAuthenticationError() {
// TODO Auto-generated method stub
}
#Override
public void onConnectionError() {
// TODO Auto-generated method stub
}
private void sendNotification(){
context = getApplicationContext();
nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notification = new Notification(R.drawable.icon, "You received new requests", System.currentTimeMillis());
intent = new Intent(getBaseContext(), RequestsActivity.class);
pIntent = PendingIntent.getActivity(getBaseContext(), 0, intent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
notification.setLatestEventInfo(context, "Request notification", "Click here to see your requests", pIntent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
if(vibrate){
notification.defaults |= Notification.DEFAULT_VIBRATE;
}
if(sound){
notification.defaults |= Notification.DEFAULT_SOUND;
}
nManager.notify(0, notification);
}
}
In my CalendarService i had the method stopSelf(); which I thought stopped itself, but did also stop AAAService which will stop the RequestService as well. Problem solved!
Your service inheritance/polymorphism hierarchy mess up all your services creation lifecycle. Take CalendarService as an example, the first thing in CalendarService.onCreate() is calling its super.onCreate(), in the super service onCreate method(your AAAService.onCreate()) it start the concrete service (your CalendarService), so both your AAAService and CalendarService get recursively created many times.
If the only thing AAAService does is created its child service, You should drop your AAAService and directly create/start your CalendarService and RequestService in your Activity.
Alternatively, you can simply try break your inheritance/polymorphism and make all your services independent. it should fix your problem.
correct me if I'm wrong, but aren't you starting the CalendarService from AAAService 's onCreate? and that's why your CalendarService is started when you start AAAService

Categories

Resources