[JAVA] Programming from 51 years old Note Service --reference

It's for myself. Look directly at the following as it may be wrong. It seems that the page contents in English and Japanese are different.

https://developer.android.com/guide/components/services

What is Service

Service: An application component that can perform long-term processing in the background without using a user interface.

You can start other application components, and if you change to another application, it will continue to process in the background.

In addition, components and services can be bound and communicated, and interprocess communication is possible. For example, network processing, music playback, file I / O, content provider communication, etc. can all be processed in the background.


3 types of Service

■Foreground foregroundService performs the process notified to the user. For example, an audio app uses ForegroundService to play on an audio track. Foreground Service displays notifications. When the user is not interacting with the app, the Foreground Service will continue to handle it.

■Background The Background Service performs processing that is not directly noticed by the user. For example, for a service that compresses your app's storage, it's a background process.

Note:
If the app is API 26 or later and the app is not set to foreground, the system imposes restrictions on the execution of background services. In such cases, do the scheduled work instead.

■Bound Bind the service to the application component with bindService () </ font>. The bound service provides a client-server interface to communicate with the component. For example, request transmission, result reception, process communication, etc.

The bound service never terminates as long as other application components are bound to the service.


Services can be both explicit start and bind, but the documentation describes start and bind separately.

The implementation either requests the service start with onStartCommand () </ font> or allows binding with onBind () </ font>. Do either.

Any application component can use Intent to start the same service in the same way that it uses any activity. It is also possible to define a prohibition from other apps in the manifest. For more information> https://developer.android.com/guide/components/services#Declaring

COUTION:
Unless you specify a method, the Service will not create its own thread and will not run in another thread.

Therefore, for heavy processing such as MP3 playback and network processing, it is necessary to create a new thread in the service and process it in another thread in order to prevent UI freeze error.

Which do you use, Service or Thread?

・ When Service is processed in the background
・ When Thread needs to be processed by other than the main thread

For example, if you want to play music only while the activity is running, create a thread in onCreate (), start execution with onStart (), and stop with onStop (). You can also use AsyncTasc or HandlerThread instead of Thread.

Override method important for creating Service

onStartCommand() / onBind() / onCreate() / onDestroy()

■onStartCommand() The system calls ** onStartCommand () ** when another component, such as an activity, calls ** startService () ** to request the start of the Service. Service is started when onStartCommand () is executed.

When implementing onStartCommand (), use ** stopSelf () ** or ** stopServece () ** to stop the service by itself when the service is completed (onStartCommand () is to provide binding only. You don't have to implement it).

■onBind() The system calls ** onBind () ** when you call ** bindService () ** to bind other components to the Service.

When implementing onBind (), it is necessary to return IBinder </ font> to provide the interface that Klein uses to communicate with Service.

The implementation of onBind () is always required, but if you don't allow binding you should return ** null **.

■onCreate() A method that is called for a one-time setup process when the service is first created, before calling onStartCommand () or onBind ().

■onDestroy() A method that is called when the Service has not been used for a long time or has been destroyed. Service implements this method to clean up resources for threads, registered listeners, and receivers. This method is the last call that Service receives.


End of service

■stopSelf() stopService() Once a component has started a Service with startService () in onStartCommand (), the service will continue to run until the service terminates itself with stopSelf () or another component executes stopService ().

■unbind If the component creates a Service with bindService () </ font> without calling onStartCommand (), the Service will continue to run as long as the component is bound to the Service. When all services have been unbound from the client, the system destroys the service.

■ Destruction of Service by Android System

The android system stops the service only when the memory is low and the system resources of the activity you are interacting with need to be recovered. Services bound to the activity the user is using are less likely to be destroyed. Services defined to run in Foreground are rarely destroyed.

Over time, the system lowers Service's position in the background task list. The developer should design the service return process by the system. Depending on the return value of onStartCommand () </ font>, if the system destroys the Service, the system will recover the resources and bring the Service back. For more information> https://developer.android.com/guide/components/processes-and-threads.html


Manifest Declaration

<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>

~ </ Service> defines the properties required to start the service or the process that executes the service.

■android:name Specify the class name of Service. Only required attribute, immutable ** To keep your app safe, always use an explicit Intent when starting or binding a Service. ** **

COUTION:
To keep your app safe, always use an explicit Intent when starting a Service and don't declare a Service Intent filter.

Implicit intents are dangerous. The developer may not be able to see the Service returned by the intent, or the user may not be aware of the start of the Service.

In Android5.0 (API21) and later, when you call bindService (), the system throws an exception.

■android:exported By defining false in the android: exported </ font> attribute and adding it, you can make Service available only to that app. This way, even if you use explicit Intent, the Service will not be called by other apps.

■android:description

Note:
Users can see which services are running on the device. If it finds a service that the user does not allow or trust, the user can stop the service.

To prevent users from accidentally stopping a service, add a android: description attribute to the element in your app's manifest to make sure the service is needed / useful. Please explain in a short sentence.

If you want to manage the service life cycle in more detail> https://developer.android.com/guide/components/services#Lifecycle

~~ If you want to leave ambiguity about which Service to start, define an Intent filter in Service, exclude the component name from Intent, and then setPackage (to clear the ambiguity of the target service) You need to set the Intent package with) . ~~

