尝试执行以下代码时,我的Android应用程序关闭(没有错误或任何内容)一直存在问题:
JNIEXPORT void Java_teamjeff_oggstreamtest_MainTest_audioFunc(JNIEnv* env, jobject obj) {
//<REMOVED VARIABLE INITIALIZATION>
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID writeDataFunc = (*env)->GetMethodID(env, cls, "writeToAudioTrack", "([B)V");
if (!writeDataFunc) return;
jmethodID readDataFunc = (*env)->GetMethodID(env, cls, "readFromBuffer", "([B)I");
if (!readDataFunc) return;
rawDataRead = (*env)->NewByteArray(env, 4096);
bytes = (*env)->CallIntMethod(env, obj,readDataFunc, &rawDataRead);
char* carr = (*env)->GetByteArrayElements(env, rawDataRead, NULL);
memcpy(buffer, carr, bytes);
(*env)->DeleteLocalRef(env, rawDataRead);
//<REMOVED REST OF FUNCTION>
}
我已经跟踪了bytes = (*env)->CallIntMethod(env, obj,readDataFunc, &rawDataRead);
行的“麻烦”代码。如果我在此行之前返回,我的应用程序不会关闭,但如果我在此行之后立即返回,我的应用程序会随机关闭,甚至没有错误。
这是JAVA代码:
package teamjeff.oggstreamtest;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import com.Ostermiller.util.CircularByteBuffer;
public class MainTest extends Activity {
public static Handler mHandler = new Handler();
private final CircularByteBuffer cbb = new CircularByteBuffer(1024*512, true);
public AudioTrack mAudioTrack;
static {
System.loadLibrary("vorbis-decoder");
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
final Socket test = new Socket(InetAddress.getByName(<HOME SERVER URL>), <PORT>);
new Thread(
new Runnable(){
public void run(){
try {
while(!test.isClosed()) {
byte[] temp = new byte[4096];
int bytes = test.getInputStream().read(temp, 0, 4096);
cbb.getOutputStream().write(temp, 0, bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
).start();
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
44100,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
1024*64,
AudioTrack.MODE_STREAM);
mAudioTrack.play();
new Thread(new Runnable() {
public void run() {
audioFunc();
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
public native void audioFunc();
@SuppressWarnings("unused")
private void writeToAudioTrack(final byte[] media) {
mHandler.post(new Runnable() {
public void run() {
mAudioTrack.write(media, 0, media.length);
}
});
}
@SuppressWarnings("unused")
private int readFromBuffer(byte[] buffer) {
try {
return cbb.getInputStream().read(buffer, 0, buffer.length);
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}
}
我已经在这里和谷歌搜索了如何完成我想要做的事情。我上面的代码是将我在互联网上发现的各种代码片段粘合在一起,调整以适应我的用例。
我正在努力实现的目标:
我将从Android应用程序中的套接字读取数据,将此数据传递给我的C代码进行解码(尽管算法在算法期间逐个读取它,这意味着我无法从Java传递byteArray到C并多次调用我的C函数,因为解码器有时使用来自先前读入字节的数据)。我的C代码执行解码,并将PCM数据传递回我的Android应用程序以在AudioTrack上播放。
我正在使用循环缓冲区缓冲来自套接字的数据。
当我尝试调试我的Android应用程序时,我在读取和写入功能的条目中设置了断点,并且它们似乎永远不会被调用。
当我从我的C代码传递byteArray到JAVA以填充数据时,我做错了什么?我应该这样做吗?
答案 0 :(得分:1)
一些可能有用的说明。
&amp; rawDataRead错了。失去&amp ;.你只需传递你得到的参考号,而不是它的地址。
您无需删除该本地参考。当本机函数返回时,将删除所有本地引用。我相信这在 java 中是正确的,但是android情况可能会有所不同。
您不必继续检索方法ID。你可以把它们拿到一次并挂在它们上面。