安卓直播界面开发,自定义照相机拍照,前后摄像头切换教程加源码!
原创,转载请注明原地址,尊重他人劳动果实
第一步:
直播界面: 这个页面没什么好说的,,直接就是Fragment加relativeLayout 直接上源码
源码:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.computer.diaoyongshoujishexiangtoupaizhao.MainActivity"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 预览画布 --> <SurfaceView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/surfaceView" /> <!-- 闪光灯、前置摄像头、后置摄像头、聚焦 --> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/zhengFanCamera" android:layout_marginLeft="20dp" android:layout_marginTop="15dp" android:layout_width="wrap_content" android:orientation="horizontal" android:gravity="center" android:layout_height="wrap_content"> <ImageView android:layout_width="25dp" android:layout_height="20dp" android:src="@mipmap/xiangjifanzhaun" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="翻转" android:textSize="16sp" android:textColor="@color/colorWrite" /> </LinearLayout> <ImageView android:id="@+id/zhiBo_Tuichu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@mipmap/chahao" android:layout_alignParentRight="true" android:layout_marginRight="15dp" android:layout_marginTop="15dp" /> <EditText android:id="@+id/zhiBoBiaoTi" android:layout_centerInParent="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:hint="给直播写个标题吧" android:background="@null" android:textColorHint="@color/colorWrite" /> <TextView android:layout_marginTop="15dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/zhiBoBiaoTi" android:textSize="16sp" android:gravity="center" android:textColor="@color/colorGray" android:text="- 会显示在开播消息推送中 -" /> <LinearLayout android:layout_marginBottom="15dp" android:id="@+id/zhiBoFenXiang" android:layout_above="@+id/kaiShiZhiBo" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" > <ImageView android:layout_marginLeft="30dp" android:layout_width="15dp" android:layout_height="18dp" android:background="@mipmap/xinlang" /> <ImageView android:layout_marginLeft="30dp" android:layout_width="15dp" android:layout_height="15dp" android:background="@mipmap/weixin_pengyouquan" /> <ImageView android:layout_marginLeft="30dp" android:layout_width="15dp" android:layout_height="15dp" android:background="@mipmap/qq" /> <ImageView android:layout_marginLeft="30dp" android:layout_width="15dp" android:layout_height="15dp" android:background="@mipmap/weixin" /> <ImageView android:layout_marginLeft="30dp" android:layout_width="25dp" android:layout_height="20dp" android:background="@mipmap/qq_kongjian" /> </LinearLayout> <LinearLayout android:id="@+id/kaiShiZhiBo" android:layout_alignParentBottom="true" android:layout_marginBottom="30dp" android:layout_width="match_parent" android:layout_height="35dp" android:gravity="center" > <TextView android:background="@drawable/zhibo_zhibobtn" android:layout_width="150dp" android:layout_height="35dp" android:text="开始直播" android:gravity="center" android:textSize="16sp" android:textColor="@color/colorWrite" android:onClick="onCapture" /> </LinearLayout> </RelativeLayout> </FrameLayout> </RelativeLayout>
第二步 开始写代码啦~~ 代码每一步都有注释 可以好好看看哦
package com.example.computer.diaoyongshoujishexiangtoupaizhao; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.hardware.Camera; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback { LinearLayout zhengFanCamera; ImageView zhiBo_Tuichu; private Camera mCamera; //相机 private SurfaceView surfaceView; //实时显示照相机拍摄内容的控件 private SurfaceHolder surfaceHolder; //展示surfaceView的图像 private int cameraPosition = 1;//1代表前置摄像头,0代表后置摄像头 String filepath =null; private Camera.PictureCallback myPictureCallback=new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] bytes, Camera camera) { //这里面我们就得到了图片 做直播的话 首先 拍照的图片时主播的列表显示的图片 //那么这张照片是要上传道服务器的,暂时存在一个Bitmap里面 已做后用 BufferedOutputStream bos = null; Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); //自定义文件保存路径 以拍摄时间区分命名 filepath = Environment.getExternalStorageDirectory().getAbsolutePath()+"diGuaZhiBo"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+".jpg"; File file = new File(filepath); if(!file.exists()){ file.mkdir(); } try { bos = new BufferedOutputStream(new FileOutputStream(file)); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩的流里面 bos.close();// 关闭此输出流并释放与此流有关的所有系统资源 } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } bitmap.recycle();//回收bitmap空间 } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏 this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//拍照过程屏幕一直处于高亮 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //设置手机屏幕朝向,一共有7种 setContentView(R.layout.activity_main); zhiBo_Tuichu= (ImageView) findViewById(R.id.zhiBo_Tuichu); zhiBoTuichu(); surfaceView= (SurfaceView) findViewById(R.id.surfaceView); zhengFanCamera= (LinearLayout) findViewById(R.id.zhengFanCamera); zhengFan(); surfaceHolder=surfaceView.getHolder(); surfaceHolder.addCallback(this); } /** * 退出直播 * */ private void zhiBoTuichu(){ zhiBo_Tuichu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { releaseCamera(); MainActivity.this.finish(); } }); } /** * 实现正反摄像机 * */ private void zhengFan(){ zhengFanCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //切换前后摄像头 // cameraPosition=0; Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); int cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数 if(cameraCount!=2){ Toast.makeText(MainActivity.this,"只有一个摄像头哦",Toast.LENGTH_LONG).show(); return;} switch (cameraPosition) { case 0: cameraPosition = 1; releaseCamera(); mCamera = getCamera(cameraPosition);//打开当前选中的摄像头 setStartPreview(mCamera, surfaceHolder); break; case 1: cameraPosition = 0; releaseCamera(); mCamera = getCamera(cameraPosition);//打开当前选中的摄像头 setStartPreview(mCamera, surfaceHolder); break; } } //因为我点击一次后 刚进入这个点击事件里面 要及时做处理cameraPosition // for(int i = 0; i < cameraCount; i++ ) { // Toast.makeText(MainActivity.this,"当前"+i+":当前position:"+cameraPosition,Toast.LENGTH_LONG).show(); // Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息 // if(cameraPosition == 1) { // //现在是后置,变更为前置 // if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置 // releaseCamera(); // mCamera = getCamera(cameraPosition);//打开当前选中的摄像头 // setStartPreview(mCamera,surfaceHolder); // cameraPosition = 0; // break; // } // } else { // //现在是前置, 变更为后置 // if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置 // releaseCamera(); // mCamera = getCamera(cameraPosition);//打开当前选中的摄像头 // setStartPreview(mCamera,surfaceHolder); // cameraPosition = 1; // break; // } // } // } // } }); } /** * 开始预览相机的内容,其实就是讲surfaceHolder与之绑定 */ private void setStartPreview(Camera camera,SurfaceHolder holder){ //直接调用系统方式绑定预览 try { camera.setPreviewDisplay(holder); //由于系统默认使用横屏预览,,所以要进行设置 camera.setDisplayOrientation(90); camera.startPreview(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 获取系统的一个Camera对象 */ private Camera getCamera(int i){ Camera camera=null; try{ camera=Camera.open(i); }catch(Exception e){ e.printStackTrace(); } return camera; } /** * 拍照的一些参数设置,点击此按钮之后会触发拍照的会掉,进而实现拍照的效果 * @param view */ public void onCapture(View view){ Camera.Parameters parameters=mCamera.getParameters(); //设置照片的类型 parameters.setPictureFormat(ImageFormat.JPEG); parameters.setPictureSize(800, 600); //设置为自动聚焦 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); //设置为自动聚焦是不够的,因为我们先得到的是最为清晰的图片,所以要在聚焦成功的时候才进行拍照 mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub //boolean success 对焦是否准确了 if(success){ //执行拍照 mCamera.takePicture(null, null, myPictureCallback); } } }); } /** * 释放相机的资源 */ private void releaseCamera(){ if(mCamera !=null ){ mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera=null; } } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); releaseCamera(); } @Override protected void onResume() { super.onResume(); if(mCamera==null){ mCamera=getCamera(cameraPosition); if(surfaceHolder!=null){ setStartPreview(mCamera,surfaceHolder); } } } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { setStartPreview(mCamera, this.surfaceHolder); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { mCamera.stopPreview(); setStartPreview(mCamera, this.surfaceHolder); } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { releaseCamera(); } }如果没有懂照相机部分代码 没关系 大家可以看我上一篇博客 说明的很清楚 下方也有教学视频地址 直接看 以上代码复制可以直接用 亲测可用!!