一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - Android仿微信錄制小視頻

Android仿微信錄制小視頻

2022-02-15 17:24Anro丶 Android

這篇文章主要為大家詳細介紹了Android仿微信錄制小視頻,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Android仿微信錄制小視頻的具體代碼,供大家參考,具體內容如下

先上張圖片看看效果

Android仿微信錄制小視頻

簡單敘述下

  • 首先通過Camera類調用系統相機
  • 通過surfaceview繪制出來
  • 通過MediaRecorder來錄制視頻
  • 閃光燈 和 切換攝像頭 需要重新配置Camera的參數
  • Camera預覽界面畫面拉升的原因是因為Surfaceview的大小與設定的比例不一致的

**本次版本更新了 切換前置攝像頭錄制視頻問題
Android部分手機錄制視頻適配IOS手機問題 (OPPO手機部分不適配 目前啟用的H264格式)**

完整的代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
 
import com.tongxun.atongmu.dialog.CommonDialog;
 
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
 
public class CircleViedoActivity extends Activity implements View.OnClickListener,MediaRecorder.OnErrorListener {
 
 private SurfaceView mSurfaceView;
 private SurfaceHolder mSurfaceHolder;
 private ProgressBar mProgressBar;
 private Button shoot_button;
 private ImageView circle_light_btn;
 private ImageView circle_change_camera_btn;
 private TextView circle_camera_time;
 
 private MediaRecorder mMediaRecorder;
 private Camera mCamera;
 private Timer mTimer;// 計時器
 private OnRecordFinishListener mOnRecordFinishListener;// 錄制完成回調接口
 private int mWidth;// 視頻分辨率寬度
 private int mHeight;// 視頻分辨率高度
 private boolean isOpenCamera;// 是否一開始就打開攝像頭
 private int mRecordMaxTime;// 一次拍攝最長時間
 private int mTimeCount;// 時間計數
 private int mNumberOfCameras=0;//手機攝像頭的數量
 Bitmap bitmap;//圖片縮略圖
 private int screenWidth;
 public static File mVecordFile = null;// 文件
 private boolean isOpenFlash=false;
 private boolean isBackCamera=true;
 private int mbackCamera;
 private int mfrontCamera;
 private CommonDialog commonDialog;
 
