| --- |
| title: Android |
| sidebar_position: 14 |
| id: android |
| license: | |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --- |
| |
| ## Android Runtime |
| |
| Fory Java supports Android 8.0+ (API level 26+) through the regular `fory-core` artifact. No separate |
| Android artifact is required for core object serialization. |
| |
| Use core object serialization on Android: |
| |
| - `Fory#serialize(Object)` and `Fory#deserialize(byte[])`. |
| - `BaseFory#deserialize(ByteBuffer)` for heap, direct, and read-only `ByteBuffer` inputs. |
| - Stream, channel, and out-of-band buffer APIs through byte-array, heap-buffer, or `ByteBuffer` copy |
| paths. |
| - Java collections/maps and xlang collections/maps. |
| |
| `java/fory-format` row-format APIs are JVM-only and are not supported on Android. |
| |
| ## Runtime Codegen |
| |
| Runtime serializer code generation is disabled on Android. If `withCodegen(true)` is set, Fory keeps |
| Android serialization on the non-codegen path and logs a warning. |
| |
| Android apps that need generated serializers should use build-time static generated serializers |
| instead. |
| |
| ## Static Generated Serializers |
| |
| Use `@ForyStruct` static generated serializers for Android application classes. They are generated by |
| javac during the app build and work without runtime bytecode generation. |
| |
| ### Install The Annotation Processor |
| |
| Add `fory-annotation-processor` to the annotation processor path of the module that compiles your |
| Android model classes: |
| |
| ```xml |
| <build> |
| <plugins> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-compiler-plugin</artifactId> |
| <configuration> |
| <annotationProcessorPaths> |
| <path> |
| <groupId>org.apache.fory</groupId> |
| <artifactId>fory-annotation-processor</artifactId> |
| <version>${fory.version}</version> |
| </path> |
| </annotationProcessorPaths> |
| </configuration> |
| </plugin> |
| </plugins> |
| </build> |
| ``` |
| |
| Then annotate Android model classes with `@ForyStruct`. |
| |
| Static generated serializers are required on Android when a serialized class uses Fory type-use |
| annotations, for example: |
| |
| ```java |
| import java.util.List; |
| import org.apache.fory.annotation.ForyStruct; |
| import org.apache.fory.annotation.UInt8Type; |
| |
| @ForyStruct |
| public class ImageBlock { |
| public List<@UInt8Type Integer> pixels; |
| } |
| ``` |
| |
| Without the generated static descriptors, Android reflection may not expose the nested type-use |
| metadata needed for annotations such as `@Ref`, `@Int8Type`, `@UInt8Type`, `@Float16Type`, or |
| `@BFloat16Type`. Serialization for those classes will not have the schema information Fory needs. |
| |
| See [Static Generated Serializers](static-generated-serializers.md) for setup instructions. |
| |
| ## Object Model Requirements |
| |
| Android serializers use public Android APIs. For application classes, prefer: |
| |
| - accessible no-argument constructors, or records with supported constructors. |
| - public, protected, or package-private serialized fields. |
| - non-private getters and setters for private serialized fields. |
| - `@ForyStruct` static generated serializers for Android model classes. |
| |
| Final fields in ordinary classes are not suitable for generated read/copy methods. Use records for |
| constructor-based immutable values. |
| |
| ## Unsupported Features |
| |
| The following JVM features are not supported on Android: |
| |
| - Runtime serializer code generation and async compilation. |
| - Lambda and `SerializedLambda` serialization. |
| - Native-address serialization APIs and native-address `MemoryBuffer` wrapping. |
| - Raw unsafe memory copy APIs. |
| - `java/fory-format` row-format APIs. |
| |
| ## ByteBuffer |
| |
| `BaseFory#deserialize(ByteBuffer)` supports heap, direct, and read-only buffers on Android by copying |
| the remaining bytes into a Fory-owned heap buffer. The caller buffer position and limit are not |
| changed. |
| |
| Raw direct-buffer address wrapping is a JVM-only fast path and is not used on Android. |
| |
| ## Collections, Maps, And Proxies |
| |
| Common JDK collection and map implementations are supported on Android. In xlang mode, collection and |
| map serialization uses the xlang protocol and does not encode Java wrapper/view internals. |
| |
| `java.lang.reflect.Proxy` serialization is supported for normal proxy usage. Do not invoke, log, or |
| use a proxy as a map/set key while it is still being deserialized; the invocation handler may not be |
| ready yet. |
| |
| ## Kotlin on Android |
| |
| Apache Fory Kotlin supports Kotlin/JVM and Android. Android support is built on |
| the existing Fory Java implementation plus Kotlin serializers from |
| `fory-kotlin`. Kotlin schema serializers are generated by `fory-kotlin-ksp` at |
| build time. |
| |
| Use this page for Android setup and release-build constraints. Use |
| [Static Generated Serializers](static-generated-serializers.md) for the Kotlin |
| KSP serializer model itself. If your Android project also contains Java |
| `@ForyStruct` classes, use the Java annotation processor documented in |
| [Java Static Generated Serializers](../java/static-generated-serializers.md). |
| |
| ## Dependencies |
| |
| Add `fory-kotlin` to the Android module that uses Fory. Add |
| `fory-kotlin-ksp` to the module that compiles Kotlin `@ForyStruct` model |
| classes. |
| |
| ```kotlin |
| plugins { |
| id("com.android.application") |
| id("org.jetbrains.kotlin.android") |
| id("com.google.devtools.ksp") |
| } |
| |
| dependencies { |
| implementation("org.apache.fory:fory-kotlin:<fory-version>") |
| ksp("org.apache.fory:fory-kotlin-ksp:<fory-version>") |
| } |
| ``` |
| |
| For Android library modules, apply KSP in the library module that owns the |
| annotated Kotlin classes. The generated serializers and generated consumer R8 |
| rules must be packaged with that library artifact. |
| |
| ## Fory Setup |
| |
| Create the Fory instance with `ForyKotlin.builder().withXlang(true)`, then register application classes |
| through the Kotlin `register<T>` extension or the normal Fory Java registration |
| APIs. |
| |
| ```kotlin |
| import org.apache.fory.kotlin.ForyKotlin |
| import org.apache.fory.kotlin.register |
| |
| val fory = ForyKotlin.builder() |
| .withXlang(true) |
| .requireClassRegistration(true) |
| .build() |
| |
| fory.register<User>("example.User") |
| ``` |
| |
| Do not reference generated serializer classes from application code. Fory |
| resolves generated serializers from the registered target class. |
| |
| ## Xlang Schema Mode |
| |
| Android Kotlin structs that participate in Fory cross-language schema |
| serialization should use KSP generated serializers. Generated serializers avoid |
| using runtime reflection as the source of Kotlin schema metadata and call the |
| same Fory Java serializer infrastructure used by other generated serializers. |
| |
| Kotlin KSP generated serializers are xlang/schema serializers only. They do not |
| replace Java native object serializers and do not preserve concrete JVM |
| collection implementation identity. For example, a Kotlin `List<String>` field |
| is schema `list<string>`; deserialization only guarantees a value assignable to |
| the declared field type. |
| |
| ## Minified Release Builds |
| |
| Validate Fory Android behavior with a minified release build. Debug builds do |
| not prove that generated serializers, generated constructor entry points, or |
| Kotlin metadata survive R8. |
| |
| KSP emits generated consumer R8/ProGuard rules under `META-INF/proguard/` for |
| the generated serializer constructors and Kotlin metadata required by Fory. |
| Android apps should not need broad user-written keep rules for generated Kotlin |
| serializers. If a custom packaging setup drops generated `META-INF/proguard/` |
| resources, fix that packaging path instead of adding broad keep rules for every |
| generated serializer. |
| |
| The Apache Fory repository validates this path with |
| `integration_tests/android_tests`, including release-minified instrumented |
| tests. |
| |
| ## Java Models In Android Apps |
| |
| Kotlin KSP only processes Kotlin source. If your Android app contains Java |
| classes annotated with `@ForyStruct`, configure the Java |
| `fory-annotation-processor` for those Java sources. |
| |
| Static generated Java serializers are also important on Android when Java model |
| classes use Fory type-use annotations on nested types, such as |
| `List<@UInt8Type Integer>`. See |
| [Java Static Generated Serializers](../java/static-generated-serializers.md) |
| for that path. |
| |
| ## Unsupported Targets |
| |
| `fory-kotlin` and `fory-kotlin-ksp` target Kotlin/JVM and Android only. |
| Kotlin/Native and Kotlin/JS are not supported. |