Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Android Build

on:
workflow_dispatch:
pull_request:
paths:
# Android project itself, plus the shared C++ runtime it compiles from source.
- "runtime/android/**"
- "runtime/bindings/android/**"
- "runtime/CMakeLists.txt"
- "runtime/CMakePresets.json"
- "runtime/processor/**"
- "runtime/utils/**"
- "runtime/cmake/**"
- ".github/workflows/android.yml"

jobs:
build-android:
name: build (android)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'

# Caches downloaded Gradle distribution and dependencies across runs.
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
build-root-directory: runtime/android

# Puts sdkmanager on PATH, accepts licenses, installs platform + build-tools.
- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
packages: 'platforms;android-34 build-tools;34.0.0'

# sdkmanager has no bare "ndk" package — must install "ndk;X.Y.Z". Pick the
# newest side-by-side NDK from the package list.
- name: Install NDK (latest)
run: |
NDK_PKG=$(sdkmanager --list 2>/dev/null \
| grep -oE 'ndk;[0-9]+\.[0-9]+\.[0-9]+' \
| sort -t';' -k2 -V \
| tail -1)
if [ -z "$NDK_PKG" ]; then
echo "ERROR: no ndk;* package found in sdkmanager --list" >&2
sdkmanager --list 2>/dev/null | grep -i ndk | head -20 >&2 || true
exit 1
fi
echo "Installing $NDK_PKG"
sdkmanager --install "$NDK_PKG"
NDK_VER="${NDK_PKG#ndk;}"
echo "Using NDK $NDK_VER"
echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/$NDK_VER" >> "$GITHUB_ENV"

# Build the native lib with CMake presets and install it into jniLibs/<abi>/.
# Gradle does NOT drive CMake; it only packages the prebuilt .so.
- name: Build native lib
working-directory: runtime
run: |
cmake --preset android-arm64-v8a
cmake --build --preset android-arm64-v8a
cmake --install build/aarch64-linux-android --component jni

- uses: actions/setup-python@v5
with:
python-version: '3.x'

# Generate the four FST models straight into assets/ so the APK ships with
# them (the app loads zh_tn_* and zh_itn_* at runtime).
- name: Generate model assets
run: |
pip install pynini importlib_resources
assets=runtime/android/app/src/main/assets
python -m tn --language zh --overwrite_cache --cache_dir "$assets"
python -m itn --language zh --overwrite_cache --cache_dir "$assets"

- name: Build APK
working-directory: runtime/android
run: ./gradlew :app:assembleDebug -PabiFilters=arm64-v8a --no-daemon

- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: app-debug-arm64-v8a
path: runtime/android/app/build/outputs/apk/debug/app-debug.apk
if-no-files-found: error
4 changes: 4 additions & 0 deletions .github/workflows/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
pull_request:
paths:
- "runtime/**"
# Android has its own workflow; don't rebuild the desktop runtime for
# Android-only changes (shared processor/utils/cmake still match above).
- "!runtime/android/**"
- "!runtime/bindings/android/**"
- ".github/workflows/runtime.yml"

jobs:
Expand Down
17 changes: 14 additions & 3 deletions runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ option(BUILD_TESTING "whether to build unit test" OFF)

