Ich habe zahlreiche Fragen zu fehlerhaften SurfaceView-Callbacks erhalten, aber keine hatte eine klare Lösung. Ich habe eine sehr einfache Layout-Datei, die eine SurfaceView, eine TextView und eine unbestimmte Fortschrittsanzeige hat. Meine ScanActivity registriert sich selbst als Callback zu der SurfaceView in ihrem Layout, aber nur surfaceDestroyed(SurfaceHolder holder)
wird je nach meinen Logs aufgerufen. Aber die Aktivität hat eine Vorschau der Kamera, was seltsam ist, weil ich die SurfaceView als Kameravorschau in surfaceCreated
anschloss und "Surface created". wird nie protokolliert, während "Oberfläche zerstört" ist. ist.SurfaceCreated (SurfaceHolder-Halter) wird nicht aufgerufen
scan.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/black"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_gravity="bottom|center_horizontal">
<TextView
android:id="@+id/scan_instructions"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textSize="16sp"
android:gravity="center"
android:visibility="visible"
android:textColor="@android:color/primary_text_dark"
android:text="@string/scan_instructions"
/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_margin="5dp"
android:indeterminate="true"
/>
</LinearLayout>
</FrameLayout>
ScanActivity.java
public class ScanActivity extends Activity implements SurfaceHolder.Callback {
private Camera camera;
private Scanner scanner;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scan);
scanner = new Scanner(20) {
@Override
public void onPostExecute(String result) {
System.out.println("Read QR: " + result);
onQRScanned(result);
}
};
}
/**
* Registers this class as the callback for the image surface in the layout XML.
*/
@Override
public void onStart() {
super.onStart();
((SurfaceView) findViewById(R.id.camera_preview)).getHolder().addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("Surface created.");
surfaceDestroyed(holder);
try {
// Open the camera.
camera = Camera.open();
camera.setPreviewDisplay(holder);
camera.setPreviewCallback(scanner);
System.out.println("Connected QR scan task.");
} catch (NullPointerException e) {
// Didn't find a camera to open.
e.printStackTrace();
surfaceDestroyed(holder);
return;
} catch (IOException e) {
// Camera preview setup failed.
e.printStackTrace();
surfaceDestroyed(holder);
return;
} catch (RuntimeException e) {
// The app was denied permission to camera services.
e.printStackTrace();
surfaceDestroyed(holder);
return;
}
// Set auto-focus mode
Parameters params = camera.getParameters();
List<String> modes = params.getSupportedFocusModes();
if (modes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
else if (modes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
else if (modes.contains(Parameters.FOCUS_MODE_AUTO)) {
params.setFocusMode(Parameters.FOCUS_MODE_AUTO);
}
camera.setParameters(params);
}
/**
* If the preview surface is altered for some reason, fixes it and refreshes the preview.
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
System.out.println("Surface changed.");
if (camera == null)
return;
camera.setDisplayOrientation(90);
camera.startPreview();
}
/**
* When the activity is closed, release the camera.
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("Surface destroyed.");
if (camera == null)
return;
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
scanner.cancel(true);
}
/**
* Called when a QR code is successfully read from the preview.
* @param content The text encoded in the QR.
*/
private void onQRScanned(String content) {
if (content != null) {
getIntent().putExtra("qr_content", content);
setResult(RESULT_OK, getIntent());
finish();
} else {
setResult(RESULT_CANCELED);
finish();
}
}
}
Sie rufen 'SurfaceDestroyed (Holder);' in 'SurfaceCreated()' –
Hört das SurfaceCreated (Halter)? –
Ja, wenn es erstellt wird, zerstörst du es mit Gewalt. –