The Glyph Matrix Developer Kit provides everything you need to know before creating a custom Glyph Matrix experience in your app or building your own Glyph Toy on compatible devices.
At its core is the Glyph Matrix Android library that can convert your designs into Glyph Matrix Data and rendering it frame by frame on the Glyph Matrix. It also provides you with identifiers so you can handle events relevant to Glyph Button.
This documentation contains the following three sections
- Getting Started: How to integrate the Glyph Matrix Android Library, configure your development environment and create preview images for your Glyph Toys.
- Developing a Glyph Toy Service: How to manage the service life cycle for Glyph Toy, handle interaction, and behavior of toy service if it has AOD capability.
- API Reference: Complete documentation of classes, methods.
Note that while the sample code in this README is written in Java, we also provide a complete demo project for learning building Glyph Toys that you can reference in GlyphMatrix-Example-Project
- After creating a new Android project, create a libs folder under your main app module.
- Copy the Android library e.g. GlyphMatrixSDK.aar file from this repository into the libs directory.
- Add the library as a library dependency in your build.gradle file. If you're using Android Studio, you can also refer to the "Add your AAR or JAR as a dependency" section on developer.android.com to learn how to do it, make sure the path you use is something like "libs/GlyphMatrixSDK.aar"
You can find the AndroidManifest.xml file at the following path <your-project>/app/src/main/AndroidManifest.xml
Add the following line within the <manifest> tag in AndroidManifest.xml
<uses-permission android:name="com.nothing.ketchum.permission.ENABLE"/>Note: This section is only required if you're developing Glyph Toys. If you're only integrating the Glyph Matrix Library into your existing application, you can skip this section.
To ensure your Nothing Phone setting recognises and can display your Glyph Toys, you'll need to register each toy as a service within the <application> tag of your AndroidManifest.xml file.
The following code demonstrates how to register two toys. Each service includes metadata for the toy's name, preview image, and supported behaviour(optional).
To prepare a preview image, please refer to Section 3: Create your Glyph Toy preview.
The first example provides a complete setup with optional features, while the second shows a minimal configuration.
Note: Replace the class names, and resource references in the examples below with your own before using.
<!-- Full Example: Registers a Glyph toy with complete metadata for enhanced functionality -->
<!-- Replace "com.nothing.demo.TestToyOne" with your service class -->
<service android:name="com.nothing.demo.TestToyOne"
android:exported="true">
<intent-filter>
<action android:name="com.nothing.glyph.TOY"/>
</intent-filter>
<!-- Required: Ensures the toy appears in the Glyph Toys manager list -->
<meta-data
android:name="com.nothing.glyph.toy.name"
android:resource="@string/toy_name_one"/> <!-- Replace with your string resource -->
<!-- Required: Allows users to preview your toy in the settings -->
<meta-data
android:name="com.nothing.glyph.toy.image"
android:resource="@drawable/img_toy_preview_one"/> <!-- Replace with your image resource -->
<!-- Optional: Provides a brief description of your toy -->
<meta-data
android:name="com.nothing.glyph.toy.summary"
android:resource="@string/toy_summary" /> <!-- Replace with your string resource -->
<!-- Optional: Links to a detailed introduction page for your toy -->
<meta-data
android:name="com.nothing.glyph.toy.introduction"
android:value="com.yourPackage.yourToyIntroduceActivity" /> <!-- Replace with your activity class -->
<!-- Optional: Enables long press functionality, default is 0 -->
<meta-data
android:name="com.nothing.glyph.toy.longpress"
android:value="1"/>
<!-- Optional: Indicates support for Always-On Display (AOD) -->
<meta-data
android:name="com.nothing.glyph.toy.aod_support"
android:value="1"/>
</service>
<!-- Minimum Example: Registers a basic Glyph toy with essential metadata -->
<service android:name="com.nothing.demo.TestToySecond"
android:exported="true">
<intent-filter>
<action android:name="com.nothing.glyph.TOY"/>
</intent-filter>
<!-- Required: Ensures the toy appears in the Glyph Toys manager list -->
<meta-data
android:name="com.nothing.glyph.toy.name"
android:resource="@string/toy_name_second"/>
<!-- Required: Allows users to preview your toy in the settings -->
<meta-data
android:name="com.nothing.glyph.toy.image"
android:resource="@drawable/img_toy_preview_second"/>
</service>To create a Glyph Toy preview image that matches the official toy and provides your users with a consistent experience, you can reference the specifications below and the Figma template. We have also created a Figma plugin that can automatically convert any 1:1 design image into a Glyph Matrix Preview image to save you some time :)
We recommend exporting your preview image as an SVG and to learn how to import your SVG preview into your project, check Running Vector Asset Studio section in the Android studio documentation.
Glyph Toys are commonly controlled using Glyph Button on the back of the device. There are mainly three types of interaction with Glyph Button:
- Short press: A quick press on
Glyph Buttoncycles through available toys. When your toy is selected and shown on theGlyph Matrix, its functions start. Tapping again navigates to the next toy. - Long press: A long press on
Glyph Buttonsends a"change"event to the currently selected toy, triggering an action you defined. For example, in the preinstalled camera toy, the first long press activates the camera and subsequent presses capture photos. For the timer toy, it toggles start/stop. (This feature must be enabled inAndroidManifest.xml). - Touch-down & Touch-up: If the user keeps the
Glyph Buttonheld down & released, it will trigger"action_down"&"action_up"events
Additionally, toys can also utilize other control inputs such as the device's gyroscope and accelerometer, to create more engaging experiences like the Magic 8 Ball & Leveler Toy we co-created with community members. Please note that only one toy can be activated at a time.
When a user selects your toy, the system binds your Service. You must implement onBind() to start its functions and onUnbind() to stop them cleanly.
The following example shows how to manage the start/stop lifecycle.
@Override
public IBinder onBind(Intent intent) {
init();// Experience that you want to create when Glyph Toy is selected
return null;
}
@Override
public boolean onUnbind(Intent intent) {
mGM.unInit();
mGM = null;
mCallback = null;
return false;
}Glyph Button relevant event is handled using GlyphToy class. To react with user's interaction to the Glyph Button, you must create a Handler to process the event and a Messenger to communicate with the system. The IBinder from this Messenger must be returned by your onBind() method.
The code below shows how to receive and handle the event, in this case the long press (change) event.
@Override
public IBinder onBind(Intent intent) {
init();
return serviceMessenger.getBinder();
}
private final Handler serviceHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case GlyphToy.MSG_GLYPH_TOY: {
Bundle bundle = msg.getData();
String event = bundle.getString(GlyphToy.MSG_GLYPH_TOY_DATA);
if (GlyphToy.EVENT_CHANGE.equals(event)) {
// Your reaction for the long press.
}
break;
}
default:
super.handleMessage(msg);
}
}
};
private final Messenger serviceMessenger = new Messenger(serviceHandler);If you have set your toy as an AOD toy, your toy will receive EVENT_AOD every minute when your toy has been selected as aod toy.
private final Handler serviceHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case GlyphToy.MSG_GLYPH_TOY: {
Bundle bundle = msg.getData();
String event = bundle.getString(GlyphToy.MSG_GLYPH_TOY_DATA);
if (GlyphToy.EVENT_AOD.equals(event)) {
// Your action for aod
}
break;
}
default:
super.handleMessage(msg);
}
}
};We highly recommend using the intent action provided below when your Glyph Toy application is ready for distribution. It is valid for system version on 20250829 or later.
This intent directs users to the system's Manage Glyph Toys screen, allowing them to add your toy to their active toy queue. Without this guidance, users can become confused about how to activate the toy after installing your application.
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.nothing.thirdparty", "com.nothing.thirdparty.matrix.toys.manager.ToysManagerActivity"));
startActivity(intent);Here are two common implementation scenarios:
-
For simple toys: Your application interface can feature a basic introduction to the toy with a button, such as "Activate toy," which triggers the intent.
-
For toys requiring setup: It is best to present the button that triggers this intent at the end of the configuration process. This guides the user to activate the toy immediately after they have finished setting it up. For instance, a toy designed to show a YouTube channel's subscriber count would first require the user to select the channel as part of the setup before it can work properly.
GlyphMatrixManager is responsible for:
- Connecting to and disconnecting from an underlying service or device.
- Registering your application to use that service/device.
- Updating the display of a Glyph Matrix with either raw color data or structured frame objects.
In addition to displaying content on the Glyph Matrix through the Glyph Toy service, you can directly control Glyph Matrix from your own app using GDK. For app-based control, always use the setAppMatrixFrame function instead of setMatrixFrame, as the latter may conflict with active Glyph Toys. This feature requires the phone system version on 20250801 or later.
Note: The Glyph Toy has a higher display priority than third party app usage on Glyph Matrix. If the user interacts with the Glyph Button, the Glyph Toy carousel it triggers will override your app’s content on the Matrix.
| Return type | Method | Description |
|---|---|---|
| void | init(Callback callback) |
Used for binding the Service. It is recommended to be created when components start. |
| void | unInit() |
Used for unbinding the Service. It is recommended to be destroyed when components end. |
| void | closeAppMatrix() |
Closes the app matrix display. Use this function to stop displaying content on the Glyph Matrix from your app. Required phone system version on 20250801 or later. |
| void | register(String target) |
Register your app for service. You need to send which target device you are working on. For Phone 3, this should be Glyph.DEVICE_23112 |
| void | setMatrixFrame(int[] color) |
Updates the Glyph Matrix display using raw color data. This overload expects a 25x25 integer array. |
| void | setMatrixFrame(GlyphMatrixFrame) |
Updates the Glyph Matrix display using a structured GlyphMatrixFrame object. |
| void | setAppMatrixFrame(int[] color) |
Same as setMatrixFrame(int[] color). If you want to use Glyph Matrix in your app. Please use this function to update Glyph Matrix display. Required phone system version on 20250801 or later. |
| void | setAppMatrixFrame(GlyphMatrixFrame frame) |
Same as setMatrixFrame(GlyphMatrixFrame frame). If you want to use Glyph Matrix in your app. Please use this function to update Glyph Matrix display. phone system version on 20250801 or later. |
GlyphMatrixFrame is in charge of handling and displaying the Glyph Matrix. Its default size is 25x25, but you can easily customise it using the Builder.
Developers can use this class to render GlyphMatrix objects into the necessary Matrix data and control how multiple objects can be overlaid on the Glyph Matrix based on the layer they are in using the builder.
| Return type | Method name | Description |
|---|---|---|
| int[] | render() |
Renders all objects previously added via the Builder and integrates them into the corresponding Glyph Matrix data. The implementation of this method may vary depending on project requirements. This method can either directly drive hardware to display on an actual Glyph Matrix, or return an array or bitmap data to the caller for further processing. |
GlyphMatrixFrame.Builder is a static inner class that uses the Builder pattern to help you construct and configure a GlyphMatrixFrame. This frame is essentially an array of data that defines how each LED on the matrix should light up, and it can be read by the GlyphMatrixManager.
You can have maximum 3 GlyphMatrixObject for each GlyphMatrixFrame,1 for each layer before you finally call build() to generate your finished GlyphMatrixFrame instance.
| Return type | Method name | Description |
|---|---|---|
| N/A | Builder() |
Initializes a new Builder instance. This creates an empty GlyphMatrixFrame.Builder ready for configuration. By default, the Matrix size is set to 25x25. |
| Return type | Method | Description |
|---|---|---|
| void | addTop(GlyphMatrixObject object) |
Adds object to top layer, rendered above middle and low layers |
| void | addMid(GlyphMatrixObject object) |
Adds object to middle layer, rendered between top and low layers |
| void | addLow(GlyphMatrixObject object) |
Adds object to bottom layer, rendered below top and middle layers |
| GlyphMatrixFrame | build(Context context) |
Constructs and returns a new GlyphMatrixFrame instance based on the currently accumulated settings. This instance is ready for display or further manipulation. |
The following example shows how to create a GlyphMatrixFrame with a butterfly object on the top layer, and then render it to the actual Glyph Matrix using mGM (GlyphMatrixManager), the class mentioned above that manages the actual matrix.
GlyphMatrixFrame.Builder frameBuilder = new GlyphMatrixFrame.Builder();
GlyphMatrixFrame frame = frameBuilder.addTop(butterfly).build();
mGM.setMatrixFrame(frame.render());The GlyphMatrixObject encapsulates a single image or frame for display on the Glyph Matrix, along with its configurable properties.
These properties, such as image source, position coordinates (X, Y), clockwise rotation angle, scaling, brightness, and transparency, can all be adjusted using the GlyphMatrixObject.Builder.
| Return type | Method name | Description |
|---|---|---|
| Object | getImageSource() |
Returns the image source object |
| Int | getPositionX() |
Returns the X-coordinate of the object's top-left corner. |
| Int | getPositionY() |
Returns the Y-coordinate of the object's top-left corner. |
| Int | getOrientation() |
Returns the counterclockwise rotation angle of the object from the original (default: 0) |
| Int | getScale() |
Returns the scaling factor of the object. (0-200, default: 100) |
| Int | getBrightness() |
Returns the brightness level of the object. (0-255, default: 255) |
GlyphMatrixObject.Builder is a static inner class of GlyphMatrixObject, used to create and configure an image object's display parameters.
| Return type | Method name | Description |
|---|---|---|
| N/A | Builder() |
If not explicitly set by other methods, the Builder will use the following default values for the GlyphMatrixObject:- Position: (0, 0) - Orientation: 0 degrees - Scale: 100 - Brightness: 255 |
| Return type | Method name | Description |
|---|---|---|
| void | setImageSource(Object imagesource) |
Sets the image source. Must be a 1:1 bitmap - other formats require conversion. Higher resolutions may impact performance. |
| void | setText(String text) |
Sets the string content to be displayed in the Glyph Matrix. |
| void | setPosition(int x, int y) |
Sets the object's top-left corner position on the Glyph Matrix |
| void | setOrientation(int) |
Sets the object's clockwise rotation angle in degrees, anchored at center. 0 = no rotation (default). Values normalized to 0-360° range |
| void | setBrightness(int brightness) |
Sets the brightness level for the object. Acceptable values range from 0 (LED off) to 255 (maximum brightness, default). Any value above 255 will be automatically capped at 255. |
| void | setScale(int scale) |
Sets the scaling factor for the object. The anchor point is in the middle of the object Valid range: 0-200 0: Object is not visible 100: Original size (default) 200: Double size |
| GlyphMatrixObject | build() |
Constructs and returns a GlyphMatrix Object instance based on the current settings. |
The following example shows how to construct a GlyphMatrixObject called butterfly.
GlyphMatrixObject.Builder butterflyBuilder = new GlyphMatrixObject.Builder();
GlyphMatrixObject butterfly = butterflyBuilder
.setImageSource(GlyphMatrixUtils.drawableToBitmap(getResources().getDrawable(R.drawable.butterfly)))
.setScale(100)
.setOrientation(0)
.setPosition(0, 0)
.setReverse(false)
.build();The following code block shows a full implementation of a Glyph Toy Service in Java. It demonstrate how to initialize the GlyphMatrixManager, register a device, and display a custom GlyphMatrixObject (for example, a butterfly image) on the Glyph Matrix.
@Override
public IBinder onBind(Intent intent) {
init();
return null;
}
@Override
public boolean onUnbind(Intent intent) {
mGM.turnOff();
mGM.unInit();
mGM = null;
mCallback = null;
return false;
}
private void init() {
mGM = GlyphMatrixManager.getInstance(getApplicationContext());
mCallback = new GlyphMatrixManager.Callback() {
@Override
public void onServiceConnected(ComponentName componentName) {
mGM.register(Glyph.DEVICE_23112);
action();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
mGM.init(mCallback);
}
private void action() {
GlyphMatrixObject.Builder butterflyBuilder = new GlyphMatrixObject.Builder();
GlyphMatrixObject butterfly = butterflyBuilder
.setImageSource(GlyphMatrixUtils.drawableToBitmap(getResources().getDrawable(R.drawable.butterfly)))
.setScale(100)
.setOrientation(0)
.setPosition(0, 0)
.setReverse(false)
.build();
GlyphMatrixFrame.Builder frameBuilder = new GlyphMatrixFrame.Builder();
GlyphMatrixFrame frame = frameBuilder.addTop(butterfly).build();
mGM.setMatrixFrame(frame.render());
}For a practical demo project on building Glyph Toys, see the GlyphMatrix-Example-Project
Kits for building a Glyph Interface experience around devices with a Glyph Light Stripe Glyph-Developer-Kit
If you've found an error in this kit, please file an issue.
If there is any problem related to development,you can contact: GDKsupport@nothing.tech
However, you may get a faster response from our community