现在社交类程序很火,里面基本包含定位,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); } }
运行效果如下:
我测试了一下录像文件音视频正常,还有就是权限自己不要忘记加了。