Generate the requested Service

** What is the requested service: ** A Service that another component called startService () and was requested to generate using the onStartCommand () method.

When a Service is started, it has its own life cycle, independent of the calling component.

The Service runs indefinitely in the background even if the calling component is destroyed. So when the process is finished, either stopSelf () </ font> will cause the Service to terminate itself, or stopService () </ font> will do the other. Terminate Service from the component of.

Application components such as activities can start a service by calling startService () </ font> and passing Intent </ font>. Intent specifies the Service to start </ font> and passes the data used by that Service. Service receives this Intent with the onStartCommand () method </ font>.

For example, suppose an activity stores data in an online database. The activity starts a companion service and passes an Intent to startService () so that it can deliver the data it stores.

Service receives Intent by onStartCommand () </ font> and executes database processing through the Internet. When the process is finished, the Service terminates itself and the Service is destroyed.

COUTION:
The Service runs in the same process as the declared application, and by default runs in the application's main thread.

If the Service runs intensively or performs a block operation while the user is interacting with the activity of the same application, the performance of the activity will be degraded.

To prevent performance degradation, create a new thread in Service and let it process the thread.

An extensible class for generating the requested service

Service Base class for all Services.

The Service uses the app's main thread by default, so the processing of the Service can slow down activity performance.

Therefore, when extending this class, it is important to create a new thread that completes the Service process.

IntentService A subclass of Service that uses a worker thread that processes all Service generation requests one by one. Ideal when the Service does not need to process multiple generation requests at the same time.

Just by implementing onHandleIntent () </ font>, you can receive the Intent of each generation request and perform background processing.


Extension of IntentService class

It is easier to implement the requested Service by extending the IntentService class than by extending the Service class. </ font> The best way to extend the Service class to handle intents is when the Service needs to run multiple threads (rather than processing start requests through the work queue). is.

Most of the services requested to start do not need to handle multiple requests at the same time. Designing with multithreading is dangerous. It's best to implement Service using the IntentService class </ font>.

How the IntentService </ font> class works.

--Create a thread to execute all the intents delivered to onStartCommand () </ font>. This thread separates from the application's main thread. --Create a work queue that passes intents one by one to onHandleIntent () </ font> so you don't have to create multiple threads. --You don't need to use stopSelf () <</ font> as it will stop the service after processing all start requests. -- onBind () </ font> is implemented by default. The implemented onBind () returns null. -- onStartCommand () </ font> is implemented by default. The implemented onStartCommand () sends an intent and an implemented onHandleIntent () </ font> to the work queue.

Implement onHandleIntent () </ font> to complete the work requested by the client, but Service requires a constructor.

IntenService implementation example </ font>

public class HelloIntentService extends IntentService {

  /**
   * the super <code><a href="/reference/android/app/IntentService.html#IntentService(java.lang.String)">IntentService(String)</a></code>
   *Call super in constructor (required)
   */

  public HelloIntentService() {
      super("HelloIntentService");
  }

  /**
   *IntentService is the intent that started the service.
   *Call this method from the default worker thread.
   *When this method returns, IntentService will stop the service if necessary.
   */

  @Override
  protected void onHandleIntent(Intent intent) {
      //Normally, this method works like downloading a file.
      //In the sample, I code the process to sleep for 5 seconds
      try {
          Thread.sleep(5000);
      } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
      }
  }
}

This is all the processing required by IntentService (), such as the implementation and constructor of onHandleIntent () </ font>.

If you want to override other callback methods such as onCreate (), onStartCommend (), onDestory () </ font>, call the super implementation (parent implementation). Manage the IntentService life cycle properly.

onStartCommand () </ font> delivers the intent to onHandleIntent () </ font> and returns the default implementation.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
    return super.onStartCommand(intent,flags,startId);
}

Besides onHandleIntent () </ font>, onBind () </ font> is the only method that doesn't need to call the superclass. These implementations are required when allowing the Service to bind.


Service class extension

When it is necessary to execute multithreading, the start request is processed by extending Service and using each Intent instead of processing via the work queue.

