Skip to content

Commit

Permalink
[Android] Update gradle version and other changes in android apps, CI…
Browse files Browse the repository at this point in the history
… modification to auto-build Android apps and upload artifacts (#11241)

* Update gradle version in android_rpc app

* Support latest gradle, bump versions, replace ndk build script with gradle tasks

* [android_rpc] Fix linter errors, disable weird ones

* [android_deploy] Support latest gradle, bump versions, fix linter errors, disable some of them

* [android_camera] Support latest gradle, bump versions, rewrite readme

* [android_camera] Fix linter errors

* Fix sanity check errors

* Add Android jobs for Github Actions

* Add python requirements for TVM and android_camera, use preinstalled NDK

* Revert to build with make

* Add minrpc include (PR #11232)

* Remove relative paths
  • Loading branch information
argrento authored May 25, 2022
1 parent 3f53e7a commit 014208e
Show file tree
Hide file tree
Showing 36 changed files with 497 additions and 251 deletions.
169 changes: 117 additions & 52 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,59 +38,124 @@ jobs:
MacOS:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: bash -l {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Build iOS RPC
run: |
IOS_VERSION="14.0"
CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_SYSTEM_VERSION=${IOS_VERSION} \
-DCMAKE_OSX_SYSROOT=iphonesimulator \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON \
-DUSE_IOS_RPC=ON"
mkdir build-ios-simulator
cd build-ios-simulator
cmake .. ${CMAKE_FLAGS}
cmake --build . --target ios_rpc
- name: Test
shell: bash -l {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test
- name: Test iOS RPC
shell: bash -l {0}
run: >-
python -m pip install tornado psutil cloudpickle &&
export PYTHONPATH=tests/python/contrib:${PYTHONPATH} &&
export BUNDLE_ID=org.apache.tvmrpc &&
export BUNDLE_PATH=build-ios-simulator/apps/ios_rpc/ios_rpc/src/ios_rpc-build/Release-iphonesimulator/tvmrpc.app &&
python -m pytest -v tests/python/contrib/test_rpc_server_device.py
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: bash -l {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Build iOS RPC
run: |
IOS_VERSION="14.0"
CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_SYSTEM_VERSION=${IOS_VERSION} \
-DCMAKE_OSX_SYSROOT=iphonesimulator \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON \
-DUSE_IOS_RPC=ON"
mkdir build-ios-simulator
cd build-ios-simulator
cmake .. ${CMAKE_FLAGS}
cmake --build . --target ios_rpc
- name: Test
shell: bash -l {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test
- name: Test iOS RPC
shell: bash -l {0}
run: >-
python -m pip install tornado psutil cloudpickle &&
export PYTHONPATH=tests/python/contrib:${PYTHONPATH} &&
export BUNDLE_ID=org.apache.tvmrpc &&
export BUNDLE_PATH=build-ios-simulator/apps/ios_rpc/ios_rpc/src/ios_rpc-build/Release-iphonesimulator/tvmrpc.app &&
python -m pytest -v tests/python/contrib/test_rpc_server_device.py
Windows:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: cmd /C call {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Test
shell: cmd /C call {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Conda Build
shell: cmd /C call {0}
run: >-
conda build --output-folder=conda/pkg conda/recipe &&
conda install tvm -c ./conda/pkg
- name: Test
shell: cmd /C call {0}
run: >-
python -m pytest -v tests/python/all-platform-minimal-test
Android:
runs-on: Ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up environment
uses: ./.github/actions/setup
- name: Set up java
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
- name: Build TVM
shell: bash -l {0}
run: |
mkdir build
cd build
../tests/scripts/task_config_build_jvm.sh .
cmake ..
make
- name: Build TVM4J
run: |
make jvmpkg
- name: Build android_rpc
working-directory: apps/android_rpc
run: |
export PATH="${ANDROID_NDK_HOME}:$PATH"
gradle clean build
- name: Upload android_rpc APK
uses: actions/upload-artifact@v2
with:
name: android_rpc-debug.apk
path: ./apps/android_rpc/app/build/outputs/apk/debug/app-debug.apk
- name: Build android_deploy
working-directory: apps/android_deploy
run: |
export PATH="${ANDROID_NDK_HOME}:$PATH"
gradle clean build
- name: Upload android_deploy APK
uses: actions/upload-artifact@v2
with:
name: android_deploy-debug.apk
path: ./apps/android_deploy/app/build/outputs/apk/debug/app-debug.apk
- name: Build android_camera
working-directory: apps/android_camera
run: |
mkdir -p app/src/main/assets/models/
export TVM_NDK_CC=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang++
export TVM_HOME=~/work/tvm/tvm
export PYTHONPATH=$TVM_HOME/python:${PYTHONPATH}
python3 ${TVM_HOME}/python/gen_requirements.py
pip3 install -r ${TVM_HOME}/python/requirements/core.txt
cd models
pip3 install -r requirements.txt
python3 prepare_model.py
cd ..
export PATH="${ANDROID_NDK_HOME}:$PATH"
gradle clean build
- name: Upload android_camera APK
uses: actions/upload-artifact@v2
with:
name: android_camera-debug.apk
path: ./apps/android_camera/app/build/outputs/apk/debug/app-debug.apk
129 changes: 104 additions & 25 deletions apps/android_camera/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,107 @@
[//]: # 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 Camera Demo Sample App
==============================

The Android Camera Demo Sample App provides a basic implementation of an Android
app that uses the tvm runtime to perform image classification in real time.

Converting Models
-----------------
<!--- 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 Camera Demo Sample App

The Android Camera Demo Sample App provides a basic implementation of an Android app that uses the tvm runtime to perform image classification in real time.

You will need JDK, [Android NDK](https://developer.android.com/ndk) and an Android device to use this.

## Build and Installation

### <a name="preparemodels">Prepare Models</a>

The `models/prepare_models.py` script provides a example flow for dumping model
parameter files for use by the app.

1. Set path to the NDK CC: `export TVM_NDK_CC=[Path to CC, e.g. /opt/android-toolchain-arm64/bin/aarch64-linux-android-g++]`
2. Switch to the script directory: `cd models`
3. Run script: `python3 prepare_model.py`

#### Sample output
```
mobilenet_v2
getting model...
building...
dumping lib...
dumping graph...
dumping params...
dumping labels...
resnet18_v1
getting model...
building...
dumping lib...
dumping graph...
dumping params...
dumping labels...
```

### <a name="buildapk">Build APK</a>

We use [Gradle](https://gradle.org) to build. Please follow [the installation instruction](https://gradle.org/install) for your operating system.

Before you build the Android application, please refer to [TVM4J Installation Guide](https://github.com/apache/tvm/blob/main/jvm/README.md) and install tvm4j-core to your local maven repository. You can find tvm4j dependency declare in `app/build.gradle`. Modify it if it is necessary.

```
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.google.android.material:material:1.5.0'
implementation 'org.apache.tvm:tvm4j-core:0.0.1-SNAPSHOT'
testImplementation 'junit:junit:4.13.2'
implementation "androidx.concurrent:concurrent-futures:1.0.0"
implementation "androidx.camera:camera-core:1.0.0-beta01"
implementation "androidx.camera:camera-camera2:1.0.0-beta01"
implementation "androidx.camera:camera-view:1.0.0-alpha08"
implementation "androidx.camera:camera-extensions:1.0.0-alpha08"
implementation "androidx.camera:camera-lifecycle:1.0.0-beta01"
}
```

Now use Gradle to compile JNI, resolve Java dependencies and build the Android application together with tvm4j. Run following script to generate the apk file.

```bash
export ANDROID_HOME=[Path to your Android SDK, e.g., ~/Android/sdk]
cd apps/android_camera
gradle clean build
```

In `app/build/outputs/apk` you'll find `app-release-unsigned.apk`, use `dev_tools/gen_keystore.sh` to generate a signature and use `dev_tools/sign_apk.sh` to get the signed apk file `app/build/outputs/apk/release/tv8mdemo-release.apk`.

Upload `tv8mdemo-release.apk` to your Android device and install it:

```bash
$ANDROID_HOME/platform-tools/adb install app/build/outputs/apk/release/tv8mdemo-release.apk
```

If you see error:

adb: failed to install app/build/outputs/apk/release/tv8mdemo-release.apk:
Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE:
Package ml.apache.tvm.android.androidcamerademo signatures do not match the previously installed version; ignoring!]

Run uninstall first:

```bash
$ANDROID_HOME/platform-tools/adb uninstall ml.apache.tvm.android.androidcamerademo
```
52 changes: 41 additions & 11 deletions apps/android_camera/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,47 @@

apply plugin: 'com.android.application'

task generateJniHeaders(type: Exec, description: 'Generate JNI Headers') {
def headerPath = "${project.projectDir}/src/main/jni"
def classPath = "${project.projectDir}/../../../jvm/core/target/*"
def filePath = "${project.projectDir}/../../../jvm/core/src/main/java/org/apache/tvm/LibInfo.java"
commandLine "javac", "-h", headerPath, "-classpath", classPath, filePath
doLast {
file("${headerPath}/org_apache_tvm_LibInfo.h").renameTo(file("${headerPath}/org_apache_tvm_native_c_api.h"))
}
}

task copyFiles(type: Copy, description: 'Copy Sources for ndk-build') {
dependsOn "generateJniHeaders"
def ndkFilesPath = "${project.projectDir}/../../../jvm/native/src/main/native"
def srcPath = "${project.projectDir}/src/main/jni/"

from "${ndkFilesPath}/org_apache_tvm_native_c_api.cc", "${ndkFilesPath}/jni_helper_func.h"
into srcPath
}

task deleteLibs(type: Delete, description: "Delete Compiled Libraries") {
dependsOn "copyFiles"
def libsPath = "${project.projectDir}/src/main/libs"
delete libsPath
}

task buildJni(type: Exec, description: 'Build JNI libs') {
commandLine 'sh', 'src/main/jni/build.sh'
dependsOn "deleteLibs"
def buildPath = "${project.projectDir}/src/main/jni"
commandLine "ndk-build", "--directory", buildPath
}

tasks.withType(JavaCompile) {
//compileTask -> compileTask.dependsOn buildJni
compileTask -> compileTask.dependsOn buildJni
}

android {
compileSdkVersion 29
compileSdkVersion 31
defaultConfig {
applicationId "ml.apache.tvm.android.androidcamerademo"
minSdkVersion 24
targetSdkVersion 29
targetSdkVersion 26
renderscriptTargetApi 18
renderscriptSupportModeEnabled true
versionCode 1
Expand All @@ -53,21 +80,24 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildToolsVersion = '29.0.3'

lintOptions {
disable "Instantiatable" // MainActivity and RPCActivity must extend android.app.Activity
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0'
implementation 'org.apache.tvm:tvm4j-core:0.0.1-SNAPSHOT'
testImplementation 'junit:junit:4.13'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.google.android.material:material:1.5.0'
implementation files('../../../jvm/core/target/tvm4j-core-0.0.1-SNAPSHOT.jar')
testImplementation 'junit:junit:4.13.2'

implementation("androidx.concurrent:concurrent-futures:1.0.0")
implementation "androidx.concurrent:concurrent-futures:1.0.0"
implementation "androidx.camera:camera-core:1.0.0-beta01"
implementation "androidx.camera:camera-camera2:1.0.0-beta01"
// If you want to use the CameraX View class
Expand Down
Loading

1 comment on commit 014208e

@zuowanbushiwo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @argrento
Why is it modified like this? If you include your activity, you can't use the compiled container of Dockerfile.demo_android? There will be a lot of version mismatch problems., and Now Only switch to tag V0.8 .

Please sign in to comment.