내가 (오류없이 또는 아무것도) 다음 코드를 실행하려고 할 때 닫는 내 안드로이드 앱 문제로 실행되었습니다 난에 "문제"코드를 추적 한JNI BYTEARRAY 통과 도움
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);
행. 이 줄 앞에서 돌아 오면 내 앱이 닫히지 않지만이 줄 바로 다음에 돌아 오면 오류없이 앱이 임의로 닫힙니다.
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에서 검색 한 다음은
는 자바 코드입니다. 위의 코드는 인터넷에서 발견 된 다양한 코드 스 니펫을 함께 사용하여 사용 사례에 맞게 조정 한 것입니다.내가 달성하기 위해 노력하고있어 : 알고리즘이 중에 조각으로 조각을 읽어하지만 내 안드로이드 응용 프로그램의 소켓에서 데이터를 읽어
(디코딩에 내 C 코드에이 데이터를 전달 알고리즘, 자바에서 byteArray를 C로 전달할 수없고, 디코더가 때때로 이전의 읽기 바이트에서 데이터를 사용하기 때문에 여러 번 C 함수를 호출 할 수 없다는 것을 의미합니다. 내 C 코드가 디코딩을 수행하고 AudioTrack에서 재생할 PCM 데이터를 다시 Android 앱에 전달합니다.
소켓의 데이터를 버퍼링하는 순환 버퍼를 사용하고 있습니다.
Android 앱을 디버깅하려고 할 때 항목의 읽기 및 쓰기 기능에 중단 점을 설정 했으므로 절대로 호출되지 않습니다.
byteArray를 C 코드에서 JAVA로 데이터를 채울 때 뭔가 잘못하고 있습니까? 이 방법을 다른 방법으로 수행해야합니까?
정말 고마워요. 그게 내 실수를 고쳤어! 그러나 몇 초 동안 실행 한 후에 DeleteLocalRef() 호출을 제거하면 응용 프로그램이 계속 충돌합니다. 내가 24MB 최대 메모리 제한의 일종을 공격하기 전에 내가 다시 그들을 넣어 때 재생 약 2-3 분. 내 프로그램을 실행하는 동안 메모리를 더 확보 할 수있는 방법이 있습니까? 로컬 참조를 삭제 한 후 GC가이 바이트 배열을 해제하지 않는 이유를 모르겠습니다! – someone1
@som 나는 * java *에 대한 장과 절을 인용 할 수 있다고 생각한다. 그래서 내가 너를 도울 수없는 안드로이드 만의 특별한 경험을하고 있다고 생각하게 만든다. – bmargulies
나는 그것을 이해했다. 밖으로 디코더 (내가 사용했던 다른 라이브러리에서 내 다른 디코딩 테스트를 받았다고 기대하지 않았던 것)보다 빨리 소모하지 않는 AudioTrack에 쓰려고 데이터 스레드를 대기시켜 메모리가 부족합니다.합리적인 양의 큐 대기열을 차단하기 위해 자바 측에 스레드 컨트롤을 추가했습니다. 모든 도움을 주셔서 다시 한 번 감사드립니다! – someone1