未调用 surfaceCreated(SurfaceHolder holder)
surfaceCreated(SurfaceHolder holder) not being called
我见过很多关于错误的 SurfaceView 回调的问题,但是 none 有一个明确的解决方案。我有一个非常简单的布局文件,它有一个 SurfaceView、一个 TextView 和一个不确定的进度指示器。根据我的日志,我的 ScanActivity 在其布局中将自己注册为 SurfaceView 的回调,但只调用了 surfaceDestroyed(SurfaceHolder holder)
。但是 activity 成功预览了相机,这很奇怪,因为我在 surfaceCreated
中附加了 SurfaceView 作为相机预览,并且 "Surface created." 从未被记录,而 "Surface destroyed." 是。
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();
}
}
}
我已经尝试了您的代码,surfaceCreated()
按预期被调用。你检查错了logcat。尝试使用 Log.d("MainActivity", "Surface created.");
而不是 System.out.println
。也学how to use debugger。
我见过很多关于错误的 SurfaceView 回调的问题,但是 none 有一个明确的解决方案。我有一个非常简单的布局文件,它有一个 SurfaceView、一个 TextView 和一个不确定的进度指示器。根据我的日志,我的 ScanActivity 在其布局中将自己注册为 SurfaceView 的回调,但只调用了 surfaceDestroyed(SurfaceHolder holder)
。但是 activity 成功预览了相机,这很奇怪,因为我在 surfaceCreated
中附加了 SurfaceView 作为相机预览,并且 "Surface created." 从未被记录,而 "Surface destroyed." 是。
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();
}
}
}
我已经尝试了您的代码,surfaceCreated()
按预期被调用。你检查错了logcat。尝试使用 Log.d("MainActivity", "Surface created.");
而不是 System.out.println
。也学how to use debugger。