CountDownTimer inside Service stopped after application killed - Android - android

I'm new to services and BroadcastReceiver so maybe this question is newbie, but I didn't found the solution for my question after a long search on the web.
I need to run a CountDownTimer inside service, so the time keep moving even the application was finished.
In my code I based on THIS EXAMPLE.
My code works fine, but after the application is finished the CountDownTimer stopped(The service doesn't destroyed, just the timer).
I tried to implement it in different ways, but nothing works for me.
This is the part of my code that relevant:
AlarmReciver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent background = new Intent(context, BackgroundService.class);
Bundle bundle = intent.getExtras();
background.putExtra("time", bundle.getInt("time"));
context.startService(background);
}
}
BackgroundService :
public class BackgroundService extends Service {
private final static String TAG = "BroadcastService";
private CountDownTimer cdt = null;
private Bundle bundle;
private boolean isRunning;
private Context context;
private int timeInMili;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
this.context = this;
this.isRunning = false;
}
#Override
public void onDestroy() {
//cdt.cancel();
Log.i(TAG, "Timer cancelled");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
bundle = intent.getExtras();
timeInMili = bundle.getInt("time");
if(!this.isRunning) {
this.isRunning = true;
}
cdt = new CountDownTimer(timeInMili, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
Log.i(TAG, "Timer finished");
stopSelf();
}
};
cdt.start();
return START_STICKY;
}
}
MainActivity (extends FragmentActivity):
public void StartBackgroundAlarm(int timeInMili)
{
Intent alarm = new Intent(this, AlarmReceiver.class);
alarm.putExtra("time", timeInMili);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarm, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent);
}
MANIFEST :
<service android:enabled="true" android:name= "com.MES.yo.servicemanager.BackgroundService" />
<receiver android:name="com.MES.yo.servicemanager.AlarmReceiver"></receiver>

Related

Service not running after app killed on Android 8 Oreo [duplicate]

This question already has answers here:
Background service for android oreo
(3 answers)
Closed 3 years ago.
i have a service for connecting my socket to server and i want restart this service when my app kill.
restarting service works fine on android 5 but not working on Oreo.
i tried so many ways to do this like : boardCastReceivers and changing manifest setting for service but not working
my codes:
in manifest
<service
android:name="com.jeen.jeen.service.ChatService"
android:enabled="true" >
</service>
<receiver
android:name="com.jeen.jeen.service.ChatReceiver"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped"
>
</receiver>
in MainActivity:
#Override
protected void onDestroy() {
stopService(mServiceIntent);
Log.i("MAINACT", "onDestroy!");
super.onDestroy();
}
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())) {
Log.i ("isMyServiceRunning?", true+"");
return true;
}
}
Log.i ("isMyServiceRunning?", false+"");
return false;
}
ChatService chatService;
Intent mServiceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
chatService = new ChatService(MainActivity.this);
mServiceIntent = new Intent(MainActivity.this, chatService.getClass());
if (!isMyServiceRunning(chatService.getClass())) {
startService(mServiceIntent);
}
setContentView(R.layout.activity_main);
}
receiver class:
public class ChatReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(ChatReceiver.class.getSimpleName(), "Service fucked up");
context.startService(new Intent(context, ChatService.class));
}
}
and service class:
public class ChatService extends Service{
public static Socket socket;
#Override
public void onCreate() {
super.onCreate();
Log.e("onCreate", "onCreate");
try {
socket = IO.socket("http://192.168.174.1:8000");
} catch (URISyntaxException e) {
e.printStackTrace();
}
// Toast.makeText(AppController.getInstance(),"Created",Toast.LENGTH_SHORT).show();
}
public ChatService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public ChatService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
onTaskRemoved(intent);
}
super.onStartCommand(intent, flags, startId);
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
if (!socket.connected()) {
socket.connect();
}
}
});
}
},
0,
5000);
return START_STICKY;
}
#Override
public void onDestroy() {
Log.i("EXIT", "ondestroy!");
super.onDestroy();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Intent restartServiceIntent = new Intent(getApplicationContext(), ChatService.class);
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 4000,
restartServicePendingIntent);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
is anyway to do this?
If you are using vivo/honor/oppo etc , your services will get killed as soon as your app is closed.

