我有一个非常奇怪的错误,我的某些代码没有被调用,但看起来没有任何理由不能调用它。
调用 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();
}
}
RecordActivity
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();
}
完整手机Stacktrace
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
答案 0 :(得分:2)
好吧,我已经遇到了类似的情况,其中一些本机代码会崩溃并且破坏当前的线程,而不会说任何东西都没有返回到Java代码。
但是因为它不是主线程,所以应用程序的其余部分似乎都很好。
也许android设备监视器会向你展示一些关于运行线程的事情。
希望这很有用。
答案 1 :(得分:1)
我认为您应该在此之前检查mediaRecorder
不是null
,然后再致电stop()
。