Android MediaRecorder stop () не вызывается

У меня действительно странная ошибка, когда часть моего кода не вызывается, но не похоже, что есть какая-то причина, по которой он не будет вызываться.

Вызывается onFinishedRecording, а тег "Finished recording." выходит из системы, но код после этого вообще не вызывается. Весь код перестает вызываться при вызове mMediaRecorder.stop();. В блок catch он тоже не заходит. Почему это происходит?

Я думал, что это может быть связано с разными потоками, но я проверил все имена потоков, и все они работают в одном и том же основном потоке.

Кроме того, может быть, что-то не так с настройками предварительного просмотра камеры? Когда я пытаюсь воспроизвести видео, оно повреждено и не может быть воспроизведено.

Помимо вышеперечисленных проблем, моя кнопка "Назад" ничего не делает в приложении. Не совсем понятно, почему и как это связано с кодом, который я реализовал.

Класс MyLibrary (класс библиотечного модуля)

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)
                && PermissionUtil.checkRecordAudioPermission(mActivity)
                && 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<String>() {
            @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<Boolean>() {
            @Override
            public void onSuccess(Boolean response) {

            }

            @Override
            public void onError() {

            }
        }).addToQueue();
    }
}

Запись активности

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();
    }
}

Итак, все работает нормально, пока не будет вызван этот метод:

    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();
    }

Полная трассировка стека телефона

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 <bottom of call stack> <bottom of call stack> 
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&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

person The Nomad    schedule 01.08.2016    source источник
comment
Попробуйте добавить RuntimeException в catch и move releaseMediaRecorder(); и т. д., чтобы окончательно заблокировать. Если это сработает, я напишу ответ, чтобы объяснить, почему это работает.   -  person Niko Adrianus Yuwono    schedule 09.08.2016
comment
Log.d(TAG, "Finished recording."); происходит, но ничего не происходит? Дополнительная информация для них: что logcat говорит для e.printStackTrace(); в try/catch, и я заметил, что вы проверяете != null, можете ли вы добавить в журнал, чтобы увидеть, являются ли они ==null?   -  person TWL    schedule 09.08.2016
comment
@NikoYuwono Добавлен RuntimeException, но ни один блок catch не выполняется. Я также переместил releaseMediaRecorder() в блок finally.   -  person The Nomad    schedule 10.08.2016
comment
@TML Да, готовый тег записи отображается в журнале, и mMediaRecorder.stop() кажется, что он вызывается при отладке, но после этого ничего не происходит. Log.d(TAG, "Media recorder stopped"); не отображается в журнале, как и ни один из e.printStackTrace(); вызовов.   -  person The Nomad    schedule 10.08.2016
comment
Можете ли вы попробовать добавить общий Exception catch (Exception e) {}   -  person arungiri_10    schedule 10.08.2016
comment
Мы хотим знать об исключении, потому что считаем, что функция stop() выдает его. Хорошо, поместите журнал прямо перед ним (также в try/catch), и я уверен, что вы его увидите. Должен отображаться printStackTrace, либо не фильтруйте свой логарифм по TAG, либо вставьте Log.d(TAG, e.toString())   -  person TWL    schedule 10.08.2016
comment
@arungiri_10 Я пытался проверить улов на общий Exception, и он все еще не выполняется.   -  person The Nomad    schedule 11.08.2016
comment
@TML stop(), похоже, не генерирует исключение (даже с Exception e). Я тестировал несколько способов: режим отладки, помещая Log.e в блок catch. Не говоря уже о том, что даже если он выдает исключение, остальная часть кода, releaseTimer() и getSignedUrl(), тоже будет вызываться, но ни один из них также не вызывается. Это только кажется, что он останавливается.   -  person The Nomad    schedule 11.08.2016
comment
Я не думаю, что смогу продолжить работу без какого-либо логарифма или компилируемого проекта. И Нет, releaseTimer и getSignedUrl, вероятно, вызываются, но они стали NULL, и вы либо не регистрируете это, либо показываете нам журналы. Честно говоря, что-то столь же загадочное, как это, нет ничего плохого в том, чтобы просто шлепать журналы по каждой строке, а затем предоставлять этот логарифм.   -  person TWL    schedule 11.08.2016
comment
@TML извините, я должен был опубликовать трассировку стека раньше. Я обновил свой OP с помощью stacktrace. Как видите, Finished Recording — это последняя запись в журнале, после которой ничего не появляется, сколько бы я ни ждал. Кроме того, я должен был опубликовать это раньше, но я пытаюсь воспроизвести видео, но все они повреждены и не могут воспроизводиться.   -  person The Nomad    schedule 11.08.2016


Ответы (3)


Учитывая, насколько далеко отслеживается выполнение кода и где он (по-видимому) теряется, я предлагаю следующие модификации вашего кода, которые должны дать вам лучшее представление о том, что происходит. Будет интересно увидеть всю трассировку стека после «Ухода в черную дыру».