Android : How can I get int value form service and set in text View on activity

My app has a countDown timer for 24 hours in his service. And show time in TextView any time even user left the app.
On service, i put an int number = 5184000. this is 24 hours converted to milliseconds;
Problems:
TextView don't show time in Activity.
I want to when timer equals 00:00:00, timer reset and new time equals 23:59:59.
MainActiviy:
public class MainActivity extends Activity {
TextView tv;
BroadcastReceiver broad;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
Intent intent = new Intent(this, MyService.class);
startService(intent);
registerReceiver(broad, new IntentFilter(MyService.BROADCAST_ACTION));
broad = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent intent1 = getIntent();
Bundle bundle = intent1.getExtras();
if (bundle != null) {
int data = bundle.getInt("DDDD");
tv.setText(data);
} else {
tv.setText("00:00:00");
}
}
};
}
Service:
public class MyService extends Service {
CountDownTimer cdt = null;
Intent intent1;
int h = 5184000;
public static final String BROADCAST_ACTION = "com.example.service";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
cdt.cancel();
Log.i("DDD", "Timer cancelled");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("TIME", "Starting timer...");
cdt = new CountDownTimer(h, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.i("TIME", "secondes: " + millisUntilFinished);
intent1 = new Intent(BROADCAST_ACTION);
intent1.putExtra("T", h);
sendBroadcast(intent1);
}
#Override
public void onFinish() {
Log.i("TIME", "Timer finished");
}
};
cdt.start();
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
xml:
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="134dp"
android:text="00:00:00"
android:textAppearance="?android:attr/textAppearanceLarge" />
You can use Alarm Manager for that.
Check out below links for AlarmManager.
AlarmManager
Scheduling Repeating Alarms

Not receiving CountDownTimer callbacks in Service

I have a Bound service which collects locations for 3 minutes every 15 minutes. I start a CountDownTimer once the Service is connected in onServiceConnected of ServiceConnection.
I receive all the Timer callbacks (onFinish) (onTick) perfectly as far the Activity which bindService is visible.
When Device is locked I do not receive any updates from the timer.
MyLocationService
public class MyLocationService extends Service implements MyTimerListener{
private IBinder mBinder = new MyLocationBinder();
public void onCreate() {
locationManager = new MyLocationManager(this);
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class MyLocationBinder extends Binder
{
public MyLocationService getService()
{
return MyLocationService.this;
}
}
public void startFetchingLocations()
{
if(locationManager != null){
locationManager.startFetchingLocations();
if(publishPeriodCountDownTimer != null) {
publishPeriodCountDownTimer.cancel();
publishPeriodCountDownTimer = null;
}
publishPeriodCountDownTimer = new MyCountTimer(gpsPublishPeriod * 60 * 1000, 1000, MyLocationService.this);
publishPeriodCountDownTimer.start();
}
}
#Override
public void onTimeFinished() {
//Start fetching locations
locationManager.startFetchingLocations(); //Start 3 min CountdownTimer
}
#Override
public void onTick() {
}
public void onAllLocationsRecieved(ArrayList<Location> locations)
{
//Do stuff on Locations
locationManager.stopFetchingGPS(); //Stops 3 min countdownTimer
}
}
MyActivty
public class MyActivity
{
#Override
protected void onStart() {
super.onStart();
btnStop.setVisibility(View.VISIBLE);
MyNoificationManager.cancelAllNotifications();
if (!isLocationServiceBound) {
Intent locServiceIntent = new Intent(this, MyLocationService.class);
bindService(locServiceIntent, locationServiceConnection, Context.BIND_AUTO_CREATE);
}
}
private ServiceConnection locationServiceConnection = new ServiceConnection(){
#Override
public void onServiceDisconnected(ComponentName name) {
isLocationServiceBound = false;
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyLocationBinder locationBinder = (MyLocationBinder) service;
locationService = locationBinder.getService();
isLocationServiceBound = true;
locationService.startFetchingLocations();
}
};
}
It works as expected when the Activity is visible. The timer doesn't provide any onTick() or onTimeFinished() callbacks when the device is locked.
What could be the problem here ?
The CountDownTimer will not work when the phone goes to sleep mode. This is by design and it's to save battery life.
Alternately you can use android.app.AlarmManager instead to achieve your goal. Following is the sample code how to do that. Set the alaram like below
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyLocationService.class);
intent.putExtra("need_to_fetch_loc", true);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, gpsPublishPeriod * 60 * 1000, alarmIntent);
Add the following method to your MyLocationService class
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(locationManager!= null && intent.getBooleanExtra("need_to_fetch_loc", false))
{
locationManager.startFetchingLocations();
}
return super.onStartCommand(intent, flags, startId);
}

