现在社交类程序很火,里面基本包含定位,IM,微视频,在智能电视TV的客户端也会提供录像功能,然后可以传送给智能电视播放,下面我们通过一个实例实现具备录像功能。
由于手机很多都是定制系统,所以当我们设置摄像头参数的时候,提示设置失败,我试了两款手机,有的手机有问题,有的正常,所以再设置参数的地方加了try来捕获。
首先看一下布局界面:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.jwzhangjie.smarttv_client.media.Video.SmartVideoSurfaceView
android:id="@+id/surface_camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.jwzhangjie.smarttv_client.widget.TVChronometer
android:id="@+id/video_show_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip"
/>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" >
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始" />
</LinearLayout>
</LinearLayout>
里面有两个封装的类,对应如下的代码:
package com.jwzhangjie.smarttv_client.media.Video;
import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class SmartVideoSurfaceView extends SurfaceView implements Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
private boolean previewRunning = false;
public SmartVideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initConfig();
}
private void initConfig(){
mHolder = this.getHolder();
mHolder.addCallback(this);
}
public Camera getVideoCamera(){
return mCamera;
}
public SurfaceHolder getMyHolder(){
return mHolder;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mCamera != null) {
if (previewRunning) {
mCamera.stopPreview();
}
try {
Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(width, height);
params.setPreviewFormat(ImageFormat.JPEG);
mCamera.setParameters(params);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
previewRunning = true;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
previewRunning = false;
mCamera.release();
}
}
}
这个是重写了SurfaceView
package com.jwzhangjie.smarttv_client.widget;
import com.jwzhangjie.smarttv_client.R;
import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.Chronometer;
import android.widget.Chronometer.OnChronometerTickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class TVChronometer extends LinearLayout implements OnChronometerTickListener{
private ImageView video_red;
private Chronometer video_show_time;
private boolean show = false;
public TVChronometer(Context context) {
super(context);
init();
}
public TVChronometer(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public void init(){
setOrientation(HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL);
video_red = new ImageView(getContext());
video_red.setImageResource(R.drawable.video_record_1);
LinearLayout.LayoutParams redParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
redParams.setMargins(0, 8, 8, 8);
addView(video_red, redParams);
video_show_time = new Chronometer(getContext());
video_show_time.setOnChronometerTickListener(this);
addView(video_show_time);
setVisibility(View.INVISIBLE);
}
public void start(){
setVisibility(View.VISIBLE);
video_show_time.setBase(SystemClock.elapsedRealtime());
video_show_time.start();
}
public void stop(){
setVisibility(View.INVISIBLE);
video_show_time.stop();
}
@Override
public void onChronometerTick(Chronometer chronometer) {
if (show) {
video_red.setImageResource(R.drawable.video_record_1);
}else {
video_red.setImageResource(R.drawable.video_record_2);
}
show = !show;
}
}
这个是用来显示录像的时候,时间显示和红点闪烁
主界面代码如下:
package com.jwzhangjie.smarttv_client.media;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.jwzhangjie.smarttv_client.R;
import com.jwzhangjie.smarttv_client.media.Video.SmartVideoSurfaceView;
import com.jwzhangjie.smarttv_client.media.Video.VideoRecorder;
import com.jwzhangjie.smarttv_client.ui.base.BaseActivity;
import com.jwzhangjie.smarttv_client.widget.TVChronometer;
public class SmartCamera extends BaseActivity implements OnClickListener{
private SmartVideoSurfaceView mSurfaceView;
private TVChronometer video_show_time;
private VideoRecorder mRecorder;
private Button play;
private boolean isRecording = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_video);
initView();
initSurfaceConfig();
initListener();
}
private void initView(){
mSurfaceView = (SmartVideoSurfaceView)findViewById(R.id.surface_camera);
play = (Button)findViewById(R.id.play);
video_show_time = (TVChronometer)findViewById(R.id.video_show_time);
}
private void initListener(){
play.setOnClickListener(this);
}
private void initSurfaceConfig(){
mRecorder = new VideoRecorder();
mRecorder.init(mSurfaceView, "/mnt/sdcard/", "test.mp4");
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.play:
if (!isRecording) {
play.setText("停止");
mRecorder.startRecording();
video_show_time.start();
}else {
play.setText("开始");
mRecorder.stopRecording();
video_show_time.stop();
}
isRecording = !isRecording;
break;
}
}
}
里面有一个封装MediaRecoder的类,代码如下:
package com.jwzhangjie.smarttv_client.media.Video;
import java.io.File;
import android.media.MediaRecorder;
import android.os.AsyncTask;
public class VideoRecorder extends MediaRecorder{
private SmartVideoSurfaceView mSurfaceView;
private boolean preView = false;
private int videoFramesPerSecond = 20;
private String fileDir;
private String fileName;
private File videoFile;
public VideoRecorder(){
}
public void setCamera(SmartVideoSurfaceView mSurfaceView){
this.mSurfaceView = mSurfaceView;
}
public void setVideoFile(String fileDir, String fileName){
this.fileDir = fileDir;
this.fileName = fileName;
}
public void init(SmartVideoSurfaceView mSurfaceView,String fileDir, String fileName ){
this.mSurfaceView = mSurfaceView;
this.fileDir = fileDir;
this.fileName = fileName;
}
public void setVideoFrameRaido(int videoFramesPerSecond){
this.videoFramesPerSecond = videoFramesPerSecond;
}
public boolean startRecording(){
new VideoAysn().execute(1);
return preView;
}
private class VideoAysn extends AsyncTask<Integer, Void, Void>{
@Override
protected Void doInBackground(Integer... params) {
try {
if (params[0] == 1) {
preView = false;
mSurfaceView.getVideoCamera().unlock();
setCamera(mSurfaceView.getVideoCamera());
setAudioSource(MediaRecorder.AudioSource.MIC);
setVideoSource(MediaRecorder.VideoSource.CAMERA);
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
videoFile = new File(fileDir, fileName);
if (videoFile.exists()) {
videoFile.delete();
}
setOutputFile(videoFile.getPath());
setVideoFrameRate(videoFramesPerSecond);
//设置这个参数会导致java.lang.RuntimeException: start failed.
// setVideoSize(mSurfaceView.getWidth(), mSurfaceView.getHeight());
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
setVideoEncoder(MediaRecorder.VideoEncoder.H264);
setPreviewDisplay(mSurfaceView.getMyHolder().getSurface());
prepare();
start();
preView = true;
}else {
if (preView) {
stop();
mSurfaceView.getVideoCamera().lock();
}
}
} catch (Exception e) {
e.printStackTrace();
preView = false;
}
return null;
}
}
public void stopRecording(){
new VideoAysn().execute(2);
}
}
运行效果如下:
我测试了一下录像文件音视频正常,还有就是权限自己不要忘记加了。