Android AsyncTask isCancelled()返回true,但doInBackground不返回';t端
我有一个录制音频的任务。问题是一旦我从UI线程调用Android AsyncTask isCancelled()返回true,但doInBackground不返回';t端,android,android-asynctask,Android,Android Asynctask,我有一个录制音频的任务。问题是一旦我从UI线程调用cancel(true),isCancelled()返回true(就像它应该返回的那样),但是doInBackground函数保持运行,如果我运行getStatus()在AsyncTask上,它返回RUNNING,并且onCancelled方法都不被称为nore doesonPostExecute 由于(!isCancelled())时,所有doInBackground代码都放在中,因此一旦任务取消,该方法应该结束 调用AsyncTask.can
cancel(true)
,isCancelled()
返回true
(就像它应该返回的那样),但是doInBackground
函数保持运行,如果我运行getStatus()
在AsyncTask上,它返回RUNNING,并且onCancelled
方法都不被称为nore doesonPostExecute
由于(!isCancelled())时,所有doInBackground
代码都放在中,因此一旦任务取消,该方法应该结束
调用AsyncTask.cancel()后,while(!isCancelled())循环结束。我认为问题在于没有调用returnnull
,这就是doInBackground
没有结束的原因。。。但我可能错了
代码:
recordSlideBar
是我编写的一个自定义视图,其中有一个onTouchListener,而recordSlideBar.setDownRun(Runnable)
为MotionEvent.ACTION\u DOWN
和recordSlideBar.setUpRun(Runnable)
为MotionEvent.ACTION\u UP
设置一个Runnable
基本上,我创建AsyncTask并在调用ACTION\u DOWN
时执行它,在调用ACTION\u UP
时取消它
我对整个音频捕获技术都是新手,所以您可能会在我的代码中看到一些关于这方面的错误。请记住,现在的问题是AsyncTask;)
编辑:这是我取消任务后调试器面板的打印屏幕。请注意,AsyncTask状态为WAIT,在变量选项卡中,mCancelled
为true
,mStatus
正在运行
中可能会阻止
读取功能
int numberOfShort=record.read(audioBuffer,0,audioBuffer.length)代码>
因此,而(!isCancelled())
可能永远不会被调用
您可以将Log.d()
放入while
中,以检查代码是否被阻止,如
而(!isCancelled())
{
Log.d(“RECTASK”,“开始读取”);
int numberOfShort=record.read(audioBuffer,0,audioBuffer.length);
numSample+=numberOfShort;
Log.d(“RECTASK”,“end read”);
}
它被卡住了,因为使用的AudioRecord.read()
方法是一个阻塞调用,它在本机级别而不是Java级别阻塞。因此,作为AsyncTask.cancel()
的一部分发送的“中断”将无效。不要使用此版本的read()
,而是使用采用readMode
参数的版本,并将其设置为read\u NON\u BLOCKING
。然后,您的循环将需要处理部分读取(以及实际处理数据-现在它只是将数据读取到一个方法本地数组中!)您可以在开始此任务的位置添加代码并取消它吗?您可以做任何事情:)尝试您的解决方案。还是一样的问题。isCancelled()变为true,但doInBackground仍在运行。如果将其设置为非阻塞,则不应发生这种情况。运行时,查看线程堆栈,并查看异步任务线程在doInBackground()
方法中的位置。我现在看到异步任务的状态正在等待,但我不明白为什么。。。如果你介意看一下我添加的屏幕截图并给出你的意见,那就太好了!这实际上是主线程在等待取消AsyncTask
。您需要查看应用程序进程的所有线程列表,并找到运行您的任务的AsyncTask
线程(它将被标记为这样的名称)。我在while循环中已经有一个Log.d,它工作正常(日志一次又一次地出现,直到isCancelled()变为true,循环结束)。我删除了日志,因为它使我的logcat崩溃…@AlonLevylog.d(“RECTASK”,“after while\niscalled=“+isCancelled())代码>这是在取消后调用的吗?是。我编辑了这个问题,并解释了while(isCancelled())循环以它结束should@AlonLevy有些事你应该知道。取消任务后,任务的状态将保持为PENDING
或RUNNING
。取消任务后,状态不会更改。您应该同时检查状态和isCanceled()
。很高兴知道这一点!但是它并没有真正解决我的问题,因为我确实检查任务是否已取消()
,并且它返回true
。我添加了一个屏幕截图,显示了任务的变量:)
package Classes;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.util.Log;
import com.appetizers.app.trytabs.Main2Activity;
/**
* Created by Alon on 09-Aug-16.
*/
public class RecordingTask2 extends AsyncTask<Void,Void,Void> {
AudioRecord record;
Context context;
int bufferSize;
int numSample=0;
private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
short[] audioBuffer;
public RecordingTask2(Context context) {
this.context = context;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.d("RECTASK", "onPre");
record = findAudioRecord();
record.startRecording();
}
@Override
protected Void doInBackground(Void... params) {
audioBuffer = new short[bufferSize/2];
Log.d("RECTASK","before while");
while(!isCancelled())
{
//Log.d("RECTASK","isCancelled = "+isCancelled());
int numberOfShort = record.read(audioBuffer, 0, audioBuffer.length);
numSample +=numberOfShort;
}
Log.d("RECTASK", "after while\nisCancelled = "+isCancelled());
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
Log.d("RECTASK", "reached onCancel()");
end();
}
@Override
protected void onCancelled(Void aVoid) {
super.onCancelled(aVoid);
Log.d("RECTASK", "reached onCancelled(Void)");
end();
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Log.d("RECTASK", "reached onPost");
end();
}
private void end()
{
Log.d("RECTASK","reached end function");
record.stop();
record.release();
((Main2Activity)context).setNumOfSamples(numSample);
((Main2Activity)context).setSamples(audioBuffer);
}
public AudioRecord findAudioRecord() {
for (int rate : mSampleRates) {
for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) {
for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) {
try {
Log.d("FINDAUDIO", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
+ channelConfig);
bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
// check if we can instantiate and have a success
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);
Log.d("FINDAUDIO", "AudioRecorder state = "+recorder.getState());
if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
return recorder;
}
} catch (Exception e) {
Log.e("FINDAUDIO", rate + "Exception, keep trying.",e);
}
}
}
}
return null;
}
}
recordSlideBar.setDownRun(new Runnable() {
@Override
public void run() {
Log.d("MAINACT","onDown");
if(recTask==null || recTask.getStatus()!= AsyncTask.Status.RUNNING) {
recTask = new RecordingTask2(Main2Activity.this);
recTask.execute();
}
}
});
recordSlideBar.setUpRun(new Runnable() {
@Override
public void run() {
Log.d("MAINACT", "onUp");
recTask.cancel(true);
Log.d("MAINACT", "after cancel\nstatus = "+recTask.getStatus());
while(recTask.getStatus()!= AsyncTask.Status.FINISHED)
{
//waiting for task to end...
}
ShortBuffer shortBuffer = ShortBuffer.allocate(samples.length);
playTask = new PlayingTask(Main2Activity.this,shortBuffer,numOfSamples);
}
});