Adding a service and removing it under next condition

I need to start a service and end it under some condition. I previously used IntentService which I found to be incorrect for the purpose(if I am right). I have started using service with BroadcastReciever. But still can't get the desired result. I may elaborate or even paste my code if needed. But for now, I just need something like a flow chart or pseudocode.
The condition would be checked from Preference settings. If checked, I would like to run the service in background else stop the service. Please, can any one out here help me.
EDITED:
My MainActivity:
public class MainActivity extends ListActivity {
private LocalWorldService s;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, LocalWorldService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onPause() {
super.onPause();
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
LocalWorldService.MyBinder b = (LocalWorldService.MyBinder) binder;
s = b.getService();
Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT)
.show();
}
public void onServiceDisconnected(ComponentName className) {
s = null;
Toast.makeText(MainActivity.this, "Disconnected", Toast.LENGTH_SHORT)
.show();
}
};
My Service:
public class LocalWorldService extends Service {
private final IBinder mBinder = new MyBinder();
private ArrayList<String> list = new ArrayList<String>();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Magnet is on", Toast.LENGTH_LONG).show();
return Service.START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBinder;
}
public class MyBinder extends Binder{
LocalWorldService getService(){
return LocalWorldService.this;
}
}
public List<String> getWordList(){
return list;
}
Following are two class for BroadCastReceiver:
public class MyScheduleReceiver extends BroadcastReceiver{
private static final long REPEAT_TIME = 15 * 1000;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyStartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast( context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 15);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), REPEAT_TIME, pending);
}
And:
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent service = new Intent(context, LocalWorldService.class);
SharedPreferences pref = PreferenceManager
.getDefaultSharedPreferences(context);
Map<String, ?> x = pref.getAll();
boolean momoMagnetIsOn = (Boolean) x.get("key_momo_magnet");
if (momoMagnetIsOn){
context.startService(service);
}
else{
context.stopService(service);
}
}
CORRECTION:
I need to override onDestroy().
override onDestroy method in Service
When ever you want to start a service all you need is
startService(new Intent(this, MainService.class));
And to Stop a service anytime just call
stopService(new Intent(this, MainService.class));
Remember service needs to be declared in AndroidManifest.xml. As you said that your service is working. I'm sure you have done that. Still AndroidManifest.xml
<service android:enabled="true" android:name=".MainService" />

How to create persistent alarms even after rebooting