The same processing as the code of IntentService above is implemented by extending the Service class below. For each start request, the worker thread runs jobs and processes and processes only one request at a time.

public class HelloService extends Service {
  private Looper serviceLooper;
  private ServiceHandler serviceHandler;

  //Handler receives a message from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
          //Normally, you do it here, just like downloading a file
          //Below is a sample code that sleeps for 5 seconds
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
          }
          //When there are multiple processing requests
          //Stop service using start ID
          //You can't stop without using your start ID
          stopSelf(msg.arg1);
      }
  }

  @Override
  public void onCreate() {
    //Start a thread to run the service
    //Service processing in another thread to ensure the performance of the main thread
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();

    //Gets the handle's thread looper and passes it to the handle.
    serviceLooper = thread.getLooper();
    serviceHandler = new ServiceHandler(serviceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      //When you start the request, send a message to the process you started and also send the start ID.
      //When the process is completed, the work to be stopped can be confirmed by ID.
      Message msg = serviceHandler.obtainMessage();
      msg.arg1 = startId;
      serviceHandler.sendMessage(msg);

      //If the service is killed, come back here and restart
      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }

  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
  }
}

Since each call to onStartCommand () </ font> is executed by the Service itself, it is possible to execute multiple requests at the same time. If it suits your situation, you can create a new thread for each request and run it immediately (no need to wait for the previous request to complete).

The onStartCommand () method must return an integer </ font>. This integer is a value that indicates how to continue the service when the system kills the service (below).

  • START_NOT_STICKY --If the system kills the service after returning from onStartCommand () </ font>, the system will not restart the service unless there are intents pending delivery. .. This is the safest option to avoid running unwanted services if you don't need them and your application can resume incomplete jobs.

  • START_STICKY --If the system kills the service after returning from onStartComand () </ font>, recreate the service and onStartCommand () Calls </ font> but does not redistribute the last intent. The system instead calls onStartCommand () </ font> with a null intent, unless the intent to deploy the service is pending. If there is a pending intent, that intent will be delivered. This is suitable for media players (and similar services) that do not run commands, but run indefinitely and wait for jobs.

  • START_REDELIVER_INTENT --If the system kills the service after returning from onStartCommand () </ font>, recreate the service and <font onStartComannd () </ font>. All pending intents will be delivered in sequence. This is suitable for services that perform processes such as file downloads and need to be restarted immediately after completion.


Service start

Intent </ font> (specify start Service) from activity or other application component, startService () </ font>, or startForegroundService () </ font> to start the service.

The Android system calls the Service's onStartCommand () method and passes the Intent. Intent specifies the service to start.

Note:
If your app is API 26 or later and your app is not in the Foreground, the system imposes restrictions on the use and generation of background services. If you want to generate your app with ForegroundService, use startForegroundService () . Once a Service is created, it must call the startForegroun () method within 5 seconds.
Using explicit Intent with startService () Sample code to start the service
Intent intent = new Intent(this,HelloService.class);
startService(intent);

The startService () </ font> method causes the Android system to execute the Service's onStartCommand () </ font> method. If the Service is not already running, the system will first run onCreate () </ font> and then onStartCommand () </ font>. > Is executed.

When the Service does not provide a binding, the Intent delivered by startService () </ font> is the only means of communication between the application component and the Service.

