Android Studio: приложение «Замораживание цикла» - PullRequest
0 голосов
/ 19 января 2019

Мой код в приложении в Android Studio, состоящий из кнопки «Пуск / Стоп» для записи звука с использованием AudioRecord и последующего вывода этих аудиоданных в текстовое представление, прекрасно работает, когда выполняется один раз. Если я несколько раз нажимаю на кнопку, это тоже работает. Однако, если я поместил его в цикл while, приложение зависнет (только приложение зависнет; тот же результат на эмуляторе и реальном смартфоне). Я полагаю, что обнаружил, что он не имеет ничего общего с AudioRecord, не помещает цикл в слушатель кнопки, не помещает его в метод, вызванный из слушателя, или запускает и останавливает запись в вызываемом методе, в отличие от слушатель, или даже лямбда-выражения или что-нибудь. Без цикла 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();
    }
}

1 Ответ

0 голосов
/ 19 января 2019

Причина, по которой приложение зависает, заключается в том, что в Android реализована такая концепция потока пользовательского интерфейса: короче говоря, поток, который отображает пользовательский интерфейс, отвечает за ввод данных пользователем и т. Д. Чтобы убедиться, что приложение не работает медленно, необходимо иметь возможность выполнять рендеринг.в каждые 16 мс Windows для 60 кадров в секунду.Таким образом, если вы перегружаете поток пользовательского интерфейса (как в большом цикле / ввод-выводе) - система не сможет визуализировать пользовательский интерфейс, вовремя реагировать на события, поэтому приложение зависнет.

Чтобы избежать этоговам нужно получить данные асинхронными.Наилучшим вариантом будет размещение в Сервисе.На GitHub есть много примеров, вот хороший:

https://github.com/dkim0419/SoundRecorder

Пример службы записи

...