2011-04-09 71 views
1

我一直運行到我的Android應用程序關閉問題嘗試執行以下代碼時(沒有錯誤或任何東西):JNI的ByteArray通過幫助

​​

我跟蹤的「麻煩」的代碼到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代碼解碼(雖然算法一塊一塊在讀它算法,這意味着我無法將byteArray從Java傳遞到C,並且多次調用我的C函數,因爲解碼器有時使用先前讀入字節中的數據)。我的C代碼進行解碼,並將PCM數據傳回我的Android應用程序,以便在AudioTrack上播放。

我正在使用循環緩衝區緩衝來自套接字的數據。

當我嘗試調試我的Android應用程序,我設置的條目突破點,同時讀寫功能,他們似乎從來沒有被調用。

難道我做錯了什麼,當我經過的ByteArray從我的C代碼,JAVA來填充數據?我應該以另一種方式做這個嗎?

回答

1

一些注意事項可能有幫助。

  1. & rawDataRead是錯誤的。失去&。你只需傳遞你得到的ref,而不是它的地址。

  2. 你不需要刪除那個本地文獻。當本地函數返回時,所有本地引用都將被刪除。我相當有信心,這是java,但android的情況可能會有所不同。

  3. 你不必守檢索方法ID。你可以得到它們一次並掛上它們。

+0

太謝謝你了。這解決了我的錯誤!但是,當我在運行幾秒後刪除了DeleteLocalRef()調用時,我的應用程序繼續崩潰。當我把它們放回去時,我會在播放某種24MB最大內存限制之前獲得大約2-3分鐘的播放時間。有沒有辦法在執行我的程序時進一步釋放內存?我不知道爲什麼刪除本地引用後,這些字節數組沒有被GC釋放! – someone1 2011-04-10 16:21:05

+0

@som我想我可以在* java *上引用你的章節和經文。這導致我認爲你遇到了特定於android的東西,我無法幫助你。 – bmargulies 2011-04-10 17:38:52

+1

我想通了。事實證明,由於數據線程排隊等待寫入AudioTrack,而不是解碼器解碼耗盡的速度(我沒有預料到給出了其他使用其他庫的解碼測試),所以我的內存不足。我在JAVA端添加了一些線程控制來阻塞線程排隊到合理的數量。再次感謝你的幫助! – someone1 2011-04-11 06:22:16