一般情况下,可以使用MediaRecorder来录制视频,视频数据也可在SurfaceView上显示,但是那要写数据到存储设备上。而且我们项目是视频聊天,就不能使用Media了。
网上找了找资料,自己给改了下:
public class CameravedioActivity extends Activity{ private static final String TAG = "CameravedioActivity"; private Camera camera; private boolean preview = false ; private SeekBar mSeekBar; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* *设置窗口属性:一定要在 setContentView(R.layout.main) 之前 */ // 窗口标题,其实可以在manifes文件里面注册 // requestWindowFeature(Window.FEATURE_NO_TITLE); // 全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView); surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.getHolder().setFixedSize(200, 200); surfaceView.getHolder().addCallback(new SurfaceViewCallback()); /** * seekbar 用来实现变焦逻辑 */ mSeekBar = (SeekBar)findViewById(R.id.seekbar); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub Log.d(TAG, "progress:"+progress); } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub Log.d(TAG, "onStartTrackingTouch"); } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub Log.d(TAG, "onStartTrackingTouch"); } }); } private final class SurfaceViewCallback implements Callback { /** * surfaceView 被创建成功后调用此方法 */ @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG,"surfaceCreated"); /* * 在SurfaceView创建好之后 打开摄像头 * 注意是 android.hardware.Camera */ camera = Camera.open(); /* * This method must be called before startPreview(). otherwise surfaceview没有图像 */ try { camera.setPreviewDisplay(holder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } Camera.Parameters parameters = camera.getParameters(); /* 设置预览照片的大小,此处设置为全屏 */ // WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 获取当前屏幕管理器对象 // Display display = wm.getDefaultDisplay(); // 获取屏幕信息的描述类 // parameters.setPreviewSize(display.getWidth(), display.getHeight()); // 设置 parameters.setPreviewSize(200, 200); /* 每秒从摄像头捕获5帧画面, */ parameters.setPreviewFrameRate(5); /* 设置照片的输出格式:jpg */ parameters.setPictureFormat(PixelFormat.JPEG); /* 照片质量 */ parameters.set("jpeg-quality", 85); /* 设置照片的大小:此处照片大小等于屏幕大小 */ // parameters.setPictureSize(display.getWidth(), display.getHeight()); parameters.setPictureSize(200, 200); /* 将参数对象赋予到 camera 对象上 */ // camera.setParameters(parameters); mSeekBar.setMax(100); camera.startPreview(); /** * Installs a callback to be invoked for every preview frame in addition to displaying them on the screen. * The callback will be repeatedly called for as long as preview is active. This method can be called at * any time, even while preview is live. Any other preview callbacks are overridden. * a callback object that receives a copy of each preview frame, or null to stop receiving */ camera.setPreviewCallback(new Camera.PreviewCallback(){ @Override public void onPreviewFrame(byte[] data, Camera camera) { // TODO Auto-generated method stub //在视频聊天中,这里传送本地frame数据给remote端 Log.d(TAG, "camera:"+camera); Log.d(TAG, "byte:"+data); } }); preview = true; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG,"surfaceChanged"); } /** * SurfaceView 被销毁时释放掉 摄像头 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { if(camera != null) { /* 若摄像头正在工作,先停止它 */ if(preview) { camera.stopPreview(); preview = false; } //如果注册了此回调,在release之前调用,否则release之后还回调,crash camera.setPreviewCallback(null); camera.release(); } } } /** * 处理照片被拍摄之后的事件 */ private final class TakePictureCallback implements PictureCallback { @Override public void onPictureTaken(byte[] data, Camera camera) { } } }
main.xml:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <SurfaceView android:id="@+id/surfaceView" android:layout_width="300dip" android:layout_height="300dip" android:visibility="visible" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <SeekBar android:id="@+id/seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> </FrameLayout>我在自己机器上测试surfaceview必须包含在FrameLayout中
manifest文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.edu.wtu" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!-- android:screenOrientation="landscape" 表示横向界面 --> <activity android:name=".CameravedioActivity" android:label="@string/app_name" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="7" /> <!-- 在SDCard中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 往SDCard写入数据权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 申请使用摄像头的权限 --> <uses-permission android:name="android.permission.CAMERA"/> </manifest>注意哦,有些手机是不支持变焦的,所以设置Camera的Parameter会crash,所以要实现变焦逻辑首先判断手机是否支持smoothzoom
sdk 2.1还是不支持setZoom的,2.3.3可以,2.2没有测试