自定义相机安卓
Posted
技术标签:
【中文标题】自定义相机安卓【英文标题】:Custom camera android 【发布时间】:2012-01-22 12:22:32 【问题描述】:我想在活动中使用camera preview
。我想添加图像(表面视图上的透明框架)。我尝试了以下代码,以便我可以轻松地自定义 xml 布局:
package com.demo;
import java.io.IOException;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class CameraDemoActivity extends Activity implements SurfaceHolder.Callback
/** Called when the activity is first created. */
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
camera = Camera.open();
if(camera!=null)
try
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
catch (IOException e)
Toast.makeText(this, (CharSequence) e, Toast.LENGTH_LONG).show();
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
// TODO Auto-generated method stub
@Override
public void surfaceCreated(SurfaceHolder holder)
// TODO Auto-generated method stub
@Override
public void surfaceDestroyed(SurfaceHolder holder)
// TODO Auto-generated method stub
这是我的清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demo"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".CameraDemoActivity"
android:label="@string/app_name" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android:hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
</manifest>
这是我的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:layout_
>
<SurfaceView
android:id="@+id/surfaceview"
android:layout_
android:layout_/>
</LinearLayout>
不知道为什么不显示camera
的预览?
【问题讨论】:
【参考方案1】:使用此代码
PreviewDemo.java
public class PreviewDemo extends Activity implements OnClickListener
private SurfaceView preview = null;
private SurfaceHolder previewHolder = null;
private Camera camera = null;
private boolean inPreview = false;
ImageView image;
Bitmap bmp, itembmp;
static Bitmap mutableBitmap;
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
File imageFileName = null;
File imageFileFolder = null;
private MediaScannerConnection msConn;
Display d;
int screenhgt, screenwdh;
ProgressDialog dialog;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.preview);
image = (ImageView) findViewById(R.id.image);
preview = (SurfaceView) findViewById(R.id.surface);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
previewHolder.setFixedSize(getWindow().getWindowManager()
.getDefaultDisplay().getWidth(), getWindow().getWindowManager()
.getDefaultDisplay().getHeight());
@Override
public void onResume()
super.onResume();
camera = Camera.open();
@Override
public void onPause()
if (inPreview)
camera.stopPreview();
camera.release();
camera = null;
inPreview = false;
super.onPause();
private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters)
Camera.Size result = null;
for (Camera.Size size: parameters.getSupportedPreviewSizes())
if (size.width <= width && size.height <= height)
if (result == null)
result = size;
else
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea)
result = size;
return (result);
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback()
public void surfaceCreated(SurfaceHolder holder)
try
camera.setPreviewDisplay(previewHolder);
catch (Throwable t)
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(PreviewDemo.this, t.getMessage(), Toast.LENGTH_LONG)
.show();
public void surfaceChanged(SurfaceHolder holder,
int format, int width,
int height)
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height,
parameters);
if (size != null)
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
camera.startPreview();
inPreview = true;
public void surfaceDestroyed(SurfaceHolder holder)
// no-op
;
Camera.PictureCallback photoCallback = new Camera.PictureCallback()
public void onPictureTaken(final byte[] data, final Camera camera)
dialog = ProgressDialog.show(PreviewDemo.this, "", "Saving Photo");
new Thread()
public void run()
try
Thread.sleep(1000);
catch (Exception ex)
onPictureTake(data, camera);
.start();
;
public void onPictureTake(byte[] data, Camera camera)
bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
mutableBitmap = bmp.copy(Bitmap.Config.ARGB_8888, true);
savePhoto(mutableBitmap);
dialog.dismiss();
class SavePhotoTask extends AsyncTask < byte[], String, String > @Override
protected String doInBackground(byte[]...jpeg)
File photo = new File(Environment.getExternalStorageDirectory(), "photo.jpg");
if (photo.exists())
photo.delete();
try
FileOutputStream fos = new FileOutputStream(photo.getPath());
fos.write(jpeg[0]);
fos.close();
catch (java.io.IOException e)
Log.e("PictureDemo", "Exception in photoCallback", e);
return (null);
public void savePhoto(Bitmap bmp)
imageFileFolder = new File(Environment.getExternalStorageDirectory(), "Rotate");
imageFileFolder.mkdir();
FileOutputStream out = null;
Calendar c = Calendar.getInstance();
String date = fromInt(c.get(Calendar.MONTH)) + fromInt(c.get(Calendar.DAY_OF_MONTH)) + fromInt(c.get(Calendar.YEAR)) + fromInt(c.get(Calendar.HOUR_OF_DAY)) + fromInt(c.get(Calendar.MINUTE)) + fromInt(c.get(Calendar.SECOND));
imageFileName = new File(imageFileFolder, date.toString() + ".jpg");
try
out = new FileOutputStream(imageFileName);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
scanPhoto(imageFileName.toString());
out = null;
catch (Exception e)
e.printStackTrace();
public String fromInt(int val)
return String.valueOf(val);
public void scanPhoto(final String imageFileName)
msConn = new MediaScannerConnection(PreviewDemo.this, new MediaScannerConnectionClient()
public void onMediaScannerConnected()
msConn.scanFile(imageFileName, null);
Log.i("msClient obj in Photo Utility", "connection established");
public void onScanCompleted(String path, Uri uri)
msConn.disconnect();
Log.i("msClient obj in Photo Utility", "scan completed");
);
msConn.connect();
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0)
onBack();
return super.onKeyDown(keyCode, event);
public void onBack()
Log.e("onBack :", "yes");
camera.takePicture(null, null, photoCallback);
inPreview = false;
@Override
public void onClick(View v)
Preview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_>
<android.view.SurfaceView
android:id="@+id/surface"
android:layout_
android:layout_
/>
</RelativeLayout>
使用设备菜单按钮拍照。
在 Manifest 文件中添加权限
检查图片库中的旋转文件夹以获取捕获的图像。
【讨论】:
你能给我完整的 zip 文件吗?只是这个带有按钮的基本摄像头供稿? 你能给我完整的工作项目吗?我无法获得上述完整代码。 非常好的代码。我用 2.3.3 检查了它。在具有“new MediaScannerConnectionClient()”的行上,必须将其更改为“new MediaScannerConnection.MediaScannerConnectionClient() 在 kitkat nexus 4 中尝试过此代码...相机预览调整为 90 dergees..惊讶地看到 你有 image = (ImageView) findViewById(R.id.image);没用过的以上是关于自定义相机安卓的主要内容,如果未能解决你的问题,请参考以下文章