-
Notifications
You must be signed in to change notification settings - Fork 678
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Android]Add android sdk and sample app (#262)
* add android * update readme * add android workflow * update android workflow * updaye android ignore and upload some files * updaye android ignore and upload some files * fix step - Rename and upload AAR * fix step - Upload AAR as an artifact * add job to upload arr to assets * update build aar pipeline
- Loading branch information
Showing
111 changed files
with
4,322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
name: Build Android AAR | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
- android-sdk | ||
pull_request: | ||
|
||
jobs: | ||
build: | ||
name: Build AAR | ||
runs-on: ubuntu-latest | ||
if: github.event_name == 'push' | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v3 | ||
|
||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v3 | ||
with: | ||
distribution: 'temurin' | ||
java-version: '17' | ||
|
||
- name: Cache Gradle packages | ||
uses: actions/cache@v3 | ||
with: | ||
path: ~/.gradle/caches | ||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | ||
restore-keys: | | ||
${{ runner.os }}-gradle- | ||
- name: Navigate to android Directory and Build AAR | ||
run: | | ||
echo "Navigating to the example directory..." | ||
cd android/llama.android | ||
echo "Starting Gradle build process in $(pwd)..." | ||
./gradlew assembleRelease --stacktrace --info | ||
shell: bash | ||
|
||
- name: Rename and upload AAR | ||
run: | | ||
echo "Navigating to the android directory to find AAR output..." | ||
cd android/llama.android | ||
mkdir -p ../artifacts | ||
ls -ld ../artifacts || echo "Artifacts directory does not exist." | ||
AAR_PATH=$(find ./llama/build/outputs/aar -type f -name "*.aar" | head -n 1) | ||
if [ -z "$AAR_PATH" ]; then | ||
echo "No AAR file found. Build might have failed." | ||
exit 1 | ||
fi | ||
BRANCH_NAME=${{ github.ref_name }} | ||
CUSTOM_NAME="com-nexa-${BRANCH_NAME}-${{ github.run_number }}.aar" | ||
echo "Found AAR at $AAR_PATH, renaming to $CUSTOM_NAME..." | ||
mv "$AAR_PATH" "../artifacts/$CUSTOM_NAME" | ||
shell: bash | ||
|
||
- name: Upload AAR as an artifact | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: custom-aar-${{ github.ref_name }}-${{ github.run_number }} | ||
path: android/artifacts/ | ||
|
||
release: | ||
name: Create GitHub Release | ||
needs: build | ||
runs-on: ubuntu-latest | ||
if: github.event_name == 'push' && contains(github.ref, 'main') | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v3 | ||
|
||
- name: Download Artifacts | ||
uses: actions/download-artifact@v3 | ||
with: | ||
name: custom-aar-${{ github.ref_name }}-${{ github.run_number }} | ||
path: release-artifacts | ||
|
||
- name: Create Release | ||
id: create_release | ||
uses: actions/create-release@v1 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
tag_name: v${{ github.run_number }} | ||
release_name: "Release v${{ github.run_number }}" | ||
body: | | ||
This is an automated release containing the latest AAR build. | ||
- **Branch:** ${{ github.ref_name }} | ||
- **Build Number:** ${{ github.run_number }} | ||
draft: false | ||
prerelease: false | ||
|
||
- name: Upload AAR to Release | ||
uses: actions/upload-release-asset@v1 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
upload_url: ${{ steps.create_release.outputs.upload_url }} | ||
asset_path: release-artifacts/com-nexa-${{ github.ref_name }}-${{ github.run_number }}.aar | ||
asset_name: com-nexa-${{ github.ref_name }}-${{ github.run_number }}.aar | ||
asset_content_type: application/java-archive |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Gradle files | ||
.gradle/ | ||
build/ | ||
|
||
# Local configuration file (sdk path, etc) | ||
local.properties | ||
|
||
# Log/OS Files | ||
*.log | ||
|
||
# Android Studio generated files and folders | ||
captures/ | ||
.externalNativeBuild/ | ||
.cxx/ | ||
*.apk | ||
output.json | ||
|
||
# IntelliJ | ||
*.iml | ||
.idea/ | ||
misc.xml | ||
deploymentTargetDropDown.xml | ||
render.experimental.xml | ||
|
||
# Keystore files | ||
*.jks | ||
*.keystore | ||
|
||
# Google Services (e.g. APIs or Firebase) | ||
google-services.json | ||
|
||
# Android Profiling | ||
*.hprof |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Nexa | ||
|
||
**Nexa** is a Kotlin wrapper for the [llama.cpp](https://github.com/ggerganov/llama.cpp.git) library. offering a convenient Kotlin API for Android developers. It allows seamless integration of llama.cpp models into Android applications. | ||
**NOTE:** Currently, Nexa supports Vision-Language Model (VLM) inference capabilities. | ||
|
||
## Installation | ||
|
||
To add Nexa to your Android project, follow these steps: | ||
|
||
- Create a libs folder in your project’s root directory. | ||
- Copy the .aar file into the libs folder. | ||
- Add dependency to your build.gradle file: | ||
|
||
``` | ||
implementation files("libs/com.nexa.aar") | ||
``` | ||
|
||
## Usage | ||
### 1. Initialize NexaSwift with model path and projector path | ||
|
||
Create a configuration and initialize NexaSwift with the path to your model file: | ||
|
||
```kotlin | ||
nexaVlmInference = NexaVlmInference(pathToModel, | ||
mmprojectorPath, imagePath, | ||
maxNewTokens = 128, | ||
stopWords = listOf("</s>")) | ||
nexaVlmInference.loadModel() | ||
``` | ||
|
||
### 2. Completion API | ||
|
||
#### Streaming Mode | ||
|
||
```swift | ||
nexaVlmInference.createCompletionStream(prompt, imagePath) | ||
?.catch { | ||
print(it.message) | ||
} | ||
?.collect { print(it) } | ||
``` | ||
|
||
### 3. release all resources | ||
```kotlin | ||
nexaVlmInference.dispose() | ||
``` | ||
|
||
## Quick Start | ||
|
||
Open the [android test project](./app-java) folder in Android Studio and run the project. | ||
|
||
## Download Models | ||
|
||
You can download models from the [Nexa AI ModelHub](https://nexa.ai/models). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/build | ||
!*.png |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
plugins { | ||
id 'com.android.application' | ||
id 'kotlin-android' | ||
} | ||
|
||
android { | ||
namespace 'ai.nexa.app_java' | ||
compileSdk 34 | ||
|
||
defaultConfig { | ||
applicationId "ai.nexa.app_java" | ||
minSdk 33 | ||
targetSdk 34 | ||
versionCode 1 | ||
versionName "1.0" | ||
|
||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_17 // or VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_17 // or VERSION_1_8 | ||
} | ||
|
||
kotlinOptions { | ||
jvmTarget = "17" // or "1.8" | ||
} | ||
} | ||
|
||
dependencies { | ||
|
||
implementation 'androidx.appcompat:appcompat:1.7.0' | ||
implementation 'com.google.android.material:material:1.12.0' | ||
testImplementation 'junit:junit:4.13.2' | ||
androidTestImplementation 'androidx.test.ext:junit:1.2.1' | ||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' | ||
|
||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.20" | ||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3" | ||
|
||
implementation 'com.github.bumptech.glide:glide:4.16.0' | ||
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' | ||
|
||
implementation project(":llama") | ||
// implementation files("libs/com.nexa.aar") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
26 changes: 26 additions & 0 deletions
26
...llama.android/app-java/src/androidTest/java/ai/nexa/app_java/ExampleInstrumentedTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package ai.nexa.app_java; | ||
|
||
import android.content.Context; | ||
|
||
import androidx.test.platform.app.InstrumentationRegistry; | ||
import androidx.test.ext.junit.runners.AndroidJUnit4; | ||
|
||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
/** | ||
* Instrumented test, which will execute on an Android device. | ||
* | ||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a> | ||
*/ | ||
@RunWith(AndroidJUnit4.class) | ||
public class ExampleInstrumentedTest { | ||
@Test | ||
public void useAppContext() { | ||
// Context of the app under test. | ||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); | ||
assertEquals("ai.nexa.app_java", appContext.getPackageName()); | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
android/llama.android/app-java/src/main/AndroidManifest.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | ||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission android:name="android.permission.RECORD_AUDIO"/> | ||
<uses-permission android:name="android.permission.SEND_SMS"/> | ||
<uses-permission android:name="android.permission.CAMERA"/> | ||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | ||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> | ||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> | ||
|
||
<application | ||
android:allowBackup="true" | ||
android:dataExtractionRules="@xml/data_extraction_rules" | ||
android:fullBackupContent="@xml/backup_rules" | ||
android:icon="@mipmap/octopus" | ||
android:label="VlmSDK" | ||
android:roundIcon="@mipmap/octopus_round" | ||
android:supportsRtl="true" | ||
android:theme="@style/Theme.LayoutTest" | ||
android:networkSecurityConfig="@xml/network_security_config"> | ||
<activity | ||
android:name=".MainActivity" | ||
android:exported="true" | ||
android:windowSoftInputMode="adjustResize">> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
|
||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
<meta-data | ||
android:name="preloaded_fonts" | ||
android:resource="@array/preloaded_fonts" /> | ||
|
||
<provider | ||
android:name="androidx.core.content.FileProvider" | ||
android:authorities="${applicationId}.fileprovider" | ||
android:exported="false" | ||
android:grantUriPermissions="true"> | ||
<meta-data | ||
android:name="android.support.FILE_PROVIDER_PATHS" | ||
android:resource="@xml/file_paths" /> | ||
</provider> | ||
</application> | ||
|
||
</manifest> |
Oops, something went wrong.