Creating Android Services

From RAD Studio
Jump to: navigation, search

Go Up to Creating an Android App

An Android Service is an application without user interface that performs background tasks. There are essentially two types of services:

  • A started service: This service is started by an Android application. The service can run in the background indefinitely, even if the application is closed. This type of service usually performs a single task and automatically stops after finishing.
  • A bound service: This service only runs while it is bound to an Android application. There is an interaction between the application and the service, and it remains active until the application unbinds. More than one application can bind to the same service.

To create an Android Service project:

  1. Use the New Android Service wizard to create the Android Service. See Creating an Android Service.
  2. Use the Add New Android Service wizard to add the Android Service to the Multi-Device Application. See Adding an Android Service to an Application.

There are some differences between a stand-alone application and an Android Service project application:

Creating an Android Service

RAD Studio provides a wizard to create Android Service projects.

To create a new Android Service project, choose File > New > Other, then navigate to:

  • Delphi Projects > Android Service

Use this wizard to specify the type of service, local or remote.

  • A local service is private to an application. Access from other applications is blocked adding a line to the Android Manifest file:
<service android:exported="false" android:name="com.embarcadero.services.<service_name>"/>
  • A remote service is public, and other applications can access it. Access to the service is granted adding a line to the Android Manifest file:
<service android:exported="true" android:name="com.embarcadero.services.<service_name>"/>

For more information about the different options, see Android Service.

For more information about the Android Manifest attributes, see Exported Provider Element.

Note: If the developer has changed the <SERVICE-NAME>.template.java file (local template file), and the JavaClasses folder from the root folder of an Android Service folder generated by a previous product release, it is very important to introduce the same changes into the local template file generated by RAD Studio 10.4.

Adding an Android Service to an Application

Android services are not stand-alone applications, they work together with Multi-Device applications.

Once the service is created, it appears on the Projects Window as lib<project_name>.so.

To add the Android Service project to the Multi-Device application:

  1. Add all the visual components to the data module, and the functions and procedures to the code.
  2. Save the Android Service project.
    Note1: Save each Android Service project in an exclusive folder.
    Note2: Do not name the Android Service project as Service.
  3. Build the Android Service project before adding it to the application in order to generate the binary files.
  4. Add to the Projects Window the application to which you want to add the service:
    1. For an existing application, on the project group, right-click and select Add Existing Project.
    2. For a new Multi-Device Application, on the project group, right-click and select Add New Project, then navigate to:
      • Delphi Projects > Multi-Device Application.
  5. On the Multi-Device Application, select the Android target platform.
    1. On the Android target platform, right-click and select Add Android Service.
    2. The Add New Android Service wizard appears. You have two options to add a new Android service. Choose one of the following:
      1. Search files automatically from project base path.
        • Choose this option to select the folder where your Android Service project is saved. The wizard will search the required files automatically.
          Warning: If you have more than one Andoird service in the given folder, the wizard will select one of them randomly. If you want to add a specific Android service, use the second option.
        • Click Next.
        • Click ProjectOptionsEllipsis.jpg to select the folder where your Android Service project is saved.
      2. I will select all required files manually.
        • Choose this option to select all the required files manually.
          Warning: Make sure that step 3 is done. Otherwise, you will not have the binary files available.
        • Click Next.
        • Click ProjectOptionsEllipsis.jpg to select each requested file.
    3. Click Next.
      1. If everything is correct, then the files that are going to be added to your Multi-Device application appear listed.
      2. If an extra window appears requesting information about the Android Service paths, save and build the Android Service, then try it again.
  6. Click Finish to add the files to the application:
    • The main binary file, lib<project_name>.so. The binary file is added to the Deployment Manager.
    • The libProxyAndroidService.so file. This library is added to the Deployment Manager.
      Note: This file is shared by all the services added to the application.
    • The Java archive, <project_name>.jar file. The jar file is added to the Libraries node on the Projects Window, under the Android target platform.
    • The data module file, <project_name>.pas file. The data module is added to the Projects Window.
  7. Compile the Multi-Device Application to generate the Android Manifest file. The line that corresponds to the type of service previously selected (local or remote) is automatically added. See Creating an Android Service.
    Note: Each service needs a corresponding <service> declaration in the AndroidManifest.xml. This is automatically added by the IDE.

Adding Several Android Services to an Application

You can add any number of services to an Android application.

Follow the steps on Adding an Android Service to an Application for each of the services to add.