private void onFinishedRecording() {
    Log.d(TAG, "Going into the black hole.");
    try {
        Log.d(TAG, "So far so good, but if you don't see this just pull your hair ...");
        mMediaRecorder.stop();
        Log.d(TAG, "Media recorder stopped.");
    } catch (Error e) {
        Log.d(TAG, "So there was an error ...");
        e.printStackTrace();
        Log.d(TAG, "Did you get what that error was?");
    } catch (Exception e) {
        Log.d(TAG, "So there was some kind of an exception.");
        e.printStackTrace();
        Log.d(TAG, "Did you get what the exception was?");
    } finally {
        Log.d(TAG, "Leaving the black hole.");
    }
    Log.d(TAG, "So I did get out of the black hole after all ...");
    releaseMediaRecorder();
    releaseTimer();
    getSignedUrl();
}

Удачи!

Обновлять:

Пожалуйста, включите необработанные записи logcat (не ограничивайте их своим приложением). Некоторые ошибки в нативном коде могут вызывать ошибки, которые могут показаться не связанными с вашим приложением, но на самом деле они могут быть таковыми. Кроме того, имейте в виду, что размер предварительного просмотра должен быть таким же, как выбранный размер видео. Дополнительные сведения см. в этом сообщении.

Обновление 2:

Извините, я отсутствовал и не имел возможности погрузиться. Однако, бегло взглянув, я заметил отсылку к тайм-ауту камеры:

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

Из того, что я могу сказать, сразу после выдачи stop() есть попытка остановить видео, но оно остается в состоянии Остановка и никогда не переходит в состояние Остановлено, а затем через пару строк время ожидания CameraSource истекло. Возможно, вы захотите добавить еще несколько записей в журнал, чтобы увидеть, что происходит после подготовки и начала записи. Там могут быть какие-то подсказки. Похоже, что каким-то образом вызов stop() неопределенно долго ожидает чего-то, например камеры (тупик). Это согласуется с отсутствием признаков какой-либо ошибки, но после этого ничего не происходит. Поставьте точку останова прямо там и проверьте состояние различных ресурсов (в частности, камеры) и посмотрите, заблокировано ли оно или находится в таком состоянии, что вызывает ожидание stop(). Наконец, я хотел бы убедиться, что в предварительном просмотре используется поддерживаемый размер/разрешение, и убедиться, что он совместим с вашим размером и разрешением записи. Потенциальные проблемы/несоответствия могут быть внутренней причиной взаимоблокировки (или чего-то еще, что препятствует выполнению остановки).

person Kaamel    schedule 14.08.2016
comment
Итак, я добавил все эти журналы, и вот результат 08-14 18:35:57.788 14089-14089/com.walintukai.heatmapdemo D/RecordingService: Going into the black hole. 08-14 18:35:57.788 14089-14089/com.walintukai.heatmapdemo D/RecordingService: So far so good, but if you don't see this just pull your hair ... - person The Nomad; 15.08.2016
comment
Практически тот же результат, что и раньше. Код просто останавливается при попытке остановить MediaRecorder. - person The Nomad; 15.08.2016
comment
Не могли бы вы добавить еще несколько записей logcat после последней строки, хотя/если они не связаны с вашим приложением? - person Kaamel; 15.08.2016
comment
Я включил большую часть полной трассировки стека телефона. Я бы добавил больше, но исчерпал лимит символов для поста. - person The Nomad; 16.08.2016
comment
Нашли что-нибудь необычное в моем logcat? - person The Nomad; 18.08.2016

Что ж, я уже встречал подобную ситуацию, когда какой-то нативный код давал сбой и уничтожал текущий поток, ничего не говоря и не возвращаясь к коду Java.

Но поскольку это не было основным потоком, остальная часть приложения, казалось, работала нормально.

Возможно, монитор устройства Android покажет вам что-то важное о запущенных потоках.

Надеюсь, это было полезно.

person J.Jacobs-VP    schedule 11.08.2016
comment
хорошо, я проверю это позже! Это звучит так, как будто что-то может произойти. Хотя я выходил из потока, прежде чем некоторые методы выполнялись, и все они оказались в основном потоке. - person The Nomad; 11.08.2016
comment
Добро пожаловать в Переполнение стека! Хотя ваш вклад может быть ценным, это комментарий, а не ответ. Вы сможете комментировать везде с 50 повторениями, и вы почти у цели. Придерживайтесь вопросов, на которые вы можете прямо сейчас ответить. - person jpaugh; 16.08.2016

Я думаю, вы должны проверить, что mediaRecorder не является null в этот момент, прежде чем вызывать для него stop().

person Hassan Semiu Ayomon    schedule 15.08.2016
comment
На данный момент это определенно не ноль. Во-первых, он выдаст NullPointerException в моем блоке catch Exception e, а он ничего не выбрасывает. Кроме того, я отладил, и на данный момент MediaRecorder не равно нулю. - person The Nomad; 16.08.2016