 private static final int MOVICE_SUCCESS=1000;//錄制完成
 private static final int MOVICE_FILE=1001;//錄制失敗
 
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_super_video);
 init_datas();
 init_view();
 set_datas();
 init_event();
 }
 
 private void init_datas() {
 isOpenCamera=true;//默認一開始就打開相機
 mRecordMaxTime=10;//設置錄制的時間
 
 //獲取手機攝像頭的數量
 Camera.CameraInfo cameraInfo=new Camera.CameraInfo();
 mNumberOfCameras=Camera.getNumberOfCameras();
 for(int camidx=0;camidx<mNumberOfCameras;camidx++){
  Camera.getCameraInfo(camidx, cameraInfo);
  if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_BACK){
  mbackCamera=camidx;
  }else if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_FRONT){
  mfrontCamera=camidx;
  }
 }
 
 
 
 }
 
 private void init_view() {
 mWidth=640;
 mHeight=480;
 
 //獲取屏幕的寬度
 screenWidth = getWindowManager().getDefaultDisplay().getWidth();
 mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);//預覽界面
 mProgressBar = (ProgressBar) findViewById(R.id.progressBar);//進度條
 shoot_button = (Button) findViewById(R.id.shoot_button);//拍攝按鈕
 circle_camera_time= (TextView) findViewById(R.id.circle_camera_time);
 circle_change_camera_btn= (ImageView) findViewById(R.id.circle_change_camera_btn);//切換攝像頭
 circle_light_btn= (ImageView) findViewById(R.id.circle_light_btn);//開啟閃光燈
 ViewGroup.LayoutParams params=mSurfaceView.getLayoutParams();
 params.height=(screenWidth*4)/3;
 params.width=screenWidth;
 mSurfaceView.setLayoutParams(params);
 
 
 top_model2_left_img= (ImageView)findViewById(R.id.top_model2_left_img);
 top_model2_left_img.setOnClickListener(this);
 top_model2_right_img= (ImageView)findViewById(R.id.top_model2_right_img);
 top_model2_right_img.setVisibility(View.INVISIBLE);
 top_model2_txt= (TextView)findViewById(R.id.top_model2_txt);
 top_model2_txt.setText("視頻錄制");
 }
 
 
 private void set_datas() {
 mSurfaceHolder = mSurfaceView.getHolder();
 mProgressBar.setMax(mRecordMaxTime);// 設置進度條最大量
 mSurfaceHolder.setKeepScreenOn(true);//設置屏幕常亮
 mSurfaceHolder.addCallback(new CustomCallBack());
 mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 circle_camera_time.setText("");
 }
 
 private void init_event() {
 circle_light_btn.setOnClickListener(this);
 circle_change_camera_btn.setOnClickListener(this);
 shoot_button.setOnTouchListener(new View.OnTouchListener() {
  @Override
  public boolean onTouch(View v, MotionEvent event) {
  if (event.getAction() == MotionEvent.ACTION_DOWN) {
   record(new OnRecordFinishListener() {
   @Override
   public void onRecordFinish() {
    //錄制時間達到最大值
    handler.sendEmptyMessage(MOVICE_SUCCESS);
   }
   });
  } else if (event.getAction() == MotionEvent.ACTION_UP) {
   if (mTimeCount > 1 && mTimeCount<10) { //防止達到最大值up事件
   //錄制時間大于一秒
   handler.sendEmptyMessage(MOVICE_SUCCESS);
   } else if(mTimeCount<=1) {
   //刪除小于一秒的視頻
   if (getmVecordFile() != null) {
    getmVecordFile().delete();
   }
   handler.sendEmptyMessage(MOVICE_FILE);
 
   }
  }
  return true;
  }
 });
 }
 
 @Override
 protected void onResume() {
 super.onResume();
 if(mCamera!=null){
  freeCameraResource();
 }
 try {
  initCamera();
 } catch (IOException e) {
  e.printStackTrace();
 }
 }
 
 @Override
 public void onSaveInstanceState(Bundle outState) {
 super.onSaveInstanceState(outState);
 // mRecorderView.stop();
 }
 
 private Handler handler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  //停止拍攝
  stopRecord();
  switch (msg.what){
  case MOVICE_SUCCESS:
   String msgs = "確認上傳嗎?";
   commonDialog = new CommonDialog(CircleViedoActivity.this, new CommonDialog.GoCommonDialog() {
   @Override
   public void go() {
    finishActivity();
    commonDialog.dismiss();
   }
   @Override
   public void cancel() {
    //刪除沒有上傳的視頻
    if (getmVecordFile() != null) {
    getmVecordFile().delete();
    }
    commonDialog.dismiss();
   }
   }, msgs, "確定", "取消");
   commonDialog.show();
 
 
   break;
  case MOVICE_FILE:
   Toast.makeText(CircleViedoActivity.this, "視頻錄制時間太短", Toast.LENGTH_SHORT).show();
   break;
  }
 
 }
 };
 
 
 private void finishActivity() {
 stop();
 Bitmap bitmap = null;
 if (getmVecordFile() != null) {
  //得到文件 File類型
  File mfile = getmVecordFile();
  bitmap = getVideoThumbnail(mfile.toString());
 }
 
 /**
 * 部分Android手機縮略圖拉不到,找到一種解決辦法不是太滿意 有沒有大神提供思路
 */
 
 // VideoPlayerActivity.startActivity(this, mRecorderView.getVecordFile().toString());
 Intent intent = new Intent();
 intent.putExtra("bitmap",bitmap);
 setResult(RESULT_OK,intent);
 finish();
 }
 
 @Override
 public void onError(MediaRecorder mr, int what, int extra) {
 try {
  if (mr != null)
  mr.reset();
 } catch (IllegalStateException e) {
  e.printStackTrace();
 } catch (Exception e) {
  e.printStackTrace();
 }
 }
 
 @Override
 public void onClick(View v) {
 switch (v.getId()){
  case R.id.circle_light_btn:
  //開啟關閉閃光燈 默認關閉
  if(isOpenFlash){
   isOpenFlash=false;
   circle_light_btn.setImageResource(R.drawable.camera_light);
  }else {
   isOpenFlash=true;
   circle_light_btn.setImageResource(R.drawable.camera_no_light);
  }
  try {
   initCamera();
  } catch (IOException e) {
   e.printStackTrace();
  }
  break;
  case R.id.circle_change_camera_btn:
  if(isBackCamera){
   isBackCamera=false;
  }else {
   isBackCamera=true;
  }
  try {
   initCamera();
  } catch (IOException e) {
   e.printStackTrace();
  }
  break;
  case R.id.top_model2_left_img:
  stop();
  finish();
  break;
 }
 }
 
 private class CustomCallBack implements SurfaceHolder.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) {
 
 }
 }
 /**
 * 初始化攝像頭
 */
 private void initCamera() throws IOException {
 if (mCamera != null) {
  freeCameraResource();
 }
 try {
  if(isBackCamera){
  mCamera = Camera.open(mbackCamera);//打開后攝像頭
  setCameraParams(isOpenFlash);
  }else {
  mCamera=Camera.open(mfrontCamera);//打開前攝像頭
  }
 } catch (Exception e) {
  e.printStackTrace();
  freeCameraResource();
 }
 if (mCamera == null)
  return;
 
 mCamera.setDisplayOrientation(90);
 mCamera.setPreviewDisplay(mSurfaceHolder);
 mCamera.startPreview();
 mCamera.unlock();
 }
 
 
 /**
 * 設置攝像頭為豎屏
 */
 private void setCameraParams(Boolean isOpenFlash) {
 if (mCamera != null) {
  Camera.Parameters params = mCamera.getParameters();
  //獲取預覽的各種分辨率
  List<Camera.Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
  params.set("orientation", "portrait");//豎屏錄制
  params.setPreviewSize(mWidth, mHeight);//默認640*480
  params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//持續對焦
  if(isBackCamera){
  if(isOpenFlash){
   //開啟閃光燈
   params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
 
  }else {
   //關閉閃光燈
   params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
  }
 
  }else {
 
  }
  mCamera.setParameters(params);
 }
 }
 
 
 /**
 * 釋放攝像頭資源
 */
 private void freeCameraResource() {
 if (mCamera != null) {
  mCamera.setPreviewCallback(null);
  mCamera.stopPreview();
  mCamera.lock();
  mCamera.release();
  mCamera = null;
 }
 }
 
 private void createRecordDir() {
 File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "ATOMImg/video/");
 if (!sampleDir.exists()) {
  sampleDir.mkdirs();
 }
 File vecordDir = sampleDir;
 // 創建文件
 try {
  mVecordFile = File.createTempFile("recording", ".mp4", vecordDir);//mp4格式
 
 } catch (IOException e) {
 }
 }
 
 /**
 * 初始化
 */
 private void initRecord() throws IOException {
 mMediaRecorder = new MediaRecorder();
 mMediaRecorder.reset();
 if (mCamera != null)
  mMediaRecorder.setCamera(mCamera);
 mMediaRecorder.setOnErrorListener(this);
 mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
 mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 視頻源
 mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 音頻源
 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 視頻輸出格式
 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 音頻格式
 mMediaRecorder.setVideoSize(mWidth, mHeight);// 設置分辨率:
 // mMediaRecorder.setVideoFrameRate(16);// 這個我把它去掉了,感覺沒什么用
 mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);// 設置幀頻率,然后就清晰了
 if(isBackCamera) {
  mMediaRecorder.setOrientationHint(90);// 輸出旋轉90度,保持豎屏錄制
 }else {
  mMediaRecorder.setOrientationHint(270);
 }mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 視頻錄制格式
 
 
 
