Android相机教程(使用surfaceview)

Posted

技术标签:

【中文标题】Android相机教程(使用surfaceview)【英文标题】:Camera Tutorial for Android (using surfaceview) 【发布时间】:2012-08-29 17:34:45 【问题描述】:

这是我的示例代码:

package newslab.video.server;

import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class VideoServer extends Activity implements SurfaceHolder.Callback 
    TextView testView;

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;

    private final String tag = "VideoServer";

    Button start, stop;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        start = (Button)findViewById(R.id.btn_start);
        start.setOnClickListener(new Button.OnClickListener() 
            public void onClick(View arg0) 
                start_camera();
            
        );

        stop = (Button)findViewById(R.id.btn_stop);
        stop.setOnClickListener(new Button.OnClickListener() 
            public void onClick(View arg0) 
                stop_camera();
            
        );

        surfaceView = (SurfaceView)findViewById(R.id.surfaceView1);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    

    private void start_camera() 
        try
            camera = Camera.open();
        catch(RuntimeException e)
            Log.e(tag, "init_camera: " + e);
            return;
        
        Camera.Parameters param;
        param = camera.getParameters();
        //modify parameter
        param.setPreviewFrameRate(20);
        param.setPreviewSize(176, 144);
        camera.setParameters(param);
        try 
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
         catch (Exception e) 
            Log.e(tag, "init_camera: " + e);
            return;
        
    

    private void stop_camera() 
        camera.stopPreview();
        camera.release();
    

    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) 
        // TODO Auto-generated method stub
    

    public void surfaceCreated(SurfaceHolder holder) 
        // TODO Auto-generated method stub
    

    public void surfaceDestroyed(SurfaceHolder holder) 
        // TODO Auto-generated method stub
    

但是,它只显示预览并停止摄像头。 有没有其他教程教进一步处理,比如如何保存图像或使用位图处理图像?

【问题讨论】:

不使用原生相机是什么意思?你用的是什么相机? 你的基本查询得到解决方案了吗? 下面的评论还有一个问题^^ 【参考方案1】:

好的。所以这里是解决方案:

我没有添加任何尝试捕获。 这只是为了捕获图像并将其存储到 sdcard 中。

public class VideoServer extends Activity implements SurfaceHolder.Callback 
    TextView testView;

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    PictureCallback rawCallback;
    ShutterCallback shutterCallback;
    PictureCallback jpegCallback;
    private final String tag = "VideoServer";

    Button start, stop, capture;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        start = (Button)findViewById(R.id.btn_start);
        start.setOnClickListener(new Button.OnClickListener()
        
            public void onClick(View arg0) 
                start_camera();
            
        );
        stop = (Button)findViewById(R.id.btn_stop);
        capture = (Button) findViewById(R.id.capture);
        stop.setOnClickListener(new Button.OnClickListener()
        
            public void onClick(View arg0) 
                stop_camera();
            
        );
        capture.setOnClickListener(new OnClickListener() 

            @Override
            public void onClick(View v) 
                // TODO Auto-generated method stub
                captureImage();
            
        );

        surfaceView = (SurfaceView)findViewById(R.id.surfaceView1);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        rawCallback = new PictureCallback() 
            public void onPictureTaken(byte[] data, Camera camera) 
                Log.d("Log", "onPictureTaken - raw");
            
        ;

        /** Handles data for jpeg picture */
        shutterCallback = new ShutterCallback() 
            public void onShutter() 
                Log.i("Log", "onShutter'd");
            
        ;
        jpegCallback = new PictureCallback() 
            public void onPictureTaken(byte[] data, Camera camera) 
                FileOutputStream outStream = null;
                try 
                    outStream = new FileOutputStream(String.format(
                            "/sdcard/%d.jpg", System.currentTimeMillis()));
                    outStream.write(data);
                    outStream.close();
                    Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);
                 catch (FileNotFoundException e) 
                    e.printStackTrace();
                 catch (IOException e) 
                    e.printStackTrace();
                 finally 
                
                Log.d("Log", "onPictureTaken - jpeg");
            
        ;
    

    private void captureImage() 
        // TODO Auto-generated method stub
        camera.takePicture(shutterCallback, rawCallback, jpegCallback);
    

    private void start_camera()
    
        try
            camera = Camera.open();
        catch(RuntimeException e)
            Log.e(tag, "init_camera: " + e);
            return;
        
        Camera.Parameters param;
        param = camera.getParameters();
        //modify parameter
        param.setPreviewFrameRate(20);
        param.setPreviewSize(176, 144);
        camera.setParameters(param);
        try 
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
            //camera.takePicture(shutter, raw, jpeg)
         catch (Exception e) 
            Log.e(tag, "init_camera: " + e);
            return;
        
    

    private void stop_camera()
    
        camera.stopPreview();
        camera.release();
    

    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) 
        // TODO Auto-generated method stub
    

    public void surfaceCreated(SurfaceHolder holder) 
        // TODO Auto-generated method stub
    

    public void surfaceDestroyed(SurfaceHolder holder) 
        // TODO Auto-generated method stub
    


不要在开始之前按捕获按钮,因为我没有检查它。我只是想向您展示如何捕获图像并将其存储到 sdcard

【讨论】:

了解更多信息。访问此网站marakana.com/forums/android/examples/39.html 您的解决方案非常完美。但是还有一个问题,我怎样才能将捕获的图像作为位图来获得进一步的效果? 为此,您必须使用它从 sdcard 中获取捕获的图像。位图位图 = BitmapFactory.decodeFile("/path/images/imageName.jpg");你可以对位图做进一步的操作 @NarendraPal 当我点击开始按钮时显示:java.lang.RuntimeException: 无法连接到 logcat 上的相机服务 @mahdi 请查看我在 cmets 中提到的完整示例代码,如果这不起作用,请告诉我。【参考方案2】:

不要忘记在Android Manifest文件中获取使用相机的权限,

<uses-permission android:name="android.permission.CAMERA" ></uses-permission>

此外,您还必须获得在 SD 卡上存储图像的权限,

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

【讨论】:

【参考方案3】:

manifiest 文件中的相机权限:

<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />

将来自sdcard 的图像存储在manifiest 文件中的权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

【讨论】:

【参考方案4】:

我在使用相机时遇到问题,正在弄清楚如何实施和使用并遇到以下资源:Camera preview。在页面底部,您有最常见场景的示例以及原始问题中的示例:Take and preview Photo

【讨论】:

【参考方案5】:

如果您使用的是 android 10 或更高版本,请不要忘记将其添加到您的清单文件中

android:requestLegacyExternalStorage="true"
android:grantUriPermissions="true"

【讨论】:

以上是关于Android相机教程(使用surfaceview)的主要内容,如果未能解决你的问题,请参考以下文章

android - 使用没有surfaceview或textureview的相机

使用 SurfaceView 的 Android 游戏循环;快速更改相机“镜头”会导致黑色闪光等

如何在surfaceview中将Android相机更改为人像?

android相机surfaceview方向

无法创建支持android 4.0 及更高版本的surfaceview 相机应用。

如何在Android中修复相机预览(surfaceview)的正确纵横比?