我正在开发一个GPS应用程序,用户可以在屏幕上的任意位置点按以录制音频片段,然后在录制时将其附加到轨道。我正在使用媒体记录器在我的应用程序内执行此操作,而不是发出隐含的意图。这样,用户可以“无眼睛”操作,如下所示。我编写了两种模式:(1)用户点击和应用程序记录一个简短的,固定的(10秒)片段; (2)用户点击以启动媒体记录器,然后再次点击以停止它。
我在Overlay.onTap中观察点击,并在自己的线程中运行媒体记录器。代码如下。
这是我的问题,在模式(2)中:第一次点击后,媒体记录器启动正常,但没有后续的点击触发。实际上,在60秒的录制过程中,UI线程似乎已完全冻结。
顺便说一下,我最初在活动中编写了媒体记录器的东西;然后我把它移到后台线程试图解决冻结问题,但没有用。重叠代码如下:
/**
* DKR: When User has tapped on a media icon,
* The MapView calls us here, giving us the GeoPoint
* (lat and lon) where User tapped.
*/
@Override
public boolean onTap(GeoPoint tappedGeoPoint, MapView mapview)
{
return commonOnTap(tappedGeoPoint);
}
//boolean isRecording = false;
boolean oneTapAudio = false;
boolean twoTapAudio = true;
boolean firstTap = false;
/**
* Method AsyncOverlay.onTap calls commonOnTap and sends us the GeoPoint of the tap.
* Send the tapped GeoPoint to each segment object, to see which one has
* the corresponding media waypoint, if any.
*/
public boolean commonOnTap(GeoPoint tappedGeoPoint)
{
boolean isLogging = GPSLoggerService.isLogging();
if ( isLogging )
{
if ( oneTapAudio ) // Override so that tap takes User to audio recorder @ InsertNote.addQuickAudio
{ // Possibly run addQuickAudio in background thread for greater reliability.
Intent intent = new Intent(mLoggerMap.getActivity(), InsertNote.class);
String s = GPStracking.AUTHORITY+"/Request";
intent.putExtra(s, InsertNote.ONETAPAUDIO);
mLoggerMap.getActivity().startActivity(intent);
return true;
//mLoggerMap.invalidate();
//InsertNote insert = new InsertNote();
//insert.addQuickAudio();
}
if ( twoTapAudio )
{
if ( !firstTap )
{
firstTap = true;
Intent intent = new Intent(mLoggerMap.getActivity(), InsertNote.class);
String s = GPStracking.AUTHORITY+"/Request";
intent.putExtra(s, InsertNote.TWOTAPONAUDIO);
mLoggerMap.getActivity().startActivity(intent);
}
else
{
firstTap = false;
Intent intent = new Intent(mLoggerMap.getActivity(), InsertNote.class);
String s = GPStracking.AUTHORITY+"/Request";
intent.putExtra(s, InsertNote.TWOTAPOFFAUDIO);
mLoggerMap.getActivity().startActivity(intent);
}
return true;
}
}
boolean handled = false;
for (SegmentRendering segment : mSegmentRenderersList)
{
if (!handled)
{
handled = segment.commonOnTap(tappedGeoPoint);
}
}
return handled;
}
活动代码如下:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setVisible(false);
paused = false;
isRecording = false;
mLoggerServiceManager = new GPSLoggerServiceManager(this);
final Semaphore audioSemaphore = new Semaphore(0);
mRecordAudioThread = new Thread("audioRecorder")
{
@Override
public void run()
{
Looper.prepare(); // Initialize the current thread as a looper.
mAudioThreadHandler = new Handler(); // Create an Handler to communicate with the Looper.
audioSemaphore.release(); // the only release in the whole program
Looper.loop(); // Run the message queue in this thread.
}
};
mRecordAudioThread.start();
try
{
audioSemaphore.acquire();
}
catch (InterruptedException e)
{
Log.e(TAG, "Failed waiting for a semaphore", e);
}
}
@Override
protected void onResume()
{
int request = 0;
super.onResume();
String s = GPStracking.AUTHORITY+"/Request";
Bundle extras = getIntent().getExtras();
if (extras != null) request = extras.getInt(s);
if ( request == ONETAPAUDIO || request == TWOTAPONAUDIO || request == TWOTAPOFFAUDIO )
{
QuickAudioLogic( request );
return;
}
if (mServiceBindAction == null)
{
mServiceBindAction = new Runnable()
{
@Override
public void run()
{
showDialog(DIALOG_INSERTNOTE);
}
};
}
;
mLoggerServiceManager.startup(this, mServiceBindAction);
}
@Override
protected void onPause()
{
super.onPause();
mLoggerServiceManager.shutdown(this);
paused = true;
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
}
public void QuickAudioLogic(int request)
{
mRecorder = new MediaRecorder();
if ( request == ONETAPAUDIO )
{
if ( !isRecording )
{
isRecording = true;
mDuration = ONETAPDURATION;
mAudioThreadHandler.post(recordAudioAsync);
// QuickAudioAction ( ONETAPDURATION );
}
return;
}
if ( request == TWOTAPONAUDIO )
{
if ( !isRecording )
{
isRecording = true;
mDuration = TWOTAPDURATION;
mAudioThreadHandler.post(recordAudioAsync);
// QuickAudioAction ( TWOTAPDURATION );
}
return;
}
if ( request == TWOTAPOFFAUDIO )
{
if ( isRecording )
{
isRecording = false;
Toast.makeText(this, "Stop recording audio",Toast.LENGTH_SHORT).show();
mRecorder.reset();
mRecorder.release();
mRecorder = null;
finish();
}
}
}
后台(媒体记录器)线程如下:
public Runnable recordAudioAsync = new Runnable()
{
@Override
public void run()
{
String newName;
Calendar c = Calendar.getInstance();
newName = String.format( "Audio" + getString( R.string.dialog_filename_default)+".3gpp", c, c, c, c, c, c );
//newName = String.format("Audio_%tY-%tm-%td_%tH%tM%tS.3gpp", c, c, c, c, c, c);
File newFile = new File(Constants.getSdCardDirectory(InsertNote.this) + newName);
newName = newFile.toString();
android.net.Uri.Builder builder = new Uri.Builder();;
sUri = builder.scheme("file").appendEncodedPath("/"+newName).build();
//sUri = Uri.parse(newName); // store Uri static, so that
try {
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile(newName);
mRecorder.setMaxDuration( mDuration );//mDuration = 10000 for one tap or 60000 for two tap mode
mRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener(){
@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if(what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED )
{
InsertNote.this.mLoggerServiceManager.storeMediaUri(sUri);
//setResult(MENU_VOICE, new Intent());
//mLoggerMap.invalidate();
isRecording = false;
Toast.makeText(InsertNote.this, "Timeout recording audio",Toast.LENGTH_SHORT).show();
mRecorder.reset();
mRecorder.release();
finish();
//startActivity(new Intent(this.getApplicationContext(), ANOTHERACTIVITY.class));
}
}
});
mRecorder.prepare();
isRecording = true;
Toast.makeText(InsertNote.this, "Start recording audio",Toast.LENGTH_LONG).show();
mRecorder.start();
//((Button)(findViewById(R.id.record_button))).setText("stop");
}
catch (Exception e) {
Toast.makeText(InsertNote.this, "Error starting audio recorder.",Toast.LENGTH_SHORT).show();
}
return;
}
};
答案 0 :(得分:0)
只能从UI线程修改UI组件。 删除toast消息或尝试将线程作为UI线程运行。
public void run(){
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
// Things to do
}
});
}