Presently, I am working on app that works like "To Do Task List". I have successfully implemented the NotificationService and SchedularService in my application. Also I am getting the alerts(Notifications) at the time set for the tasks.
Here are my queries as below:
With this code will my alarms will be deleted after reboot ? If yes, how to overcome this.
I have kept the Priority feature for the tasks. But i want the mechanism such that if user selects priority "High" then he should receive notifications thrice, say, before 30 minutes, before 15 minutes and on the time set. How to achieve this ?
I want to set Phone's vibrate feature when Notifications are raised. How to achieve this ?
And i want to know about, what can be done for the deprecated methods and constructor in NotifyService.java. Thesse are deprecated in API level 11: Notification notification = new Notification(icon, text, time); and notification.setLatestEventInfo(this, title, text, contentIntent);. On developer.android.com, they have suggested to Use Notification.Builder instead. So how to make my app compatible with all the API levels.
Here's my snippet code for scheduling alarm:
...
scheduleClient.setAlarmForNotification(c, tmp_task_id);
...
Here's the class ScheduleClient.java:
public class ScheduleClient {
private ScheduleService mBoundService;
private Context mContext;
private boolean mIsBound;
public ScheduleClient(Context context)
{
mContext = context;
}
public void doBindService()
{
mContext.bindService(new Intent(mContext, ScheduleService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mBoundService = ((ScheduleService.ServiceBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
}
};
public void setAlarmForNotification(Calendar c, int tmp_task_id){
mBoundService.setAlarm(c, tmp_task_id);
}
public void doUnbindService() {
if (mIsBound)
{
mContext.unbindService(mConnection);
mIsBound = false;
}
}
}
Here's the ScheduleService.java:
public class ScheduleService extends Service {
int task_id;
public class ServiceBinder extends Binder {
ScheduleService getService() {
return ScheduleService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new ServiceBinder();
public void setAlarm(Calendar c, int tmp_task_id) {
new AlarmTask(this, c, tmp_task_id).run();
}
}
Here's the AlarmTask.java:
public class AlarmTask implements Runnable{
private final Calendar date;
private final AlarmManager am;
private final Context context;
int task_id;
public AlarmTask(Context context, Calendar date, int tmp_task_id) {
this.context = context;
this.am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
this.date = date;
task_id = tmp_task_id;
}
#Override
public void run() {
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(NotifyService.INTENT_NOTIFY, true);
intent.putExtra("task_id", task_id);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
am.set(AlarmManager.RTC, date.getTimeInMillis(), pendingIntent);
}
}
Here's the NotifyService.java:
public class NotifyService extends Service {
public class ServiceBinder extends Binder
{
NotifyService getService()
{
return NotifyService.this;
}
}
int task_id;
private static final int NOTIFICATION = 123;
public static final String INTENT_NOTIFY = "com.todotaskmanager.service.INTENT_NOTIFY";
private NotificationManager mNM;
SQLiteDatabase database;
#Override
public void onCreate() {
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String tmp_task_brief = null;
task_id = intent.getIntExtra("task_id", 0);
loadDatabase();
Cursor cursor = database.query("task_info", new String[]{"task_brief"}, "task_id=?", new String[]{task_id+""}, null, null, null);
while(cursor.moveToNext())
{
tmp_task_brief = cursor.getString(0);
}
cursor.close();
if(intent.getBooleanExtra(INTENT_NOTIFY, false))
showNotification(tmp_task_brief);
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new ServiceBinder();
private void showNotification(String tmp_task_brief) {
CharSequence title = "To Do Task Notification!!";
int icon = R.drawable.e7ca62cff1c58b6709941e51825e738f;
CharSequence text = tmp_task_brief;
long time = System.currentTimeMillis();
Notification notification = new Notification(icon, text, time);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TaskDetails.class), 0);
notification.setLatestEventInfo(this, title, text, contentIntent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
mNM.notify(NOTIFICATION, notification);
stopSelf();
}
void loadDatabase()
{
database = openOrCreateDatabase("ToDoDatabase.db",
SQLiteDatabase.OPEN_READWRITE, null);
}
}
With this code will my alarms will be deleted after reboot ? If yes, how to overcome this.
Yes alarm will get deleted, to overcome this, you need to use Android's Component called BroadcastReceiver as follows,
First, you need the permission in your manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Also, in your manifest, define your service and listen for the boot-completed action:
<receiver
android:name=".receiver.StartMyServiceAtBootReceiver"
android:enabled="true"
android:exported="true"
android:label="StartMyServiceAtBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Then you need to define the receiver that will get the BOOT_COMPLETED action and start your service.
public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent serviceIntent = new Intent("com.myapp.NotifyService");
context.startService(serviceIntent);
}
}
}
And now your service should be running when the phone starts up.
2 For Vibration
Again you need to define a permission in AndroidManifest.xml file as follows,
<uses-permission android:name="android.permission.VIBRATE"/>
Here is the code for vibration,
// Get instance of Vibrator from current Context
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 300 milliseconds
v.vibrate(300);

Categories

Resources