我的应用程序启动时如何在没有预览的情况下从相机拍照?
Posted
技术标签:
【中文标题】我的应用程序启动时如何在没有预览的情况下从相机拍照?【英文标题】:How to take pictures from the camera without preview when my app starts? 【发布时间】:2014-01-08 04:33:48 【问题描述】:现在我想要的只是一个在启动时从相机中拍照的应用程序。没有布局,没有相机预览......什么都没有,只是一个简单的应用程序图标来启动应用程序。一旦启动,相机应该会拍照。
这是预览图像,我不想出现在我的应用中。我只想让我的应用程序点击图片中环绕的拍照按钮:
拍完照片后,我需要将其保存在我的照片库中。
有人可以在这里指导我吗?谢谢
这是我在模拟器和设备上尝试过的一些代码。
import java.io.IOException;
import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
public class Main extends Activity implements SurfaceHolder.Callback
private Camera camera;
private ImageButton cameraClick;
private SurfaceHolder mHolder;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SurfaceView surfaceView = (SurfaceView)findViewById(R.id.surfaceView1);
mHolder = surfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
cameraClick = (ImageButton) findViewById(R.id.cameraClick);
cameraClick.setOnClickListener( new OnClickListener()
public void onClick(View v)
camera.takePicture(shutterCallback, rawCallback,jpegCallback);
);
// Handles when shutter open
ShutterCallback shutterCallback = new ShutterCallback()
public void onShutter()
;
/** Handles data for raw picture */
PictureCallback rawCallback = new PictureCallback()
public void onPictureTaken(byte[] data, Camera camera)
;
/** Handles data for jpeg picture */
PictureCallback jpegCallback = new PictureCallback()
public void onPictureTaken(byte[] data, Camera camera)
// we do something using return byte[] of taken image.
;
@Override
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height)
// Set camera preview size,orientation,rotation using parameters
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setParameters(parameters);
camera.startPreview();
@Override
public void surfaceCreated(SurfaceHolder holder)
camera = Camera.open();
try
camera.setPreviewDisplay(holder);
catch (IOException e)
e.printStackTrace();
@Override
public void surfaceDestroyed(SurfaceHolder holder)
camera.stopPreview();
camera.release();
camera = null;
现在我可以听到点击模拟器和设备上的按钮的图片。现在我也想保存图片。有什么线索吗?
【问题讨论】:
我查看了示例代码。任何地方都没有提到这样的功能或特性。 如果我正确理解了您的问题,您只需要整个布局中的一个按钮,在点击时点击照片而不进行预览吗? @AbhishekV 绝对正确!这是我需要的。 那么您提供的答案应该可以正常工作 @Muhammad Maqsoodur R 在任何可以隐藏surfaceView的布局后面使用surfaceView。在您的情况下,通过在该表面视图上进行设计布局来隐藏表面视图 【参考方案1】:使用下面的代码。它经过测试并为我工作。有任何问题请随时提出 cmets。
private void takeSnapShots()
Toast.makeText(getApplicationContext(), "Image snapshot Started",Toast.LENGTH_SHORT).show();
// here below "this" is activity context.
SurfaceView surface = new SurfaceView(this);
Camera camera = Camera.open();
try
camera.setPreviewDisplay(surface.getHolder());
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
camera.startPreview();
camera.takePicture(null,null,jpegCallback);
/** picture call back */
PictureCallback jpegCallback = new PictureCallback()
public void onPictureTaken(byte[] data, Camera camera)
FileOutputStream outStream = null;
try
String dir_path = "";// set your directory path here
outStream = new FileOutputStream(dir_path+File.separator+image_name+no_pics+".jpg");
outStream.write(data);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
camera.stopPreview();
camera.release();
camera = null;
Toast.makeText(getApplicationContext(), "Image snapshot Done",Toast.LENGTH_LONG).show();
Log.d(TAG, "onPictureTaken - jpeg");
;
【讨论】:
SurfaceView 表面 = 新 SurfaceView(this);给我一个空对象引用 你应该在活动中使用一段代码,或者尝试传递活动上下文 抱歉之前的评论...实际上它在这一行中给出了空对象引用 camera.setPreviewDisplay(surface.getHolder()); 检查哪个上下文正在通过表面创建。请尝试设置活动上下文。 图片顺时针旋转90度【参考方案2】:从 API 级别 11 开始,添加了 SurfaceTexture。有了它,不再需要 SurfaceView。我用我的三星 Galaxy S3 Neo 测试了以下代码。
mCamera = Camera.open();
try
mCamera.setPreviewTexture(new SurfaceTexture(10));
catch (IOException e1)
Log.e(Version.APP_ID, e1.getMessage());
Parameters params = mCamera.getParameters();
params.setPreviewSize(640, 480);
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
params.setPictureFormat(ImageFormat.JPEG);
mCamera.setParameters(params);
mCamera.startPreview();
mCamera.takePicture(null, null, null, new PictureCallback()
@Override
public void onPictureTaken(byte[] data, Camera camera)
Log.i(Version.APP_ID, "picture-taken");
);
【讨论】:
SurfaceTexture
需要camera.startPreview()
呼叫。它与SurfaceView
非常相似。所以我无法通过SurfaceTexture
逃脱预览“冻结”。【参考方案3】:
相机预览只是布局中的一种特殊视图,因此,如果您不想显示它但仍使用现有代码而无需进行大量修改,则可以使用一些技巧。
例如,在您添加相机预览 SurfaceView 的布局文件中,您可以在其顶部添加另一个视图以阻止预览。这样,您仍然可以使用现有代码而无需进行太多修改,并且相机预览将像以前一样工作,但您将获得您正在寻找的效果,但不会显示相机预览。
【讨论】:
但从性能的角度来看并不是一个很好的方法。如果我们遵循SurfaceTexture
方式,我们将有一层额外的透支可以避免..【参考方案4】:
在大量研究发现由于某种原因您必须开始预览甚至在 SurfaceView 中显示该内容才能获得图片之前和之后,我已经尝试过您需要的东西,显然是背后的系统场景刷新缓冲区中用于渲染预览的 SurfaceView 的任何内容,现在我为克服这个问题所做的(在没有预览的情况下拍照)只是将我的布局中的 SurfaceView 设置为 1dp 宽度和 1dp 高度(注意它必须是1dp, 0dp 会导致崩溃)。
<SurfaceView
android:layout_
android:layout_/>
摆脱“预览”图像绝对不是一种非常优雅的方式,但它确实可以解决问题,让我有空间去做我想做的所有其他事情。
希望这会有所帮助...
问候
【讨论】:
【参考方案5】:对于那些正在寻找做同样事情但使用 CAMERA 2 API 的人,您可以在此处查看我的答案。 Capture picture without preview using camera2 API.
【讨论】:
以上是关于我的应用程序启动时如何在没有预览的情况下从相机拍照?的主要内容,如果未能解决你的问题,请参考以下文章