# Titanium.Android.Service

> Android application component that executes in the background.

- Source: https://titaniumsdk.com/docs/sdk/12.6.4/Titanium.Android.Service
- Titanium SDK version: 12.6.4
- Kind: proxy
- Platforms: Android
- Since: Titanium SDK 1.5
- Extends: Titanium.Proxy
- Inheritance: Titanium.Proxy

A service is a component started by an application that runs in the background. The service
does not have any application UI associated with it, so the user does not directly interact
with it, only your application.

The Titanium SDK gives you the ability to write your own Android Services using JavaScript.
The service executes your JavaScript code at intervals you specify.  Note that the service
may stop running if the application is killed.

To create a service:

  1. Write the JavaScript code you want the service to execute in a separate file.
     The service can execute any Titanium APIs but you should only use non-UI APIs.
  2. Register the service in your `tiapp.xml` file. Refer to the example below.
  3. Create a service intent by passing the JavaScript file to
     the [Titanium.Android.createServiceIntent](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#createServiceIntent) method and set the interval to run the
     code using the intent's `putExtra()` method.
  4. Pass the Intent object to either the [Titanium.Android.createService](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#createService) method
     to create a `Service` object (*bound service*), where the application can
     manage the service by invoking methods and binding callbacks on the object,
     or to the [Titanium.Android.startService](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#startService) method to start the service (*started service*)
     and the service manages itself.

Use the `Titanium.Android.Service` API to manage the service.

To get a reference to the `Service` inside the JavaScript service code, use the
[Titanium.Android.currentService](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#currentService) property to retrieve a reference to the service,
then invoke the `Titanium.Android.Service` APIs on the `Service` object.

Further Reading:

  * [Android Services guide](https://titaniumsdk.com/guide/Titanium_SDK/Titanium_SDK_How-tos/Platform_API_Deep_Dives/Android_API_Deep_Dives/Android_Services.html)
  * [Android Developer: Service](https://developer.android.com/reference/android/app/Service.html)

### Background Location Service Example
In order to obtain location events while the application is backgrounded a foreground service must be used.
Below is an example of a simple background location service.

tiapp.xml:
``` xml
<android>
    <manifest>
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    </manifest>
    <services>
    <service url="locationService.js"/>
    </services>
</android>
```

locationService.js:
``` js
console.log(`Background location service started.`);

// Create foreground service.
Ti.Android.currentService.foregroundNotify(
    123,
    Ti.Android.createNotification({
    contentTitle: "Background Location Service",
    contentText: "Obtaining location data...",
    contentIntent: Ti.Android.createPendingIntent({
        intent: Ti.App.Android.launchIntent || Ti.Android.createIntent(),
    })
    }),
    Ti.Android.FOREGROUND_SERVICE_TYPE_LOCATION
);
```

app.js:
``` js
const win = Ti.UI.createWindow({ backgroundColor: 'gray', layout: 'vertical' });
const backgroundServiceBtn = Ti.UI.createButton({ title: 'START BACKGROUND SERVICE' });
const listView = Ti.UI.createListView();

let count = 1;
let service = null;

// Set accuracy to high
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_HIGH;

// Enable manual configuration via location providers.
Ti.Geolocation.Android.manualMode = true;

// Define a location provider.
Ti.Geolocation.Android.addLocationProvider(
    Ti.Geolocation.Android.createLocationProvider({
        name: Ti.Geolocation.Android.PROVIDER_GPS,
        minUpdateDistance: 0,
        minUpdateTime: 5000
    })
);

function getLocation () {

    // Create location event listener.
    Ti.Geolocation.addEventListener('location', e => {

        // Create new section for location data.
        let section = Ti.UI.createListSection({ headerTitle: `#${count++} - ${new Date().toTimeString()}` });
        if (e.success) {
            if (e.coords) {
                e = e.coords;
            }

            // Insert location data.
            section.items = [
                { properties: { title: 'LOCATION:\n' + e.latitude + ', ' + e.longitude, color: 'green' } },
                { properties: { title: 'ALTITUDE:\n' + e.altitude, color: 'green' } },
                { properties: { title: 'ACCURACY:\n' + e.accuracy, color: 'green' } }
            ])

        } else {

            // Oops! Something bad happened.
            section.items = [
                { properties: { title: 'ERROR:\n' + e.error, color: 'red' } }
            ];
        }

        // Add section to listView
        listView.appendSection(section);
    });
}

function startBackgroundLocationService() {
    if (service) {
        console.log('Starting background location service...');
        service.start();
        backgroundServiceBtn.title = 'STOP BACKGROUND SERVICE';
    }
}

function stopBackgroundLocationService() {
    if (service) {
        console.log('Stopping background location service...');
        service.stop();
        backgroundServiceBtn.title = 'START BACKGROUND SERVICE';
    }
}

win.addEventListener('open', () => {

    // Request location permissions.
    Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_ALWAYS, e => {
        if (e.success) {
            getLocation();
        } else {
            alert('Could not obtain location permissions.');
        }
    });
});

backgroundServiceBtn.addEventListener('click', () => {
    if (!service) {

        // Create background location service.
        const intent = Ti.Android.createServiceIntent({ url: 'locationService.js' });
        service = Ti.Android.createService(intent);

        // Android 10+ request background location permissions.
        if (parseInt(Ti.Platform.version.split('.')[0]) >= 10) {
            Ti.Android.requestPermissions([ 'android.permission.ACCESS_BACKGROUND_LOCATION' ], e => {
                if (e.success) {
                    startBackgroundLocationService();
                } else {
                    alert('Could not obtain background location permissions.');
                }
            });
        } else {
            startBackgroundLocationService();
        }

    } else {
        stopBackgroundLocationService();
    }
});

win.add([backgroundServiceBtn, listView]);
win.open();
```

## Example: Hello World Service

This example shows how to create a service in JavaScript.
Your service code is included in its own JavaScript file.

In this example, the service reads data from the <Titanium.Android.Intent> which created it,
to see what it should say besides "Hello World".

File: myservice.js:
``` js
var service = Titanium.Android.currentService;
var intent = service.intent;
var message = intent.getStringExtra("message_to_echo");
Titanium.API.info("Hello World!  I am a Service.  I have this to say: " + message);
```

Register the service in tiapp.xml:
``` xml
<ti:app>
    <android xmlns:android="http://schemas.android.com/apk/res/android">
        <services>
            <service url="myservice.js" type="interval"/>
        </services>
    </android>
</ti:app>
```

Code in "regular" Titanium file to launch the service and listen for pause/resume events.
Code also stops the service after its code runs 3 times.

``` js
var intent = Titanium.Android.createServiceIntent( { url: 'myservice.js' } );
// Service should run its code every 2 seconds.
intent.putExtra('interval', 2000);
// A message that the service should 'echo'
intent.putExtra('message_to_echo', 'Titanium rocks!');

var service = Titanium.Android.createService(intent);
service.addEventListener('resume', function(e) {
    Titanium.API.info('Service code resumes, iteration ' + e.iteration);
});
service.addEventListener('pause', function(e) {
    Titanium.API.info('Service code pauses, iteration ' + e.iteration);
    if (e.iteration === 3) {
        Titanium.API.info('Service code has run 3 times, will now stop it.');
        service.stop();
    }
});
service.start();
```

Console Output:
```
[INFO] [29,1942] Service code resumes, iteration 1
[INFO] [70,2029] Hello World! I am a Service. I have this to say: Titanium rocks!
[INFO] [3,2070] Service code pauses, iteration 1
[INFO] [2,3915] Service code resumes, iteration 2
[INFO] [31,3961] Hello World! I am a Service. I have this to say: Titanium rocks!
[INFO] [5,3968] Service code pauses, iteration 2
[INFO] [2,5917] Service code resumes, iteration 3
[INFO] [27,5961] Hello World! I am a Service. I have this to say: Titanium rocks!
[INFO] [16,5980] Service code pauses, iteration 3
[INFO] [1,5981] Service code has run 3 times, will now stop it.
```

## Properties

### intent

- Type: Titanium.Android.Intent
- Platforms: Android
- Permission: read-only

The intent used to start or bind to the Service.

### serviceInstanceId

- Type: Number
- Platforms: Android
- Permission: read-only

A service can be started more than once -- this number (based on an incrementing integer)
indicates which "start number" in the sequence the current service instance is.

## Methods

### foregroundCancel

- Platforms: Android
- Since: Titanium SDK 7.3.0

Puts the service into the "background" state and removes its foreground notification.

If you call the [foregroundNotify()](https://titaniumsdk.com/docs/sdk/Titanium.Android.Service.md#foregroundNotify) method to
put the service into the "foreground" state, then you call this method to put the service
back into the "background" state. This will also automatically remove the foreground service's
notification that was put into the status bar.

Note that stopping a foreground service will remove its foreground notification from
the status bar as well. So, you do not have to call this method to remove it. This method
is only intended to be used by services that need to dynamically change states.

### foregroundNotify

- Platforms: Android
- Since: Titanium SDK 7.3.0

Puts the service into the "foreground" state and displays a notification.

Calling this method will change the service from the "background" state (the default)
to the "foreground" state. It will also post a notification to the status bar to notify the
end-user that the app is doing work, even while backgrounded. This feature is typically
used by apps that play music, monitor current location, or perform large downloads while
the app is in the background.

Note that a foreground service is far less likely to be terminated by the operating system
while the app is in the background. A foreground service is also needed if the app
needs to acquire location data since Android 8.0 and higher throttles location acquisition
while the app is in the background.

See Android 8.0 "Background Execution Limits":

  * https://developer.android.com/about/versions/oreo/background

You can call this method before or after the service has been started. If you need to
change the displayed notification, then you can call this method again with the same
notification ID and with an updated [notification][Titanium.Android.Notification](https://titaniumsdk.com/docs/sdk/Titanium.Android.Notification.md) object.

The notification will be automatically removed from the status bar when the service has
been stopped or if you call the [foregroundCancel()](https://titaniumsdk.com/docs/sdk/Titanium.Android.Service.md#foregroundCancel)
method.

This method will fail on Android 9.0 and above unless you set the following Android manifest
permission in your "tiapp.xml" file.

``` xml
<ti:app>
    <android xmlns:android="http://schemas.android.com/apk/res/android">
        <manifest>
            <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
        </manifest>
    </android>
</ti:app>
```

Parameters:

- `id` (Number): Unique integer ID to be assigned to the notification. Cannot be zero.
- `notification` (Titanium.Android.Notification): Notification to display in the status bar. Cannot be null.
- `foregroundServiceType` (Number, optional): Notification service type specified by <Titanium.Android.FOREGROUND_SERVICE_TYPE_*>. Default: `Titanium.Android.FOREGROUND_SERVICE_TYPE_NONE`.

### start

- Platforms: Android

Starts the Service.

Effective only if this instance of [Titanium.Android.Service](https://titaniumsdk.com/docs/sdk/Titanium.Android.Service.md) was created
with [Titanium.Android.createService](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#createService).

### stop

- Platforms: Android

Stops this running instance of the Service.

## Events

### pause

- Platforms: Android

For Javascript-based services that you create, `pause` fires after each time the JavaScript
code executes.

The `resume` and `pause` events occur in pairs, with `resume` firing just before your
JavaScript service code executes, and `pause` just after.

Event properties:

- `iteration` (Number): Incrementing integer indicating which iteration of an interval-based Service is pausing. For example, if you have an interval-based Service running every 10 seconds, iteration 3 would occur at about 30 seconds after you start the instance (assuming your service code runs quickly).

### resume

- Platforms: Android

For JavaScript-based Services which you create, `resume` fires each time the JavaScript
code executes.

For example, if your Service runs on an interval of 10000 (10 seconds), you would expect
to see `resume` fired every 10 seconds, just as the JavaScript service code you wrote is
about to execute.

Event properties:

- `iteration` (Number): Incrementing integer indicating which iteration of an interval-based Service is pausing. For example, if you have an interval-based Service running every 10 seconds, iteration 3 would occur at about 30 seconds after you start the instance (assuming your service code runs quickly).

### start

- Platforms: Android

Fired when the bound service instance starts.

Bound service instances are created via [Titanium.Android.createService](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#createService).

### stop

- Platforms: Android

Fired when the bound service instance stops.

The service stops when [Titanium.Android.Service.stop](https://titaniumsdk.com/docs/sdk/Titanium.Android.Service.md#stop) or
[Titanium.Android.stopService](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#stopService) is called and there are no more bound,
un-stopped clients.

### taskremoved

- Platforms: Android

Fired when the task that comes from the service's application has been removed.

This event is fired if the service is currently running and the user has removed a task
that comes from the service's application, eg. the user swipes the application away from
the recent applications list. It only works for unbound service which is
started using [Titanium.Android.startService](https://titaniumsdk.com/docs/sdk/Titanium.Android.md#startService).

## Inherited members

7 members are inherited. Each is documented on the type that declares it.

- [Titanium.Proxy](https://titaniumsdk.com/docs/sdk/12.6.4/Titanium.Proxy.md): `addEventListener`, `apiName`, `applyProperties`, `bubbleParent`, `fireEvent`, `lifecycleContainer`, `removeEventListener`

---

- This corpus documents Titanium SDK 13.4.1. Anything here that does not name a version describes 13.4.1.
- Titanium is maintained by TiDev. The Appcelerator toolchain is retired: there is no `appc` CLI, no Appcelerator Studio and no hosted build service. The supported CLI is `titanium` on npm, invoked as `ti`.

