界面是这个样子滴.
我也知不知道怎么给图片搞小一点o(╯□╰)o
布局文件是这样的【认真脸】
中间发现一个特务就是混进来的自定义录制视频的的MovieRecorderView这个家伙
package cn.com.jwtimes.www.jwtimes.view; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.res.TypedArray; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.media.MediaRecorder; import android.media.MediaRecorder.AudioEncoder; import android.media.MediaRecorder.AudioSource; import android.media.MediaRecorder.OnErrorListener; import android.media.MediaRecorder.OutputFormat; import android.media.MediaRecorder.VideoEncoder; import android.media.MediaRecorder.VideoSource; import android.os.Build; import android.os.Environment; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.widget.LinearLayout; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Timer; import java.util.TimerTask; import cn.com.jwtimes.www.jwtimes.R; /** * Created by 王超然 on 2016/6/3. */ public class MovieRecorderView extends LinearLayout implements OnErrorListener { private static final String LOG_TAG = "MovieRecorderView"; private Context context; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private MediaRecorder mediaRecorder; private Camera camera; private Timer timer;//计时器 private int mWidth;//视频录制分辨率宽度 private int mHeight;//视频录制分辨率高度 private boolean isOpenCamera;//是否一开始就打开摄像头 private int recordMaxTime;//最长拍摄时间 private int timeCount;//时间计数 private File recordFile = null;//视频文件 private long sizePicture = 0; public MovieRecorderView(Context context) { this(context, null); } public MovieRecorderView(Context context, AttributeSet attrs) { this(context, attrs, 0); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) public MovieRecorderView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MovieRecorderView, defStyle, 0); mWidth = a.getInteger(R.styleable.MovieRecorderView_record_width, 640);//默认640 mHeight = a.getInteger(R.styleable.MovieRecorderView_record_height, 360);//默认360 isOpenCamera = a.getBoolean(R.styleable.MovieRecorderView_is_open_camera, true);//默认打开摄像头 recordMaxTime = a.getInteger(R.styleable.MovieRecorderView_record_max_time, 10);//默认最大拍摄时间为10s LayoutInflater.from(context).inflate(R.layout.movie_recorder_view, this); surfaceView = (SurfaceView) findViewById(R.id.surfaceview); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(new CustomCallBack()); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); a.recycle(); } /** * SurfaceHolder回调 */ private class CustomCallBack implements Callback { @Override public void surfaceCreated(SurfaceHolder holder) { if (!isOpenCamera) return; try { initCamera(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (!isOpenCamera) return; freeCameraResource(); } } /** * 初始化摄像头 */ public void initCamera() throws IOException { if (camera != null) { freeCameraResource(); } try { if (checkCameraFacing(Camera.CameraInfo.CAMERA_FACING_BACK)) { camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); } else if (checkCameraFacing(Camera.CameraInfo.CAMERA_FACING_FRONT)) { camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); } } catch (Exception e) { e.printStackTrace(); freeCameraResource(); ((Activity) context).finish(); } if (camera == null) return; setCameraParams(); camera.setDisplayOrientation(90); camera.setPreviewDisplay(surfaceHolder); camera.startPreview(); camera.unlock(); } /** * 检查是否有摄像头 * * @param facing 前置还是后置 * @return */ private boolean checkCameraFacing(int facing) { int cameraCount = Camera.getNumberOfCameras(); Camera.CameraInfo info = new Camera.CameraInfo(); for (int i = 0; i < cameraCount; i++) { Camera.getCameraInfo(i, info); if (facing == info.facing) { return true; } } return false; } /** * 设置摄像头为竖屏 */ private void setCameraParams() { if (camera != null) { Parameters params = camera.getParameters(); params.set("orientation", "portrait"); ListsupportedPictureSizes = params.getSupportedPictureSizes(); for (Camera.Size size : supportedPictureSizes) { sizePicture = (size.height * size.width) > sizePicture ? size.height * size.width : sizePicture; } // LogUtil.e(LOG_TAG,"手机支持的最大像素supportedPictureSizes===="+sizePicture); setPreviewSize(params); camera.setParameters(params); } } /** * 根据手机支持的视频分辨率,设置预览尺寸 * * @param params */ private void setPreviewSize(Parameters params) { if (camera == null) { return; } //获取手机支持的分辨率集合,并以宽度为基准降序排序 List previewSizes = params.getSupportedPreviewSizes(); Collections.sort(previewSizes, new Comparator () { @Override public int compare(Camera.Size lhs, Camera.Size rhs) { if (lhs.width > rhs.width) { return -1; } else if (lhs.width == rhs.width) { return 0; } else { return 1; } } }); float tmp = 0f; float minDiff = 100f; float ratio = 3.0f / 4.0f;//TODO 高宽比率3:4,且最接近屏幕宽度的分辨率,可以自己选择合适的想要的分辨率 Camera.Size best = null; for (Camera.Size s : previewSizes) { tmp = Math.abs(((float) s.height / (float) s.width) - ratio); Log.e(LOG_TAG, "setPreviewSize: width:" + s.width + "...height:" + s.height); // LogUtil.e(LOG_TAG,"tmp:" + tmp); if (tmp < minDiff) { minDiff = tmp; best = s; } } params.setPreviewSize(best.width, best.height);//预览比率 Log.e(LOG_TAG, "setPreviewSize BestSize: width:" + best.width + "...height:" + best.height); //TODO 大部分手机支持的预览尺寸和录制尺寸是一样的,也有特例,有些手机获取不到,那就把设置录制尺寸放到设置预览的方法里面 if (params.getSupportedVideoSizes() == null || params.getSupportedVideoSizes().size() == 0) { mWidth = best.width; mHeight = best.height; } else { setVideoSize(params); } } /** * 根据手机支持的视频分辨率,设置录制尺寸 * * @param params */ private void setVideoSize(Parameters params) { if (camera == null) { return; } //获取手机支持的分辨率集合,并以宽度为基准降序排序 List previewSizes = params.getSupportedVideoSizes(); Collections.sort(previewSizes, new Comparator () { @Override public int compare(Camera.Size lhs, Camera.Size rhs) { if (lhs.width > rhs.width) { return -1; } else if (lhs.width == rhs.width) { return 0; } else { return 1; } } }); float tmp = 0f; float minDiff = 100f; float ratio = 3.0f / 4.0f;//高宽比率3:4,且最接近屏幕宽度的分辨率 Camera.Size best = null; for (Camera.Size s : previewSizes) { tmp = Math.abs(((float) s.height / (float) s.width) - ratio); Log.e(LOG_TAG, "setVideoSize: width:" + s.width + "...height:" + s.height); if (tmp < minDiff) { minDiff = tmp; best = s; } } Log.e(LOG_TAG, "setVideoSize BestSize: width:" + best.width + "...height:" + best.height); //设置录制尺寸 mWidth = best.width; mHeight = best.height; } /** * 释放摄像头资源 */ private void freeCameraResource() { try { if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.lock(); camera.release(); camera = null; } } catch (Exception e) { e.printStackTrace(); } finally { camera = null; } } /** * 创建视频文件 */ private void createRecordDir() { File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "SampleVideo/video/"); if (!sampleDir.exists()) { sampleDir.mkdirs(); } try { //TODO 文件名用的时间戳,可根据需要自己设置,格式也可以选择3gp,在初始化设置里也需要修改 recordFile = new File(sampleDir, System.currentTimeMillis() + ".mp4"); // recordFile = new File(sampleDir, System.currentTimeMillis() + ".mp4"); // File.createTempFile(AccountInfo.userId, ".mp4", sampleDir); // LogUtil.e(LOG_TAG, recordFile.getAbsolutePath()); } catch (Exception e) { e.printStackTrace(); } } /** * 录制视频初始化 */ private void initRecord() throws Exception { mediaRecorder = new MediaRecorder(); mediaRecorder.reset(); if (camera != null) mediaRecorder.setCamera(camera); mediaRecorder.setOnErrorListener(this); mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); mediaRecorder.setVideoSource(VideoSource.CAMERA);//视频源 mediaRecorder.setAudioSource(AudioSource.MIC);//音频源 mediaRecorder.setOutputFormat(OutputFormat.MPEG_4);//TODO 视频输出格式 也可设为3gp等其他格式 mediaRecorder.setAudioEncoder(AudioEncoder.AMR_NB);//音频格式 mediaRecorder.setVideoSize(mWidth, mHeight);//设置分辨率 // mediaRecorder.setVideoFrameRate(25);//TODO 设置每秒帧数 这个设置有可能会出问题,有的手机不支持这种帧率就会录制失败,这里使用默认的帧率,当然视频的大小肯定会受影响 // LogUtil.e(LOG_TAG,"手机支持的最大像素supportedPictureSizes===="+sizePicture); if (sizePicture < 3000000) {//这里设置可以调整清晰度 mediaRecorder.setVideoEncodingBitRate(3 * 1024 * 512); } else if (sizePicture <= 5000000) { mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 512); } else { mediaRecorder.setVideoEncodingBitRate(1 * 1024 * 512); } mediaRecorder.setOrientationHint(90);//输出旋转90度,保持竖屏录制 mediaRecorder.setVideoEncoder(VideoEncoder.H264);//视频录制格式 //mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000); mediaRecorder.setOutputFile(recordFile.getAbsolutePath()); mediaRecorder.prepare(); mediaRecorder.start(); } /** * 开始录制视频 * * @param onRecordFinishListener 达到指定时间之后回调接口 */ public void record(final OnRecordFinishListener onRecordFinishListener) { this.onRecordFinishListener = onRecordFinishListener; createRecordDir(); try { //如果未打开摄像头,则打开 if (!isOpenCamera) initCamera(); initRecord(); timeCount = 0;//时间计数器重新赋值 timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { timeCount++; //progressBar.setProgress(timeCount);//设置进度条 if (onRecordProgressListener != null) { onRecordProgressListener.onProgressChanged(recordMaxTime, timeCount); } //达到指定时间,停止拍摄 if (timeCount == recordMaxTime) { stop(); if (MovieRecorderView.this.onRecordFinishListener != null) MovieRecorderView.this.onRecordFinishListener.onRecordFinish(); } } }, 0, 1000); } catch (Exception e) { e.printStackTrace(); if (mediaRecorder != null) { mediaRecorder.release(); } freeCameraResource(); } } /** * 停止拍摄 */ public void stop() { stopRecord(); releaseRecord(); freeCameraResource(); } /** * 停止录制 */ public void stopRecord() { //progressBar.setProgress(0); if (timer != null) timer.cancel(); if (mediaRecorder != null) { mediaRecorder.setOnErrorListener(null);//设置后防止崩溃 mediaRecorder.setPreviewDisplay(null); try { mediaRecorder.stop(); } catch (Exception e) { e.printStackTrace(); } } } /** * 释放资源 */ private void releaseRecord() { if (mediaRecorder != null) { mediaRecorder.setOnErrorListener(null); try { mediaRecorder.release(); } catch (Exception e) { e.printStackTrace(); } } mediaRecorder = null; } /** * 获取当前录像时间 * * @return timeCount */ public int getTimeCount() { return timeCount; } /** * 设置最大录像时间 * * @param recordMaxTime */ public void setRecordMaxTime(int recordMaxTime) { this.recordMaxTime = recordMaxTime; } /** * 返回录像文件 * * @return recordFile */ public File getRecordFile() { return recordFile; } /** * 录制完成监听 */ private OnRecordFinishListener onRecordFinishListener; /** * 录制完成接口 */ public interface OnRecordFinishListener { void onRecordFinish(); } /** * 录制进度监听 */ private OnRecordProgressListener onRecordProgressListener; /** * 设置录制进度监听 * * @param onRecordProgressListener */ public void setOnRecordProgressListener(OnRecordProgressListener onRecordProgressListener) { this.onRecordProgressListener = onRecordProgressListener; } /** * 录制进度接口 */ public interface OnRecordProgressListener { /** * 进度变化 * * @param maxTime 最大时间,单位秒 * @param currentTime 当前进度 */ void onProgressChanged(int maxTime, int currentTime); } @Override public void onError(MediaRecorder mr, int what, int extra) { try { if (mr != null) mr.reset(); } catch (Exception e) { e.printStackTrace(); } } }
这个是抄的,感谢那个伟大的程序员,我踩在了巨人的肩膀上。
button的样式:
然后是Activity:
package cn.com.jwtimes.www.jwtimes.ui.disaupload; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import java.io.File; import java.io.IOException; import cn.com.jwtimes.www.jwtimes.R; import cn.com.jwtimes.www.jwtimes.view.MovieRecorderView; public class MovieRecorderActivity extends AppCompatActivity { private static final String LOG_TAG = "RecordVideoActivity"; private static final int REQ_CODE = 110; private static final int RES_CODE = 111; /** * 录制进度 */ private static final int RECORD_PROGRESS = 100; /** * 录制结束 */ private static final int RECORD_FINISH = 101; private MovieRecorderView movieRecorderView; private Button buttonShoot; private RelativeLayout rlBottomRoot; private ProgressBar progressVideo; private TextView textViewCountDown; private TextView textViewUpToCancel;//上移取消 private TextView textViewReleaseToCancel;//释放取消 /** * 是否结束录制 */ private boolean isFinish = true; /** * 是否触摸在松开取消的状态 */ private boolean isTouchOnUpToCancel = false; /** * 当前进度 */ private int currentTime = 0; private ImageButton imb_back; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case RECORD_PROGRESS: progressVideo.setProgress(currentTime); if (currentTime < 10) { textViewCountDown.setText("00:0" + currentTime); } else { textViewCountDown.setText("00:" + currentTime); } break; case RECORD_FINISH: if (isTouchOnUpToCancel) {//录制结束,还在上移删除状态没有松手,就复位录制 resetData(); } else {//录制结束,在正常位置,录制完成跳转页面 isFinish = true; buttonShoot.setEnabled(false); finishActivity(); } break; } } }; /** * 按下的位置 */ private float startY; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_movie_recorder); initView(); } private void initView() { imb_back = (ImageButton) findViewById(R.id.imb_back); imb_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MovieRecorderActivity.this.finish(); overridePendingTransition(R.anim.anim_slide_left_in, R.anim.anim_slide_right_out); } }); movieRecorderView = (MovieRecorderView) findViewById(R.id.movieRecorderView); buttonShoot = (Button) findViewById(R.id.shoot_button); rlBottomRoot = (RelativeLayout) findViewById(R.id.rl_bottom_root); //progressVideo = (DonutProgress) findViewById(R.id.progress_video); progressVideo = (ProgressBar) findViewById(R.id.progressBar_loading); textViewCountDown = (TextView) findViewById(R.id.textView_count_down); textViewCountDown.setText("00:00"); textViewUpToCancel = (TextView) findViewById(R.id.textView_up_to_cancel); textViewReleaseToCancel = (TextView) findViewById(R.id.textView_release_to_cancel); DisplayMetrics dm = getApplicationContext().getResources().getDisplayMetrics(); int width = dm.widthPixels; FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) movieRecorderView.getLayoutParams(); layoutParams.height = width * 4 / 3;//根据屏幕宽度设置预览控件的尺寸,为了解决预览拉伸问题 //LogUtil.e(LOG_TAG, "mSurfaceViewWidth:" + width + "...mSurfaceViewHeight:" + layoutParams.height); movieRecorderView.setLayoutParams(layoutParams); FrameLayout.LayoutParams rlBottomRootLayoutParams = (FrameLayout.LayoutParams) rlBottomRoot.getLayoutParams(); rlBottomRootLayoutParams.height = width / 3 * 2; rlBottomRoot.setLayoutParams(rlBottomRootLayoutParams); //处理触摸事件 buttonShoot.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { textViewUpToCancel.setVisibility(View.VISIBLE);//提示上移取消 isFinish = false;//开始录制 startY = event.getY();//记录按下的坐标 movieRecorderView.record(new MovieRecorderView.OnRecordFinishListener() { @Override public void onRecordFinish() { handler.sendEmptyMessage(RECORD_FINISH); } }); } else if (event.getAction() == MotionEvent.ACTION_UP) { textViewUpToCancel.setVisibility(View.GONE); textViewReleaseToCancel.setVisibility(View.GONE); if (startY - event.getY() > 100) {//上移超过一定距离取消录制,删除文件 if (!isFinish) { resetData(); } } else { if (movieRecorderView.getTimeCount() > 3) {//录制时间超过三秒,录制完成 handler.sendEmptyMessage(RECORD_FINISH); } else {//时间不足取消录制,删除文件 Toast.makeText(MovieRecorderActivity.this, "视频录制时间太短", Toast.LENGTH_SHORT).show(); resetData(); } } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { //根据触摸上移状态切换提示 if (startY - event.getY() > 100) { isTouchOnUpToCancel = true;//触摸在松开就取消的位置 if (textViewUpToCancel.getVisibility() == View.VISIBLE) { textViewUpToCancel.setVisibility(View.GONE); textViewReleaseToCancel.setVisibility(View.VISIBLE); } } else { isTouchOnUpToCancel = false;//触摸在正常录制的位置 if (textViewUpToCancel.getVisibility() == View.GONE) { textViewUpToCancel.setVisibility(View.VISIBLE); textViewReleaseToCancel.setVisibility(View.GONE); } } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { resetData(); } return true; } }); progressVideo.setMax(10); movieRecorderView.setOnRecordProgressListener(new MovieRecorderView.OnRecordProgressListener() { @Override public void onProgressChanged(int maxTime, int currentTime) { MovieRecorderActivity.this.currentTime = currentTime; handler.sendEmptyMessage(RECORD_PROGRESS); } }); } @Override public void onResume() { super.onResume(); checkCameraPermission(); } /** * 检测摄像头和录音权限 */ private void checkCameraPermission() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { // Camera permission has not been granted. Toast.makeText(this, "视频录制和录音没有授权", Toast.LENGTH_LONG); this.finish(); } else { resetData(); } } /** * 重置状态 */ private void resetData() { if (movieRecorderView.getRecordFile() != null) movieRecorderView.getRecordFile().delete(); movieRecorderView.stop(); isFinish = true; currentTime = 0; progressVideo.setProgress(0); buttonShoot.setEnabled(true); textViewUpToCancel.setVisibility(View.GONE); textViewReleaseToCancel.setVisibility(View.GONE); try { movieRecorderView.initCamera(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); isFinish = true; movieRecorderView.stop(); } /** * 递归删除目录下的所有文件及子目录下所有文件 * * @param dir 将要删除的文件目录 * @return */ private boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); //递归删除目录中的子目录下 for (int i = 0; i < children.length; i++) { if (!deleteDir(new File(dir, children[i]))) { return false; } } } return dir.delete(); } // @Override // public void onDestroy() { // //TODO 退出界面删除文件,如果要删除文件夹,需要提供文件夹路径 // if (movieRecorderView.getRecordFile() != null) { // File file = new File(movieRecorderView.getRecordFile().getAbsolutePath()); // if (file != null && file.exists()) { // Log.e(LOG_TAG, "file.exists():" + file.exists()); // file.delete(); // } // } // super.onDestroy(); // } //视频录制结束后,跳转的函数 private void finishActivity() { if (isFinish) { movieRecorderView.stop(); Intent intent = new Intent(this, SendMovieActivity.class); Bundle bundle = new Bundle(); bundle.putString("text", movieRecorderView.getRecordFile().getAbsolutePath()); intent.putExtras(bundle); startActivity(intent); Toast.makeText(MovieRecorderActivity.this, "录制结束", Toast.LENGTH_SHORT); MovieRecorderActivity.this.finish(); overridePendingTransition(R.anim.anim_slide_right_in, R.anim.anim_slide_left_out); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQ_CODE && resultCode == RES_CODE) { setResult(RES_CODE); finish(); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { MovieRecorderActivity.this.finish(); overridePendingTransition(R.anim.anim_slide_left_in, R.anim.anim_slide_right_out); return false; } return super.onKeyDown(keyCode, event); } }
我把那个跳出页面就删除的给注释掉了,因为我要点击这个小的,把url传到播放的页面让他全屏播放。