include(FetchContent)
set(FETCHCONTENT_QUIET OFF)
get_filename_component(fc_base "fc_base-${CMAKE_CXX_COMPILER_ID}" REALPATH BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(FETCHCONTENT_BASE_DIR ${fc_base})
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
Expand All @@ -25,14 +23,27 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set(CMAKE_MACOSX_RPATH 1)
endif()

if(ANDROID)
set(BUILD_SHARED_LIBS OFF)
endif()

include(openfst)
include(glog)
include(gflags)
include_directories(${PROJECT_SOURCE_DIR})

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")

add_subdirectory(utils)
add_subdirectory(processor)
add_subdirectory(bin)

if(ANDROID)
# JNI shared library; only meaningful when cross-compiling with the NDK.
add_subdirectory(bindings/android)
else()
# Command-line tools are host-only; skip them for Android.
add_subdirectory(bin)
endif()

if(BUILD_TESTING)
include(gtest)
Expand Down
69 changes: 69 additions & 0 deletions runtime/CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"version": 10,
"cmakeMinimumRequired": {
"major": 3,
"minor": 23,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"binaryDir": "${sourceDir}/build/default.release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "android-base",
"hidden": true,
"generator": "Ninja",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake",
"ANDROID_PLATFORM": "android-21",
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "android-armeabi-v7a",
"inherits": "android-base",
"binaryDir": "${sourceDir}/build/arm-linux-androideabi",
"cacheVariables": {
"ANDROID_ABI": "armeabi-v7a",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/android/app/src/main/jniLibs/armeabi-v7a"
}
},
{
"name": "android-arm64-v8a",
"inherits": "android-base",
"binaryDir": "${sourceDir}/build/aarch64-linux-android",
"cacheVariables": {
"ANDROID_ABI": "arm64-v8a",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/android/app/src/main/jniLibs/arm64-v8a"
}
},
{
"name": "android-x86",
"inherits": "android-base",
"binaryDir": "${sourceDir}/build/i686-linux-android",
"cacheVariables": {
"ANDROID_ABI": "x86",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/android/app/src/main/jniLibs/x86"
}
},
{
"name": "android-x86_64",
"inherits": "android-base",
"binaryDir": "${sourceDir}/build/x86_64-linux-android",
"cacheVariables": {
"ANDROID_ABI": "x86_64",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/android/app/src/main/jniLibs/x86_64"
}
}
],
"buildPresets": [
{ "name": "android-armeabi-v7a", "configurePreset": "android-armeabi-v7a" },
{ "name": "android-arm64-v8a", "configurePreset": "android-arm64-v8a" },
{ "name": "android-x86", "configurePreset": "android-x86" },
{ "name": "android-x86_64", "configurePreset": "android-x86_64" }
]
}
3 changes: 1 addition & 2 deletions runtime/android/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
app/src/main/jniLibs/
103 changes: 33 additions & 70 deletions runtime/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
plugins {
id 'com.android.application'
alias(libs.plugins.android.application)
}

repositories {
jcenter()
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
}
def nativeAbis() {
return (project.findProperty('abiFilters') ?: 'armeabi-v7a,arm64-v8a,x86,x86_64')
.split(',').collect { it.trim() }.findAll { it }
}

android {
lintOptions {
abortOnError false
namespace = "com.wenet.WeTextProcessing"
lint {
abortOnError = false
}
signingConfigs {
release {
Expand All @@ -21,85 +20,49 @@ android {
keyPassword '123456'
}
}
packagingOptions {
jniLibs {
pickFirsts += ['lib/arm64-v8a/libc++_shared.so']
}
}
configurations {
extractForNativeBuild
}
compileSdkVersion 30
buildToolsVersion "30.0.3"
compileSdk = 34

defaultConfig {
applicationId "com.mobvoi.WeTextProcessing"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
applicationId = "com.wenet.WeTextProcessing"
minSdk = 21
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
targets "wetextprocessing"
cppFlags "-std=c++14", "-DC10_USE_GLOG", "-DC10_USE_MINIMAL_GLOG", "-DANDROID", "-Wno-c++11-narrowing", "-fexceptions"
}
}
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

ndkVersion '21.1.6352462'
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
abiFilters.addAll(nativeAbis())
}
}

buildTypes {
release {
minifyEnabled false
signingConfig signingConfigs.release
minifyEnabled = false
signingConfig = signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}

dependencies {

implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

implementation 'com.github.pengzhendong:wenet-openfst-android:1.0.2'
extractForNativeBuild 'com.github.pengzhendong:wenet-openfst-android:1.0.2'
implementation libs.androidx.appcompat
implementation libs.material
implementation libs.androidx.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
}

task extractAARForNativeBuild {
doLast {
configurations.extractForNativeBuild.files.each {
def file = it.absoluteFile
copy {
from zipTree(file)
into "$buildDir/$file.name"
include "headers/**"
include "jni/**"
}
}
}
}

tasks.whenTaskAdded { task ->
if (task.name.contains('externalNativeBuild')) {
task.dependsOn(extractAARForNativeBuild)
}
}
// Native libs are NOT built by Gradle. Build them beforehand with CMake presets
// (from repo root) so the .so files exist in app/src/main/jniLibs/<abi>/:
// export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/<version>
// cd runtime
// cmake --preset android-arm64-v8a
// cmake --build --preset android-arm64-v8a
// cmake --install build/aarch64-linux-android --component jni
// Gradle only packages whatever is already present under jniLibs.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mobvoi.WeTextProcessing;
package com.wenet.WeTextProcessing;

import android.content.Context;

Expand All @@ -21,6 +21,6 @@ public class ExampleInstrumentedTest {
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.mobvoi.WeTextProcessing", appContext.getPackageName());
assertEquals("com.wenet.WeTextProcessing", appContext.getPackageName());
}
}
}
7 changes: 4 additions & 3 deletions runtime/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.mobvoi.WeTextProcessing">
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand All @@ -10,7 +9,9 @@
android:supportsRtl="true"
tools:replace="android:theme"
android:theme="@style/Theme.Wenet">
<activity android:name=".MainActivity">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
Loading
Loading