Writing core services
In addition to writing custom apps, Candella offers support for writing custom core services that other apps can rely on. Core services are handled by the CACoreService
class and function similarly to Candella apps. Core services also inherit the properties of CAObservable
, allowing it to emit signals to observers.
Creating a core service
The recommended way of creating a core service from scratch is to use the Candella SDK and follow the interactive prompts:
candella-sdk --action create --type service
Likewise, you can also follow the instructions below to make a core service manually:
- Create a folder with the structure
YourAppName.aosapp
inside of the System/CoreServices folder. - Create a manifest file inside of the service folder using the manifest structure (see "The manifest file").
- Create the
Resources/Iconset
folders inside of the service directory. - Add service icons for the following sizes in pixels (their names will be the corresponding size): 16, 24, 32, 48, 64, 128, 256, 512, 1024.
- Create a file with your service's name with the
rpy
extension. Use the template below to fill the contents of your service.
#
# ServiceName.rpy
# Service Name
#
# (C) Year Author.
#
init offset = 5
init python:
class Service(CACoreService):
"""Service description"""
def __init__(self):
CACoreService.__init__(
self,
AS_CORESERVICES_DIR + "ServiceName.aoscservice/"
)
# Initialize your core service here.
# Initialize the service outside of the class.
service = Service()
The manifest file
Like Candella apps, core services also include a manifest file that defines the service, as well as its permissions and requisites. This is also located in the root of the service folder and should be named manifest.json
.
Field | What it does |
---|---|
name |
A short name of your service. |
id |
An identifier for the service. It is recommended to use reverse domain notation. |
author |
The author of the service. It is recommended to use the Name <[email protected]> format. |
version |
The current version of the service. |
description |
A summary of what your service does. |
license |
The license your service falls under as an SPDX expression. |
permissions |
A list of strings containing what permissions your service requires. See permissions in the app manifest. |
requisites |
(Optional) A list of strings containing the names of the frameworks this service relies on. |
Unrestricted access
Core services typically have unrestricted access to resources, unlike Candella apps, when declared in the manifest. Ensure that you declare only the permissions you need and that you use those resource wisely.
Validating service requisites
Core services that depend on requisite frameworks should be declared in the app's manifest under the requisites
field. At initialization time, the service will determine whether or not the frameworks are present.
Core service lifecycle
Like Candella apps, core services have a lifecycle based on the structure of AliceOS core services. These methods are called when a stage of the service lifecycle will happen and when the stage has finished; for launch, this would be ASCoreServiceRepresentative.serviceWillLaunch
and ASCoreServiceRepresentative.serviceDidLaunch
, respectively. The same applies for when an service's termination cycle.
Candella services can still hook into these methods by defining similar methods:
- For launch,
CACoreService.service_will_launch
andCACoreService.service_did_launch
. - For teardown,
CACoreService.service_will_terminate
.
Candella services also have two new methods at their disposal that make calls to these methods:
CACoreService.launch
for launch stages in the services's lifecycle.CACoreService.terminate
for termination stages.
Whether you want to use the AliceOS-style approach or the new launch/terminate approach is up to you, but remember to keep your logic in a consistent order. If you decide to override the latter methods, be sure to emit the appropriate signals:
- In
launch
,emit_signal("service_launched", name=self.__class__.__name__)
- In
terminate
,emit_signal("service_terminated")
Sending service signals
Core services have the ability to emit signals, just like Candella apps; more information on signals can be found in the documentation about the Observable framework.
By default, core services emit the following signals:
Signal | Arguments | Purpose |
---|---|---|
service_launched |
name=self.__class__.__name__ |
Indicates that the service launched successfully. |
service_launched_at_login |
name=self.__class__.__name__ |
Indicates that the service launched during boot successfully. |
service_terminated |
None | Indicates the service was terminated successfully. |
service_requested_notification |
response=response |
Indicates that the service sent a notification request and received a response from the user. |
Service storage
Like apps, core services also have access to containerized storage for the currently logged-on user. Details on how to use service storage can be found in the Multiuser framework documentation.