Skip to content

Commit 198abe3

Browse files
authored
feat(plugins): typed invoke arguments for mobile plugins (#8076)
1 parent a74ff46 commit 198abe3

File tree

31 files changed

+431
-934
lines changed

31 files changed

+431
-934
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch:breaking
3+
---
4+
5+
The Android `PluginManager.loadConfig` now takes a third parameter to define the class type of the config object.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch:enhance
3+
---
4+
5+
Mobile plugins can now resolve using an arbitrary object instead of using the `JSObject` class via `Invoke.resolve` on iOS and `Invoke.resolveObject` on Android.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch:breaking
3+
---
4+
5+
Mobile plugins now have access to a parser for the invoke arguments instead of relying on the `Invoke#get${TYPE}` methods.

.changes/update-mobile-template.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-cli": patch:breaking
3+
"@tauri-apps/cli": patch:breaking
4+
---
5+
6+
Updated the mobile plugin templates following the tauri v2.0.0-alpha.17 changes.

core/tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ development = [ "quickcheck_macros" ]
4242

4343
[dependencies]
4444
serde_json = { version = "1.0", features = [ "raw_value" ] }
45-
serde = { version = "1.0", features = [ "derive" ] }
45+
serde = { version = "1.0", features = [ "derive", "rc" ] }
4646
tokio = { version = "1", features = [ "rt", "rt-multi-thread", "sync", "fs", "io-util" ] }
4747
futures-util = "0.3"
4848
uuid = { version = "1", features = [ "v4" ], optional = true }

core/tauri/mobile/android/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ dependencies {
3838
implementation("androidx.core:core-ktx:1.7.0")
3939
implementation("androidx.appcompat:appcompat:1.6.0")
4040
implementation("com.google.android.material:material:1.7.0")
41+
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
4142
testImplementation("junit:junit:4.13.2")
4243
androidTestImplementation("androidx.test.ext:junit:1.1.5")
4344
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

core/tauri/mobile/android/proguard-rules.pro

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@
2323
@app.tauri.annotation.Permission <methods>;
2424
public <init>(...);
2525
}
26+
27+
-keep @app.tauri.annotation.InvokeArg public class * {
28+
*;
29+
}

core/tauri/mobile/android/src/main/java/app/tauri/PermissionHelper.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,19 @@ object PermissionHelper {
9595
* @param neededPermissions The permissions needed.
9696
* @return The permissions not present in AndroidManifest.xml
9797
*/
98-
fun getUndefinedPermissions(context: Context, neededPermissions: Array<String>): Array<String?> {
99-
val undefinedPermissions = ArrayList<String?>()
98+
fun getUndefinedPermissions(context: Context, neededPermissions: Array<String>): Array<String> {
99+
val undefinedPermissions = ArrayList<String>()
100100
val requestedPermissions = getManifestPermissions(context)
101-
if (requestedPermissions != null && requestedPermissions.isNotEmpty()) {
101+
if (!requestedPermissions.isNullOrEmpty()) {
102102
val requestedPermissionsList = listOf(*requestedPermissions)
103103
val requestedPermissionsArrayList = ArrayList(requestedPermissionsList)
104104
for (permission in neededPermissions) {
105105
if (!requestedPermissionsArrayList.contains(permission)) {
106106
undefinedPermissions.add(permission)
107107
}
108108
}
109-
var undefinedPermissionArray = arrayOfNulls<String>(undefinedPermissions.size)
110-
undefinedPermissionArray = undefinedPermissions.toArray(undefinedPermissionArray)
111-
return undefinedPermissionArray
109+
return undefinedPermissions.toTypedArray()
112110
}
113-
return neededPermissions as Array<String?>
111+
return neededPermissions
114112
}
115113
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
2+
// SPDX-License-Identifier: Apache-2.0
3+
// SPDX-License-Identifier: MIT
4+
5+
package app.tauri.annotation
6+
7+
@Retention(AnnotationRetention.RUNTIME)
8+
@Target(AnnotationTarget.CLASS)
9+
annotation class InvokeArg

core/tauri/mobile/android/src/main/java/app/tauri/plugin/Channel.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,30 @@
44

55
package app.tauri.plugin
66

7-
class Channel(val id: Long, private val handler: (data: JSObject) -> Unit) {
7+
import com.fasterxml.jackson.core.JsonParser
8+
import com.fasterxml.jackson.databind.DeserializationContext
9+
import com.fasterxml.jackson.databind.JsonDeserializer
10+
import com.fasterxml.jackson.databind.ObjectMapper
11+
12+
const val CHANNEL_PREFIX = "__CHANNEL__:"
13+
14+
internal class ChannelDeserializer(val sendChannelData: (channelId: Long, data: String) -> Unit, private val objectMapper: ObjectMapper): JsonDeserializer<Channel>() {
15+
override fun deserialize(
16+
jsonParser: JsonParser?,
17+
deserializationContext: DeserializationContext
18+
): Channel {
19+
val channelDef = deserializationContext.readValue(jsonParser, String::class.java)
20+
val callback = channelDef.substring(CHANNEL_PREFIX.length).toLongOrNull() ?: throw Error("unexpected channel value $channelDef")
21+
return Channel(callback, { res -> sendChannelData(callback, res) }, objectMapper)
22+
}
23+
}
24+
25+
class Channel(val id: Long, private val handler: (data: String) -> Unit, private val objectMapper: ObjectMapper) {
826
fun send(data: JSObject) {
9-
handler(data)
27+
handler(PluginResult(data).toString())
28+
}
29+
30+
fun sendObject(data: Any) {
31+
handler(objectMapper.writeValueAsString(data))
1032
}
1133
}

0 commit comments

Comments
 (0)