一般情况下,可以使用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没有测试