0

我是 Java 和 Android 编程的新手,虽然我已经完成了一些广泛的 PHP 编码,所以我很快就理解了大多数概念。我不知道做事的“方法”。

作为一个练习应用程序,我想编写一个快速傅立叶变换应用程序,向我显示录制的音频频谱(我是物理专业的,所以这似乎是一个值得和有趣的小项目。)(是的,我知道它以前做过)。

到目前为止,我已经设置了 AudioRecord 阅读器并让它读取字节,我发现如果我想让它在后台运行而不冻结应用程序,我需要创建一个发布到处理程序的线程,我想了解如何将数据传递给 Handler。现在它只是在 MainActivity 的 TextView 中显示字节,所以我可以“看到”正在发生的事情。

我被卡住的地方显然是因为我的处理程序不是静态的,在我的应用程序完美运行几秒钟后,GC 会破坏一些东西(我不知道是什么),然后它就崩溃了。经过一番阅读,我似乎发现我需要扩展 Handler 并实现一些 WeakReference,但老实说,它已经到了我不知道自己在做什么的地步。如果有人能解释这里到底发生了什么,或者我如何从某个外部类中引用我的 TextView,我将不胜感激。在此先感谢东风

这是代码:

private Handler uiCallback = new Handler () {
    public void handleMessage (Message msg) {

        tv.setText(Arrays.toString(msg.getData().getByteArray("data")));
    }
};

@Override
protected void onResume() {
    super.onResume();

    tv = (TextView) findViewById(R.id.mainView);

    bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
    ar = new AudioRecord(AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); 

    shortbuffer = new short[bufferSize];
    bytebuffer = new byte[bufferSize];

    ar.startRecording();

    tv.setText("Hello");

    int N = 0;

    // now you can start reading the bytes from the AudioRecord
    Thread t = new Thread() {
        public void run() {
            Bundle b = new Bundle();
            Message msg = Message.obtain();
            while (true) {
                ar.read(bytebuffer, 0, bytebuffer.length);
                byte[] pkt = Arrays.copyOf(bytebuffer, bytebuffer.length);

                //tv.setText(Arrays.toString(pkt));

                b.putByteArray("data", pkt);
                msg.setData(b);
                uiCallback.sendMessage(msg);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }
    };

    t.start();
}

@Override
protected void onPause() {
    super.onPause();

    ar.stop();
}
4

2 回答 2

0

您在循环中多次发送相同的消息,您必须在发送之前获取一条新消息

于 2013-04-17T19:32:52.043 回答
0

弱引用是避免访问已从其容器(例如活动)中删除的视图的提示。

一个可能的替代解决方案是您执行以下操作:

class YourSpecialAudioClass implements ISpecialAudioClass
{
/**this class can be used by the outside UI world, inside the implementation of the runnable in the CTOR*/
@override
public byte[] getData(){...}

public YourSpecialAudioClass(Runnable doSomethingWithDataRunnable)
  {
  this.doSomethingWithDataRunnable=doSomethingWithDataRunnable;
  this.handler=new Handler();
  }
...
  while(true)
    {
    ...
    this.handler.post(this.doSomethingWithDataRunnable);
    }
...
}

不要忘记在不需要时停止线程更新 UI,尤其是在 Activity 正在关闭时。

于 2013-04-17T20:25:32.810 回答