----------
 
 
/**
 這里是配置攝像頭的重點 因為我們錄制視頻需要適配IOS開發和Android不同版本的手機 而IOS和Android通配的視頻格式不多 我們這里采用H264格式 它的兼容范圍更廣闊 主要解決的就是部分OPPO手機不適配問題
*/
 
 
----------
 
 
 // mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000);
 mMediaRecorder.setOutputFile(mVecordFile.getAbsolutePath());
 mMediaRecorder.prepare();
 try {
  mMediaRecorder.start();
 } catch (IllegalStateException e) {
  e.printStackTrace();
 } catch (RuntimeException e) {
  e.printStackTrace();
 } catch (Exception e) {
  e.printStackTrace();
 }
 }
 
 /**
 * 錄制完成回調接口
 */
 public interface OnRecordFinishListener {
 public void onRecordFinish();
 }
 
 /**
 * 錄制
 * @param onRecordFinishListener
 */
 public void record(final OnRecordFinishListener onRecordFinishListener) {
 this.mOnRecordFinishListener = onRecordFinishListener;
 createRecordDir();//創建目錄
 
 try {
  if (!isOpenCamera)// 如果未打開攝像頭,則打開
  initCamera();//初始化攝像頭
  initRecord();//初始化錄制參數
  mTimeCount = 0;// 時間計數器重新賦值
 
  mTimer = new Timer();//創建一個定時器
 
  mTimer.schedule(new TimerTask() {
 
  @Override
  public void run() {
   // TODO Auto-generated method stub
   mTimeCount++;
   mProgressBar.setProgress(mTimeCount);// 設置進度條
   // handler.sendEmptyMessage(TIME_CHANGW);
   runOnUiThread(new Runnable() {
   @Override
   public void run() {
    circle_camera_time.setText(mTimeCount + "″");
   }
   });
   if (mTimeCount == mRecordMaxTime) {// 達到指定時間,停止拍攝
   //錄制完成調用錄制回調接口
   if (mOnRecordFinishListener != null)
    mOnRecordFinishListener.onRecordFinish();
   }
  }
  }, 0, 1000);
 } catch (IOException e) {
  e.printStackTrace();
 }
 }
 /**
 * 停止拍攝
 */
 public void stop() {
 stopRecord();
 releaseRecord();
 freeCameraResource();
 }
 
 /**
 * 停止錄制
 */
 public void stopRecord() {
 mProgressBar.setProgress(0);
 circle_camera_time.setText("");
 if (mTimer != null)
  mTimer.cancel();
 if (mMediaRecorder != null) {
  // 設置后不會崩
  mMediaRecorder.setOnErrorListener(null);
  mMediaRecorder.setPreviewDisplay(null);
  try {
  mMediaRecorder.stop();
  } catch (IllegalStateException e) {
  e.printStackTrace();
  } catch (RuntimeException e) {
  e.printStackTrace();
  } catch (Exception e) {
  e.printStackTrace();
  }
 }
 }
 
 /**
 * 獲取的視頻的位置
 * @return
 */
 public File getmVecordFile() {
 return mVecordFile;
 }
 
 /**
 * 釋放資源
 */
 private void releaseRecord() {
 if (mMediaRecorder != null) {
  mMediaRecorder.setOnErrorListener(null);
  try {
  mMediaRecorder.release();
  } catch (IllegalStateException e) {
  e.printStackTrace();
  } catch (Exception e) {
  e.printStackTrace();
  }
 }
 mMediaRecorder = null;
 }
 
 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {
 if ((keyCode == KeyEvent.KEYCODE_BACK)) {
  stop();
  finish();
  return false;
 }else {
  return super.onKeyDown(keyCode, event);
 }
 
 }
 
 /**
 * 獲取視頻縮略圖
 * @param filePath
 * @return
 */
 public Bitmap getVideoThumbnail(String filePath) {
 Bitmap bitmap = null;
 MediaMetadataRetriever retriever = new MediaMetadataRetriever();
 try {
  retriever.setDataSource(filePath);
  bitmap = retriever.getFrameAtTime();
 }
 catch(IllegalArgumentException e) {
  e.printStackTrace();
 }
 catch (RuntimeException e) {
  e.printStackTrace();
 }
 finally {
  try {
  retriever.release();
  }
  catch (RuntimeException e) {
  e.printStackTrace();
  }
 }
 return bitmap;
 }
 
 @Override
 protected void onDestroy() {
 super.onDestroy();
 if(bitmap!=null){
  try {
  bitmap.recycle();
  } catch (Exception e) {
  e.printStackTrace();
  }
  bitmap=null;
 }
 
 }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/qq_24731595/article/details/51940958

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 91亚洲精品久久91综合 | 青青热久免费精品视频精品 | 二区三区在线观看 | 久久久WWW免费人成精品 | 午夜视频一区二区三区 | 女同xx美女放| 98在线视频噜噜噜国产 | 倩女还魂在线观看完整版免费 | 国产99视频精品免视看9 | 色综合精品 | 欧美一级欧美三级在线 | 把女的下面扒开添视频 | 欧美伊人久久久久久久久影院 | 成年视频在线播放 | 波多野结衣之双方调教在线观看 | 性欧美高清强烈性视频 | 肉宠文很肉到处做1v1 | 国内精品久久久久久不卡影院 | 国产精品久久久久久岛国 | 日韩一区三区 | 99精品视频免费观看 | 亚洲高清在线精品一区 | 亚洲国内精品久久 | 精品久久久久久久久免费影院 | 香蕉久久一区二区三区啪啪 | 欧美精品久久一区二区三区 | 女上男下gifxxoo动态视频 | 日本老妇和子乱视频 | 亚洲人成综合在线播放 | 国产精品久久久久无毒 | 欧美最新在线 | 热久久最新视频 | 二区三区视频 | 午夜一级 | 黑人biglackon10十| 97影院3| 免费观看一级一片 | 日韩一区在线播放 | 变态 另类 人妖小说 | 久久久久久免费高清电影 | 日韩高清在线免费观看 |