У меня возникли проблемы с закрытием приложения для 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;
}
}
Я искал несколько дней здесь и в Google, как выполнить то, что я хочу сделать. Мой код выше - это склейка различных фрагментов кода, которые я нашел в интернете, с настройками, подходящими для моего варианта использования.
Что я пытаюсь сделать:
Я прочитаю данные из сокета в моем приложении для Android, передам эти данные в мой код C для декодирования (хотя алгоритм читает их по частям во время выполнения алгоритма, то есть я не могу передать byteArray из Java на C и вызываю мою функцию C несколько раз, так как декодер иногда использует данные из предыдущих байтов чтения). Мой код C выполняет декодирование и передает данные PCM обратно в мое приложение Android для воспроизведения на AudioTrack.
Я использую кольцевой буфер для буферизации данных из сокета.
Когда я пытаюсь отладить свое Android-приложение, я устанавливаю точки останова на входах для функций чтения и записи, и они, кажется, никогда не вызываются.
Что-то не так, когда я передаю byteArray из моего C-кода в JAVA для заполнения данными? Должен ли я сделать это альтернативным способом?