mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: KMP Migration, Messaging Modularization, and Handshake Robustness (#4631)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
b3f88bd94f
commit
d408964f07
144 changed files with 1460 additions and 664 deletions
|
|
@ -17,6 +17,7 @@
|
|||
package org.meshtastic.core.common
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Application
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.IntentFilter
|
||||
|
|
@ -25,6 +26,11 @@ import android.location.LocationManager
|
|||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
/** Global accessor for Android Application. Must be initialized at app startup. */
|
||||
object ContextServices {
|
||||
lateinit var app: Application
|
||||
}
|
||||
|
||||
/** Checks if the device has a GPS receiver. */
|
||||
fun Context.hasGps(): Boolean {
|
||||
val lm = getSystemService(Context.LOCATION_SERVICE) as? LocationManager
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ package org.meshtastic.core.common.util
|
|||
import android.os.Build
|
||||
|
||||
/** Utility for checking build properties, such as emulator detection. */
|
||||
object BuildUtils {
|
||||
actual object BuildUtils {
|
||||
/** Whether the app is currently running on an emulator. */
|
||||
val isEmulator: Boolean
|
||||
actual val isEmulator: Boolean
|
||||
get() =
|
||||
Build.FINGERPRINT.startsWith("generic") ||
|
||||
Build.FINGERPRINT.startsWith("unknown") ||
|
||||
|
|
@ -32,4 +32,7 @@ object BuildUtils {
|
|||
Build.MODEL.contains("Android SDK built for") ||
|
||||
Build.MANUFACTURER.contains("Genymotion") ||
|
||||
Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")
|
||||
|
||||
actual val sdkInt: Int
|
||||
get() = Build.VERSION.SDK_INT
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
actual class CommonUri(private val uri: Uri) {
|
||||
actual val host: String?
|
||||
get() = uri.host
|
||||
|
||||
actual val fragment: String?
|
||||
get() = uri.fragment
|
||||
|
||||
actual val pathSegments: List<String>
|
||||
get() = uri.pathSegments
|
||||
|
||||
actual fun getQueryParameter(key: String): String? = uri.getQueryParameter(key)
|
||||
|
||||
actual fun getBooleanQueryParameter(key: String, defaultValue: Boolean): Boolean =
|
||||
uri.getBooleanQueryParameter(key, defaultValue)
|
||||
|
||||
actual override fun toString(): String = uri.toString()
|
||||
|
||||
actual companion object {
|
||||
actual fun parse(uriString: String): CommonUri = CommonUri(Uri.parse(uriString))
|
||||
}
|
||||
|
||||
fun toUri(): Uri = uri
|
||||
}
|
||||
|
||||
actual fun CommonUri.toPlatformUri(): Any = this.toUri()
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
import android.text.format.DateUtils
|
||||
import org.meshtastic.core.common.ContextServices
|
||||
import java.text.DateFormat
|
||||
|
||||
actual object DateFormatter {
|
||||
actual fun formatRelativeTime(timestampMillis: Long): String = DateUtils.getRelativeTimeSpanString(
|
||||
timestampMillis,
|
||||
nowMillis,
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE,
|
||||
)
|
||||
.toString()
|
||||
|
||||
actual fun formatDateTime(timestampMillis: Long): String = DateUtils.formatDateTime(
|
||||
ContextServices.app,
|
||||
timestampMillis,
|
||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_TIME or DateUtils.FORMAT_ABBREV_ALL,
|
||||
)
|
||||
|
||||
actual fun formatShortDate(timestampMillis: Long): String {
|
||||
val now = nowMillis
|
||||
val isWithin24Hours = (now - timestampMillis) <= DateUtils.DAY_IN_MILLIS
|
||||
|
||||
return if (isWithin24Hours) {
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT).format(timestampMillis)
|
||||
} else {
|
||||
DateFormat.getDateInstance(DateFormat.SHORT).format(timestampMillis)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,18 +19,6 @@ package org.meshtastic.core.common.util
|
|||
import android.os.RemoteException
|
||||
import co.touchlab.kermit.Logger
|
||||
|
||||
/**
|
||||
* Wraps and discards exceptions, but reports them to the crash reporter before logging. Use this for operations that
|
||||
* should not crash the process but are still unexpected.
|
||||
*/
|
||||
fun exceptionReporter(inner: () -> Unit) {
|
||||
try {
|
||||
inner()
|
||||
} catch (@Suppress("TooGenericExceptionCaught") ex: Exception) {
|
||||
Exceptions.report(ex, "exceptionReporter", "Uncaught Exception")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an operation and converts any thrown exceptions into [RemoteException] for safe return through an AIDL
|
||||
* interface.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
import android.icu.util.LocaleData
|
||||
import android.icu.util.ULocale
|
||||
import android.os.Build
|
||||
import java.util.Locale
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
actual fun getSystemMeasurementSystem(): MeasurementSystem {
|
||||
val locale = Locale.getDefault()
|
||||
|
||||
// Android 14+ (API 34) introduced user-settable locale preferences.
|
||||
if (Build.VERSION.SDK_INT >= 34) {
|
||||
try {
|
||||
val localePrefsClass = Class.forName("androidx.core.text.util.LocalePreferences")
|
||||
val getMeasurementSystemMethod =
|
||||
localePrefsClass.getMethod("getMeasurementSystem", Locale::class.java, Boolean::class.javaPrimitiveType)
|
||||
val result = getMeasurementSystemMethod.invoke(null, locale, true) as String
|
||||
return when (result) {
|
||||
"us",
|
||||
"uk",
|
||||
-> MeasurementSystem.IMPERIAL
|
||||
else -> MeasurementSystem.METRIC
|
||||
}
|
||||
} catch (@Suppress("TooGenericExceptionCaught") ignored: Exception) {
|
||||
// Fallback
|
||||
}
|
||||
}
|
||||
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
when (LocaleData.getMeasurementSystem(ULocale.forLocale(locale))) {
|
||||
LocaleData.MeasurementSystem.SI -> MeasurementSystem.METRIC
|
||||
else -> MeasurementSystem.IMPERIAL
|
||||
}
|
||||
} else {
|
||||
when (locale.country.uppercase(locale)) {
|
||||
"US",
|
||||
"LR",
|
||||
"MM",
|
||||
"GB",
|
||||
-> MeasurementSystem.IMPERIAL
|
||||
else -> MeasurementSystem.METRIC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
import android.net.InetAddresses
|
||||
import android.os.Build
|
||||
import android.util.Patterns
|
||||
|
||||
actual fun String?.isValidAddress(): Boolean = if (this.isNullOrBlank()) {
|
||||
false
|
||||
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
@Suppress("DEPRECATION")
|
||||
Patterns.IP_ADDRESS.matcher(this).matches() || Patterns.DOMAIN_NAME.matcher(this).matches()
|
||||
} else {
|
||||
InetAddresses.isNumericAddress(this) || Patterns.DOMAIN_NAME.matcher(this).matches()
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
import android.os.Parcelable
|
||||
|
||||
actual typealias CommonParcelable = Parcelable
|
||||
|
||||
actual typealias CommonParcelize = kotlinx.parcelize.Parcelize
|
||||
|
||||
actual typealias CommonIgnoredOnParcel = kotlinx.parcelize.IgnoredOnParcel
|
||||
|
||||
actual typealias CommonParceler<T> = kotlinx.parcelize.Parceler<T>
|
||||
|
||||
actual typealias CommonTypeParceler<T, P> = kotlinx.parcelize.TypeParceler<T, P>
|
||||
|
||||
actual typealias CommonParcel = android.os.Parcel
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
/** Utility for checking build properties, such as emulator detection. */
|
||||
expect object BuildUtils {
|
||||
/** Whether the app is currently running on an emulator. */
|
||||
val isEmulator: Boolean
|
||||
|
||||
/** The SDK version of the current platform. On non-Android platforms, this returns 0. */
|
||||
val sdkInt: Int
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
/** Platform-agnostic URI representation to decouple core logic from android.net.Uri. */
|
||||
expect class CommonUri {
|
||||
val host: String?
|
||||
val fragment: String?
|
||||
val pathSegments: List<String>
|
||||
|
||||
fun getQueryParameter(key: String): String?
|
||||
|
||||
fun getBooleanQueryParameter(key: String, defaultValue: Boolean): Boolean
|
||||
|
||||
override fun toString(): String
|
||||
|
||||
companion object {
|
||||
fun parse(uriString: String): CommonUri
|
||||
}
|
||||
}
|
||||
|
||||
/** Extension to convert platform Uri to CommonUri in Android source sets. */
|
||||
expect fun CommonUri.toPlatformUri(): Any
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
/** Platform-agnostic Date formatter utility. */
|
||||
expect object DateFormatter {
|
||||
/** Formats a timestamp into a relative "time ago" string. */
|
||||
fun formatRelativeTime(timestampMillis: Long): String
|
||||
|
||||
/** Formats a timestamp into a localized date and time string. */
|
||||
fun formatDateTime(timestampMillis: Long): String
|
||||
|
||||
/**
|
||||
* Formats a timestamp into a short date or time string.
|
||||
*
|
||||
* Typically shows time if within the last 24 hours, otherwise the date.
|
||||
*/
|
||||
fun formatShortDate(timestampMillis: Long): String
|
||||
}
|
||||
|
|
@ -46,3 +46,15 @@ fun ignoreException(silent: Boolean = false, inner: () -> Unit) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps and discards exceptions, but reports them to the crash reporter before logging. Use this for operations that
|
||||
* should not crash the process but are still unexpected.
|
||||
*/
|
||||
fun exceptionReporter(inner: () -> Unit) {
|
||||
try {
|
||||
inner()
|
||||
} catch (@Suppress("TooGenericExceptionCaught") ex: Exception) {
|
||||
Exceptions.report(ex, "exceptionReporter", "Uncaught Exception")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
@file:Suppress("MatchingDeclarationName")
|
||||
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.asin
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
object GPSFormat {
|
||||
fun toDec(latitude: Double, longitude: Double): String {
|
||||
// Simple decimal formatting for KMP
|
||||
fun Double.format(digits: Int): String {
|
||||
val multiplier = 10.0.pow(digits)
|
||||
val rounded = (this * multiplier).toLong() / multiplier
|
||||
return rounded.toString()
|
||||
}
|
||||
return "${latitude.format(5)}, ${longitude.format(5)}"
|
||||
}
|
||||
}
|
||||
|
||||
private const val EARTH_RADIUS_METERS = 6371e3
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun Double.toRadians(): Double = this * PI / 180.0
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun Double.toDegrees(): Double = this * 180.0 / PI
|
||||
|
||||
/** @return distance in meters along the surface of the earth (ish) */
|
||||
@Suppress("MagicNumber")
|
||||
fun latLongToMeter(latitudeA: Double, longitudeA: Double, latitudeB: Double, longitudeB: Double): Double {
|
||||
val lat1 = latitudeA.toRadians()
|
||||
val lon1 = longitudeA.toRadians()
|
||||
val lat2 = latitudeB.toRadians()
|
||||
val lon2 = longitudeB.toRadians()
|
||||
|
||||
val dLat = lat2 - lat1
|
||||
val dLon = lon2 - lon1
|
||||
|
||||
val a = sin(dLat / 2).pow(2) + cos(lat1) * cos(lat2) * sin(dLon / 2).pow(2)
|
||||
val c = 2 * asin(sqrt(a))
|
||||
|
||||
return EARTH_RADIUS_METERS * c
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the bearing in degrees between two points on Earth.
|
||||
*
|
||||
* @param lat1 Latitude of the first point
|
||||
* @param lon1 Longitude of the first point
|
||||
* @param lat2 Latitude of the second point
|
||||
* @param lon2 Longitude of the second point
|
||||
* @return Bearing between the two points in degrees. A value of 0 means due north.
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
fun bearing(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
|
||||
val lat1Rad = lat1.toRadians()
|
||||
val lon1Rad = lon1.toRadians()
|
||||
val lat2Rad = lat2.toRadians()
|
||||
val lon2Rad = lon2.toRadians()
|
||||
|
||||
val dLon = lon2Rad - lon1Rad
|
||||
|
||||
val y = sin(dLon) * cos(lat2Rad)
|
||||
val x = cos(lat1Rad) * sin(lat2Rad) - sin(lat1Rad) * cos(lat2Rad) * cos(dLon)
|
||||
val bearing = atan2(y, x).toDegrees()
|
||||
|
||||
return (bearing + 360) % 360
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
/** Represents the system's preferred measurement system. */
|
||||
enum class MeasurementSystem {
|
||||
METRIC,
|
||||
IMPERIAL,
|
||||
}
|
||||
|
||||
/** returns the system's preferred measurement system. */
|
||||
expect fun getSystemMeasurementSystem(): MeasurementSystem
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
/** Validates if the given string is a valid network address (IP or domain). */
|
||||
expect fun String?.isValidAddress(): Boolean
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2025-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/>.
|
||||
*/
|
||||
package org.meshtastic.core.common.util
|
||||
|
||||
/** Platform-agnostic Parcelable interface. */
|
||||
expect interface CommonParcelable
|
||||
|
||||
/** Platform-agnostic Parcelize annotation. */
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
expect annotation class CommonParcelize()
|
||||
|
||||
/** Platform-agnostic IgnoredOnParcel annotation. */
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
expect annotation class CommonIgnoredOnParcel()
|
||||
|
||||
/** Platform-agnostic Parceler interface. */
|
||||
expect interface CommonParceler<T> {
|
||||
fun create(parcel: CommonParcel): T
|
||||
|
||||
fun T.write(parcel: CommonParcel, flags: Int)
|
||||
}
|
||||
|
||||
/** Platform-agnostic TypeParceler annotation. */
|
||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@Repeatable
|
||||
expect annotation class CommonTypeParceler<T, P : CommonParceler<in T>>()
|
||||
|
||||
/** Platform-agnostic Parcel representation for manual parceling (e.g. AIDL support). */
|
||||
expect class CommonParcel {
|
||||
fun readString(): String?
|
||||
|
||||
fun readInt(): Int
|
||||
|
||||
fun readLong(): Long
|
||||
|
||||
fun readFloat(): Float
|
||||
|
||||
fun createByteArray(): ByteArray?
|
||||
|
||||
fun writeByteArray(b: ByteArray?)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue