Dev:Libactivator

libactivator is a library that provides a centralized system of activation methods for all of our jailbroken extensions. To accomplish this, the hooks of the activation methods are in one centralized Substrate plugin, which uses small bundles and preference panes to select the activation method for each plugin.

libactivator works by connecting an event (represented by an ) to one or multiple actions (represented by  ). Developers can create new events or actions to extend the functionality of a device.

How to use this library
Headers are available from Activator's GitHub project, and the library can be found at  on a device where Activator is installed. If using Theos, place the headers in, the library in   and add   to the   Makefile variable. See for more usage advice.

Observing Events (via LAListener)
There are three steps to follow: describing the action, implementing the code, and allowing users to change activation methods. Optionally, you can also add a method to register your plugin for a certain event on installation, which allows you to implement libactivator without confusing prior users.

Describing an Action
Provide information about your listener to libactivator by specifying the group it belongs to, its name and a short description, along with metadata and an icon.

Title and Description
Provide all the textual information about your listener. You can do so by using a plist or a tweak-like package.

Method One: No Code
Create a file in the directory  named   with the following contents:

To do: add a nice table specifying all the valid keys.

Method Two: Some Code
The  protocol contains a number of optional methods that are queried by Activator. These can be used if the exact title and description of listeners aren't known until runtime.

To do: add more API methods, and a short commented description about them.

Icon
Provide a visual description of your listener. There are two available options to do so: PNG or PDF.

Method One: No Code
Place your icons in

For the PNG, make a 29x29 pixels image named. Optionally an @2x version,.

For the PDF, make a vector image named.

Method Two: Some Code
The  protocol contains a number of optional methods that are queried by Activator. These can be used if the icon images of listeners aren't known until runtime.

To do: explain image-provider API.

Receiving Raw Events
Receiving raw events causes the original event behaviour to be suppressed, even in cases where it could leave users "trapped" inside of the application. Listeners that support receiving raw event should specify 'receives-raw-events' = 1; in their listener's Info.plist. Most listeners should not need to receive raw events.

rpetrich comments on this and tells us the proper way to do it.

Implementing the Code
Implementing the code can be done in two different methods, depending on your plugin. If you have an object that is always in memory, you can use method one, otherwise, use method two.

Method One: Add the Code
First,  and have your class implement the LAListener protocol.

To register for events, you must add a piece of code to your init method, replacing the parts as needed:

Then, you must also implement two simple delegate methods:

In the first method, you should first check if your plugin is already active. If it is active, you should deactivate your plugin and return. Otherwise, just activate your plugin. In addition, in the activator:recieveEvent: method, you must call [event setHandled:YES] if you wish to disable the default OS action for that activation event. If you do not set handled then receive event may be called twice for the same event. In the second method you should simply deactivate your plugin.

The implementation of these methods is left completely up to the programmer. The LAEvent objects can be used to discover more information about the event, such as the type, if you wish to perform a different action based on the type of event. Use the event's  dictionary to get extra information. Do not use that information to disable certain types of events for your plugin!

Method Two: New Object
The second method of implementing libactivator is to insert a new class in your code, one instance of which is always initialized, and informs your main classes when an activation event has occurred (so your main plugin can activate). A sample class is provided below with placeholder comments where additional code would be needed:

Default Activation Methods
To implement default activation methods, call  before registering your listener:

Allowing Activator Assignment from a Settings Pane
''Modern versions of Activator (1.1 and later) support assigning actions from the settings pane provided via Activator. This section provided for packages that wish to provide integration with their existing settings panes or apps.''

Simple Method
The simplest method to allow users to change activation methods is if you use PreferenceLoader and a simple plist format. Then, you can just paste in this code to create a cell that when tapped will allow users to select an activation method (again replacing the package id with the correct one):

If you are assigning a flipswitch, it will be:

Advanced Method
A more complex method is to integrate the settings pane directly into your application's navigation controller:

Sending Events (via LAEvent)
There are 2 steps to follow: dispatching event and providing metadata.

Dispatching Events
Custom events can be sent to assigned listeners by constructing an  object and passing it to the   method. Activator will take care of looking up which listeners are assigned and delivering the event to them.

Example event dispatch using the  method of

If the device is locked and one of the assigned listeners does not support receiving events at the lock screen, Activator will attempt to unlock the device. If a passcode is set, the user will be prompted to enter it.

Providing Event Metadata
Activator requires metadata on which events are possible to allow assignment through the settings pane.

The simplest way to provide event metadata is to create a subfolder in  with the name of your event, and describe it using an  :



Alternatively, event metadata can be setup by passing an object conforming to  to  's   method. This allows for adding and removing events based on runtime conditions.

Equivalent example, performed in code:

Registering s must be performed from within SpringBoard.

Packaging
Packages that provide Activator actions or events (especially if this is their primary purpose) should set up a dependency on the earliest version of Activator they support, as part of their package's control file:

Packages that work without Activator installed but still provide some level of Activator integration should conflict with older versions of Activator that they are untested with:

Runtime access to Activator
If you do not want to depend on libactivator being installed, you can use the following snippet as a starting line, to access Activator APIs: