ilabs-flir 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/Flir/build.gradle.kts +14 -27
- package/android/Flir/libs/androidsdk-release.aar +0 -0
- package/android/Flir/libs/thermalsdk-release.aar +0 -0
- package/android/Flir/src/main/java/flir/android/FlirDownloadManager.kt +23 -44
- package/android/Flir/src/main/java/flir/android/FlirModule.kt +32 -0
- package/android/Flir/src/main/java/flir/android/FlirSDKLoader.kt +35 -194
- package/android/Flir/src/main/java/flir/android/FlirSdkManager.java +410 -1161
- package/package.json +1 -1
- package/src/index.d.ts +21 -1
- package/android/Flir/libs/flir-stubs.jar +0 -0
- package/android/Flir/src/main/java/com/flir/thermalsdk/ErrorCode.java +0 -13
- package/android/Flir/src/main/java/com/flir/thermalsdk/ErrorCodeException.java +0 -14
- package/android/Flir/src/main/java/com/flir/thermalsdk/ThermalSdkAndroid.java +0 -16
- package/android/Flir/src/main/java/com/flir/thermalsdk/androidsdk/image/BitmapAndroid.java +0 -20
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/ImageBuffer.java +0 -11
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/JavaImageBuffer.java +0 -35
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/Palette.java +0 -15
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/PaletteManager.java +0 -16
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/Point.java +0 -11
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/ThermalImage.java +0 -23
- package/android/Flir/src/main/java/com/flir/thermalsdk/image/ThermalValue.java +0 -9
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/Camera.java +0 -26
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/CameraType.java +0 -8
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/CommunicationInterface.java +0 -16
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/ConnectParameters.java +0 -16
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/Identity.java +0 -23
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/IpSettings.java +0 -9
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/RemoteControl.java +0 -16
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/connectivity/ConnectionStatusListener.java +0 -7
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/discovery/DiscoveryEventListener.java +0 -14
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/discovery/DiscoveryFactory.java +0 -33
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/remote/OnReceived.java +0 -5
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/remote/OnRemoteError.java +0 -7
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/streaming/Stream.java +0 -8
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/streaming/ThermalStreamer.java +0 -28
- package/android/Flir/src/main/java/com/flir/thermalsdk/live/streaming/VisualStreamer.java +0 -18
|
@@ -14,21 +14,20 @@ android {
|
|
|
14
14
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
sourceCompatibility = JavaVersion.
|
|
19
|
-
targetCompatibility = JavaVersion.
|
|
17
|
+
compileOptions {
|
|
18
|
+
sourceCompatibility = JavaVersion.VERSION_21
|
|
19
|
+
targetCompatibility = JavaVersion.VERSION_21
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
kotlinOptions {
|
|
23
|
-
jvmTarget =
|
|
23
|
+
jvmTarget = JavaVersion.VERSION_21.toString()
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
languageVersion.set(JavaLanguageVersion.of(21))
|
|
29
|
-
}
|
|
25
|
+
|
|
26
|
+
buildFeatures {
|
|
27
|
+
viewBinding = true
|
|
30
28
|
}
|
|
31
29
|
|
|
30
|
+
|
|
32
31
|
publishing {
|
|
33
32
|
singleVariant("release") {
|
|
34
33
|
withJavadocJar()
|
|
@@ -37,35 +36,23 @@ android {
|
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
repositories {
|
|
41
|
-
google()
|
|
42
|
-
mavenCentral()
|
|
43
|
-
// Resolve local AARs which will be installed into mavenLocal by CI (JitPack)
|
|
44
|
-
mavenLocal()
|
|
45
|
-
flatDir { dirs("libs") }
|
|
46
|
-
}
|
|
47
|
-
|
|
48
39
|
dependencies {
|
|
49
40
|
// React Native
|
|
50
41
|
implementation("com.facebook.react:react-native:+")
|
|
51
42
|
|
|
52
|
-
// Kotlin coroutines
|
|
43
|
+
// Kotlin coroutines
|
|
53
44
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
|
54
45
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// The actual SDK AARs are downloaded on-demand at runtime via FlirDownload.download()
|
|
61
|
-
compileOnly(files("libs/flir-stubs.jar"))
|
|
46
|
+
// FLIR SDK - Use the actual AAR files from libs folder
|
|
47
|
+
// Using 'api' to expose SDK classes to consumers and Java source files
|
|
48
|
+
// flatDir must be configured in settings.gradle or root build.gradle
|
|
49
|
+
api(files("libs/androidsdk-release.aar"))
|
|
50
|
+
api(files("libs/thermalsdk-release.aar"))
|
|
62
51
|
|
|
63
52
|
// Minimal compile deps to satisfy source references
|
|
64
53
|
implementation("androidx.annotation:annotation:1.5.0")
|
|
65
54
|
|
|
66
|
-
|
|
67
55
|
// Prevent duplicate SLF4J classes when a consumer also brings `org.slf4j:slf4j-api`
|
|
68
|
-
// The vendor AAR may embed slf4j classes; exclude the API from being pulled transitively
|
|
69
56
|
configurations.all {
|
|
70
57
|
exclude(group = "org.slf4j", module = "slf4j-api")
|
|
71
58
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
package flir.android
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.bridge.*
|
|
4
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
5
|
-
import kotlinx.coroutines.*
|
|
6
4
|
|
|
5
|
+
/**
|
|
6
|
+
* FlirDownloadManager - React Native module for SDK status
|
|
7
|
+
*
|
|
8
|
+
* Since the SDK is now bundled in the AAR, this module just reports
|
|
9
|
+
* that the SDK is always available.
|
|
10
|
+
*/
|
|
7
11
|
class FlirDownloadManager(private val reactContext: ReactApplicationContext) :
|
|
8
12
|
ReactContextBaseJavaModule(reactContext) {
|
|
9
13
|
|
|
10
|
-
private var downloadJob: Job? = null
|
|
11
|
-
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
|
12
|
-
|
|
13
14
|
override fun getName() = "FlirDownloadManager"
|
|
14
15
|
|
|
15
16
|
@ReactMethod
|
|
16
17
|
fun isFlirAvailable(promise: Promise) {
|
|
17
|
-
|
|
18
|
+
// SDK is bundled - always available
|
|
19
|
+
promise.resolve(true)
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
@ReactMethod
|
|
21
23
|
fun getDownloadSize(promise: Promise) {
|
|
22
|
-
|
|
24
|
+
// No download needed
|
|
25
|
+
promise.resolve(0.0)
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
@ReactMethod
|
|
@@ -29,48 +32,24 @@ class FlirDownloadManager(private val reactContext: ReactApplicationContext) :
|
|
|
29
32
|
|
|
30
33
|
@ReactMethod
|
|
31
34
|
fun downloadFlirSDK(promise: Promise) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
sendEvent("FlirDownloadProgress", Arguments.createMap().apply {
|
|
35
|
-
putDouble("bytesDownloaded", downloaded.toDouble())
|
|
36
|
-
putDouble("totalBytes", total.toDouble())
|
|
37
|
-
putDouble("percent", (downloaded.toDouble() / total) * 100)
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
result.fold(
|
|
42
|
-
onSuccess = {
|
|
43
|
-
sendEvent("FlirDownloadComplete", Arguments.createMap())
|
|
44
|
-
promise.resolve(true)
|
|
45
|
-
},
|
|
46
|
-
onFailure = { error ->
|
|
47
|
-
sendEvent("FlirDownloadError", Arguments.createMap().apply {
|
|
48
|
-
putString("error", error.message)
|
|
49
|
-
})
|
|
50
|
-
promise.reject("E_DOWNLOAD", error.message, error)
|
|
51
|
-
}
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
@ReactMethod
|
|
57
|
-
fun cancelDownload() {
|
|
58
|
-
downloadJob?.cancel()
|
|
35
|
+
// SDK is bundled - no download needed
|
|
36
|
+
promise.resolve(true)
|
|
59
37
|
}
|
|
60
38
|
|
|
61
39
|
@ReactMethod
|
|
62
|
-
fun
|
|
63
|
-
|
|
40
|
+
fun getSDKStatus(promise: Promise) {
|
|
41
|
+
val status = Arguments.createMap().apply {
|
|
42
|
+
putBoolean("available", true)
|
|
43
|
+
putBoolean("bundled", true)
|
|
44
|
+
putString("arch", FlirSDKLoader.getDeviceArch())
|
|
45
|
+
putString("version", "4.16.0")
|
|
46
|
+
}
|
|
47
|
+
promise.resolve(status)
|
|
64
48
|
}
|
|
65
49
|
|
|
66
50
|
@ReactMethod
|
|
67
|
-
fun
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
fun removeListeners(count: Int) {}
|
|
71
|
-
|
|
72
|
-
private fun sendEvent(name: String, params: WritableMap) {
|
|
73
|
-
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
74
|
-
.emit(name, params)
|
|
51
|
+
fun cancelDownload(promise: Promise) {
|
|
52
|
+
// Nothing to cancel
|
|
53
|
+
promise.resolve(true)
|
|
75
54
|
}
|
|
76
55
|
}
|
|
@@ -71,4 +71,36 @@ class FlirModule(private val reactContext: ReactApplicationContext) : ReactConte
|
|
|
71
71
|
promise.reject("ERR_FLIR_DEVICE_INFO", e)
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
@ReactMethod
|
|
76
|
+
fun isSDKDownloaded(promise: Promise) {
|
|
77
|
+
try {
|
|
78
|
+
val available = FlirSDKLoader.isSDKAvailable(reactContext)
|
|
79
|
+
promise.resolve(available)
|
|
80
|
+
} catch (e: Exception) {
|
|
81
|
+
promise.reject("ERR_FLIR_SDK_CHECK", e)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@ReactMethod
|
|
86
|
+
fun getSDKStatus(promise: Promise) {
|
|
87
|
+
try {
|
|
88
|
+
val available = FlirSDKLoader.isSDKAvailable(reactContext)
|
|
89
|
+
val arch = FlirSDKLoader.getDeviceArch()
|
|
90
|
+
val dexPath = FlirSDKLoader.getDexPath(reactContext)
|
|
91
|
+
val nativeLibDir = FlirSDKLoader.getNativeLibDir(reactContext)
|
|
92
|
+
|
|
93
|
+
val result = com.facebook.react.bridge.Arguments.createMap()
|
|
94
|
+
result.putBoolean("available", available)
|
|
95
|
+
result.putString("arch", arch)
|
|
96
|
+
result.putString("dexPath", dexPath?.absolutePath ?: "not downloaded")
|
|
97
|
+
result.putString("nativeLibPath", nativeLibDir?.absolutePath ?: "not downloaded")
|
|
98
|
+
result.putBoolean("dexExists", dexPath?.exists() == true)
|
|
99
|
+
result.putBoolean("nativeLibsExist", nativeLibDir?.exists() == true)
|
|
100
|
+
|
|
101
|
+
promise.resolve(result)
|
|
102
|
+
} catch (e: Exception) {
|
|
103
|
+
promise.reject("ERR_FLIR_SDK_STATUS", e)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
74
106
|
}
|
|
@@ -3,67 +3,18 @@ package flir.android
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.os.Build
|
|
5
5
|
import android.util.Log
|
|
6
|
-
import kotlinx.coroutines.*
|
|
7
|
-
import org.json.JSONObject
|
|
8
|
-
import java.io.File
|
|
9
|
-
import java.io.FileOutputStream
|
|
10
|
-
import java.net.HttpURLConnection
|
|
11
|
-
import java.net.URL
|
|
12
|
-
import java.util.zip.ZipInputStream
|
|
13
6
|
|
|
14
7
|
/**
|
|
15
|
-
* FlirSDKLoader -
|
|
8
|
+
* FlirSDKLoader - SDK availability checker
|
|
16
9
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* URLs are read from sdk-manifest.json in assets folder
|
|
10
|
+
* Since the SDK is now bundled via AAR files, this class simply reports
|
|
11
|
+
* that the SDK is always available. The AAR files include native .so libraries
|
|
12
|
+
* for all supported architectures, which Android handles automatically.
|
|
22
13
|
*/
|
|
23
14
|
object FlirSDKLoader {
|
|
24
15
|
|
|
25
16
|
private const val TAG = "FlirSDKLoader"
|
|
26
17
|
|
|
27
|
-
// Cached manifest data
|
|
28
|
-
private var cachedManifest: SDKManifest? = null
|
|
29
|
-
|
|
30
|
-
// Manifest data classes
|
|
31
|
-
data class ArchPackage(val downloadUrl: String, val sizeBytes: Long)
|
|
32
|
-
data class SDKManifest(val version: String, val packages: Map<String, ArchPackage>)
|
|
33
|
-
|
|
34
|
-
private fun getSDKDirectory(context: Context) = File(context.filesDir, "FlirSDK")
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Load manifest from assets
|
|
38
|
-
*/
|
|
39
|
-
private fun loadManifest(context: Context): SDKManifest? {
|
|
40
|
-
if (cachedManifest != null) return cachedManifest
|
|
41
|
-
|
|
42
|
-
return try {
|
|
43
|
-
val json = context.assets.open("sdk-manifest.json").bufferedReader().readText()
|
|
44
|
-
val root = JSONObject(json)
|
|
45
|
-
val android = root.getJSONObject("android")
|
|
46
|
-
val packagesJson = android.getJSONObject("packages")
|
|
47
|
-
|
|
48
|
-
val packages = mutableMapOf<String, ArchPackage>()
|
|
49
|
-
packagesJson.keys().forEach { arch ->
|
|
50
|
-
val pkg = packagesJson.getJSONObject(arch)
|
|
51
|
-
packages[arch] = ArchPackage(
|
|
52
|
-
downloadUrl = pkg.getString("downloadUrl"),
|
|
53
|
-
sizeBytes = pkg.getLong("sizeBytes")
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
SDKManifest(
|
|
58
|
-
version = root.getString("version"),
|
|
59
|
-
packages = packages
|
|
60
|
-
).also { cachedManifest = it }
|
|
61
|
-
} catch (e: Exception) {
|
|
62
|
-
Log.e(TAG, "Failed to load manifest: ${e.message}")
|
|
63
|
-
null
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
18
|
/**
|
|
68
19
|
* Get the primary ABI for this device
|
|
69
20
|
*/
|
|
@@ -71,7 +22,7 @@ object FlirSDKLoader {
|
|
|
71
22
|
val supportedAbis = Build.SUPPORTED_ABIS
|
|
72
23
|
Log.d(TAG, "Device supported ABIs: ${supportedAbis.joinToString()}")
|
|
73
24
|
|
|
74
|
-
val knownArchs = setOf("arm64-v8a", "armeabi-v7a", "x86_64")
|
|
25
|
+
val knownArchs = setOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86")
|
|
75
26
|
for (abi in supportedAbis) {
|
|
76
27
|
if (abi in knownArchs) {
|
|
77
28
|
Log.d(TAG, "Selected ABI: $abi")
|
|
@@ -82,162 +33,52 @@ object FlirSDKLoader {
|
|
|
82
33
|
}
|
|
83
34
|
|
|
84
35
|
/**
|
|
85
|
-
* Check if SDK is
|
|
36
|
+
* Check if SDK is available - always true since bundled in AAR
|
|
86
37
|
*/
|
|
87
38
|
fun isSDKAvailable(context: Context): Boolean {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
val dexFile = File(sdkDir, "classes.dex")
|
|
92
|
-
val soDir = File(sdkDir, "jni/$arch")
|
|
93
|
-
|
|
94
|
-
val hasDex = dexFile.exists() && dexFile.length() > 0
|
|
95
|
-
val hasSo = soDir.exists() && soDir.listFiles()?.isNotEmpty() == true
|
|
96
|
-
|
|
97
|
-
Log.d(TAG, "SDK available: dex=$hasDex, so=$hasSo")
|
|
98
|
-
return hasDex && hasSo
|
|
39
|
+
Log.d(TAG, "SDK is bundled in AAR - always available")
|
|
40
|
+
return true
|
|
99
41
|
}
|
|
100
42
|
|
|
101
43
|
/**
|
|
102
|
-
*
|
|
44
|
+
* No download needed - SDK is bundled
|
|
103
45
|
*/
|
|
104
|
-
fun
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*/
|
|
112
|
-
fun getNativeLibDir(context: Context): File? {
|
|
113
|
-
val arch = getDeviceArch()
|
|
114
|
-
val libDir = File(getSDKDirectory(context), "jni/$arch")
|
|
115
|
-
return if (libDir.exists()) libDir else null
|
|
46
|
+
suspend fun downloadSDK(
|
|
47
|
+
context: Context,
|
|
48
|
+
onProgress: ((progress: Int, bytesDownloaded: Long, totalBytes: Long) -> Unit)? = null
|
|
49
|
+
): Boolean {
|
|
50
|
+
Log.d(TAG, "SDK is bundled - no download needed")
|
|
51
|
+
onProgress?.invoke(100, 0, 0)
|
|
52
|
+
return true
|
|
116
53
|
}
|
|
117
54
|
|
|
118
55
|
/**
|
|
119
|
-
* Get
|
|
56
|
+
* Get SDK status
|
|
120
57
|
*/
|
|
121
|
-
fun
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
58
|
+
fun getSDKStatus(context: Context): Map<String, Any> {
|
|
59
|
+
return mapOf(
|
|
60
|
+
"available" to true,
|
|
61
|
+
"bundled" to true,
|
|
62
|
+
"arch" to getDeviceArch(),
|
|
63
|
+
"version" to "4.16.0" // SDK version from AAR
|
|
64
|
+
)
|
|
125
65
|
}
|
|
126
66
|
|
|
127
67
|
/**
|
|
128
|
-
*
|
|
68
|
+
* Get DEX path - not applicable when bundled via AAR
|
|
69
|
+
* Returns null since SDK is bundled in AAR, no separate DEX needed
|
|
129
70
|
*/
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
): Result<Unit> = withContext(Dispatchers.IO) {
|
|
134
|
-
try {
|
|
135
|
-
val arch = getDeviceArch()
|
|
136
|
-
val manifest = loadManifest(context)
|
|
137
|
-
?: return@withContext Result.failure(Exception("Failed to load manifest"))
|
|
138
|
-
|
|
139
|
-
val archPackage = manifest.packages[arch]
|
|
140
|
-
?: return@withContext Result.failure(Exception("No package for architecture: $arch"))
|
|
141
|
-
|
|
142
|
-
val downloadUrl = archPackage.downloadUrl
|
|
143
|
-
Log.i(TAG, "Downloading SDK for $arch from $downloadUrl")
|
|
144
|
-
|
|
145
|
-
val sdkDir = getSDKDirectory(context).apply { mkdirs() }
|
|
146
|
-
val zipFile = File(context.cacheDir, "flir-sdk-$arch.zip")
|
|
147
|
-
|
|
148
|
-
// Download with redirect handling (GitHub uses 302 redirects)
|
|
149
|
-
var connection = URL(downloadUrl).openConnection() as HttpURLConnection
|
|
150
|
-
connection.instanceFollowRedirects = true
|
|
151
|
-
connection.connectTimeout = 30000
|
|
152
|
-
connection.readTimeout = 60000
|
|
153
|
-
|
|
154
|
-
// Handle redirects manually for cross-protocol redirects
|
|
155
|
-
var redirectCount = 0
|
|
156
|
-
while (connection.responseCode in 301..302 && redirectCount < 5) {
|
|
157
|
-
val redirectUrl = connection.getHeaderField("Location")
|
|
158
|
-
Log.d(TAG, "Redirect to: $redirectUrl")
|
|
159
|
-
connection.disconnect()
|
|
160
|
-
connection = URL(redirectUrl).openConnection() as HttpURLConnection
|
|
161
|
-
connection.instanceFollowRedirects = true
|
|
162
|
-
redirectCount++
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (connection.responseCode != HttpURLConnection.HTTP_OK) {
|
|
166
|
-
return@withContext Result.failure(Exception("HTTP error ${connection.responseCode}"))
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
val totalSize = connection.contentLengthLong.let {
|
|
170
|
-
if (it > 0) it else archPackage.sizeBytes
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
connection.inputStream.use { input ->
|
|
174
|
-
FileOutputStream(zipFile).use { output ->
|
|
175
|
-
val buffer = ByteArray(8192)
|
|
176
|
-
var totalRead = 0L
|
|
177
|
-
var bytesRead: Int
|
|
178
|
-
|
|
179
|
-
while (input.read(buffer).also { bytesRead = it } != -1) {
|
|
180
|
-
output.write(buffer, 0, bytesRead)
|
|
181
|
-
totalRead += bytesRead
|
|
182
|
-
withContext(Dispatchers.Main) {
|
|
183
|
-
onProgress(totalRead, totalSize)
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
connection.disconnect()
|
|
189
|
-
|
|
190
|
-
Log.i(TAG, "Download complete: ${zipFile.length()} bytes")
|
|
191
|
-
|
|
192
|
-
// Extract
|
|
193
|
-
unzip(zipFile, sdkDir)
|
|
194
|
-
zipFile.delete()
|
|
195
|
-
|
|
196
|
-
// Verify
|
|
197
|
-
val dexFile = File(sdkDir, "classes.dex")
|
|
198
|
-
val soDir = File(sdkDir, "jni/$arch")
|
|
199
|
-
|
|
200
|
-
if (!dexFile.exists()) {
|
|
201
|
-
return@withContext Result.failure(Exception("DEX file not extracted"))
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
dexFile.setReadOnly()
|
|
205
|
-
Log.i(TAG, "SDK installed: dex=${dexFile.length()} bytes, libs=${soDir.listFiles()?.size ?: 0} files")
|
|
206
|
-
|
|
207
|
-
Result.success(Unit)
|
|
208
|
-
} catch (e: Exception) {
|
|
209
|
-
Log.e(TAG, "Download failed", e)
|
|
210
|
-
Result.failure(e)
|
|
211
|
-
}
|
|
71
|
+
fun getDexPath(context: Context): java.io.File? {
|
|
72
|
+
// SDK is bundled in AAR - no separate DEX file
|
|
73
|
+
return null
|
|
212
74
|
}
|
|
213
75
|
|
|
214
76
|
/**
|
|
215
|
-
*
|
|
77
|
+
* Get native library directory - not applicable when bundled via AAR
|
|
78
|
+
* Returns null since native libs are included in AAR and handled by Android
|
|
216
79
|
*/
|
|
217
|
-
fun
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
private fun unzip(source: File, destination: File) {
|
|
222
|
-
Log.d(TAG, "Extracting ${source.name} to ${destination.absolutePath}")
|
|
223
|
-
|
|
224
|
-
ZipInputStream(source.inputStream()).use { zip ->
|
|
225
|
-
var entry = zip.nextEntry
|
|
226
|
-
while (entry != null) {
|
|
227
|
-
val file = File(destination, entry.name)
|
|
228
|
-
Log.d(TAG, " Extracting: ${entry.name}")
|
|
229
|
-
|
|
230
|
-
if (entry.isDirectory) {
|
|
231
|
-
file.mkdirs()
|
|
232
|
-
} else {
|
|
233
|
-
file.parentFile?.mkdirs()
|
|
234
|
-
file.outputStream().use { output ->
|
|
235
|
-
zip.copyTo(output)
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
zip.closeEntry()
|
|
239
|
-
entry = zip.nextEntry
|
|
240
|
-
}
|
|
241
|
-
}
|
|
80
|
+
fun getNativeLibDir(context: Context): java.io.File? {
|
|
81
|
+
// SDK native libs are bundled in AAR and extracted automatically by Android
|
|
82
|
+
return null
|
|
242
83
|
}
|
|
243
|
-
}
|
|
84
|
+
}
|