zoukankan      html  css  js  c++  java
  • Android Camera学习总结:如何在android中使用摄像头获取照片

    这学期补修了Android这门课,短短的八次课让我对Android有了初步的了解。作为结课项目,老师让我们用Camera/Surfaceview完成相机功能。现将学习的心得记录下来。

    整个相机程序实现的思路是,使用Camera实例,设置好参数后,得到摄像头传回的图像数据,将这些数据在Surfaceview实例中进行展示,实现预览功能。在Surfaceview下,设置click button,当单击click button后,调用Camera.takePicture方法,完成照相动作,将图片保存到手机本地。

    整个工程的核心是实现了SurfaceHolder.Callback接口,重写接口中的几个方法,而这几个方法,都是Surfaceview实例将要调用的关键方法。他们分别是:surfaceCreated/surfaceDestroyed/surfaceChanged。然后可以通过Surfaceview.getHolder().addCallback(Callback)方法,将这个Callback与前端layout中的surfaceview相关联起来。

    下面来看下Callback中方法具体代码:

     1 @Override
     2         public void surfaceChanged(SurfaceHolder holder, int format, int width,
     3                 int height) {
     4             Log.e("tag", " surfaceChanged");
     5             mParameters = camera.getParameters();
     6             mParameters.setPictureFormat(PixelFormat.JPEG);
     7             Log.e("tag",
     8                     "parameters.getPictureSize()"
     9                             + mParameters.getPictureSize().width);
    10             setPictureSize(mParameters);
    11             Log.i("tag", "holder " + width + "  height:" + height);
    12             // parameters.setPreviewSize(width, height);//需要判断支持的预览
    13 
    14             camera.setParameters(mParameters);
    15 
    16             camera.startPreview();
    17         }
    18 
    19 private void setPictureSize(Parameters parameters) {
    20         List<Size> sizes = parameters.getSupportedPictureSizes();
    21         if (sizes == null) {
    22             return;
    23         }
    24         int maxSize = 0;
    25         int width = 0;
    26         int height = 0;
    27         for (int i = 0; i < sizes.size(); i++) {
    28             Size size = sizes.get(i);
    29             int pix = size.width * size.height;
    30             if (pix > maxSize) {
    31                 maxSize = pix;
    32                 width = size.width;
    33                 height = size.height;
    34             }
    35         }
    36         Log.i("tag", "图片的大小:" + width + " height:" + height);
    37         parameters.setPictureSize(width, height);
    38     }

    上段代码重写了surfaceChanged方法。该方法中完成了设置相机的参数,包括图片格式,预览尺寸,并开始预览功能,即在surfaceview中实时显示摄像头中捕捉的画面。其中setPicturesize方法使用了相对的图片大小设置,如果将图片大小设置成绝对值,可能会造成不同尺寸屏幕的机器不能正常运行程序的异常发生。

    在另外两个方法中分别完成了camera实例的获取和销毁工作,具体代码如下:

    @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                Log.i("tag", " surfaceDestroyed");
                if (camera != null) {
                    camera.stopPreview();
                    camera.release();
                    camera = null;
                }
            }
    
    @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    if (camera == null) {
                        camera = Camera.open();
                    }
                    camera.setPreviewDisplay(holder);
                    Log.i("", "camera created");
                    //WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
                    //Display display = wm.getDefaultDisplay();
    //                Camera.Parameters parameters = camera.getParameters();
    //                //parameters.setPreviewSize(display.getWidth(), display.getHeight());//设置预览照片的大小
    //                parameters.setPreviewFrameRate(3);//每秒3帧
    //                parameters.setPictureFormat(PixelFormat.JPEG);//设置照片的输出格式
    //                parameters.set("jpeg-quality", 100);//照片质量
    //                //parameters.setPictureSize(display.getWidth(), display.getHeight());//设置照片的大小
    //                camera.setParameters(parameters);
    //                camera.setPreviewDisplay(surfaceView.getHolder());//通过SurfaceView显示取景画面
    //                camera.startPreview();//开始预览
    //                preview = true;
                } catch (IOException e) {
                    if (camera != null) {
                        camera.stopPreview();
                        camera.release();
                        camera = null;
                    }
                    e.printStackTrace();
                }
                
            }

    下面将整个项目的代码贡献出来,包括实现自动对焦,手动调焦距,设置闪光灯等功能。

    共包含一个mainActivity和CameraCallback两个类

    mainActivity的代码如下:

    import android.app.Activity;
    import android.hardware.Camera;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnTouchListener;
    import android.widget.Button;
    import android.widget.SeekBar;
    import android.widget.Toast;
    import android.widget.SeekBar.OnSeekBarChangeListener;
    
    public class MainActivity extends Activity implements OnClickListener {
        private Camera mCamera;
        private SurfaceView mSurfaceView;
        private SurfaceHolder mHolder;
        private CameraCallback mCallback;
        private Button mTakePicButton;
        private Button mSwitchButton;
        private Button mflashButton;
    
        private boolean saved = true;
        private boolean isFrontCamera;
    
        public static final int MESSAGE_SVAE_SUCCESS = 0;
        public static final int MESSAGE_SVAE_FAILURE = 1;
    
        private final int FLASH_MODE_AUTO = 0;
        private final int FLASH_MODE_ON = 1;
        private final int FLASH_MODE_OFF = 2;
        private int mFlashMode = 0;
    
        private Handler mHandler = new Handler() {
            public void handleMessage(Message msg) {
                saved = true;
                switch (msg.what) {
                case MESSAGE_SVAE_SUCCESS:
                    Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT)
                            .show();
                    break;
                case MESSAGE_SVAE_FAILURE:
                    Toast.makeText(MainActivity.this, "保存失败", Toast.LENGTH_SHORT)
                            .show();
                    break;
                }
            };
        };
        private SeekBar mZoomBar;
        private View mZoomLayout;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            initView();
    
        }
    
        private void initView() {
    
            mTakePicButton = (Button) findViewById(R.id.camera_take_btn);
            mTakePicButton.setOnClickListener(this);
            mSwitchButton = (Button) findViewById(R.id.camera_switch_btn);
            mSwitchButton.setOnClickListener(this);
            mflashButton = (Button) findViewById(R.id.flashMode);
            mflashButton.setOnClickListener(this);
    
            mZoomLayout = findViewById(R.id.zoomLayout);
            mZoomBar = (SeekBar) findViewById(R.id.seekBar1);
            mZoomBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
    
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                }
    
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
                }
    
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress,
                        boolean fromUser) {
                    mCallback.setZoom(progress);
                }
            });
    
            initSurfaceView();
        }
    
        private void initSurfaceView() {
            mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
            mHolder = mSurfaceView.getHolder();
            mCallback = new CameraCallback(this);
            mHolder.addCallback(mCallback);
            mSurfaceView.setOnTouchListener(new OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP
                            && !isFrontCamera) {// 前置摄像头取消触摸自动聚焦功能
                        View view = findViewById(R.id.RelativeLayout1);
                        mCallback.autoFocus(view, event);
                    }
    
                    return true;
                }
            });
    
            // 判断是否支持前置摄像头
            int cameras = mCallback.getNumberOfCameras();
            if (cameras <= 1) {
                mSwitchButton.setVisibility(View.GONE);
            }
    
            // 是否支持闪关灯
            if (!mCallback.isSupportedFlashMode()) {
                mflashButton.setVisibility(View.GONE);
            }
    
            if (mCallback.isSupportedZoom()) {
                mZoomBar.setMax(mCallback.getMaxZoom());
            } else {
                mZoomBar.setVisibility(View.GONE);
            }
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.camera_take_btn:
                if (saved) {
                    saved = false;
                    mCallback.takePicture(mHandler);
                }
                break;
            case R.id.camera_switch_btn:
                isFrontCamera = !isFrontCamera;
                if (isFrontCamera) {
                    mSwitchButton.setText("打开后摄像头");
                    mflashButton.setVisibility(View.GONE);
                    mZoomLayout.setVisibility(View.GONE);
                } else {
                    mSwitchButton.setText("打开前摄像头");
                    mflashButton.setVisibility(View.VISIBLE);
                    mZoomLayout.setVisibility(View.VISIBLE);
                }
                mCallback.switchCamera(mSurfaceView, isFrontCamera);
                break;
            case R.id.flashMode:
                mFlashMode = (mFlashMode + 1) % 3;
                switch (mFlashMode) {
                case FLASH_MODE_AUTO:
                    mflashButton.setText("flash_auto");
                    break;
                case FLASH_MODE_ON:
                    mflashButton.setText("flash_on");
                    break;
                case FLASH_MODE_OFF:
                    mflashButton.setText("flash_off");
                    break;
    
                default:
                    break;
                }
                mCallback.SetFlashMode(mFlashMode);
                break;
    
            default:
                break;
            }
    
        }
    
    }

    CameraCallback类代码如下:

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.List;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.PixelFormat;
    import android.graphics.Bitmap.CompressFormat;
    import android.hardware.Camera;
    import android.hardware.Camera.AutoFocusCallback; //import android.hardware.Camera.CameraInfo;
    import android.hardware.Camera.Parameters;
    import android.hardware.Camera.PictureCallback;
    import android.hardware.Camera.Size;
    import android.os.Environment;
    import android.os.Handler;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.animation.Animation;
    import android.view.animation.ScaleAnimation;
    import android.view.animation.Animation.AnimationListener;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.RelativeLayout.LayoutParams;
    
    public class CameraCallback implements SurfaceHolder.Callback {
        private Context mContext;
        private Camera mCamera;
        private boolean isShowFrame;
        private SurfaceHolder mHolder;
        // 在2.3的Camera.CameraInfo类中
        // CAMERA_FACING_BACK常量的值为0,CAMERA_FACING_FRONT为1
        private static final int CAMERA_FACING_BACK = 0;
        private static final int CAMERA_FACING_FRONT = 1;
    
        private final int FLASH_MODE_AUTO = 0;
        private final int FLASH_MODE_ON = 1;
        private final int FLASH_MODE_OFF = 2;
    
        private Parameters mParameters;
    
        public CameraCallback(Context context) {
            this.mContext = context;
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
            Log.e("tag", " surfaceChanged");
            mParameters = mCamera.getParameters();
            if (isSupportedFlashMode()) {// 需要判断是否支持闪光灯
                mParameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
            }
            mParameters.setPictureFormat(PixelFormat.JPEG);
            Log.e("tag",
                    "parameters.getPictureSize()"
                            + mParameters.getPictureSize().width);
            setPictureSize(mParameters);
            // parameters.setPreviewFormat(PixelFormat.JPEG);//
            Log.i("tag", "holder " + width + "  height:" + height);
            // parameters.setPreviewSize(width, height);//需要判断支持的预览
    
            mCamera.setParameters(mParameters);
    
            mCamera.startPreview();
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            mHolder = holder;
            Log.e("tag", " surfaceCreated");
            try {
                if (mCamera == null) {
                    mCamera = Camera.open();
                }
                setDisplayOrientation(mCamera);
                mCamera.setPreviewDisplay(holder);
                Log.i("", "mCamera 2");
    
            } catch (IOException e) {
                if (mCamera != null) {
                    mCamera.stopPreview();
                    mCamera.release();
                    mCamera = null;
                }
                e.printStackTrace();
            }
    
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            Log.e("tag", " surfaceDestroyed");
            if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
    
        }
    
        public int getNumberOfCameras() {
            try {
                Method method = Camera.class.getMethod("getNumberOfCameras", null);
                if (method != null) {
                    Object object = method.invoke(mCamera, null);
                    if (object != null) {
                        return (Integer) object;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return 0;
        }
    
        private void setDisplayOrientation(Camera camera) {
            try {
                Method method = Camera.class.getMethod("setDisplayOrientation",
                        int.class);
                if (method != null) {
                    method.invoke(camera, 90);
                }
                Log.i("tag", "方法名:" + method.getName());
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        public Camera open(int i) {
            try {
                Method method = Camera.class.getMethod("open", int.class);
                if (method != null) {
                    Object object = method.invoke(mCamera, i);
                    if (object != null) {
                        return (Camera) object;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        // 设置图片大小
        private void setPictureSize(Parameters parameters) {
            List<Size> sizes = parameters.getSupportedPictureSizes();
            if (sizes == null) {
                return;
            }
            int maxSize = 0;
            int width = 0;
            int height = 0;
            for (int i = 0; i < sizes.size(); i++) {
                Size size = sizes.get(i);
                int pix = size.width * size.height;
                if (pix > maxSize) {
                    maxSize = pix;
                    width = size.width;
                    height = size.height;
                }
            }
            Log.i("tag", "图片的大小:" + width + " height:" + height);
            parameters.setPictureSize(width, height);
        }
    
        public Camera getCamera() {
            return mCamera;
        }
    
        // 自动对焦
        public void autoFocus(View v, MotionEvent event) {
            if (isShowFrame) {
                return;
            }
            mCamera.autoFocus(new AutoFocusCallback() {
    
                @Override
                public void onAutoFocus(boolean success, Camera camera) {
                }
            });
    
            RelativeLayout layout = (RelativeLayout) v;
    
            final ImageView imageView = new ImageView(mContext);
            Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),
                    R.drawable.lcamera_focus_frame1);
            imageView.setImageBitmap(bitmap);
            LayoutParams params = new RelativeLayout.LayoutParams(
                    bitmap.getWidth(), bitmap.getHeight());
            // imageView.setLayoutParams(params);
            Log.e("tag", "bitmap.getWidth:" + bitmap.getWidth());
            params.leftMargin = (int) (event.getX() - bitmap.getWidth() / 2);
            params.topMargin = (int) (event.getY() - bitmap.getHeight() / 2);
            layout.addView(imageView, params);
            imageView.setVisibility(View.VISIBLE);
            ScaleAnimation animation = new ScaleAnimation(1, 0.5f, 1, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                    0.5f);
            animation.setDuration(300);
            animation.setFillAfter(true);
            animation.setAnimationListener(new AnimationListener() {
    
                @Override
                public void onAnimationStart(Animation animation) {
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
                }
    
                @Override
                public void onAnimationEnd(final Animation animation) {
                    imageView.setImageResource(R.drawable.lcamera_focus_frame2);
    
                    new Thread() {
                        public void run() {
                            try {
                                Thread.sleep(400);
                                ((Activity) (mContext))
                                        .runOnUiThread(new Runnable() {
    
                                            @Override
                                            public void run() {
                                                imageView
                                                        .setImageResource(R.drawable.lcamera_focus_frame3);
                                            }
                                        });
                                Thread.sleep(200);
                                ((Activity) (mContext))
                                        .runOnUiThread(new Runnable() {
    
                                            @Override
                                            public void run() {
                                                imageView.clearAnimation();
                                                imageView.setVisibility(View.GONE);
                                                isShowFrame = false;
                                            }
                                        });
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
    
                        };
                    }.start();
                }
            });
            imageView.startAnimation(animation);
            isShowFrame = true;
        }
    
        // 拍照
        public void takePicture(final Handler handler) {
            mCamera.takePicture(null, null, new PictureCallback() {
    
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    FileOutputStream fos = null;
                    try {
                        File directory;
                        if (Environment.getExternalStorageState().equals(
                                Environment.MEDIA_MOUNTED)) {
                            directory = new File(Environment
                                    .getExternalStorageDirectory(), "camera");
                        } else {
                            directory = new File(mContext.getCacheDir(), "camera");
                        }
                        if (!directory.exists()) {
                            directory.mkdir();
                        }
                        File file = new File(directory, System.currentTimeMillis()
                                + ".jpg");
                        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
                                data.length);
                        fos = new FileOutputStream(file);
                        boolean compress = bitmap.compress(CompressFormat.JPEG,
                                100, fos);
                        if (compress) {
                            handler.sendEmptyMessage(MainActivity.MESSAGE_SVAE_SUCCESS);
                        } else {
                            handler.sendEmptyMessage(MainActivity.MESSAGE_SVAE_FAILURE);
                        }
                        mCamera.startPreview();
                        Log.i("tag", " 保存是否成功:" + compress + "  file.exists:"
                                + file.exists());
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } finally {
                        if (fos != null) {
                            try {
                                fos.close();
                            } catch (IOException e) {
                            }
                        }
                    }
    
                }
            });
    
        }
    
        // 多镜头切换
        public void switchCamera(SurfaceView surfaceView, boolean isFrontCamera) {
            if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
    
            int cameraId = isFrontCamera ? CAMERA_FACING_FRONT : CAMERA_FACING_BACK;// CAMERA_FACING_FRONT为前置摄像头
    
            mCamera = open(cameraId);
            Parameters parameters = mCamera.getParameters();
            Log.e("tag",
                    "parameters.getPictureSize()"
                            + parameters.getPictureSize().width);
            setPictureSize(parameters);
    
            parameters.setPictureFormat(PixelFormat.JPEG);
            mCamera.setParameters(parameters);
            Log.e("tag",
                    "2 parameters.getPictureSize()"
                            + parameters.getPictureSize().width);
            setDisplayOrientation(mCamera);
            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        public boolean isSupportedZoom() {
            if (mCamera != null) {
                Parameters parameters = mCamera.getParameters();
                return parameters.isZoomSupported();
            }
            return false;
        }
    
        public int getMaxZoom() {
            if (mCamera == null) {
                mCamera = Camera.open();
            }
            mParameters = mCamera.getParameters();
            return mParameters.getMaxZoom();
        }
    
        // 设置Zoom
        public void setZoom(int value) {
            Log.i("tag", "value:" + value);
            mParameters.setZoom(value);
            mCamera.setParameters(mParameters);
            mCamera.startPreview();
        }
    
        public boolean isSupportedFlashMode() {
            if (mCamera == null) {
                mCamera = Camera.open();
            }
            Parameters parameters = mCamera.getParameters();
            List<String> modes = parameters.getSupportedFlashModes();
            if (modes != null && modes.size() != 0) {
                boolean autoSupported = modes.contains(Parameters.FLASH_MODE_AUTO);
                boolean onSupported = modes.contains(Parameters.FLASH_MODE_ON);
                boolean offSupported = modes.contains(Parameters.FLASH_MODE_OFF);
                return autoSupported && onSupported && offSupported;
            }
            return false;
        }
    
        // 设置闪光灯模式
        public void SetFlashMode(int flashMode) {
            switch (flashMode) {
            case FLASH_MODE_AUTO:
                mParameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
                break;
            case FLASH_MODE_ON:
                mParameters.setFlashMode(Parameters.FLASH_MODE_ON);
                break;
            case FLASH_MODE_OFF:
                mParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
                break;
            }
            mCamera.setParameters(mParameters);
            mCamera.startPreview();
        }
    }

    layout中main.xml声明相应的surfaceview和相应的button/seekbar

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/RelativeLayout1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <SurfaceView
            android:id="@+id/surfaceView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_marginBottom="55dp" />
    
        <RelativeLayout
            android:id="@+id/camera_bottom"
            android:layout_width="fill_parent"
            android:layout_height="55.0dip"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:background="#88ffffff"
            android:orientation="vertical" >
    
            <Button
                android:id="@+id/camera_take_btn"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:layout_gravity="center"
                android:layout_marginLeft="3.0dip"
                android:text="拍照" />
        </RelativeLayout>
    
        <Button
            android:id="@+id/camera_switch_btn"
            android:layout_width="120dp"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="5dp"
            android:gravity="center"
            android:text="打开前置摄像头" >
        </Button>
    
        <Button
            android:id="@+id/flashMode"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginTop="5dp"
            android:text="flash_auto" />
    
        <LinearLayout
            android:id="@+id/zoomLayout"
            android:layout_width="wrap_content"
            android:layout_height="20dp"
            android:layout_above="@+id/camera_bottom"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="5dp"
            android:orientation="horizontal" >
    
            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=" - "
                android:textColor="#ffffff" />
    
            <SeekBar
                android:id="@+id/seekBar1"
                android:layout_width="250dp"
                android:layout_height="13dp"
                android:layout_gravity="center_vertical"
                android:maxHeight="6dp"
                android:progressDrawable="@drawable/seekbar_progress"
                android:thumb="@drawable/camera_seekbar_progress_ball"
                android:thumbOffset="0dp" />
    
            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="top"
                android:gravity="top"
                android:text=" + "
                android:textColor="#ffffff" />
        </LinearLayout>
    
    </RelativeLayout>

    在AndroidManifest中做如下权限声明

        <uses-sdk android:minSdkVersion="8" />
    
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.CAMERA" />
    
        <uses-feature android:name="android.hardware.camera" />
        <uses-feature android:name="android.hardware.camera.autofocus" />
  • 相关阅读:
    BNUOJ 34978 汉诺塔 (概率dp)
    hdu1427 速算24点
    vim学习之以退为进——可反复移动和可反复改动的美妙结合
    C++设计模式实现--策略(Strategy)模式
    ios怎样在一个UIImageButton的里面加一些自己定义的箭头
    HTML5 Canvas 画图入门
    AT3728 Squirrel Migration
    HTTP请求的GET与POST方式的区别
    HTTP 的请求过程?
    servlet的生命周期
  • 原文地址:https://www.cnblogs.com/chlde/p/3074244.html
Copyright © 2011-2022 走看看