Android应用开发Camera系列(一):SurfaceView实现相机预览demo--新手上路

    这是工作第一份任务。任务要求是用GLSurfaceView做相机预览,笔者只有那么一点安卓常识,完全不知道GLSurfaceView的存在,故用SurfaceView做好就交工了,才发现,搬砖之前要搞清楚搬哪块砖啊!

    进入正题。SurfaceView是一个类,类名是SurfaceView。它可以做很多事情,今天只拿来做视图!就是屏幕上你能看见的(这句话套用在Activity上也适用)。提醒:毫无基础从一看起,只要重点直接到四,括号内容可以忽略。

    开始流程:

    一、安卓程序运行是从AndroidMainfest.xml中查找MainActivity开始

/AndroidMainfest.xml




    

    

    
        
            
                

                
            
        
    


   说明:这里要学的东西还是蛮多的,但基本上不用你学,会改就行(you know ,copy right?)。

    注意:包名(package)!!!要用相机当然要加使用相机的权限(permission)!!!还有你的SDK版本不对就自行修改一下。

    二、找到MainActivity.java之后呢,之后是执行onCreate方法

/src/org.kintai.cameratest/MainActivity.java

package org.kintai.cameratest;

import android.os.Bundle;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.util.Log;
import android.view.Window;

public class MainActivity extends Activity {
	private static final String TAG = "Kintai";
	private MySurfaceView mView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 横屏
		requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题

		initUI();
		setContentView(R.layout.activity_main);
	}

	private void initUI() {
		Log.d(TAG, "initUI...");
		mView = (MySurfaceView) findViewById(R.id.mView);
	}

}
 
      再次说明: 
  

1.这个MainActivity和C/C++程序中main起的名字都很像,所以作用也很像。进来之后首先会在onCreate方法内执行相应代码,之前呢?之前会加载一些static库,一般NDK才有。有些情况需要注意代码的顺序 (比如在口袋里的钱包取钱这个动作,一般顺序:手——口袋——钱包——钱;非一般顺序:手——钱,能确定拿到的钱 数额 就是你要的么?不够再拿~.~)

2.initUI方法。这个是笔者写的,各式各样都有,名字要直观,就是初始化界面,用于当前Activity上加载视图SurfaceView,即这里的mView。有些小地方需要在程序调试过程中慢慢体验(横屏、去标题、log.d是有点多余的,不写也行,就是这里放放。这个都不知道,LogCat就更不用说了)

3.findViewById方法。传的参数是 R.id.mView ,与R相关的是自动生成的东西,它一般在xml中,只要写的合法就会自动生成,为什么要等它生成在R里面才能拿来用?安全起见,用不合规则的砖会把程序搞蹦跶呢。(很不幸每一个安卓初学者都要接触这个东西,用它找TextView然后贴上“HelloWorld”...)

    三、mView要在布局文件activity_main.xml中注册,findViewById才能找到它

/res/layout/activity_main.xml



    

    
     
  再次注意: 
  

1.context对应的名字要写对,名字前面有个“.”这里是 .MainActivity 。

2.MySurfaceView在后面创建。(Button无关紧要,就是后面要拍照啊,要切换前后摄像头可能会用到,就先贴一个在这里)

    四、MySurfaceView.java非常关键,负责将相机看到的内容展示在屏幕上

/src/org.kintai.cameratest/MySurfaceView.java

package org.kintai.cameratest;

import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView implements
		SurfaceHolder.Callback {
	private static final String TAG = "Kintai";

	private static SurfaceHolder holder;
	private Camera mCamera;

	public MySurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		Log.i(TAG, "new View ...");

		holder = getHolder();//后面会用到!
		holder.addCallback(this);
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		Log.i(TAG, "surfaceCreated...");
		if (mCamera == null) {
			mCamera = Camera.open();//开启相机,可以放参数 0 或 1,分别代表前置、后置摄像头,默认为 0
			try {
				mCamera.setPreviewDisplay(holder);//整个程序的核心,相机预览的内容放在 holder
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		Log.i(TAG, "surfaceChanged...");
		mCamera.startPreview();//该方法只有相机开启后才能调用
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		Log.i(TAG, "surfaceChanged...");
		if (mCamera != null) {
			mCamera.release();//释放相机资源
			mCamera = null;
		}
	}

}
 
  

    讲解:MySurfaceView继承至SurfaceView,实现了SurfaceHolder.Callback接口

1.从构造器(方法名和类名一样的)开始就有不一样的味道,一般只有context参数,这里多了个AttributeSet参数。这是因为 SurfaceView写在布局xml,而要从xml中通过findViewById方法生成视图则有此 特定的要求,如果不写则无法生成MySurfaceView的实例.(onCreate中setContentView直接加载SurfaceView则不用)

2.构造器里的holder。一直不理解为什么会有这样的东西,后来想想。一个视图是很大一块内存,如果不给它起个名字或者取个地址,要用到的时候怎么传啊?使用getHolder就找到它了,同时还要添加一个回调addCallback,代表holder和this (即这个类的本体) 的一种关联。

3.Callback接口。要用接口就要实现其带来的功能,即方法。这里有三个SurfaceCreated、SurfaceChanged和SurfaceDestoryed,参数可以不用管先,暂时并不用在视图上做特殊操作,只要求把相机的预览呈现。

    SurfaceCreated:

                     View创建的时候调用,这里做了两个事情打开相机,设置预览显示;

                     预览显示当然需要界面,故有try~catch;

                     mCamera是相机实体,通过Camera.open指定该实体是后置摄像头,方便后续调用;

     SurfaceChanged:

                     View有变化的时候调用,其实它一直在变化...

                                   mCamera要用到了,startPreview开始预览;

   SurfaceDestoryed:

                                   View在销毁的时候调用,就是要随手关灯;

                                    mCamera又要用到了,release释放资源,mCamera不指定;

预览效果图:

源码地址:

-----------------------------------------------------------------------------------Kintai原创,欢迎转载

  

你可能感兴趣的:(Android应用开发)