However, if the Service returns a result, the client requesting the Service can create a PendingIntent </ font> for the broadcast ( getBroadcast () < (Use / font>), it can be delivered to the requested Service Intent </ font>. The Service can then use the broadcast to deliver the results.

If there are multiple Service requests, multiple calls will be made to onStartCommand () </ font> to handle them, but to stop, Only one # 099 "> stopSelf () </ font> or stopService () </ font> is required.


Stop Service

After starting the service, manage the life cycle of the service. After executing onStartCommand () </ font>, the Service will run indefinitely and the system will not stop or destroy the Service except when recovering system memory. To stop the Service, either the Service itself executes stopSelf () </ font>, or stopService () </ font> from another component. Run and do it.

Once stopSelf () </ font> or stopService </ font> is executed, the system will immediately drop the service.

When Service processes multiple requests to onStartCommand () </ font>, one request is stopped because all other requests are stopped by one stop processing. Do not stop the Service when it is complete.

Use stopSelf (int) to stop the Service that handles multiple requests. This method ensures that the Service stop request is always based on the latest start request.

Specifically, stopSelf (int) </ font> passes the ID of the start request according to the request you want to stop (startId sent to onStartCommand ()). If the Service receives a new start request before stopSelf (int) </ font> can be executed, the start request ID and the stop supply ID will not match, so that Service does not stop.

COUTION:
To avoid wasting system resources and draining battery power, always stop the service when the application is finished.

If necessary, stop the Service by running stopService () from another component.

If you have Service binding enabled and the Service is running with onStartCommand () , use stopSelf () to stop the Service itself.

Create a bound service

Binding to a Service with bindService () allows the application component to connect for a long time (usually the service cannot be started by the component calling starService ()).

Generates a bound Service when you respond to activities within an application, other components and Services, or provide application functionality to other applications via interprocess communication.


Create a bound service

--Implement onBind ()
Returns IBinder that defines the interface for communication with Service

--Application component calls bindService ()
Gets interface IBinder and starts calling Service methods

When there are no more bound components, the system destroys the service (the bound service does not have to be stopped in the same way it was started with onStartCommand ()).

To generate a bound Service, you need to define an interface. This interface specifies how to communicate with the client and service. The interface responsible for the communication between the client and the Service must implement IBinder </ font>, and Servise calls onBind () </ font>. Must be an IBinder returned by the back method. Once the client receives the IBilder, it can operate the Service through the interface.

Multiple clients can bind to the service at the same time. When a client finishes a Service operation, it executes unbindService () </ font> to unbind it. If there are no more clients to bind to the Service, the system will destroy the Service.

There are several ways to implement a bound service, and that implementation is more complicated than starting a Service, so see this document for more information> https://developer.android.com/guide/components/bound- services.html

Send notifications to users

Once the service is up and running, you can notify the user with a toast notification or status bar notification. A toast notification is a message that appears on the screen for a moment. Status bar notifications display an icon in the status bar with a message. The user can choose the action to operate from the notification (such as starting Service).

Status bar notifications are usually the best technique for doing things like completing a file download in the background. When the user selects a notification from the expanded view, you can start the activity from the notification (to see the downloaded file).

Learn more about toast notifications and status bar notifications>

Learn more toast notifications> https://developer.android.com/guide/topics/ui/notifiers/toasts.html For more details Status bar notifications> https://developer.android.com/guide/topics/ui/notifiers/notifications.html

Run Service on Foreground

ForegroundService is a state in which the user can recognize the Service, so even if it runs out of memory, it is not a candidate for forced termination by the system. The ForegroundService should notify you in the status bar and will appear under the "In Progress" heading. The notification will not disappear unless the service is stopped or removed from the Foreground.

COUTION: Foreground Service usage restrictions
ForegroundService is only available if you know your app is on track and you need to run it without the user having to interact with it directly.

ForegroundService sets the importance of notifications and displays them in the status bar to ensure that users know what your app is doing.

You should consider using scheduled processing instead of Service for actions that have the lowest importance.

Apps that use Service put a load on the system and consume system resources. Setting low importance and hiding notifications can hurt the performance of the app the user is using, so if you want to run the service with the lowest importance, the bottom of the notification drawer Call the app with. (Is it likely that the lower part of the notification drawer will be forcibly terminated due to system reasons?)

Music players that play music on the Service should be configured to run on the Foreground in order for the user to explicitly recognize the running of the app. Status bar notifications display the music being played or operate the music player to launch any activity. Similarly, an app that tracks a user's travel requires a Foreground Service that tracks the user's location.

Note:
Apps using Foreground Service on Android 9 (API 28) or later will request FOREGROUND_SERVICE permission. This is a normal permit, so the system will automatically grant it to the requesting app.

If you create a ForegroundService at API 28 or lower without requesting FOREGROUND_SERVICE, the system will throw a safety exception.

Foreground Sercice The Foreground Service must display the notification and cannot be dismissed unless the Service is stopped or the Service is removed from the Foreground.


Create a Foreground Service

Execute startForeground (Id, notification) ・ Notification ・ Intent ・ PendingIntent ・ Notification.setLatestEventInfo (this, title, text, PendingIntent) ・ StartForeground (Id, notification) </ font>

new notification is currently deprecated. Use notificationCompat setLatestEventInfo is currently deprecated. Let's use builder startForegroundService is API26 or above </ font>

Notification notification = new Notification(
                                R.drawable.icon,
                                getText(R.string.ticker_text),
                                System.currentTimeMillis()
                                );
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(
                              this, 
                              getText(R.string.notification_title),
                              getText(R.string.notification_message), 
                              pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

0 is NG for the ID passed to startForeground () </ font>


Foregourd Service removal

stopForeground() ・ Remove Service from Foreground ・ We also accept bool values that indicate whether to remove notifications. ・ Service does not stop </ font> However, if the Service is still running in Foreground and hangs, the notification will be removed.

Service lifecycle management

abridgement

Recommended Posts