我有一个应用程序,应该使用camera.takePicture拍照。我使用的代码如下:
private Bitmap bitmapPicture;
//inside onCreate
btn.setOnClickListener(new OnClickListener(){
public void onClick(View v){
camera.takePicture(myShutterCallback,
myPictureCallback_RAW, myPictureCallback_JPG);
}
});
//inside the activity
ShutterCallback myShutterCallback = new ShutterCallback(){
@Override
public void onShutter() {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_RAW = new PictureCallback(){
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_JPG = new PictureCallback(){
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
bitmapPicture = BitmapFactory.decodeByteArray(arg0, 0, arg0.length);
}};
当我点击按钮时,会播放快门声音,SurfaceView上的图像会冻结但应用程序崩溃。为什么会这样?当我在模拟器上使用模拟摄像头运行它时,它正在工作但在设备上崩溃。
答案 0 :(得分:0)
使用此简单代码使用设备相机进行捕捉
IMP注意:将这些权限添加到mainfest文件
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
mainActivity
public class MainActivity extends Activity {
private static final int CAMERA_PIC_REQUEST = 1111;//Constant ID for ActivityResult
private ImageView mImage; // To display the thumbnail
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImage = (ImageView) findViewById(R.id.camera_image);
// Start an intent for Camera Capture with ResultActivity
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_PIC_REQUEST) {
// Get the image in a Bitmap extension to assign it to the ImageView
if (data.getExtras() == null)
return;
Bitmap thumb = (Bitmap) data.getExtras().get("data");
mImage.setImageBitmap(thumb);
// Compress the Bitmap image into JPEG to save it on the device
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumb.compress(Bitmap.CompressFormat.JPEG, 100, bytes);// 100 is the scale..for less quality decrease the number
// Save the image on the root SDCard
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "imageName.png");
try {
// Create the file to save the image
file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.close();
} catch (Exception e) {
}
}
}
}
将它放在您的Layout MainActivity.XML布局中:
<ImageView android:id="@+id/camera_image"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
答案 1 :(得分:0)
我终于解决了这个问题。下面我给一些想要知道如何截取布局截图,无意图的相机图片,SurfaceView内容的截图(点击)以及将屏幕截图保存在文件夹中的人提供一些代码:
public class Cam_View extends Activity implements SurfaceHolder.Callback{
protected static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;
private SurfaceView SurView;
private SurfaceHolder camHolder;
private boolean previewRunning;
final Context context = this;
public static Camera camera = null;
private RelativeLayout CamView;
private Bitmap inputBMP=null,bmp,bmp1;
private ImageView mImage;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
CamView = (RelativeLayout) findViewById(R.id.camview);//RELATIVELAYOUT OR
//ANY LAYOUT OF YOUR XML
SurView = (SurfaceView)findViewById(R.id.sview);//SURFACEVIEW FOR THE PREVIEW
//OF THE CAMERA FEED
camHolder = SurView.getHolder(); //NEEDED FOR THE PREVIEW
camHolder.addCallback(this); //NEEDED FOR THE PREVIEW
camHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//NEEDED FOR THE PREVIEW
camera_image = (ImageView) findViewById(R.id.camera_image);//NEEDED FOR THE PREVIEW
Button btn = (Button) findViewById(R.id.button1); //THE BUTTON FOR TAKING PICTURE
btn.setOnClickListener(new OnClickListener() //THE BUTTON CODE
{
public void onClick(View v)
{
camera.takePicture(null, null, mPicture);//TAKING THE PICTURE
//THE mPicture IS CALLED
//WHICH IS THE LAST METHOD(SEE BELOW)
}
});
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,//NEEDED FOR THE PREVIEW
int height) {
if(previewRunning){
camera.stopPreview();
}
Camera.Parameters camParams = camera.getParameters();
Camera.Size size = camParams.getSupportedPreviewSizes().get(0);
camParams.setPreviewSize(size.width, size.height);
camera.setParameters(camParams);
try{
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning=true;
}catch(IOException e){
e.printStackTrace();
}
}
public void surfaceCreated(SurfaceHolder holder) { //NEEDED FOR THE PREVIEW
try{
camera=Camera.open();
}catch(Exception e){
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
finish();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) { //NEEDED FOR THE PREVIEW
camera.stopPreview();
camera.release();
camera=null;
}
public void TakeScreenshot(){ //THIS METHOD TAKES A SCREENSHOT AND SAVES IT AS .jpg
Random num = new Random();
int nu=num.nextInt(1000); //PRODUCING A RANDOM NUMBER FOR FILE NAME
CamView.setDrawingCacheEnabled(true); //CamView OR THE NAME OF YOUR LAYOUR
CamView.buildDrawingCache(true);
Bitmap bmp = Bitmap.createBitmap(CamView.getDrawingCache());
CamView.setDrawingCacheEnabled(false); // clear drawing cache
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata);
String picId=String.valueOf(nu);
String myfile="Ghost"+picId+".jpeg";
File dir_image = new File(Environment.getExternalStorageDirectory()+//<---
File.separator+"Ultimate Entity Detector"); //<---
dir_image.mkdirs(); //<---
//^IN THESE 3 LINES YOU SET THE FOLDER PATH/NAME . HERE I CHOOSE TO SAVE
//THE FILE IN THE SD CARD IN THE FOLDER "Ultimate Entity Detector"
try {
File tmpFile = new File(dir_image,myfile);
FileOutputStream fos = new FileOutputStream(tmpFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
Toast.makeText(getApplicationContext(),
"The file is saved at :SD/Ultimate Entity Detector",Toast.LENGTH_LONG).show();
bmp1 = null;
camera_image.setImageBitmap(bmp1); //RESETING THE PREVIEW
camera.startPreview(); //RESETING THE PREVIEW
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private PictureCallback mPicture = new PictureCallback() { //THIS METHOD AND THE METHOD BELOW
//CONVERT THE CAPTURED IMAGE IN A JPG FILE AND SAVE IT
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File dir_image2 = new File(Environment.getExternalStorageDirectory()+
File.separator+"Ultimate Entity Detector");
dir_image2.mkdirs(); //AGAIN CHOOSING FOLDER FOR THE PICTURE(WHICH IS LIKE A SURFACEVIEW
//SCREENSHOT)
File tmpFile = new File(dir_image2,"TempGhost.jpg"); //MAKING A FILE IN THE PATH
//dir_image2(SEE RIGHT ABOVE) AND NAMING IT "TempGhost.jpg" OR ANYTHING ELSE
try {//SAVING
FileOutputStream fos = new FileOutputStream(tmpFile);
fos.write(data);
fos.close();
//grabImage();
} catch (FileNotFoundException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
}
String path = (Environment.getExternalStorageDirectory()+
File.separator+"Ultimate EntityDetector"+
File.separator+"TempGhost.jpg");//<---
BitmapFactory.Options options = new BitmapFactory.Options();//<---
options.inPreferredConfig = Bitmap.Config.ARGB_8888;//<---
bmp1 = BitmapFactory.decodeFile(path, options);//<---
//THE LINES ABOVE READ THE FILE WE SAVED BEFORE AND CONVERT IT INTO A BitMap
camera_image.setImageBitmap(bmp1); //SETTING THE BitMap AS IMAGE IN AN IMAGEVIEW(SOMETHING
//LIKE A BACKGROUNG FOR THE LAYOUT)
TakeScreenshot();//CALLING THIS METHOD TO TAKE A SCREENSHOT
}
};
}
如果你想拍一个简单的截图(不需要摄像头),你可以单独使用TakeScreenshot方法。
如果你想直接从surfaceview获取一个surfaceView的截图,请使用mPicture,将你捕获的图片设置为背景幕,然后调用TakeScreenshot来截取屏幕截图。(如上所示)
如果您想使用相机拍摄照片而不打算使用其他相机应用程序,请使用带有mPicture的takePicture和上面代码中的surfaceView内容。
如果按“原样”使用,之前的代码所做的是截取布局内容(按钮,图像视图等)的截图,并将相机中的图像设置为背景。
下面我还提供了上一代码的基本布局xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/camview">
<SurfaceView
android:id="@+id/sview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<ImageView
android:id="@+id/camera_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/app_name" />
<Button
android:id="@+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
答案 2 :(得分:0)
只需添加一个回调即可在相机实例上开始预览。事情是在相机实例上开始预览后,需要一些时间才能拍照。试试这个:
camera.startPreview();
camera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
camera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// do something you want with your picture and stop preview
camera.stopPreview();
}
});