Search code examples
androidandroid-intentandroid-serviceandroid-alarmsandroid-backup-service

part-1 persistent foreGround android service that starts by UI, works at sleep mode too, also starts at phone restart


Status:--- I equally accept Karakuri's and Sharad Mhaske's answer, but since Sharad Mhaske answer after the start of bounty, the bounty should go to him.

Part-2 made: part-2 persistent foreGround android service that starts by UI, works at sleep mode too, also starts at phone restart

In stack overflow, only one answer may be accepted. I see both answers as acceptable but one has to be chosen (I chosed at random).

Viewers are invited to up/down vote answers/question to appreciate the effort!. I upvoted Karakuri's answer to compensate reputation.

Scenario:---

  1. I want to make the user click a start/stop button and start/stop a service from UI activity. I have made the UI so dont care about that. But Just the logic of the Button click event.

  2. Do not want the service to be bound to the UI activity. If activity closes, the service should keep running.

  3. Want to make most effort that the service be persistent and does not stops in any case. Will give it most weight and run it as ForGroundSerice as it has a higher hierarchy of importance. (hope that's ok?)

  4. Unless the stop button is clicked by my apps UI, do not want it to be stopped (or should restart itself) Even if android reclaim memory. I and the user of the phone, both are/will be aware of it. The service is most of importance. Even at sleep.

    details= my app do some operations, sleep for user provided time (15 minuts usually), wakes and perform operations again. this never ends)

    If I need AlarmManager, How to implement that? or any other way? Or just put the operations in a neverending while loop and sleep for 15 minuts at the end?

  5. When the service is started (by clicked on start button). It should make an entry so that it auto starts if phone restarts.

QUESTION:---

Primary Question:

  1. Just can't get an optimal strategy for the scenario... and also stuck on small bits of code, which one to use and how.

  2. Gathered bits and pieces from stackoverflow.com questions, developer.android.com and some google results but cannot implement in integration.

  3. Please read out the Requests Section.

Secondary Question:

The comments in my code are those small questions.

Research and Code:---

Strategy:

            want this to happen every time the user opens the UI.

    //Start Button:-----
    //check if ForGroundService is running or not. if not running, make var/settings/etc "serviceStatus" as false 
            <-------(how and where to stare this and below stated  boolean?)
    //start ForGroundService 
            <-------(how?)
    //make "SericeStatus" as true

    //check if "ServiceStartOnBoot" is false
    //Put ForGroundService to start on boot -------(to make it start when ever the phone reboots/restarts) 
            <-------(how?)
    //make "ServiceStartOnBoot" as true
            // the boolean can also be used to check the service status.



    //Stop Button:------
    //makes SericeStatus and ServiceStartOnBoot as false
    //stops service and deletes the on boot entry/strategy

Activity UI class that starts/stops the service:

public class SettingsActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);

        //some button here to start / stop and their onClick Listners



    Intent mySericeIntent = new Intent(this, TheService.class);
    }


    private void startMyForGroundService(){

    startService(mySericeIntent);

    }

    private void stopMyForGroundSerice(){
        stopService(mySericeIntent);
                          /////// is this a better approach?. stopService(new Intent(this, TheService.class));          
                          /////// or making Intent mySericeIntent = new Intent(this, TheService.class);
                          /////// and making start and stop methods use the same?

                          /////// how to call stopSelf() here? or any where else? whats the best way?
    }

}

The Service class:

  public class TheService extends Service{

      @Override
      public IBinder onBind(Intent arg0) {
          // TODO Auto-generated method stub
          return null;
      }

      @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
          startForeground(1, new Notification());
                                  ////// will do all my stuff here on in the method onStart() or onCreat()?

          return START_STICKY;    ///// which return is better to keep the service running untill explicitly killed. contrary to system kill.
                                  ///// http://developer.android.com/reference/android/app/Service.html#START_FLAG_REDELIVERY

          //notes:-//  if you implement onStartCommand() to schedule work to be done asynchronously or in another thread, 
          //then you may want to use START_FLAG_REDELIVERY to have the system re-deliver an Intent for you so that it does not get lost if your service is killed while processing it
      }

      @Override
        public void onDestroy() {
          stop();
        }

      public void stop(){
          //if running
          // stop
          // make vars as false
          // do some stopping stuff
          stopForeground(true);
                                  /////// how to call stopSelf() here? or any where else? whats the best way?

      }


  }

