title: Android MediaRecorder stop() not being called
body: <p>I have this really weird bug where some of my code is not being called, but doesn't look there is any reason why it wouldn't be called.</p>
  
  <p><strong><code>onFinishedRecording</code> gets called and the tag <code>"Finished recording."</code> gets logged out, but the code after that does not get called at all. All the code stops being called when <code>mMediaRecorder.stop();</code> is called. It also does not go into the catch block either. Why is this happening?</strong></p>
  
  <p>I thought it might have to do with different threads, but I checked all the thread names and they are all running on the same main thread.</p>
  
  <p><em>Also, could there be something wrong with my camera preview setup? When I try to play the video back, it is corrupted and not able to playback.</em></p>
  
  <p><em>In addition to the above problems, my back button doesn't do anything in the application. Not quite show why or how it is related to the code that I have implemented.</em></p>
  
  <p><strong>MyLibrary class (library module class)</strong></p>
  
  <pre><code>public class MyLibrary implements PreciseCountdownTimer.PreciseCountdownTimerCallback {
  
      private static final String TAG = AngryOtter.class.getSimpleName();
      private static final long MAX_RECORD_TIME_MILLIS = 3000;
      private static final long INTERVAL_MILLIS = 1000;
  
      private static MyLibrary mInstance;
  
      private Activity mActivity;
      private CameraInitListener mCallback;
  
      private int mCameraId = -1;
      private Camera mCamera;
      private SurfaceView mCameraPreview;
      private MediaRecorder mMediaRecorder;
      private PreciseCountdownTimer mTimer;
      private File mTempVideoFile;
  
      public static MyLibrary getInstance() {
          if (mInstance == null) {
              mInstance = new MyLibrary();
          }
          return mInstance;
      }
  
      // Call this in onResume of the activity
      public void initialize(Activity activity) {
          mActivity = activity;
  
          try {
              mCallback = (CameraInitListener) mActivity;
          } catch (ClassCastException e) {
              throw new ClassCastException(activity.getClass().getSimpleName()
                      + " must implement CameraInitListener");
          }
  
          if (ViewUtil.checkValidRootView(mActivity)) {
              PermissionUtil.requestPermissions(mActivity);
              prepareCamera();
              if (mCamera == null) {
                  return;
              }
              addCameraPreview();
          }
      }
  
      // Call this in onPause of the activity
      public void release() {
          releaseMediaRecorder();
          releaseCamera();
          removeCameraPreview();
          releaseTimer();
      }
  
      public void startRecording() {
          if (checkPermissions()) {
              try {
                  mMediaRecorder.start();
                  mTimer.start();
                  Log.d(TAG, "Recording started.");
              } catch (IllegalStateException e) {
                  releaseMediaRecorder();
                  releaseTimer();
              }
          } else {
              releaseMediaRecorder();
          }
      }
  
      public void stopRecording() {
          onFinishedRecording();
      }
  
      @Override
      public void onPreciseTimerTick(long remainingTime) {
          Log.d(TAG, "TICK: " + String.valueOf(remainingTime));
      }
  
      @Override
      public void onPreciseTimerFinished() {
          Log.d(TAG, "Timer Finished.");
          mActivity.runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  onFinishedRecording();
              }
          });
      }
  
      private boolean checkPermissions() {
          if (PermissionUtil.checkCameraPermission(mActivity)
                  &amp;&amp; PermissionUtil.checkRecordAudioPermission(mActivity)
                  &amp;&amp; PermissionUtil.checkWriteExternalStoragePermission(mActivity)) {
              return true;
          } else {
              return false;
          }
      }
  
      private void prepareCamera() {
          mCameraId = CameraUtil.getFrontCameraId();
          if (mCameraId != -1) {
              try {
                  Log.d(TAG, "Initializing front camera.");
                  mCamera = Camera.open(mCameraId);
              } catch (Exception e) {
                  Log.e(TAG, "Error initializing front camera: " + e.getMessage());
                  mCamera = null;
              }
          } else {
              mCamera = null;
          }
      }
  
      private void releaseCamera() {
          if (mCamera != null){
              Log.d(TAG, "Releasing camera.");
              mCamera.release();
              mCamera = null;
          }
      }
  
      private void addCameraPreview() {
          mCameraPreview = new SurfaceView(mActivity);
          mCameraPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
              @Override
              public void surfaceCreated(SurfaceHolder holder) {
                  Log.d(TAG, "Preview surface created.");
                  try {
                      Log.d(TAG, "Setting preview display.");
                      mCamera.setPreviewDisplay(holder);
                      mCamera.startPreview();
                      onPreviewDisplaySet();
                  } catch (IOException e) {
                      Log.e(TAG, "Error setting camera preview: " + e.getMessage());
                  }
              }
  
              @Override
              public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                  Log.d(TAG, "Preview surface changed.");
                  // If your preview can change or rotate, take care of those events here.
                  // Make sure to stop the preview before resizing or reformatting it.
  
                  if (mCameraPreview.getHolder().getSurface() == null) {
                      // preview surface does not exist
                      return;
                  }
  
                  // stop preview before making changes
                  try {
                      mCamera.stopPreview();
                  } catch (Exception e){
                      // ignore: tried to stop a non-existent preview
                  }
  
                  // Adjust orientation
                  final int rotation = CameraUtil.getAdjustedDisplayOrientation(mActivity, mCameraId);
                  mCamera.setDisplayOrientation(rotation);
  
                  // set preview size and make any resize, rotate or
                  // reformatting changes here
  
                  // start preview with new settings
                  try {
                      mCamera.setPreviewDisplay(mCameraPreview.getHolder());
                      mCamera.startPreview();
                  } catch (Exception e){
                      Log.d(TAG, "Error starting camera preview: " + e.getMessage());
                  }
              }
  
              @Override
              public void surfaceDestroyed(SurfaceHolder holder) {
                  Log.d(TAG, "Preview surface destroyed.");
              }
          });
          mCameraPreview.setLayoutParams(new FrameLayout.LayoutParams(100, 100, Gravity.TOP|Gravity.RIGHT));
          mCameraPreview.setBackgroundColor(ContextCompat.getColor(mActivity, android.R.color.holo_red_dark));
  
          final WindowManager windowManager =
                  (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
          final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(1, 1,
                  WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 0, PixelFormat.UNKNOWN);
          windowManager.addView(mCameraPreview, layoutParams);
      }
  
      private void removeCameraPreview() {
          if (mCameraPreview != null) {
              final ViewGroup rootView = ViewUtil.getRootView(mActivity);
              rootView.removeView(mCameraPreview);
          }
      }
  
      private void onPreviewDisplaySet() {
          createTempVideoFile();
  
          prepareMediaRecorder();
          if (mMediaRecorder == null) {
              return;
          }
  
          prepareTimer();
          mCallback.onCameraInitialized();
      }
  
      private void createTempVideoFile() {
          mTempVideoFile = FileUtil.getTempVideoFile(mActivity);
      }
  
      private void prepareMediaRecorder() {
          if (mCamera != null) {
              mCamera.unlock();
          }
  
          mMediaRecorder = new MediaRecorder();
          mMediaRecorder.setCamera(mCamera);
          mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
          mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
          mMediaRecorder.setProfile(CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_HIGH));
          mMediaRecorder.setOutputFile(mTempVideoFile.getAbsolutePath());
          mMediaRecorder.setPreviewDisplay(mCameraPreview.getHolder().getSurface());
  //        mMediaRecorder.setOrientationHint(90);
  
          try {
              Log.d(TAG, "Preparing media recorder.");
              mMediaRecorder.prepare();
          } catch (IllegalStateException|IOException e) {
              Log.e(TAG, "Error preparing MediaRecorder: " + e.getMessage());
              releaseMediaRecorder();
          }
      }
  
      private void releaseMediaRecorder() {
          if (mMediaRecorder != null) {
              Log.d(TAG, "Releasing media recorder.");
              mMediaRecorder.reset();
              mMediaRecorder.release();
              mMediaRecorder = null;
          }
  
          if (mCamera != null) {
              mCamera.lock();
          }
      }
  
      private void prepareTimer() {
          mTimer = new PreciseCountdownTimer(MAX_RECORD_TIME_MILLIS, INTERVAL_MILLIS, this);
      }
  
      private void releaseTimer() {
          if (mTimer != null) {
              Log.d(TAG, "Stopping timer.");
              mTimer.stop();
          }
      }
  
      private void onFinishedRecording() {
          Log.d(TAG, "Finished recording.");
          try {
              mMediaRecorder.stop();
              Log.d(TAG, "Media recorder stopped.");
          } catch (Exception e) {
              e.printStackTrace();
          }
  
          releaseMediaRecorder();
          releaseTimer();
          getSignedUrl();
      }
  
      private void getSignedUrl() {
          new GcpSigningRequest(new NetworkCallback&lt;String&gt;() {
              @Override
              public void onSuccess(String response) {
                  uploadVideo(response);
              }
  
              @Override
              public void onError() {
                  Log.e(TAG, "Error getting signing request.");
              }
          }).addToQueue();
      }
  
      private void uploadVideo(String signedUrl) {
          new UploadToGoogleRequest(signedUrl, mTempVideoFile.getName(),
                  Uri.parse(mTempVideoFile.getAbsolutePath()), new NetworkCallback&lt;Boolean&gt;() {
              @Override
              public void onSuccess(Boolean response) {
  
              }
  
              @Override
              public void onError() {
  
              }
          }).addToQueue();
      }
  }
  </code></pre>
  
  <p><strong>RecordActivity</strong></p>
  
  <pre><code>public class RecordActivity extends AppCompatActivity implements
          CameraInitListener {
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
      }
  
      @Override
      protected void onResume() {
          super.onResume();
          MyLibrary.getInstance().initialize(this);
      }
  
      @Override
      protected void onPause() {
          MyLibrary.getInstance().release();
          super.onPause();
      }
  
      @Override
      public void onCameraInitialized() {
          MyLibrary.getInstance().startRecording();
      }
  }
  </code></pre>
  
  <p>So everything works fine until this method is called:</p>
  
  <pre><code>    private void onFinishedRecording() {
          Log.d(TAG, "Finished recording.");
          try {
              mMediaRecorder.stop();
              Log.d(TAG, "Media recorder stopped.");
          } catch (IllegalStateException e) {
              e.printStackTrace();
          }
  
          releaseMediaRecorder();
          releaseTimer();
          getSignedUrl();
      }
  </code></pre>
  
  <p><strong>Full Phone Stacktrace</strong></p>
  
  <pre><code>08-15 21:17:46.735 24660-24660/com.walintukai.heatmapdemo I/dalvikvm: Could not find method android.content.res.Resources.getDrawable, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawable
  08-15 21:17:46.735 24660-24660/com.walintukai.heatmapdemo W/dalvikvm: VFY: unable to resolve virtual method 690: Landroid/content/res/Resources;.getDrawable (ILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
  08-15 21:17:46.735 24660-24660/com.walintukai.heatmapdemo D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
  08-15 21:17:46.735 24660-24660/com.walintukai.heatmapdemo I/dalvikvm: Could not find method android.content.res.Resources.getDrawableForDensity, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawableForDensity
  08-15 21:17:46.735 24660-24660/com.walintukai.heatmapdemo W/dalvikvm: VFY: unable to resolve virtual method 692: Landroid/content/res/Resources;.getDrawableForDensity (IILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
  08-15 21:17:46.735 24660-24660/com.walintukai.heatmapdemo D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
  08-15 21:17:46.785 933-11266/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:46.785 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:46.785 731-2931/? E/EnterpriseContainerManager: ContainerPolicy Service is not yet ready!!!
  08-15 21:17:46.785 731-2931/? D/EnterpriseDeviceManager: ContainerId: 0
  08-15 21:17:46.785 731-2931/? W/LicenseLogService: log() failed
  08-15 21:17:46.805 170-170/? E/SMD: DCD ON
  08-15 21:17:46.865 933-11213/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:46.865 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:46.935 380-24718/? E/mm-camera: color_correct_apply_gain: cc_gain_adj 1.000, digital_gain_brightness 1.000 dig_gain = 1.000
  08-15 21:17:47.055 731-24783/? W/ContextImpl: Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:1509 com.android.server.InputMethodManagerService$4.run:2683 java.lang.Thread.run:841 &lt;bottom of call stack&gt; &lt;bottom of call stack&gt; 
  08-15 21:17:47.145 174-234/? E/qdmemalloc: heap_msk=3000000 flags=1
  
  08-15 21:17:47.165 174-234/? E/qdmemalloc: heap_msk=40000000 flags=1
  
  08-15 21:17:47.185 933-10839/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:47.185 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:47.225 933-947/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:47.245 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:47.265 933-10842/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:47.275 174-940/? E/qdmemalloc: heap_msk=3000000 flags=1
  
  08-15 21:17:47.275 174-940/? E/qdmemalloc: heap_msk=40000000 flags=1
  
  08-15 21:17:47.285 24660-24660/com.walintukai.heatmapdemo D/RecordingService: Tick: 2000
  08-15 21:17:47.295 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:47.305 179-24742/? W/CameraSource: Timed out waiting for incoming camera video frames: 0 us
  08-15 21:17:47.375 933-11213/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:47.375 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:47.506 933-953/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:47.506 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:47.666 731-838/? D/PackageManager: [MSG] CHECK_PENDING_VERIFICATION
  08-15 21:17:47.766 179-460/? D/AudioStreamOutALSA: standby
  08-15 21:17:47.766 179-460/? D/ALSAModule: s_standby: handle 0xb7c24650 h 0x0
  08-15 21:17:47.766 179-460/? E/ALSAModule: s_standby handle h 0xb7ceb678
  08-15 21:17:47.836 933-6432/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:47.846 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:47.846 174-234/? I/SurfaceFlinger: id=833 Removed ieatmapdemo (12/17)
  08-15 21:17:47.846 174-940/? I/SurfaceFlinger: id=833 Removed ieatmapdemo (-2/17)
  08-15 21:17:47.896 933-11464/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true)
  08-15 21:17:47.906 933-933/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1)
  08-15 21:17:47.956 179-460/? D/ALSAModule: checkRunningHandle return false
  08-15 21:17:47.956 179-460/? D/alsa_ucm: snd_use_case_set(): uc_mgr 0xb7bf62a0 identifier _verb value Inactive
  08-15 21:17:47.956 179-460/? D/alsa_ucm: Set mixer controls for HiFi enable 0
  08-15 21:17:47.956 179-460/? D/alsa_ucm: Setting mixer control: PRI_RX Audio Mixer MultiMedia1, value: 0
  08-15 21:17:47.956 179-460/? E/ALSAModule: Number of modifiers 1
  08-15 21:17:47.956 179-460/? E/ALSAModule: index 0 modifier Capture Music
  08-15 21:17:47.956 179-460/? E/ALSAModule: use case is Capture Music
  08-15 21:17:47.956 179-460/? E/ALSAModule: usecase_type is 2
  08-15 21:17:47.956 179-460/? D/alsa_ucm: snd_use_case_set(): uc_mgr 0xb7bf62a0 identifier _disdev value Speaker
  08-15 21:17:47.956 179-460/? D/alsa_ucm: Set mixer controls for Speaker enable 0
  08-15 21:17:47.956 179-460/? D/alsa_ucm: Setting mixer control: RX5 MIX1 INP1, value: ZERO
  08-15 21:17:47.966 179-460/? D/alsa_ucm: Setting mixer control: RX5 MIX1 INP2, value: ZERO
  08-15 21:17:47.966 179-460/? D/alsa_ucm: Setting mixer control: LINEOUT2 Volume, value: 0
  08-15 21:17:47.966 179-460/? D/alsa_ucm: Setting mixer control: LINEOUT4 Volume, value: 0
  08-15 21:17:47.966 179-460/? D/alsa_ucm: Setting mixer control: RX5 Digital Volume, value: 0
  08-15 21:17:48.286 24660-24660/com.walintukai.heatmapdemo D/RecordingService: Tick: 1000
  08-15 21:17:48.296 731-824/? D/SensorService:   0.2 -0.0 11.0
  08-15 21:17:48.647 731-824/? E/Sensors: accelHandler 0.162861 -0.044308 11.044633
  08-15 21:17:48.727 179-24722/? E/mm-camera: poll type 1 returns 0
  08-15 21:17:48.727 179-24723/? E/mm-camera: poll type 1 returns 0
  08-15 21:17:48.727 179-24721/? E/mm-camera: poll type 1 returns 0
  08-15 21:17:49.297 24660-24660/com.walintukai.heatmapdemo D/RecordingService: Tick: 0
  08-15 21:17:49.297 24660-24660/com.walintukai.heatmapdemo D/RecordingService: Timer Finished
  08-15 21:17:49.297 24660-24660/com.walintukai.heatmapdemo D/RecordingService: Finished recording
  08-15 21:17:49.297 179-20689/? D/MPEG4Writer: Stopping Video track
  08-15 21:17:49.808 170-170/? E/SMD: DCD ON
  08-15 21:17:50.309 179-24742/? W/CameraSource: Timed out waiting for incoming camera video frames: 0 us
  08-15 21:17:51.440 179-24720/? E/mm-camera: poll type 1 returns 0
  08-15 21:17:51.570 179-24724/? E/mm-camera: poll type 0 returns 0
  08-15 21:17:51.800 731-824/? D/SensorService:   0.2 -0.0 11.1
  08-15 21:17:52.111 731-856/? V/AlarmManager: waitForAlarm result :4
  08-15 21:17:52.121 731-856/? V/AlarmManager: trigger ELAPSED_REALTIME_WAKEUP or RTC_WAKEUP
  08-15 21:17:52.151 731-824/? E/Sensors: accelHandler 0.129331 -0.021555 11.078163
  08-15 21:17:52.151 19505-24874/? I/Finsky: [3562] com.google.android.finsky.receivers.FlushLogsReceiver$FlushLogsService.onHandleIntent(163): Flushing event logs for [wwRg65ZPhINg_7-olzSHzcWExtM]
  08-15 21:17:52.161 19505-19520/? I/PlayCommon: [3510] com.google.android.play.a.al.e(730): Preparing logs for uploading
  08-15 21:17:52.161 19505-20595/? I/PlayCommon: [3552] com.google.android.play.a.w.a(27553): Starting to flush logs
  08-15 21:17:52.161 19505-20595/? I/PlayCommon: [3552] com.google.android.play.a.w.a(27564): Log flushed by 0 successful uploads
  08-15 21:17:52.201 1184-1184/? I/Auth: [AuthDelegateWrapper] Service intent: Intent { cmp=com.google.android.gms/.auth.account.authenticator.DefaultAuthDelegateService }.
  08-15 21:17:52.201 1184-1184/? I/Auth: [AuthDelegateWrapper] Service intent: Intent { cmp=com.google.android.gms/.auth.account.authenticator.DefaultAuthDelegateService }.
  08-15 21:17:52.261 19505-19520/? I/PlayCommon: [3510] com.google.android.play.a.al.a(870): Connecting to server: https://play.googleapis.com/play/log?format=raw&amp;proto_v2=true
  08-15 21:17:52.441 731-826/? W/ProcessCpuTracker: Skipping unknown process pid 24877
  08-15 21:17:52.451 731-826/? W/ProcessCpuTracker: Skipping unknown process pid 24879
  08-15 21:17:52.451 731-826/? W/ProcessCpuTracker: Skipping unknown process pid 24880
  </code></pre>