Skip to content

Commit

Permalink
add java android demo (#1454)
Browse files Browse the repository at this point in the history
  • Loading branch information
JameWade authored Oct 23, 2024
1 parent bcaa91e commit 3edd8d7
Show file tree
Hide file tree
Showing 45 changed files with 1,268 additions and 0 deletions.
15 changes: 15 additions & 0 deletions android/SherpaOnnxJavaDemo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
1 change: 1 addition & 0 deletions android/SherpaOnnxJavaDemo/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
41 changes: 41 additions & 0 deletions android/SherpaOnnxJavaDemo/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
plugins {
id 'com.android.application'
}

android {
compileSdk 34

defaultConfig {
applicationId "com.k2fsa.sherpa.onnx"
minSdk 28
targetSdk 32
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_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceSets.main{
jniLibs.srcDirs = ['jniLibs']
}
}

dependencies {

implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'pub.devrel:easypermissions:3.0.0'
implementation project(path: ':sherpa')

}
21 changes: 21 additions & 0 deletions android/SherpaOnnxJavaDemo/app/proguard-rules.pro
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
32 changes: 32 additions & 0 deletions android/SherpaOnnxJavaDemo/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?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.k2fsa.sherpa.onnx">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<application
android:name=".Application"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SherpaOnnxJavaDemo"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".service.SpeechSherpaRecognitionService"
android:exported="false"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.k2fsa.sherpa.onnx;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class AppViewModel extends ViewModel {
private final MutableLiveData<String> speechRecognitionResult = new MutableLiveData<>();

public LiveData<String> getSpeechRecognitionResult() {
return speechRecognitionResult;
}

public void setSpeechRecognitionResult(String result) {
speechRecognitionResult.postValue(result);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.k2fsa.sherpa.onnx;

import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStore;
import androidx.lifecycle.ViewModelStoreOwner;


public class Application extends android.app.Application implements ViewModelStoreOwner {
public static Application sApplication;


private AppViewModel viewModel;
private ViewModelStore viewModelStore;

public static Application getInstance() {
return sApplication;
}

@Override
public void onCreate() {
super.onCreate();
sApplication = this;
viewModelStore = new ViewModelStore();
viewModel = new ViewModelProvider(this).get(AppViewModel.class);
}

@NonNull
@Override
public ViewModelStore getViewModelStore() {
return viewModelStore;
}

public AppViewModel getViewModel() {
return viewModel;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.k2fsa.sherpa.onnx;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider;

import android.Manifest;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import com.k2fsa.sherpa.onnx.service.SpeechSherpaRecognitionService;

import pub.devrel.easypermissions.EasyPermissions;

public class MainActivity extends AppCompatActivity {
private AppViewModel appViewModel;
private TextView tvText;
private static final int RC_AUDIO_PERM = 123;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvText = findViewById(R.id.text);
requestMicrophonePermission();
}


private void startSpeechService() {
Intent serviceIntent = new Intent(this, SpeechSherpaRecognitionService.class);
ContextCompat.startForegroundService(this, serviceIntent);
appViewModel = new ViewModelProvider(Application.getInstance()).get(AppViewModel.class);
appViewModel.getSpeechRecognitionResult().observe(this, this::handleSpeechRecognitionResult);
}

private void handleSpeechRecognitionResult(String result) {
tvText.setText(result);
}

private void requestMicrophonePermission() {
String[] perms = {Manifest.permission.RECORD_AUDIO};
if (EasyPermissions.hasPermissions(this, perms)) {
startSpeechService();
} else {
EasyPermissions.requestPermissions(MainActivity.this,
"We need access to your microphone for voice recognition",
RC_AUDIO_PERM, perms);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2022-2023 by zhaoming
// Copyright 2024 Xiaomi Corporation

package com.k2fsa.sherpa.onnx;

import android.content.res.AssetManager;

public class OnlineRecognizer {
static {
System.loadLibrary("sherpa-onnx-jni");
}

private long ptr = 0;

public OnlineRecognizer(OnlineRecognizerConfig config) {
ptr = newFromFile(config);
}

public OnlineRecognizer(AssetManager assetManager, OnlineRecognizerConfig config) {
ptr = newFromAsset(assetManager, config);
}

public void decode(OnlineStream s) {
decode(ptr, s.getPtr());
}

public boolean isReady(OnlineStream s) {
return isReady(ptr, s.getPtr());
}

public boolean isEndpoint(OnlineStream s) {
return isEndpoint(ptr, s.getPtr());
}

public void reset(OnlineStream s) {
reset(ptr, s.getPtr());
}

public OnlineStream createStream() {
long p = createStream(ptr, "");
return new OnlineStream(p);
}

@Override
protected void finalize() throws Throwable {
release();
}

// You'd better call it manually if it is not used anymore
public void release() {
if (this.ptr == 0) {
return;
}
delete(this.ptr);
this.ptr = 0;
}

public OnlineRecognizerResult getResult(OnlineStream s) {
Object[] arr = getResult(ptr, s.getPtr());
String text = (String) arr[0];
String[] tokens = (String[]) arr[1];
float[] timestamps = (float[]) arr[2];
return new OnlineRecognizerResult(text, tokens, timestamps);
}


private native void delete(long ptr);

private native long newFromFile(OnlineRecognizerConfig config);

private native long newFromAsset(AssetManager assetManager, OnlineRecognizerConfig config);

private native long createStream(long ptr, String hotwords);

private native void reset(long ptr, long streamPtr);

private native void decode(long ptr, long streamPtr);

private native boolean isEndpoint(long ptr, long streamPtr);

private native boolean isReady(long ptr, long streamPtr);

private native Object[] getResult(long ptr, long streamPtr);
}
Loading

0 comments on commit 3edd8d7

Please sign in to comment.