Search code examples
androidandroid-servicealarmmanager

Android AlarmManager or Service?


I have an application, that has a main.java file that sets up an alarm to call a recurring service. However when I close the application the service is no longer called for some weird reason. So I was reading around what I should be doing for my application (basically what I want is something like Twicca, where the twitter app continues to run even if you close it from your "task manager"). And it looks like what I need to do is deploy my entire application as a service, so that it will keep running indefinitely unless the system closes it. Is this what I should be doing? Or is there a more appropriate way to do this?

I was reading around SO and found a question which linked me to this - http://android-codes-examples.blogspot.com/2011/11/running-service-in-background-on.html?m=1 - is that what I should be doing? It seems that in that example basically the user closes the application but it continues to run as a service in the background, correct?

For reference here are my files:

MainActivity.java

https://gist.github.com/4414275

RepeatingAlarm.java

https://gist.github.com/4414277

I have it set up correctly in my manifest since the alarm is behaving as it should be here is that file to.

https://gist.github.com/4414285


Solution

  • You'll have to use a service. There is a complete example inside the ApiDemos - the names are AlarmService_Service and AlarmService. I will post the code here for you:

        /*
     * Copyright (C) 2007 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.example.android.apis.app;
    
    // Need the following import to get access to the app resources, since this
    // class is in a sub-package.
    import com.example.android.apis.R;
    
    import android.app.Activity;
    import android.app.AlarmManager;
    import android.app.PendingIntent;
    import android.content.Intent;
    import android.os.SystemClock;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.Toast;
    
    
    /**
     * This demonstrates how you can schedule an alarm that causes a service to
     * be started.  This is useful when you want to schedule alarms that initiate
     * long-running operations, such as retrieving recent e-mails.
     */
    public class AlarmService extends Activity {
        private PendingIntent mAlarmSender;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // Create an IntentSender that will launch our service, to be scheduled
            // with the alarm manager.
            mAlarmSender = PendingIntent.getService(AlarmService.this,
                    0, new Intent(AlarmService.this, AlarmService_Service.class), 0);
    
            setContentView(R.layout.alarm_service);
    
            // Watch for button clicks.
            Button button = (Button)findViewById(R.id.start_alarm);
            button.setOnClickListener(mStartAlarmListener);
            button = (Button)findViewById(R.id.stop_alarm);
            button.setOnClickListener(mStopAlarmListener);
        }
    
        private OnClickListener mStartAlarmListener = new OnClickListener() {
            public void onClick(View v) {
                // We want the alarm to go off 30 seconds from now.
                long firstTime = SystemClock.elapsedRealtime();
    
                // Schedule the alarm!
                AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
                am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                                firstTime, 30*1000, mAlarmSender);
    
                // Tell the user about what we did.
                Toast.makeText(AlarmService.this, R.string.repeating_scheduled,
                        Toast.LENGTH_LONG).show();
            }
        };
    
        private OnClickListener mStopAlarmListener = new OnClickListener() {
            public void onClick(View v) {
                // And cancel the alarm.
                AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
                am.cancel(mAlarmSender);
    
                // Tell the user about what we did.
                Toast.makeText(AlarmService.this, R.string.repeating_unscheduled,
                        Toast.LENGTH_LONG).show();
    
            }
        };
    }
    

    And the service:

    /*
     * Copyright (C) 2007 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.example.android.apis.app;
    
    // Need the following import to get access to the app resources, since this
    // class is in a sub-package.
    import com.example.android.apis.R;
    
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.os.Parcel;
    import android.os.RemoteException;
    import android.widget.Toast;
    
    /**
     * This is an example of implementing an application service that will run in
     * response to an alarm, allowing us to move long duration work out of an
     * intent receiver.
     * 
     * @see AlarmService
     * @see AlarmService_Alarm
     */
    public class AlarmService_Service extends Service {
        NotificationManager mNM;
    
        @Override
        public void onCreate() {
            mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    
            // show the icon in the status bar
            showNotification();
    
            // Start up the thread running the service.  Note that we create a
            // separate thread because the service normally runs in the process's
            // main thread, which we don't want to block.
            Thread thr = new Thread(null, mTask, "AlarmService_Service");
            thr.start();
        }
    
        @Override
        public void onDestroy() {
            // Cancel the notification -- we use the same ID that we had used to start it
            mNM.cancel(R.string.alarm_service_started);
    
            // Tell the user we stopped.
            Toast.makeText(this, R.string.alarm_service_finished, Toast.LENGTH_SHORT).show();
        }
    
        /**
         * The function that runs in our worker thread
         */
        Runnable mTask = new Runnable() {
            public void run() {
                // Normally we would do some work here...  for our sample, we will
                // just sleep for 30 seconds.
                long endTime = System.currentTimeMillis() + 15*1000;
                while (System.currentTimeMillis() < endTime) {
                    synchronized (mBinder) {
                        try {
                            mBinder.wait(endTime - System.currentTimeMillis());
                        } catch (Exception e) {
                        }
                    }
                }
    
                // Done with our work...  stop the service!
                AlarmService_Service.this.stopSelf();
            }
        };
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        /**
         * Show a notification while this service is running.
         */
        private void showNotification() {
            // In this sample, we'll use the same text for the ticker and the expanded notification
            CharSequence text = getText(R.string.alarm_service_started);
    
            // Set the icon, scrolling text and timestamp
            Notification notification = new Notification(R.drawable.stat_sample, text,
                    System.currentTimeMillis());
    
            // The PendingIntent to launch our activity if the user selects this notification
            PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                    new Intent(this, AlarmService.class), 0);
    
            // Set the info for the views that show in the notification panel.
            notification.setLatestEventInfo(this, getText(R.string.alarm_service_label),
                           text, contentIntent);
    
            // Send the notification.
            // We use a layout id because it is a unique number.  We use it later to cancel.
            mNM.notify(R.string.alarm_service_started, notification);
        }
    
        /**
         * This is the object that receives interactions from clients.  See RemoteService
         * for a more complete example.
         */
        private final IBinder mBinder = new Binder() {
            @Override
            protected boolean onTransact(int code, Parcel data, Parcel reply,
                    int flags) throws RemoteException {
                return super.onTransact(code, data, reply, flags);
            }
        };
    }