【发布时间】:2015-03-24 19:50:43
【问题描述】:
尝试在 android 和 AFAIK 上使用 this lib 的作品,链接和 .so 看起来不错。
调用 C 函数时出错(我关注了these intstructs)
D/OpusRecorder( 1964): Start recording!
E/art ( 1964): No implementation found for int com.droidkit.opus.OpusLib.startRecord(java.lang.String) (tried Java_com_droidkit_opus_OpusLib_startRecord and Java_com_droidkit_opus_OpusLib_startRecord__Ljava_lang_String_2)
E/AndroidRuntime( 1964): FATAL EXCEPTION: Thread-8227
E/AndroidRuntime( 1964): Process: com.borneo.speech, PID: 1964
E/AndroidRuntime( 1964): java.lang.UnsatisfiedLinkError: No implementation found for int com.droidkit.opus.OpusLib.startRecord(java.lang.String) (tried Java_com_droidkit_opus_OpusLib_startRecord and Java_com_droidkit_opus_OpusLib_startRecord__Ljava_lang_String_2)
E/AndroidRuntime( 1964): at com.droidkit.opus.OpusLib.startRecord(Native Method)
E/AndroidRuntime( 1964): at com.borneo.speech.OpusRecorder.run(OpusRecorder.java:439)
W/ActivityManager( 724): Force finishing activity 1 com.borneo.speech/.Speech_API_Activity
.so被打包在apk中
函数存在于 .so 中,Type="T"...
aar$ nm -D libopus.so | head
000084c1 T Java_com_droidkit_opus_OpusLib_closeOpusFile
000084c5 T Java_com_droidkit_opus_OpusLib_isOpusFile
00008491 T Java_com_droidkit_opus_OpusLib_openOpusFile
00008471 T Java_com_droidkit_opus_OpusLib_readOpusFile
00008489 T Java_com_droidkit_opus_OpusLib_seekOpusFile
00008145 T Java_com_droidkit_opus_OpusLib_startRecord ***
---CL 语言详细信息---
用 C 语言实现:
audio.c
#include "com_droidkit_opus_OpusLib.h" <-- from the Java class=com.droidkit.opus.OpusLib via javah
//rev belo per @Nicklas
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord(JNIEnv *env, jobject javaThis, jstring path) {
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
int result = initRecorder(pathStr);
if (pathStr != 0) {
(*env)->ReleaseStringUTFChars(env, path, pathStr);
}
return result;
}
c 标题...
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_droidkit_opus_OpusLib */
#ifndef _Included_com_droidkit_opus_OpusLib
#define _Included_com_droidkit_opus_OpusLib
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_droidkit_opus_OpusLib
* Method: startRecord
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord
(JNIEnv *, jobject, jstring);
/*
* Class: com_droidkit_opus_OpusLib
* Method: writeFrame
* Signature: (Ljava/nio/ByteBuffer;I)I
*/
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_writeFrame
(JNIEnv *, jobject, jobject, jint);
/*
* Class: com_droidkit_opus_OpusLib
* Method: stopRecord
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_droidkit_opus_OpusLib_stopRecord
(JNIEnv *, jobject);
/*
* Class: com_droidkit_opus_OpusLib
* Method: isOpusFile
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_isOpusFile
(JNIEnv *, jobject, jstring);
...
#ifdef __cplusplus
}
#endif
#endif
===JAVA 详细信息调用 C===
==EDITED== Java Native Decl.
/**
* OpusLib native binding
*/
public class OpusLib {
static {
System.loadLibrary("opus");
}
/**
* Starting opus recording
*
* @param path path to file
* @return non zero if started player
*/
public native int startRecord(String path);
/**
* Writing audio frame to encoder
*
* @param frame buffer with sound in 16 bit mono PCM 16000 format
* @param len len of data
* @return not null if successful
*/
public native int writeFrame(ByteBuffer frame, int len);
/**
* Stopping record
*/
public native void stopRecord();
/**
* Checking Opus File format
*
* @param path path to file
* @return non zero if opus file
*/
public native int isOpusFile(String path);
/**
* Opening file
*
* @param path path to file
* @return non zero if successful
*/
public native int openOpusFile(String path);
/**
* Seeking in opus file
*
* @param position position in file
* @return non zero if successful
*/
public native int seekOpusFile(float position);
/**
* Closing opus file
*/
public native void closeOpusFile();
/**
* Reading from opus file
*
* @param buffer
* @param capacity
*/
public native void readOpusFile(ByteBuffer buffer, int capacity);
/**
* Is playback finished
*
* @return non zero if playback is finished
*/
public native int getFinished();
/**
* Read block size in readOpusFile
*
* @return block size in bytes
*/
public native int getSize();
/**
* Offset of actual sound for playback
*
* @return offset
*/
public native long getPcmOffset();
/**
* Total opus pcm duration
*
* @return pcm duration
*/
public native long getTotalPcmDuration();
}
try {
opus = new OpusLib();
}catch(UnsatisfiedLinkError ulx) {
Log.e(LTAG, "Illegal native Load: " + ulx.getMessage());
}
...
public class OpusLib {
static {
System.loadLibrary("opus");
}
AFAIK,lib 加载正常
UnsatisfiedLink Excp 出现在下面的最后一行:
私有字符串 mPath = 路径;
if (mShouldRecord)
int mint = opus.startRecord(mPath); <-- throws unsatisfiedLink - no implementation found
startRecord 在符号表中,尽管我不确定所有函数参数类型都匹配吗?见“string_2”...
startRecord__Ljava_lang_String_2)
==== 构建信息 Gradle 和linkedit ===
link :
command: /usr/local/src/android-ndk-r10d/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/Android.mk APP_PLATFORM=android-19 NDK_OUT=/home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/obj NDK_LIBS_OUT=/home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/lib APP_STL=stlport_static APP_ABI=armeabi-v7a
[armeabi-v7a] Compile thumb : opus <= audio.c
...
[armeabi-v7a] SharedLibrary : libopus.so
[armeabi-v7a] Install : libopus.so => /home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/lib/armeabi-v7a/libopus.so
build.gradle
默认配置 { minSdkVersion 8 targetSdkVersion 19 版本代码 1 版本名称“1.1.1”
ndk {
moduleName "opus"
cFlags "-DANDROID_NDK " +
"-DDISABLE_IMPORTGL " +
"-w -std=gnu99 -O3 -fno-strict-aliasing -fprefetch-loop-arrays " +
"-DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 "+
"-Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno "
"-DAVOID_TABLES "
ldLibs "log", "m"
stl "stlport_static"
abiFilter "armeabi-v7a"
}
}
【问题讨论】:
-
您是否使用
javah创建签名? -
你在哪里声明你的类中的本地方法?
-
一些建议 - 在本地库加载时查找日志消息,确保您部署了最新版本的本地库,并尝试将 ndk 示例 hello-jni 合并到您的项目中,看看是否那个功能仍然有效(最后一个可能真的很有帮助——同时工作和不工作的代码往往会突出问题)
标签: java android c++ c android-ndk