Important things to take into account:

  • If you have several Android Services projects in the same folder and you want to include a specific one, choose the second option in the step 5.2. Otherwise, the wizard may add an unwanted Android service.
  • Name differently each project before adding it to the main application:
    • The Android Service project, lib<service_name>.so.
    Note: Do not name the Android Service project as Service.
    • The unit file.
    • The Data Module, by changing the Name property on the Object Inspector.

Project Dependencies

Android Service projects added to Multi-Device Applications appear as Project Dependencies.

The Android Service projects vinculated to the host application are automatically enabled in Project Dependencies to be always build before the host application.

Deleting an Android Service from an Application

On the Multi-Device Application, select the Android target platform.

  1. On the Android target platform, right-click and select Remove Android Service.
  2. The Remove Android Services wizard appears.
  3. Select the services to remove from the list.
  4. Click Next.
  5. The wizard shows a list of actions to perform, such as deleting the data modules, .so extension files, and .jar extension files.
  6. Click Finish.

Starting a Service

Services can be started with ALocalServiceConnection.StartService('<service_name>') and ALocalServiceConnection.BindService('<service_name>'), or ARemoteServiceConnection.StartService('<service_name>') and ARemoteServiceConnection.BindService('<service_name>').

You initialize the TLocalServiceConnection variable to a specific service when starting or binding to it, after that you do not need to refer to the service name for the rest of methods.

Once you add an Android Service to your Multi-Device Application:

  1. Include the following unit in the Uses clause of the interface:
  2. Uses
      System.Android.Service; // Unit that contains the methods to work with services.
    
  3. Include the <service_name.pas> unit in the uses clause of the implementation. This allows you to use all the methos defined on the service data module.
  4. implementation
    
    uses
      MyLocalService; //Key sensitive
    
    {$R *.fmx}
    
  5. Construct a TLocalServiceConnetion variable for a local service, or a TRemoteServiceConnection variable for a remote service.
    1. Declare the TLocalServiceConnection/TRemoteServiceConnection variable:
      type
        TForm1 = class(TForm)
          ...
        private
          { Private declarations }
          FServiceConnection1: TLocalServiceConnection; // For a local service.
          FServiceConnection2: TRemoteServiceConnection; // For a remote service.
        public
          { Public declarations }
        end;
      
    2. Create the TLocalServiceConnection/TRemoteServiceConnection variable:
      FServiceConnection1 := TLocalServiceConnection.Create; // For a local service.
      FServiceConnection2 := TRemoteServiceConnection.Create; // For a remote service.
      

Started Service

For a Started service, call StartService('<service_name>') to start the service.

When using services as started, you need to manage the service process stopping the service with JavaService.stopSelf;.

Sticky Start

The OnStartCommand event for the service is defined by default as START_NOT_STICKY.

  • START_STICKY is used for services that are explicitly started and stopped as needed. The system tries to re-create the service when killed.
  • START_NOT_STICKY is used for services that should only remain running while processing any commands sent to them. If the process is killed, the service is not restarted automatically.

If you want to have a START_STICKY on the OnStartCommand event, you need to specify it on the service:

function TService1DM.AndroidServiceStartCommand(const Sender: TObject;
  const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
  Result := TJService.JavaClass.START_STICKY;
end;

For more information, see Service Lifecycle.

Bound Service

For a Bound Service, call BindService('<service_name>'), to bind to the service so that you can start interacting with it, and UnBindService to disconnect from the service.

For more information, see Bound Services.

BindService / UnBindService Methods

When the main application calls BindService('<service_name>'), the connection variable gets a pointer to the memory address where the service is running.

After establishing the connection to a specific service, when you call UnBindService, and the application is the only one bound to the service, the service frees himself. Take into account that the connection variable of the main application remains pointing to the same memory address. Binding to the same service again can provoke a crash on the main application because the memory address to the service could be invalid.

There are two ways of handling this situation:

  • Avoiding ARC using the [UnSafe] attribute.
  • Assigning Nil to the variable before unbinding from the service.

Using the [Unsafe] Attribute

  private
    { Private declarations }
    [Unsafe] Service1: TAndroidService1DM;

OnBind Event

When you call BindService('<service_name>') on your application, the OnBind event triggers on the Android Service project. The OnBind method returns a IBinder object that is responsible of actually managing the connection with the service.

Overwriting the OnBind method causes that the event does not return the IBinder object that the main application needs to bring the Data Module from the service.

To use the OnBind method:

  • On the OnBind method return the IBinder object:
function TAndroidServiceDM.AndroidServiceBind(const Sender: TObject;
  const AnIntent: JIntent): JIBinder;
begin
  // .... User's code
  Result := GetBinder(Self);
end;

See Also