Android - Multiple services don't run as expected - android

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

Related

Multiple Notification not working

I have included a NotifyService in my App to show particular Notification on a selected particular Date via a Date Picker...
The Problem is that the Latest Notification is only fired & not the Previous one...
I have also tried giving a Unique Notification Id but still it didn't work...
Heres the MainActivity -
public class MainActivity extends Activity {
private ScheduleClient scheduleClient;
private DatePicker picker;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scheduleClient = new ScheduleClient(this);
scheduleClient.doBindService();
picker = (DatePicker) findViewById(R.id.scheduleTimePicker);
}
public void onDateSelectedButtonClick(View v){
int id = MyApp.preferences.getInt("notif", 0);
id++;
MyApp.preferences.edit().putInt( "notif" , id).apply();
int day = picker.getDayOfMonth();
int month = picker.getMonth();
int year = picker.getYear();
Calendar c = Calendar.getInstance();
c.set(year, month, day);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
// Ask our service to set an alarm for that date, this activity talks to the client that talks to the service
scheduleClient.setAlarmForNotification(c);
Toast.makeText(this, "Notification set for: "+ day +"/"+ (month+1) +"/"+ year, Toast.LENGTH_SHORT).show();
}
#Override
protected void onStop() {
if(scheduleClient != null)
scheduleClient.doUnbindService();
super.onStop();
}
}
ScheduleClient -
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){
mBoundService.setAlarm(c);
}
public void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
mContext.unbindService(mConnection);
mIsBound = false;
}
}
}
Schedule Service -
public class ScheduleService extends Service{
public class ServiceBinder extends Binder {
ScheduleService getService() {
return ScheduleService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("ScheduleService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly stopped, so return sticky.
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients. See
private final IBinder mBinder = new ServiceBinder();
public void setAlarm(Calendar c) {
new AlarmTask(this, c).run();
}
}
AlarmTask -
public class AlarmTask implements Runnable{
private final Calendar date;
private final AlarmManager am;
private final Context context;
public AlarmTask(Context context, Calendar date) {
this.context = context;
this.am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
this.date = date;
}
#Override
public void run() {
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(NotifyService.INTENT_NOTIFY, true);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
// Sets an alarm - note this alarm will be lost if the phone is turned off and on again
am.set(AlarmManager.RTC, date.getTimeInMillis(), pendingIntent);
}
}
& Finally the NotifyService -
public class NotifyService extends Service {
/**
* Class for clients to access
*/
public class ServiceBinder extends Binder {
NotifyService getService() {
return NotifyService.this;
}
}
// Unique id to identify the notification.
public static final String INTENT_NOTIFY = "com.blundell.tut.service.INTENT_NOTIFY";
private NotificationManager mNM;
private Notification notif;
#Override
public void onCreate() {
Log.i("NotifyService", "onCreate()");
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
if(intent.getBooleanExtra(INTENT_NOTIFY, false))
showNotification();
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// This is the object that receives interactions from clients
private final IBinder mBinder = new ServiceBinder();
/**
* Creates a notification and shows it in the OS drag-down status bar
*/
private void showNotification() {
CharSequence title = "Alarm!!";
int icon = R.drawable.ic_dialog_alert;
CharSequence text = "Your notification time is upon us.";
Notification.Builder notification = new Notification.Builder(NotifyService.this);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, SecondActivity.class), 0);
int Notif = MyApp.preferences.getInt("notif", 1);
notification.setContentTitle(title)
.setContentText(text)
.setSmallIcon(icon)
.setContentIntent(contentIntent);
notif = notification.getNotification();
notif.flags |= Notification.FLAG_AUTO_CANCEL;
mNM.notify(Notif, notif);
stopSelf();
}}
So here, when I select a Day for e.g. 31/12/2017, set the Notif & then again set another to 1/1/2018 then the 1st one is removed I guess...
Any help will be appreciated :)
In your NotifyService class, the notify() method that belongs to NotificationManager object mNM needs to a different id for the notification otherwise it will replace existing notification. Read NotificationManager.notify() docs here

How know if mediaplayer controls on notification are playing music or not?

I'm doing a sound app that contains a main activity and 2 services, in the mainActivity I can control if the music is played or paused manually with a button on the main activity(so you can see it on the screen) that starts a service which active/stop mediaplayer. Moreover, I have a media player control on notification in other service for control the play/stop on the background. The problem is that I need to cordinate the notification in the background with the main controls of the main activity, for example when I put the lockscreen (with the music is playing) and I press stop on the notification, the music doens't stop because in the main activity the service of mediaplayer continues enabled. So, I need to know when the notification is playing music or not in the main activity for doing a boolean (if the notification stops the music, i want that de mediaplayer service stops the music).
Thank you all!
This is the code of my notification :
public class Notificaciones extends Service {
public static final String ACTION_PLAY = "action_play";
public static final String ACTION_PAUSE = "action_pause";
public static final String ACTION_REWIND = "action_rewind";
public static final String ACTION_FAST_FORWARD = "action_fast_forward";
public static final String ACTION_NEXT = "action_next";
public static final String ACTION_PREVIOUS = "action_previous";
public static final String ACTION_STOP = "action_stop";
public static final String ACTION_BAR = "action_bar";
private MediaSession mSession;
private MediaSessionManager mManager;
private MediaController mController;
private MediaPlayer mMediaPlayer;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mManager == null) {
mMediaPlayer = new MediaPlayer();
mSession = new MediaSession(getApplicationContext(), "example");
mController = new MediaController(getApplicationContext(), mSession.getSessionToken());
mSession.setCallback(new MediaSession.Callback() {
#Override
public void onPlay() {
super.onPlay();
Log.e("MyServiceClass", "onPlay");
buildNotification(generateAction(android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE));
}
#Override
public void onPause() {
super.onPause();
Log.e("MyServiceClass", "onPause");
buildNotification(generateAction(android.R.drawable.ic_media_play, "Play", ACTION_PLAY));
}
#Override
public void onSkipToNext() {
super.onSkipToNext();
buildNotification(generateAction(android.R.drawable.ic_media_pause, "Pause", ACTION_PAUSE));
}
#Override
public void onFastForward() {
super.onFastForward();
}
#Override
public void onRewind() {
super.onRewind();
}
#Override
public void onStop() {
super.onStop();
Log.e("MyServiceClass", "onStop");
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(1);
Intent intent = new Intent(getApplicationContext(), MyServiceClass.class);
stopService(intent);
}
});
}
handleIntent(intent);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
Log.e("MyServiceClass", "onStop");
mController.getTransportControls().stop();
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(1);
Intent intent = new Intent(getApplicationContext(), MyServiceClass.class);
stopService(intent);
mMediaPlayer.stop();
mMediaPlayer.release();
stopSelf();
super.onDestroy();
}
private void handleIntent (Intent intent){
if (intent == null || intent.getAction()==null){
return;
}
String action = intent.getAction();
if (action.equalsIgnoreCase(ACTION_PLAY)){
mController.getTransportControls().play();
}else if (action.equalsIgnoreCase(ACTION_PAUSE)){
mController.getTransportControls().pause();
}else if (action.equalsIgnoreCase(ACTION_FAST_FORWARD)){
mController.getTransportControls().fastForward();
}else if (action.equalsIgnoreCase(ACTION_REWIND)){
mController.getTransportControls().rewind();
}else if (action.equalsIgnoreCase(ACTION_PREVIOUS)){
mController.getTransportControls().skipToPrevious();
}else if (action.equalsIgnoreCase(ACTION_NEXT)){
mController.getTransportControls().skipToNext();
}else if (action.equalsIgnoreCase(ACTION_STOP)){
mController.getTransportControls().stop();
}if (action.equalsIgnoreCase(ACTION_BAR)){
mController.getTransportControls().stop();
}
}
private android.app.Notification.Action generateAction(int icon, String title, String intentAction){
Intent intent = new Intent(getApplicationContext(), MyServiceClass.class);
intent.setAction(intentAction);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 1, intent, 0);
return new android.app.Notification.Action.Builder(icon, title, pendingIntent).build();
}
private void buildNotification(android.app.Notification.Action action){
android.app.Notification.MediaStyle style = new android.app.Notification.MediaStyle();
Intent intent = new Intent(getApplicationContext(), MyServiceClass.class);
intent.setAction(ACTION_STOP);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 1, intent, 0);
android.app.Notification.Builder builder = new android.app.Notification.Builder(this).setSmallIcon(R.drawable.logo).setContentTitle("TEEN FM").setContentText("Adolescents.cat")
.setDeleteIntent(pendingIntent).setStyle(style);
builder.addAction(generateAction(android.R.drawable.ic_media_pause, "Previous", ACTION_PREVIOUS));
builder.addAction(generateAction(android.R.drawable.ic_media_rew, "Rewind", ACTION_REWIND));
builder.addAction(action);
builder.addAction(generateAction(android.R.drawable.ic_media_ff, "Fast Forward", ACTION_FAST_FORWARD));
builder.addAction(generateAction(android.R.drawable.ic_media_next, "Next", ACTION_NEXT));
style.setShowActionsInCompactView(0, 1, 2, 3, 4);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
#Override
public boolean onUnbind(Intent intent) {
mSession.release();
return super.onUnbind(intent);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
You should declarate your MediaPlayer like a static Object in your MainActivity and you will call it from the Notificaciones Service.
private static MediaPlayer mMediaPlayer;
MainActivity main;
When you want stop it, you should do the next thing:
main=new MainActivity();
main.mMediaPlayer.stop
//this is an example, i don't know how is your player working. Because If your are creating anohe instance of you MediaPlayer you will not stop it never from the Service. The MediaPlayer service is an instance and the Activity MediaPlayer is another one.
If you need more help me. Let me know. Have a nice day!

Service not running at predefined time interval

I have defined REPEAT_TIME = 15 * 1000; but the message is displayed in 3 seconds or so.
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
system.out.println("Message");
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("On destroy used");
}
#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);
}
}
Umm, did you notice that you actually tell it to be inexact? You should use setExact()
OK I got it myself. Because I am following this
I don't even know why to restart the system. But restarting the system changed the time interval.I previously had restarted phone with REPEAT_TIME = 3 * 1000 and thus message being displayed every 3 seconds. Any explanation would be welcomed. I am new to this topic. Thank you..

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