音轨发布

AudioTrack release

我想知道是否需要在音轨上调用释放?

例如,在我的以下代码中,我在一个方法中实例化了一个 AudioTrack 实例,并且不对其调用 release(因为那样会停止播放)。

这有什么影响?

public void playTone()
{
    float[] output = createTone();

    AudioTrack track = new AudioTrack(AudioManager.STREAM_RING, 44100,
            AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT,
            (output.length*4),
            AudioTrack.MODE_STATIC);

    short[] result =  new short[output.length];

    for(int i = 0; i < output.length; i++)
        result[i] = (short) ((output[i])*32768);

    track.write(result, 0, output.length);
    track.play();
}

如果不调用 release(),就会泄漏 Java AudioTrack 对象后面的本机内存。 AudioTrack 并非完全Java,因此需要调用让本机代码释放自己的内存,因为它不会被垃圾收集。

您应该始终在完成后调用 release() 以避免与在您的应用中消耗过多内存相关的问题。

这会导致暂时的资源泄漏,但不会是永久性的。最终,垃圾收集器将释放所有内存和资源。但是您可能想调用 release() 以避免错误,因为 "eventually" 可能还不够快。

我已经在 Android 4.4.2 设备上验证,当不再在任何地方引用流 AudioTrack 并且垃圾收集是 运行 时,它将完成, stop() 是否被调用。

在Android的源代码中(我看了Android N的),finalize() calls the same native function as release()做:

static void android_media_AudioTrack_finalize(JNIEnv *env,  jobject thiz) {
    //ALOGV("android_media_AudioTrack_finalize jobject: %x\n", (int)thiz);
    android_media_AudioTrack_release(env, thiz);
}

所以是的,最终,资源将被释放,而无需您显式调用 release()

但如果在短时间内创建了太多 AudioTrack,这可能会成为一个问题。在循环中创建和取消引用它们:

for (...) {
    new AudioTrack(...);
}

我最终在日志中收到此错误:

E/AudioTrack-JNI: Error initializing AudioTrack
E/android.media.AudioTrack: Error code -20 when initializing AudioTrack.
E/AudioTrack: AudioFlinger could not create track, status: -12

垃圾收集没有解决这个问题;它不是 运行 因为有足够的普通堆内存可用。 release() 释放的类型的其他资源,运行 退出。此错误未触发立即垃圾回收。调用 release(),当然可以解决这个问题。

"...(因为那会停止播放):"如果您使用 release(),您必须非常确定所有事情都已完成并且当前未使用曲目。 play() 似乎启动了一个线程。所以
track.play(); // AudioTrack.MODE_STATIC or AudioTrack.MODE_STREAM track.release();
大部分会失败开始播放。