簡體   English   中英

Android Studio:While循環凍結應用程序

[英]Android Studio: While Loop Freezing Application

我的Android Studio應用程序代碼由一個開始/停止按鈕組成,該按鈕用於使用AudioRecord錄制音頻,然后將該音頻數據輸出到文本視圖,一次完成效果很好。 如果我反復單擊該按鈕,它也可以工作。 但是,如果我將其置於while循環中,則該應用程序將凍結(僅該應用程序將凍結;在仿真器和真正的智能手機上結果相同)。 我相信我發現它與AudioRecord沒有任何關系,也沒有將循環放入按鈕偵聽器中,或者將其放入從偵聽器調用的方法中,或者與被調用的方法相反,開始和停止了錄音。偵聽器,甚至lambda表達式或其他任何內容。 沒有while循環,它會正常工作; 它凍結了。 但是我需要連續獲取音頻數據。 非常感謝您的幫助。 我的縮寫代碼:

public class MainActivity extends AppCompatActivity {

    public static final int SAMPLE_RATE = 16000;

    private AudioRecord recorder;
    private Button btn;
    private TextView txtView;
    private boolean isRecording = false;
    private short[] buffer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn = (Button) findViewById(R.id.btn);
        txtView = (TextView) findViewById(R.id.TextView);

        initializeRecorder();

        btn.setOnClickListener(e -> {
            if (!isRecording) {
                btn.setText("Stop");
                isRecording = true;
                recorder.startRecording();
                record();
            }
            else {
                btn.setText("Start");
                isRecording = false;
                recorder.stop();
            }
        });
    }

    private void initializeRecorder() {
        int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, 
                AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT);
        buffer = new short[bufferSize];
        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
                SAMPLE_RATE,
                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 
                bufferSize);
    }

    private void record() {
        int readSize;

        while (isRecording) { // This is the loop causing trouble

            readSize = recorder.read(buffer, 0, buffer.length);
            // Perform calculations on this data and output to txtView, 
            // like:

            txtView.setText(Integer.toString(readSize));

            // BTW, I know I'm not saving this audio to a file; that's on 
            // purpose. I just need this data.
        }
    }

    @Override
    public void onDestroy() {
        recorder.release();
        super.onDestroy();
    }
}

應用程序掛起的原因是Android具有UI線程的概念:簡而言之,一個呈現UI,負責用戶輸入的線程等為了確保您的應用程序不會感到緩慢,您需要能夠每16ms進行一次渲染Windows,每秒60fps。 因此,如果您超載UI線程(例如在大循環/ IO中)-系統將無法呈現UI,請及時響應事件,因此應用程序將凍結。

為了避免這種情況,您需要使數據異步。 最好的選擇是放入服務。 GitHub上有很多示例,這是一個很好的例子:

https://github.com/dkim0419/SoundRecorder

RecordingService示例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM