mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Refactor: Create core:api module and set up publishing (#4362)
This commit is contained in:
parent
4e7de3b73c
commit
15760da074
23 changed files with 381 additions and 55 deletions
72
core/api/README.md
Normal file
72
core/api/README.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Meshtastic Android API
|
||||
|
||||
This module contains the stable AIDL interface and dependencies required to integrate with the Meshtastic Android app.
|
||||
|
||||
## Integration
|
||||
|
||||
To communicate with the Meshtastic Android service from your own application, we recommend using **JitPack**.
|
||||
|
||||
Add the JitPack repository to your root `build.gradle.kts` (or `settings.gradle.kts`):
|
||||
|
||||
```kotlin
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add the dependencies to your module's `build.gradle.kts`:
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
// Replace 'v2.7.12' with the specific version you need
|
||||
val meshtasticVersion = "v2.7.12"
|
||||
|
||||
// The core AIDL interface
|
||||
implementation("com.github.meshtastic.Meshtastic-Android:core-api:$meshtasticVersion")
|
||||
|
||||
// Data models (DataPacket, MeshUser, NodeInfo, etc.)
|
||||
implementation("com.github.meshtastic.Meshtastic-Android:core-model:$meshtasticVersion")
|
||||
|
||||
// Protobuf definitions (Portnums, Telemetry, etc.)
|
||||
implementation("com.github.meshtastic.Meshtastic-Android:core-proto:$meshtasticVersion")
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. **Bind to the Service:**
|
||||
Use the `IMeshService` interface to bind to the Meshtastic service.
|
||||
|
||||
```kotlin
|
||||
val intent = Intent("com.geeksville.mesh.Service")
|
||||
intent.setClassName("com.geeksville.mesh", "com.geeksville.mesh.service.MeshService")
|
||||
bindService(intent, serviceConnection, BIND_AUTO_CREATE)
|
||||
```
|
||||
|
||||
2. **Interact with the API:**
|
||||
Once bound, cast the `IBinder` to `IMeshService`:
|
||||
|
||||
```kotlin
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
val meshService = IMeshService.Stub.asInterface(service)
|
||||
|
||||
// Example: Send a text message
|
||||
val packet = DataPacket(
|
||||
to = DataPacket.ID_BROADCAST,
|
||||
bytes = "Hello Meshtastic!".toByteArray(),
|
||||
dataType = Portnums.PortNum.TEXT_MESSAGE_APP_VALUE,
|
||||
// ... other fields
|
||||
)
|
||||
meshService.send(packet)
|
||||
}
|
||||
```
|
||||
|
||||
## Modules
|
||||
|
||||
* **`core:api`**: Contains `IMeshService.aidl`.
|
||||
* **`core:model`**: Contains Parcelable data classes like `DataPacket`, `MeshUser`, `NodeInfo`.
|
||||
* **`core:proto`**: Contains the generated Protobuf code from `meshtastic/protobufs`.
|
||||
41
core/api/build.gradle.kts
Normal file
41
core/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
plugins {
|
||||
alias(libs.plugins.meshtastic.android.library)
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
apply(from = rootProject.file("gradle/publishing.gradle.kts"))
|
||||
|
||||
afterEvaluate {
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("release") {
|
||||
from(components["googleRelease"])
|
||||
artifactId = "core-api"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configure<com.android.build.api.dsl.LibraryExtension> {
|
||||
namespace = "org.meshtastic.core.api"
|
||||
buildFeatures { aidl = true }
|
||||
publishing { singleVariant("googleRelease") { withSourcesJar() } }
|
||||
}
|
||||
|
||||
dependencies { api(projects.core.model) }
|
||||
1
core/api/src/main/AndroidManifest.xml
Normal file
1
core/api/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
package org.meshtastic.core.service;
|
||||
|
||||
// Declare any non-default types here with import statements
|
||||
import org.meshtastic.core.model.DataPacket;
|
||||
import org.meshtastic.core.model.NodeInfo;
|
||||
import org.meshtastic.core.model.MeshUser;
|
||||
import org.meshtastic.core.model.Position;
|
||||
import org.meshtastic.core.model.MyNodeInfo;
|
||||
|
||||
/**
|
||||
This is the public android API for talking to meshtastic radios.
|
||||
|
||||
To connect to meshtastic you should bind to it per https://developer.android.com/guide/components/bound-services
|
||||
|
||||
The intent you use to reach the service should look like this:
|
||||
|
||||
val intent = Intent().apply {
|
||||
setClassName(
|
||||
"com.geeksville.mesh",
|
||||
"com.geeksville.mesh.service.MeshService"
|
||||
)
|
||||
}
|
||||
|
||||
In Android 11+ you *may* need to add the following to the client app's manifest to allow binding of the mesh service:
|
||||
<queries>
|
||||
<package android:name="com.geeksville.mesh" />
|
||||
</queries>
|
||||
For additional information, see https://developer.android.com/guide/topics/manifest/queries-element
|
||||
|
||||
|
||||
Once you have bound to the service you should register your broadcast receivers per https://developer.android.com/guide/components/broadcasts#context-registered-receivers
|
||||
|
||||
// com.geeksville.mesh.x broadcast intents, where x is:
|
||||
|
||||
// RECEIVED.<portnumm> - will **only** deliver packets for the specified port number. If a wellknown portnums.proto name for portnum is known it will be used
|
||||
// (i.e. com.geeksville.mesh.RECEIVED.TEXT_MESSAGE_APP) else the numeric portnum will be included as a base 10 integer (com.geeksville.mesh.RECEIVED.4403 etc...)
|
||||
|
||||
// NODE_CHANGE for new IDs appearing or disappearing
|
||||
// CONNECTION_CHANGED for losing/gaining connection to the packet radio
|
||||
// MESSAGE_STATUS_CHANGED for any message status changes (for sent messages only, payload will contain a message ID and a MessageStatus)
|
||||
|
||||
Note - these calls might throw RemoteException to indicate mesh error states
|
||||
*/
|
||||
interface IMeshService {
|
||||
/// Tell the service where to send its broadcasts of received packets
|
||||
/// This call is only required for manifest declared receivers. If your receiver is context-registered
|
||||
/// you don't need this.
|
||||
void subscribeReceiver(String packageName, String receiverName);
|
||||
|
||||
/**
|
||||
* Set the user info for this node
|
||||
*/
|
||||
void setOwner(in MeshUser user);
|
||||
|
||||
void setRemoteOwner(in int requestId, in int destNum, in byte []payload);
|
||||
void getRemoteOwner(in int requestId, in int destNum);
|
||||
|
||||
/// Return my unique user ID string
|
||||
String getMyId();
|
||||
|
||||
/// Return a unique packet ID
|
||||
int getPacketId();
|
||||
|
||||
/*
|
||||
Send a packet to a specified node name
|
||||
|
||||
typ is defined in mesh.proto Data.Type. For now juse use 0 to mean opaque bytes.
|
||||
|
||||
destId can be null to indicate "broadcast message"
|
||||
|
||||
messageStatus and id of the provided message will be updated by this routine to indicate
|
||||
message send status and the ID that can be used to locate the message in the future
|
||||
*/
|
||||
void send(inout DataPacket packet);
|
||||
|
||||
/**
|
||||
Get the IDs of everyone on the mesh. You should also subscribe for NODE_CHANGE broadcasts.
|
||||
*/
|
||||
List<NodeInfo> getNodes();
|
||||
|
||||
/// This method is only intended for use in our GUI, so the user can set radio options
|
||||
/// It returns a DeviceConfig protobuf.
|
||||
byte []getConfig();
|
||||
/// It sets a Config protobuf via admin packet
|
||||
void setConfig(in byte []payload);
|
||||
|
||||
/// Set and get a Config protobuf via admin packet
|
||||
void setRemoteConfig(in int requestId, in int destNum, in byte []payload);
|
||||
void getRemoteConfig(in int requestId, in int destNum, in int configTypeValue);
|
||||
|
||||
/// Set and get a ModuleConfig protobuf via admin packet
|
||||
void setModuleConfig(in int requestId, in int destNum, in byte []payload);
|
||||
void getModuleConfig(in int requestId, in int destNum, in int moduleConfigTypeValue);
|
||||
|
||||
/// Set and get the Ext Notification Ringtone string via admin packet
|
||||
void setRingtone(in int destNum, in String ringtone);
|
||||
void getRingtone(in int requestId, in int destNum);
|
||||
|
||||
/// Set and get the Canned Message Messages string via admin packet
|
||||
void setCannedMessages(in int destNum, in String messages);
|
||||
void getCannedMessages(in int requestId, in int destNum);
|
||||
|
||||
/// This method is only intended for use in our GUI, so the user can set radio options
|
||||
/// It sets a Channel protobuf via admin packet
|
||||
void setChannel(in byte []payload);
|
||||
|
||||
/// Set and get a Channel protobuf via admin packet
|
||||
void setRemoteChannel(in int requestId, in int destNum, in byte []payload);
|
||||
void getRemoteChannel(in int requestId, in int destNum, in int channelIndex);
|
||||
|
||||
/// Send beginEditSettings admin packet to nodeNum
|
||||
void beginEditSettings(in int destNum);
|
||||
|
||||
/// Send commitEditSettings admin packet to nodeNum
|
||||
void commitEditSettings(in int destNum);
|
||||
|
||||
/// delete a specific nodeNum from nodeDB
|
||||
void removeByNodenum(in int requestID, in int nodeNum);
|
||||
|
||||
/// Send position packet with wantResponse to nodeNum
|
||||
void requestPosition(in int destNum, in Position position);
|
||||
|
||||
/// Send setFixedPosition admin packet (or removeFixedPosition if Position is empty)
|
||||
void setFixedPosition(in int destNum, in Position position);
|
||||
|
||||
/// Send traceroute packet with wantResponse to nodeNum
|
||||
void requestTraceroute(in int requestId, in int destNum);
|
||||
|
||||
/// Send neighbor info packet with wantResponse to nodeNum
|
||||
void requestNeighborInfo(in int requestId, in int destNum);
|
||||
|
||||
/// Send Shutdown admin packet to nodeNum
|
||||
void requestShutdown(in int requestId, in int destNum);
|
||||
|
||||
/// Send Reboot admin packet to nodeNum
|
||||
void requestReboot(in int requestId, in int destNum);
|
||||
|
||||
/// Send FactoryReset admin packet to nodeNum
|
||||
void requestFactoryReset(in int requestId, in int destNum);
|
||||
|
||||
/// Send reboot to DFU admin packet
|
||||
void rebootToDfu(in int destNum);
|
||||
|
||||
/// Send NodedbReset admin packet to nodeNum
|
||||
void requestNodedbReset(in int requestId, in int destNum, in boolean preserveFavorites);
|
||||
|
||||
/// Returns a ChannelSet protobuf
|
||||
byte []getChannelSet();
|
||||
|
||||
/**
|
||||
Is the packet radio currently connected to the phone? Returns a ConnectionState string.
|
||||
*/
|
||||
String connectionState();
|
||||
|
||||
/// If a macaddress we will try to talk to our device, if null we will be idle.
|
||||
/// Any current connection will be dropped (even if the device address is the same) before reconnecting.
|
||||
/// Users should not call this directly, only used internally by the MeshUtil activity
|
||||
/// Returns true if the device address actually changed, or false if no change was needed
|
||||
boolean setDeviceAddress(String deviceAddr);
|
||||
|
||||
/// Get basic device hardware info about our connected radio. Will never return NULL. Will return NULL
|
||||
/// if no my node info is available (i.e. it will not throw an exception)
|
||||
MyNodeInfo getMyNodeInfo();
|
||||
|
||||
/// Start updating the radios firmware
|
||||
void startFirmwareUpdate();
|
||||
|
||||
/// Return a number 0-100 for firmware update progress. -1 for completed and success, -2 for failure
|
||||
int getUpdateStatus();
|
||||
|
||||
/// Start providing location (from phone GPS) to mesh
|
||||
void startProvideLocation();
|
||||
|
||||
/// Stop providing location (from phone GPS) to mesh
|
||||
void stopProvideLocation();
|
||||
|
||||
/// Send request for node UserInfo
|
||||
void requestUserInfo(in int destNum);
|
||||
|
||||
/// Request device connection status from the radio
|
||||
void getDeviceConnectionStatus(in int requestId, in int destNum);
|
||||
|
||||
/// Send request for telemetry to nodeNum
|
||||
void requestTelemetry(in int requestId, in int destNum, in int type);
|
||||
|
||||
/**
|
||||
* Tell the node to reboot into OTA mode for firmware update via BLE or WiFi (ESP32 only)
|
||||
* mode is 1 for BLE, 2 for WiFi
|
||||
* hash is the 32-byte firmware SHA256 hash (optional, can be null)
|
||||
*/
|
||||
void requestRebootOta(in int requestId, in int destNum, in int mode, in byte []hash);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue