2013-03-16 69 views
0

我開發一個GPS應用程序中,用戶可以點擊屏幕上的任何地方記錄的音頻片段,然後把它連接到一個軌道,因爲它記錄。我正在使用媒體記錄器在我的應用程序中執行此操作,而不是發出隱含的意圖。這樣,用戶可以操作「無眼睛」,如下所示。我已經編碼的兩個模式:(1)用戶抽頭和應用記錄了短的,固定(10秒)片段; (2)用戶點擊以啓動媒體記錄器,然後再次點擊以停止。Android的媒體記錄凍結(鎖式)UI線程

我看在Overlay.onTap水龍頭,並運行在自己的線程媒體記錄器。代碼如下。

這裏是我的問題,在模式(2):第一次輕觸後,媒體記錄器啓動正常,但沒有後續水龍頭火中的onTap。事實上,UI線程似乎完全凍結了60秒的記錄。

BTW,我最初的代碼就在活動媒體記錄的東西;然後我將它移到後臺線程以嘗試解決凍結問題,但無濟於事。

疊加代碼如下:

/** 
* 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

對不起,但你的代碼是一團糟 - 太多了,有些沒有意義。這是一個音頻捕捉指南... http://developer.android.com/guide/topics/media/audio-capture.html我建議你退後一步,並根據該指南重新編寫東西。另外,'MediaRecorder'使用它自己的線程 - 如果你得到一個UI凍結,你會做其他的錯誤。 – Squonk 2013-03-17 00:37:11

回答

0

UI組件只能從UI改性線。 要麼刪除敬酒消息或嘗試運行您的主題UI線程。

public void run(){ 
activity.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
        // Things to do 
       } 
       }); 
      } 
+0

我通過將MediaRecorder代碼移動到Overlay類中解決了此問題。一旦它在那裏,MediaRecorder不再阻止onTap方法。爲什麼?誰知道!無論如何... – BinCodinLong 2013-03-31 21:01:40