SurfaceViewをいくつかのコントロールのためにフレームレイアウトに挿入するために、FrameViewにSurfaceViewを配置しようとしています。しかし、私はそれが何であるかわからないInflateExceptionを得ました。カスタムを膨らませるためにしたい場合は以下の私のプレビュークラスのコードと私のmain.xmlFrameViewの問題(InflateException)のSurfaceView
class Preview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
Preview(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if(mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if(mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if(mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
if(width*previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height/previewHeight;
child.layout(((width) - scaledChildWidth) /2, 0, ((width) + scaledChildWidth) /2, height);
}
else {
final int scaledChildHeight = previewHeight * width/previewWidth;
child.layout(0, ((height)-scaledChildHeight)/2, width, ((height) + scaledChildHeight) /2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if(mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
}
catch (IOException exception) {
}
}
Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
int ARRAY_LENGTH = mPreviewSize.width*mPreviewSize.height*3/2;
int argb8888[] = new int[ARRAY_LENGTH];
decodeYUV(argb8888, data, mPreviewSize.width, mPreviewSize.height);
Bitmap bitmap = Bitmap.createBitmap(argb8888, mPreviewSize.width, mPreviewSize.height, Config.ARGB_8888);
FileOutputStream fos;
try {
fos = new FileOutputStream(String.format("/sdcard/testImage/%d.jpg", System.currentTimeMillis()));
BufferedOutputStream bos = new BufferedOutputStream(fos);
bitmap.compress(CompressFormat.JPEG, 75, bos);
try {
bos.flush();
} catch (IOException ex) {
Logger.getLogger(Preview.class.getName()).log(Level.SEVERE, null, ex);
}
bos.close();
fos.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Preview.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex) {
Logger.getLogger(Preview.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
// decode Y, U, and V values on the YUV 420 buffer described as YCbCr_422_SP by Android
// David Manpearl 081201
public void decodeYUV(int[] out, byte[] fg, int width, int height)
throws NullPointerException, IllegalArgumentException {
int sz = width * height;
if (out == null)
throw new NullPointerException("buffer out is null");
if (out.length < sz)
throw new IllegalArgumentException("buffer out size " + out.length
+ " < minimum " + sz);
if (fg == null)
throw new NullPointerException("buffer 'fg' is null");
if (fg.length < sz)
throw new IllegalArgumentException("buffer fg size " + fg.length
+ " < minimum " + sz * 3/2);
int i, j;
int Y, Cr = 0, Cb = 0;
for (j = 0; j < height; j++) {
int pixPtr = j * width;
final int jDiv2 = j >> 1;
for (i = 0; i < width; i++) {
Y = fg[pixPtr];
if (Y < 0)
Y += 255;
if ((i & 0x1) != 1) {
final int cOff = sz + jDiv2 * width + (i >> 1) * 2;
Cb = fg[cOff];
if (Cb < 0)
Cb += 127;
else
Cb -= 128;
Cr = fg[cOff + 1];
if (Cr < 0)
Cr += 127;
else
Cr -= 128;
}
int R = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
if (R < 0)
R = 0;
else if (R > 255)
R = 255;
int G = Y - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1)
+ (Cr >> 3) + (Cr >> 4) + (Cr >> 5);
if (G < 0)
G = 0;
else if (G > 255)
G = 255;
int B = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
if (B < 0)
B = 0;
else if (B > 255)
B = 255;
out[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R;
}
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if(mCamera != null) {
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double)w/h;
if(sizes==null) {
return null;
}
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for(Size size : sizes) {
double ratio = (double) size.width/size.height;
if(Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if(Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if(optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if(Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
//mCamera.setPreviewCallback(mPreviewCallback);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
私のmain.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<Button
android:id="@+id/showhide"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Toggle The Another Button Show/Hide" />
<Button
android:id="@+id/dummy"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="a Button" />
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<camera.test.Preview
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</FrameLayout>
Logcat
08-18 14:01:37.896: ERROR/AndroidRuntime(401): FATAL EXCEPTION: main
08-18 14:01:37.896: ERROR/AndroidRuntime(401): java.lang.RuntimeException: Unable to start activity ComponentInfo{camera.test/camera.test.MainActivity}: android.view.InflateException: Binary XML file line #21: Error inflating class camera.test.Preview
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.os.Handler.dispatchMessage(Handler.java:99)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.os.Looper.loop(Looper.java:123)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.ActivityThread.main(ActivityThread.java:3683)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at java.lang.reflect.Method.invokeNative(Native Method)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at java.lang.reflect.Method.invoke(Method.java:507)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at dalvik.system.NativeStart.main(Native Method)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): Caused by: android.view.InflateException: Binary XML file line #21: Error inflating class camera.test.Preview
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.createView(LayoutInflater.java:508)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:570)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.rInflate(LayoutInflater.java:626)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.Activity.setContentView(Activity.java:1657)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at camera.test.MainActivity.onCreate(MainActivity.java:45)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): ... 11 more
08-18 14:01:37.896: ERROR/AndroidRuntime(401): Caused by: java.lang.NoSuchMethodException: Preview(Context,AttributeSet)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at java.lang.Class.getMatchingConstructor(Class.java:643)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at java.lang.Class.getConstructor(Class.java:472)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): at android.view.LayoutInflater.createView(LayoutInflater.java:480)
08-18 14:01:37.896: ERROR/AndroidRuntime(401): ... 22 more
例外メッセージとスタックトレースを提供した方が良いでしょう。 – Xion