The Menifest file:

      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.myapp"
      android:versionCode="1"
      android:versionName="1.0" >

      <uses-sdk
          android:minSdkVersion="10"
          android:targetSdkVersion="17" />

      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
      <uses-permission android:name="android.permission.INTERNET" />

      <application

          android:allowBackup="true"
          android:debuggable="true"
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" >
          <activity
          android:name="com.example.myapp.MainActivity"
          android:label="@string/app_name" >
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />

              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
          </activity>
          <activity
          android:name="com.example.myapp.SettingsActivity"
          android:label="@string/title_activity_settings" >
          </activity>

      </application>

      </manifest>

References:---

Android - implementing startForeground for a service? pointing answer 1, example code.

Trying to start a service on boot on Android

Android: Start Service on boot?

http://developer.android.com/guide/components/services.html

http://developer.android.com/reference/android/app/Service.html

http://developer.android.com/training/run-background-service/create-service.html not preffered by me.

http://developer.android.com/guide/components/processes-and-threads.html my starting point of research

Requests:---

I think this question is a normal practice for most people who are dealing with services. In that vision, please only answer if you have experience in the scenario and can comprehensively explain the aspects and strategy with maximum sample code as a complete version so it would be a help to the community as well.

Vote up and down (with responsibility) to the answers as it matters to me who shared their views, time and experience and helped me and the community.


Solution

  • Que:Want to make most effort that the service be persistent and does not stops in any case. Will give it most weight and run it as ForGroundSerice as it has a higher hierarchy of importance. (hope that's ok?)

    Answer:you need to start service with using START_STICKY Intent flag.

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    
    // We want this service to continue running until it is explicitly
    // stopped, so return sticky.
    return START_STICKY;
    }
    

    Que:If I need AlarmManager, How to implement that? or any other way? Or just put the operations in a neverending while loop and sleep for 15 minuts at the end?

    Answer:you need to register alarmmanager within service for the time after to some task. //register alarm manager within service.

    PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new         Intent("com.xxxxx.tq.TQServiceManager"), PendingIntent.FLAG_UPDATE_CURRENT);
    
            AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    
        alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000 , 30 * 1000 , pendingIntent);
    

    //now have a broadcastreceiver to receive this intent.

    class Alarmreceiver extends Broadcastreceiver
    {
       //u can to task in onreceive method of receiver.
    }
    

    //register this class in manifest for alarm receiver action.

    Que:When the service is started (by clicked on start button). It should make an entry so that it auto starts if phone restarts.

    Answer:use broadcast reciver to listen for onboot completed intent.

    public class StartAtBootServiceReceiver extends BroadcastReceiver{
    
        @Override
        public void onReceive(Context context, Intent intent) {
            try {           
                if( "android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {                
    
                    ComponentName comp = new ComponentName(context.getPackageName(), LicensingService.class.getName());
                    ComponentName service = context.startService(new Intent().setComponent(comp));
                    if (null == service){
                        // something really wrong here
                        //Log.Write("Could not start service " + comp.toString(),Log._LogLevel.NORAML);
                    }
                }
                else {
                    //Log.Write("Received unexpected intent " + intent.toString(),Log._LogLevel.NORAML);   
                }
            } catch (Exception e) {
                //Log.Write("Unexpected error occured in Licensing Server:" + e.toString(),Log._LogLevel.NORAML);
            }
        }
    }
    

    //need to register this receiver for Action_BOOTCOMPLETED intent in manifest.xml file Hope this helps you clear out things :)