我正在编程一个Android应用程序,并且在两个设备上我的应用程序因以下问题而崩溃:
更新:似乎存在一个问题,该问题与mediarecorder有关。现在我遇到了一个稍微不同的问题:
FATAL EXCEPTION: AsyncTask #3
Process: online.simpledesign.bikelog, PID: 14660
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:353)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:203)
at android.os.Handler.<init>(Handler.java:117)
at android.app.Dialog.<init>(Dialog.java:123)
at android.app.Dialog.<init>(Dialog.java:168)
at android.support.v7.app.AppCompatDialog.<init>(AppCompatDialog.java:46)
at android.support.v7.app.AlertDialog.<init>(AlertDialog.java:97)
at android.support.v7.app.AlertDialog$Builder.create(AlertDialog.java:980)
at online.simpledesign.bikelog.Record$MediaPrepareTask.doInBackground(Record.java:539)
at online.simpledesign.bikelog.Record$MediaPrepareTask.doInBackground(Record.java:524)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
... 4 more
发生错误时执行的代码是:
class MediaPrepareTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... voids) {
// initialize video camera
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
//Rückmeldung: Kamera konnte nicht gestartet werden
AlertDialog alertDialog = new AlertDialog.Builder(Record.this).create();
alertDialog.setTitle("Achtung");
alertDialog.setMessage("Kamera konnte nicht gestartet werden. Du kannst trotzdem die Daten aufzeichnen und mir so helfen.");
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Okay",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
if (!result) {
Record.this.finish();
}
}
}
我在这里尝试了所有解决方案,但没有一个起作用。更令我困惑的是,在某些设备上它可以正常工作。 装有Android 8.0的Xperia XZ1 Compact和装有Android 7.1的Google Pixel都会引发此问题。
任何建议都值得赞赏。
编辑:这是在prepareVideoRecorder中发生的事情:
private boolean prepareVideoRecorder() {
// BEGIN_INCLUDE (configure_preview)
mCamera = CameraHelper.getDefaultCameraInstance();
if(CamcorderProfile.hasProfile(0,CamcorderProfile.QUALITY_QVGA)){
// We need to make sure that our preview and recording video size are supported by the
// camera. Query camera to find all the sizes and choose the optimal size given the
// dimensions of our preview surface.
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
List<Camera.Size> mSupportedVideoSizes = parameters.getSupportedVideoSizes();
Camera.Size optimalSize = CameraHelper.getOptimalVideoSize(mSupportedVideoSizes, mSupportedPreviewSizes, mPreview.getWidth(), mPreview.getHeight());
// Use the same size for recording profile.
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA);
profile.videoFrameWidth = optimalSize.width;
profile.videoFrameHeight = optimalSize.height;
// likewise for the camera object itself.
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setDisplayOrientation(90);
mCamera.setParameters(parameters);
try {
// Requires API level 11+, For backward compatibility use {@link setPreviewDisplay}
// with {@link SurfaceView}
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
} catch (IOException e) {
Log.e(TAG, "Surface texture is unavailable or unsuitable" + e.getMessage());
return false;
}
// END_INCLUDE (configure_preview)
// BEGIN_INCLUDE (configure_media_recorder)
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setOrientationHint(90);
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(profile);
mMediaRecorder.setVideoEncodingBitRate(1000000);
// Step 4: Set output file
mOutputFile = CameraHelper.getOutputMediaFile(getFilesDir().getAbsolutePath());
if (mOutputFile == null) {
return false;
}
mMediaRecorder.setOutputFile(mOutputFile.getPath());
// END_INCLUDE (configure_media_recorder)
// Step 5: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
else {
return false;
}
}
答案 0 :(得分:0)
在方法prepareVideoRecorder()
中,应首先检查是否支持要使用的配置文件-
if(CamcorderProfile.hasProfile()){
// then get profile ....
}
public static boolean hasProfile(int cameraId, int quality);
如果它不支持,则总是会崩溃,因为该设备不支持该配置文件。因此,您需要先检查(如果仅受支持),然后再执行其余操作。