来,我们一起学猫叫,一起喵,喵,喵;
看到这张图片,头没有觉得熟悉,哎,熟悉就好,每天都得点个几十次。
今天在写自定义录制视频,我的个乖乖,太好了,听说后置摄像头默认旋转了90°,前置摄像头默认旋转了180°,咦,真厉害,一开始想,我把预览的控件旋转90°或者旋转180°是不是就可以了,想一想,我太聪明了,这样的办法都能给我想出来,真实天才。
首先在这里先感谢一下这位仁兄:https://blog.csdn.net/qugengting/article/details/86613328
我的想法已经跳出三界之外,不在五行之中了,所以这只是一个不切实际的想法,看到这里的童鞋就可以放弃旋转控件的这个想法了哈,因为,并没有什么*用,接下来呢,我就把我的放在这,一来呢是方便自己以后开发,万一忘记了还可以有资料可以看看,二来呢是帮助一下那些正在为这个问题苦恼的童鞋,好了,话不多少,走起。
1、6.0权限判断,如果你没有在配置文件申明你的权限,就得在这里手动注册权限,
private boolean checkPublishPermission() {
if (Build.VERSION.SDK_INT >= 23) {
List<String> permissions = new ArrayList<>();
if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA)) {
permissions.add(Manifest.permission.CAMERA);
}
if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO)) {
permissions.add(Manifest.permission.RECORD_AUDIO);
}
if (permissions.size() != 0) {
ActivityCompat.requestPermissions(MainActivity.this,
(String[]) permissions.toArray(new String[0]),
WRITE_PERMISSION_REQ_CODE);
return false;
}
}
return true;
}
2、权限回调
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case WRITE_PERMISSION_REQ_CODE:
for (int ret : grantResults) {
if (ret != PackageManager.PERMISSION_GRANTED) {
return;
}
}
bPermission = true;
break;
default:
break;
}
}
//初始化屏幕设置
public void initScreen(){
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
// 选择支持半透明模式,在有surfaceview的activity中使用。
getWindow().setFormat(PixelFormat.TRANSLUCENT);
}
3、初始化相机
/*初始化相机*/
public void initCamera(){
if (mCamera==null && !isView){
mCamera=Camera.open(cameraID);
Log.i(TAG,"camera.open()");
}
if(mCamera != null && !isView) {
try {
myParameters = mCamera.getParameters();
myParameters.setPreviewSize(1920, 1080);
myParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
mCamera.setParameters(myParameters);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
isView = true;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
Log.i(TAG,"初始化相机错误");
}
}
}
4、获取储存文件名
/**
* 获取系统时间,保存文件以系统时间戳命名
*/
public String getDate(){
Calendar ca = Calendar.getInstance();
int year = ca.get(Calendar.YEAR);
int month = ca.get(Calendar.MONTH);
int day = ca.get(Calendar.DATE);
int minute = ca.get(Calendar.MINUTE);
int hour = ca.get(Calendar.HOUR);
int second = ca.get(Calendar.SECOND);
String date = "" + year + (month + 1 )+ day + hour + minute + second;
Log.d(TAG, "date:" + date);
return date;
}
6、获取手机储存文件
/**
* 获取SD path
*/
public String getSDPath(){
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
if (sdCardExist)
{
sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
return sdDir.toString();
}
return null;
}
7、设置预览
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
// TODO Auto-generated method stub
mSurfaceHolder = holder;
initCamera();
mVideo.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startRecode(mCamera);
}
});
mReplace.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
if (isRecord){
Toast.makeText(MainActivity.this, "视频录制中,不允许调转摄像头", Toast.LENGTH_SHORT).show();
}else {
changeCamera();
}
} catch (IOException e) {
e.printStackTrace();
isRecord=false;
cameraThread.stop();
Log.i(TAG,"切换相机错误");
}
}
});
}
8、开始录制
public void startRecode(Camera mCamera){
isRecord=true;
if (!mStartedFlg) {
// Start
if (mRecorder == null) {
mRecorder = new MediaRecorder(); // Create MediaRecorder
}
try {
mCamera.unlock();
mRecorder.setCamera(mCamera);
// Set audio and video source and encoder
// 这两项需要放在setOutputFormat之前
mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_1080P));
// Set output file path
String path = getSDPath();
if (path != null) {
File dir = new File(path + "/dlysc");
Log.i(TAG,(dir.exists())+"");
if (!dir.exists()) {
dir.mkdir();
}
path = dir + "/" + getDate() + ".mp4";
mRecorder.setOutputFile(path);
if (cameraID==FRONT){
mRecorder.setOrientationHint(90 + 180);
}
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
Log.d(TAG, "bf mRecorder.prepare()");
mRecorder.prepare();
Log.d(TAG, "af mRecorder.prepare()");
Log.d(TAG, "bf mRecorder.start()");
mRecorder.start(); // Recording is now started
Log.d(TAG, "af mRecorder.start()");
cameraThread.start();
mStartedFlg = true;
mVideo.setImageResource(R.drawable.haha_stop);
Log.i(TAG,path);
}
} catch (Exception e) {
e.printStackTrace();
releaseMediaRecorder();
}
} else {
// stop
if (mStartedFlg) {
try {
stopCamera();
} catch (Exception e) {
e.printStackTrace();
}
}
mStartedFlg = false;
}
}
差不多就到这就完了,这个已经处理好了前后摄像头录制的问题,对于有些大神来说呢,就是so easy的东西,不过我只是一个刚开始出来实习的对于这些理解的不是很多。不多,觉得自己还是棒棒哒!
最后奉上我的完整的代码:
private final String TAG="AppCompatActivity";
private static final int FRONT = Camera.CameraInfo.CAMERA_FACING_FRONT;//前置摄像头标记
private static final int BACK = Camera.CameraInfo.CAMERA_FACING_BACK;//后置摄像头标记
private Camera mCamera;
private Camera.Parameters myParameters;
private boolean isView=false;
private SurfaceHolder mSurfaceHolder;
private SurfaceHolder holder;
private boolean mStartedFlg = false;
private MediaRecorder mRecorder;
private int cameraID;
private boolean isRecord=false;
private String time="00:00";
/**
* 6.0权限处理
**/
private boolean bPermission = false;
private final int WRITE_PERMISSION_REQ_CODE = 100;
private SurfaceView mSurfaceView;
private ImageView mReplace;
private ImageView mVideo;
private TextView mCameraTime;
private CameraThread cameraThread;
private boolean checkPublishPermission() {
if (Build.VERSION.SDK_INT >= 23) {
List<String> permissions = new ArrayList<>();
if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA)) {
permissions.add(Manifest.permission.CAMERA);
}
if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO)) {
permissions.add(Manifest.permission.RECORD_AUDIO);
}
if (permissions.size() != 0) {
ActivityCompat.requestPermissions(MainActivity.this,
(String[]) permissions.toArray(new String[0]),
WRITE_PERMISSION_REQ_CODE);
return false;
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case WRITE_PERMISSION_REQ_CODE:
for (int ret : grantResults) {
if (ret != PackageManager.PERMISSION_GRANTED) {
return;
}
}
bPermission = true;
break;
default:
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initScreen();
setContentView(R.layout.activity_main);
cameraID=BACK;
bPermission = checkPublishPermission();
mSurfaceView = findViewById(R.id.surfaceView);
mReplace = findViewById(R.id.replace);
mVideo = findViewById(R.id.video);
mCameraTime=findViewById(R.id.cmeraTime);
cameraThread = new CameraThread(mCameraTime);
if (bPermission) {
OpenCamera();
}else {
Toast.makeText(this, "没有权限", Toast.LENGTH_SHORT).show();
}
}
public void OpenCamera(){
holder = mSurfaceView.getHolder();// 取得holder
holder.addCallback(this); // holder加入回调接口
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
/*初始化相机*/
public void initCamera(){
if (mCamera==null && !isView){
mCamera=Camera.open(cameraID);
Log.i(TAG,"camera.open()");
}
if(mCamera != null && !isView) {
try {
myParameters = mCamera.getParameters();
myParameters.setPreviewSize(1920, 1080);
myParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
mCamera.setParameters(myParameters);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
isView = true;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
Log.i(TAG,"初始化相机错误");
}
}
}
/**
* 获取系统时间,保存文件以系统时间戳命名
*/
public String getDate(){
Calendar ca = Calendar.getInstance();
int year = ca.get(Calendar.YEAR);
int month = ca.get(Calendar.MONTH);
int day = ca.get(Calendar.DATE);
int minute = ca.get(Calendar.MINUTE);
int hour = ca.get(Calendar.HOUR);
int second = ca.get(Calendar.SECOND);
String date = "" + year + (month + 1 )+ day + hour + minute + second;
Log.d(TAG, "date:" + date);
return date;
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
// TODO Auto-generated method stub
mSurfaceHolder = holder;
initCamera();
mVideo.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startRecode(mCamera);
}
});
mReplace.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
if (isRecord){
Toast.makeText(MainActivity.this, "视频录制中,不允许调转摄像头", Toast.LENGTH_SHORT).show();
}else {
changeCamera();
}
} catch (IOException e) {
e.printStackTrace();
isRecord=false;
cameraThread.stop();
Log.i(TAG,"切换相机错误");
}
}
});
}
public void startRecode(Camera mCamera){
isRecord=true;
if (!mStartedFlg) {
// Start
if (mRecorder == null) {
mRecorder = new MediaRecorder(); // Create MediaRecorder
}
try {
mCamera.unlock();
mRecorder.setCamera(mCamera);
// Set audio and video source and encoder
// 这两项需要放在setOutputFormat之前
mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_1080P));
// Set output file path
String path = getSDPath();
if (path != null) {
File dir = new File(path + "/dlysc");
Log.i(TAG,(dir.exists())+"");
if (!dir.exists()) {
dir.mkdir();
}
path = dir + "/" + getDate() + ".mp4";
mRecorder.setOutputFile(path);
if (cameraID==FRONT){
mRecorder.setOrientationHint(90 + 180);
}
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
Log.d(TAG, "bf mRecorder.prepare()");
mRecorder.prepare();
Log.d(TAG, "af mRecorder.prepare()");
Log.d(TAG, "bf mRecorder.start()");
mRecorder.start(); // Recording is now started
Log.d(TAG, "af mRecorder.start()");
cameraThread.start();
mStartedFlg = true;
mVideo.setImageResource(R.drawable.haha_stop);
Log.i(TAG,path);
}
} catch (Exception e) {
e.printStackTrace();
releaseMediaRecorder();
}
} else {
// stop
if (mStartedFlg) {
try {
stopCamera();
} catch (Exception e) {
e.printStackTrace();
}
}
mStartedFlg = false;
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
// TODO Auto-generated method stub
mSurfaceHolder = holder;
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
/**
* 获取SD path
*/
public String getSDPath(){
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
if (sdCardExist)
{
sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
return sdDir.toString();
}
return null;
}
//初始化屏幕设置
public void initScreen(){
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
// 选择支持半透明模式,在有surfaceview的activity中使用。
getWindow().setFormat(PixelFormat.TRANSLUCENT);
}
public void stopCamera(){
mCamera.lock();
mRecorder.stop();
mRecorder.reset();
mVideo.setImageResource(R.drawable.video);
isRecord=false;
cameraThread.stop();
}
private void changeCamera() throws IOException {
mCamera.stopPreview();
mCamera.release();
if(cameraID == FRONT){
cameraID=BACK;
mCamera = Camera.open(BACK);
} else if (cameraID == BACK) {
cameraID = FRONT;
mCamera = Camera.open(FRONT);
mSurfaceView.setRotation(180);
}
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
}
@Override
protected void onPause() {
Log.i(TAG,"后台1");
super.onPause();
isRecord=false;
cameraThread.stop();
releaseMediaRecorder();
releaseCamera();
}
@Override
protected void onRestart() {
Log.i(TAG,"后台2");
super.onRestart();
}
@Override
protected void onResume() {
Log.i(TAG,"后台3");
OpenCamera();
super.onResume();
}
@Override
protected void onStart() {
Log.i(TAG,"后台4");
super.onStart();
}
private void releaseMediaRecorder(){
if (mRecorder != null) {
mRecorder.reset(); // clear recorder configuration
mRecorder.release(); // release the recorder object
mRecorder = null;
mCamera.lock(); // lock camera for later use
}
}
private void releaseCamera(){
if (mCamera != null){
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
public class CameraThread extends Thread{
private TextView textView;
public CameraThread(TextView textView) {
this.textView = textView;
}
@Override
public void run() {
int second = 0;
int minute=0;
while (isRecord) {
if (second>10){
time = "0" + minute + ":"+ second;
}else {
time="0"+minute+":"+"0"+second;
}
second++;
if (second==60){
minute++;
second=0;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(time);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/cmeraTime"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:text="00:00"
android:textSize="14dp"
android:textColor="@color/bangdan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/replace"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:layout_alignParentRight="true"
android:src="@drawable/replage"
android:layout_width="30dp"
android:layout_height="30dp"/>
<LinearLayout
android:background="#4d000000"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="60dp">
<ImageView
android:id="@+id/video"
android:layout_gravity="center"
android:src="@drawable/video"
android:layout_width="50dp"
android:layout_height="50dp"/>
</LinearLayout>
</RelativeLayout>