feat(example): Add packet log and UI improvements (#4455)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-02-05 07:24:15 -06:00 committed by GitHub
parent c44d2f3268
commit f1520eb383
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 258 additions and 97 deletions

View file

@ -24,8 +24,8 @@ 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"
// Replace 'v2.7.13' with the specific version you need
val meshtasticVersion = "v2.7.13"
// The core AIDL interface
implementation("com.github.meshtastic.Meshtastic-Android:core-api:$meshtasticVersion")
@ -33,42 +33,70 @@ dependencies {
// Data models (DataPacket, MeshUser, NodeInfo, etc.)
implementation("com.github.meshtastic.Meshtastic-Android:core-model:$meshtasticVersion")
// Protobuf definitions (Portnums, Telemetry, etc.)
// Protobuf definitions (PortNum, 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.
### 1. Bind to the 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)
```
Use the `IMeshService` interface to bind to the Meshtastic service. It is recommended to query the package manager to find the correct service component, as the package name may vary between build flavors (e.g., Play Store vs. F-Droid).
2. **Interact with the API:**
Once bound, cast the `IBinder` to `IMeshService`:
```kotlin
val intent = Intent("com.geeksville.mesh.Service")
val resolveInfo = packageManager.queryIntentServices(intent, 0)
```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)
}
```
if (resolveInfo.isNotEmpty()) {
val serviceInfo = resolveInfo[0].serviceInfo
intent.setClassName(serviceInfo.packageName, serviceInfo.name)
bindService(intent, serviceConnection, Context.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 broadcast text message
val packet = DataPacket(
to = DataPacket.ID_BROADCAST,
bytes = "Hello Meshtastic!".encodeToByteArray().toByteString(),
dataType = PortNum.TEXT_MESSAGE_APP.value,
id = meshService.packetId,
wantAck = true
)
meshService.send(packet)
}
```
### 3. Register a BroadcastReceiver
To receive packets and status updates, register a `BroadcastReceiver`.
**Important:** On Android 13+ (API 33), you **must** use `RECEIVER_EXPORTED` since you are receiving broadcasts from a different application.
```kotlin
val intentFilter = IntentFilter().apply {
addAction("com.geeksville.mesh.RECEIVED.TEXT_MESSAGE_APP")
addAction("com.geeksville.mesh.NODE_CHANGE")
addAction("com.geeksville.mesh.CONNECTION_CHANGED")
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(meshtasticReceiver, intentFilter, Context.RECEIVER_EXPORTED)
} else {
registerReceiver(meshtasticReceiver, intentFilter)
}
```
## 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`.
* **`core:proto`**: Contains the generated Protobuf code (Wire).