不用预览,录制固定时间的视频
activity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
/** 开始摄像 **/
startService(new Intent(MainActivity.this, VideoSerivice.class));
}
});
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e("Service", "stopService");
/** * 启动定时器,到规定时间recordTime后执行停止录像任务 */
Intent intents = new Intent();
intents.setAction("com.example.testvideo.VideoService");
}
});
}
}
public class VideoSerivice extends Service implements
SurfaceHolder.Callback {
private SurfaceView surfaceview;// 视频预览控件
private LinearLayout lay; // 愿揽控件的
private SurfaceHolder surfaceHolder; // //和surfaceView相关的
private Context context;
private boolean isRecorder = false;
WindowManager wm;
LinearLayout relLay;
CramerThread thread;
/**
* 检测摄像头硬件 如果应用程序未使用manifest声明对摄像头需求进行特别指明,则应该在运行时检查一下摄像头是否可用
*/
public boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
return true;
}
return false;
}
@Override
public void onCreate() {
super.onCreate();
Log.e("","onCreate");
if (!checkCameraHardware(this)) {
Toast.makeText(this, "摄像头被占用或不存在", Toast.LENGTH_LONG).show();
return;
}
// 设置悬浮窗体属性
// 1.得到WindoeManager对象:
wm = (WindowManager) getApplicationContext().getSystemService("window");
// 2.得到WindowManager.LayoutParams对象,为后续设置相关参数做准备:
WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
// 3.设置相关的窗口布局参数,要实现悬浮窗口效果,要需要设置的参数有
// 3.1设置window type
wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
// 3.2设置图片格式,效果为背景透明 //wmParams.format = PixelFormat.RGBA_8888;
wmParams.format = 1;
// 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
// 4.// 设置悬浮窗口长宽数据
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
// 5. 调整悬浮窗口至中间
wmParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER;
// 6. 以屏幕左上角为原点,设置x、y初始值
wmParams.x = 0;
wmParams.y = 0;
// 7.将需要加到悬浮窗口中的View加入到窗口中了:
// 如果view没有被加入到某个父组件中,则加入WindowManager中
surfaceview = new SurfaceView(this);
surfaceHolder = surfaceview.getHolder();
WindowManager.LayoutParams params_sur = new WindowManager.LayoutParams();
params_sur.width = 1;
params_sur.height = 1;
params_sur.alpha = 255;
surfaceview.setLayoutParams(params_sur);
surfaceview.getHolder()
.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// surface.getHolder().setFixedSize(800, 1024);
surfaceview.getHolder().addCallback((SurfaceHolder.Callback) this);
relLay = new LinearLayout(this);
WindowManager.LayoutParams params_rel = new WindowManager.LayoutParams();
params_rel.width = WindowManager.LayoutParams.WRAP_CONTENT;
params_rel.height = WindowManager.LayoutParams.WRAP_CONTENT;
relLay.setLayoutParams(params_rel);
relLay.addView(surfaceview);
wm.addView(relLay, wmParams); // 创建View
}
@Override
public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2,
int arg3) {
System.out.println("*****");
// 将holder,这个holder为开始在oncreat里面取得的holder,将它赋给surfaceHolder
surfaceHolder = holder;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("++++++");
// 将holder,这个holder为开始在oncreat里面取得的holder,将它赋给surfaceHolder
surfaceHolder = holder;
Log.i("process", Thread.currentThread().getName());
// //录像线程,当然也可以在别的地方启动,但是一定要在onCreate方法执行完成以及surfaceHolder被赋值以后启动
thread = new CramerThread(50000, surfaceview,
surfaceHolder);// 设置录制时间为2小时
thread.start();
Toast.makeText(VideoSerivice.this, "开始录像", Toast.LENGTH_LONG).show();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("*****");
// surfaceDestroyed的时候同时对象设置为null
surfaceview = null;
surfaceHolder = null;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class CramerThread extends Thread {
private MediaRecorder mediarecorder;// 录制视频的类private long
private SurfaceHolder surfaceHolder;
private SurfaceView surfaceview;// 显示视频的控件
private Camera mCamera;
private long recordTime;
private long startTime = Long.MIN_VALUE;
private long endTime = Long.MIN_VALUE;
private HashMap<String, String> map = new HashMap<String, String>();
private static final String TAG = "SEDs508EG";
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
public CramerThread(long recordTime, SurfaceView surfaceview,
SurfaceHolder surfaceHolder) {
this.recordTime = recordTime;
this.surfaceview = surfaceview;
this.surfaceHolder = surfaceHolder;
}
@Override
public void run() {
/** * 开始录像 */
startRecord();
/** * 启动定时器,到规定时间recordTime后执行停止录像任务 */
Timer timer = new Timer();
timer.schedule(new TimerThread(), recordTime);
}
/** * 获取摄像头实例对象 * * @return */
public Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
// 打开摄像头错误
Log.i("info", "打开摄像头错误");
}
return c;
}
/** * 开始录像 */
public void startRecord() {
mediarecorder = new MediaRecorder();// 创建mediarecorder对象
mCamera = getCameraInstance(); // 解锁camera
mCamera.unlock();
mediarecorder.setCamera(mCamera); // 设置录制视频源为Camera(相机)
mediarecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置录制文件质量,格式,分辨率之类,这个全部包括了
mediarecorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_LOW));
mediarecorder.setPreviewDisplay(surfaceHolder.getSurface()); // 设置视频文件输出的路径
// mediarecorder.setOutputFile("/sdcard/sForm.3gp");
mediarecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO)
.toString());
try { // 准备录制
mediarecorder.prepare(); // 开始录制
mediarecorder.start();
// time.setVisibility(View.VISIBLE);// 设置录制时间显示
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void releaseMediaRecorder() {
if (mediarecorder != null) {
// 清除recorder配置
mediarecorder.reset();
// 释放recorder对象
mediarecorder.release();
mediarecorder = null;
// 为后续使用锁定摄像头
mCamera.lock();
}
}
/** * 停止录制 */
public void stopRecord() {
System.out.println("--------------");
if (mediarecorder != null) {
// 停止录制
mediarecorder.stop();
// 释放资源
mediarecorder.release();
mediarecorder = null;
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
}
/** * 定时器 * @author bcaiw * */
public class TimerThread extends TimerTask {
/** * 停止录像 */
@Override
public void run() {
try {
stopRecord();
this.cancel();
} catch (Exception e) {
map.clear();
map.put("recordingFlag", "false");
String ac_time = getVedioRecordTime();// 录像时间
map.put("recordTime", ac_time);
// sendMsgToHandle(m_msgHandler, iType, map);
}
}
}
/**
* 通用方法,接收多线程过来的数据,有可能不仅仅是msg,所以定义map对象
*
* @param handle
* @param iType
* @param info
*/
public void sendMsgToHandle(Handler handle, int iType,
Map<String, String> info) {
Message threadMsg = handle.obtainMessage();
threadMsg.what = iType;
Bundle threadbundle = new Bundle();
threadbundle.clear();
for (Iterator i = info.keySet().iterator(); i.hasNext();) {
Object obj = i.next();
threadbundle.putString(obj.toString(), info.get(obj));
}
threadMsg.setData(threadbundle);
handle.sendMessage(threadMsg);
}
/**
* 计算当前已录像时间,默认值返回0
*
* @return
*/
public String getVedioRecordTime() {
String result = "0";
if (startTime != Long.MIN_VALUE && endTime != Long.MIN_VALUE) {
long tempTime = (endTime - startTime);
result = String.valueOf(tempTime);
}
return result;
}
private static File getOutputMediaFile(int type) {
// 判断SDCard是否存在
if (!Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
Log.d(TAG, "SDCard不存在");
return null;
}
File mediaStorageDir = new File(
Environment.getExternalStorageDirectory() + File.separator
+ "/MyXingCheCamera3GP/");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdir()) {
Log.d(TAG, "failed to create directory");
return null;
}
}
// 创建媒体文件名
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timestamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timestamp + ".3gp");
} else {
Log.d(TAG, "文件类型有误");
return null;
}
return mediaFile;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.videotest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".VideoSerivice"/>
</application>
<!-- 录制视频/音频权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
<!-- 调用摄像头权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- sd卡读写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<!-- 挂载sd卡 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<!-- 悬浮窗口权限 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- 关闭应用程序的权限 -->
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
</manifest>