Android 呼叫攝像頭功能【拍照與視訊】
應用場景:
在Android開發過程中,有時需要呼叫手機自身裝置的功能,上篇文章主要側重攝像頭拍照功能的呼叫。本篇文章將綜合實現拍照與視訊的操作。知識點介紹:
該部分請閱讀 【Android 呼叫攝像頭功能】使用方式:
第一步:新建一個Android專案CameraPhotoVedio,包含兩個Activity: MainActivity、CameraActivity。
第二步:
【activity_main.xml】
<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"
android:background="@drawable/shape_main"
tools:context=".MainActivity" >
<LinearLayout android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_width="match_parent"
android:orientation="vertical">
<ImageView android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:src="@drawable/main"/>
</LinearLayout>
<LinearLayout android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<Button
android:id="@+id/main_button"
android:layout_height="50dp"
android:layout_marginBottom="50dp"
android:background="@drawable/shape_main"
android:layout_width="match_parent"
android:textColor="#FFFFFF"
android:text="使用攝像頭"/>
</LinearLayout>
</RelativeLayout>
【MainActivity.java】
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button button; //呼叫攝像頭按鈕
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
button = (Button) findViewById(R.id.main_button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), CameraActivity.class));
}
});
}
}
【activity_camera.xml】
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#FFFFFF"
android:layout_height="match_parent"
tools:context=".CameraActivity" >
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/camera_surfaceview"/>
<TextView android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="計時區域"
android:id="@+id/camera_time"/>
<LinearLayout android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button android:layout_height="30dp"
android:layout_width="match_parent"
android:layout_marginBottom="20dp"
android:layout_weight="1"
android:background="@drawable/shape_main"
android:id="@+id/camera_photo"
android:layout_marginLeft="5dp"
android:textColor="#FFFFFF"
android:layout_marginRight="5dp"
android:text="照片攝取"/>
<Button android:layout_height="30dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_weight="1"
android:background="@drawable/shape_main"
android:id="@+id/camera_vedio"
android:layout_marginLeft="5dp"
android:textColor="#FFFFFF"
android:layout_marginRight="5dp"
android:text="視訊攝取"/>
</LinearLayout>
</RelativeLayout>
【CameraActivity.java】
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import com.example.cameraphotovideo.utils.FormatUtil;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.app.Activity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class CameraActivity extends Activity {
private String tag ="MaHaochen_______CameraActivity";
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Camera camera;
private MediaRecorder mediaRecorder;
private Button photoButton; //拍照按鈕
private Button vedioButton; //攝像按鈕
private TextView timeTextView;
protected boolean isPreview = false; //攝像區域是否準備良好
private boolean isRecording = true; // true表示沒有錄影,點選開始;false表示正在錄影,點選暫停
private boolean bool;
private int hour = 0;
private int minute = 0; //計時專用
private int second = 0;
private File mRecVedioPath;
private File mRecAudioFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
initCamera();
initViews();
}
//初始化攝像頭
private void initCamera() {
mRecVedioPath = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/mahc/video/temp/");
if (!mRecVedioPath.exists()) {
mRecVedioPath.mkdirs();
}
surfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview);
SurfaceHolder cameraSurfaceHolder = surfaceView.getHolder();
cameraSurfaceHolder.addCallback(new Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();
//設定Camera的角度/方向
camera.setDisplayOrientation(90);
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewFrameRate(5); // 每秒5幀
parameters.setPictureFormat(ImageFormat.JPEG);// 設定照片的輸出格式
parameters.set("jpeg-quality", 85);// 照片質量
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
isPreview = true;
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
surfaceHolder = holder;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
surfaceHolder = holder;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
if (isPreview) {
camera.stopPreview();
isPreview = false;
}
camera.release();
camera = null; // 記得釋放Camera
}
surfaceView = null;
surfaceHolder = null;
mediaRecorder = null;
}
});
//開發時建議設定
//This method was deprecated in API level 11. this is ignored, this value is set automatically when needed.
cameraSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
//初始化檢視元件
private void initViews() {
timeTextView = (TextView) findViewById(R.id.camera_time);
timeTextView.setVisibility(View.GONE);
photoButton = (Button) findViewById(R.id.camera_photo);
vedioButton = (Button) findViewById(R.id.camera_vedio);
ButtonOnClickListener onClickListener = new ButtonOnClickListener();
photoButton.setOnClickListener(onClickListener);
vedioButton.setOnClickListener(onClickListener);
}
class ButtonOnClickListener implements OnClickListener{
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.camera_vedio:
//點選開始錄影
if(isRecording){
if (isPreview) {
camera.stopPreview();
camera.release();
camera = null;
}
second = 0;
minute = 0;
hour = 0;
bool = true;
if(null==mediaRecorder){
mediaRecorder = new MediaRecorder();
}else {
mediaRecorder.reset();
}
//表面設定顯示記錄媒體(視訊)的預覽
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
//開始捕捉和編碼資料到setOutputFile(指定的檔案)
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//設定用於錄製的音源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//設定在錄製過程中產生的輸出檔案的格式
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
//設定視訊編碼器,用於錄製
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
//設定audio的編碼格式
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
//設定要捕獲的視訊的寬度和高度
mediaRecorder.setVideoSize(320, 240);
// 設定要捕獲的視訊幀速率
mediaRecorder.setVideoFrameRate(15);
try {
mRecAudioFile = File.createTempFile("Vedio", ".3gp",
mRecVedioPath);
} catch (IOException e) {
e.printStackTrace();
}
mediaRecorder.setOutputFile(mRecAudioFile.getAbsolutePath());
try {
mediaRecorder.prepare();
timeTextView.setVisibility(View.VISIBLE);
handler.postDelayed(task, 1000);
mediaRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
isRecording = !isRecording;
Log.e(tag, "=====開始錄製視訊=====");
}else {
//點選停止錄影
bool = false;
mediaRecorder.stop();
timeTextView.setText(FormatUtil.format(hour)+":"+FormatUtil.format(minute)+":"+ FormatUtil.format(second));
mediaRecorder.release();
mediaRecorder = null;
FormatUtil.videoRename(mRecAudioFile);
Log.e(tag, "=====錄製完成,已儲存=====");
isRecording = !isRecording;
try {
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
// parameters.setPreviewFrameRate(5); // 每秒5幀
parameters.setPictureFormat(ImageFormat.JPEG);// 設定照片的輸出格式
parameters.set("jpeg-quality", 85);// 照片質量
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
isPreview = true;
} catch (Exception e) {
e.printStackTrace();
}
}
break;
case R.id.camera_photo:
if (mediaRecorder != null) {
try {
bool = false;
mediaRecorder.stop();
timeTextView.setText(FormatUtil.format(hour) + ":" + FormatUtil.format(minute) + ":"
+ FormatUtil.format(second));
mediaRecorder.release();
mediaRecorder = null;
FormatUtil.videoRename(mRecAudioFile);
} catch (Exception e) {
e.printStackTrace();
}
isRecording = !isRecording;
Log.e(tag, "=====錄製完成,已儲存=====");
try {
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
// parameters.setPreviewFrameRate(5); // 每秒5幀
parameters.setPictureFormat(ImageFormat.JPEG);// 設定照片的輸出格式
parameters.set("jpeg-quality", 85);// 照片質量
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
isPreview = true;
} catch (Exception e) {
e.printStackTrace();
}
}
if (camera != null) {
camera.autoFocus(null);
camera.takePicture(null, null, new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
new SavePictureTask().execute(data);
camera.startPreview();
Log.e(tag,"=====拍照成功=====");
}
}); // 拍照
}
break;
default:
break;
}
}
}
/*
* 定時器設定,實現計時
*/
private Handler handler = new Handler();
private Runnable task = new Runnable() {
public void run() {
if (bool) {
handler.postDelayed(this, 1000);
second++;
if (second >= 60) {
minute++;
second = second % 60;
}
if (minute >= 60) {
hour++;
minute = minute % 60;
}
timeTextView.setText(FormatUtil.format(hour) + ":" + FormatUtil.format(minute) + ":"
+ FormatUtil.format(second));
}
}
};
class SavePictureTask extends AsyncTask<byte[], String, String> {
@Override
protected String doInBackground(byte[]... params) {
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/mahc/image";
File out = new File(path);
if (!out.exists()) {
out.mkdirs();
}
File picture = new File(path+"/"+new Date().getTime()+".jpg");
try {
FileOutputStream fos = new FileOutputStream(picture.getPath());
fos.write(params[0]);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
Log.e(tag, "=====照片儲存完成=====");
CameraActivity.this.finish();
return null;
}
}
}
第三步:該專案需要一個工具類FormatUtil.java
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.os.Environment;
public class FormatUtil {
/**
* 將快取資料夾的資料轉存到vedio檔案下
* @param recAudioFile
*/
public static void videoRename(File recAudioFile) {
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath()+ "/mahc/video/"+ "0" + "/";
String fileName = new SimpleDateFormat("yyyyMMddHHmmss")
.format(new Date()) + ".3gp";
File out = new File(path);
if (!out.exists()) {
out.mkdirs();
}
out = new File(path, fileName);
if (recAudioFile.exists())
recAudioFile.renameTo(out);
}
/**
* 用以計時操作的相關方法
* @param num
* @return
*/
public static String format(int num){
String s = num + "";
if (s.length() == 1) {
s = "0" + s;
}
return s;
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#FFCC99"
android:endColor="#99CC66"
android:centerColor="#0066CC"
android:angle="45" />
</shape>
頁面效果:
效果截圖
下載地址:
該資源正在稽核中,敬請期待! 點此下載資源!相關文章
- Android呼叫攝像頭拍照Android
- 照片系列之android呼叫攝像頭拍照Android
- Android呼叫攝像頭拍照並顯示照片Android
- 安卓呼叫攝像頭拍照安卓
- Android提供的攝像頭拍照Android
- 在Android中呼叫攝像頭拍照並顯示出來Android
- UVC攝像頭按鍵拍照功能
- 純JavaScript實現的呼叫裝置攝像頭並拍照的功能JavaScript
- android studio呼叫攝像頭拍照及具體步驟演示程式碼Android
- 瀏覽器呼叫攝像頭進行拍照程式瀏覽器
- html5呼叫攝像頭功能HTML
- 【Android】【opencv】實現攝像頭拍照和錄影AndroidOpenCV
- web呼叫攝像頭拍照並上傳到伺服器Web伺服器
- Android中呼叫攝像頭拍照儲存,並在相簿中選擇圖片顯示Android
- jQuery webcam plugin呼叫攝像頭jQueryWebPlugin
- android opencv 前置攝像頭AndroidOpenCV
- android 開啟攝像頭Android
- px30-android8.1-USB攝像頭錄製視訊異常Android
- HTML5如何呼叫攝像頭?HTML
- 教你如何利用python呼叫攝像頭Python
- html5中呼叫攝像頭拍照並上傳(附繞過https的想法)HTMLHTTP
- android studio之簡單呼叫攝像頭並且獲取其照片Android
- 如何在SAP UI5應用裡新增使用攝像頭拍照的功能UI
- html5呼叫攝像頭截圖HTML
- 安卓開發之呼叫攝像頭安卓
- Android Studio 呼叫Camera實現拍照功能Android
- [譯]Android的多攝像頭支援Android
- [譯] Android 的多攝像頭支援Android
- HTML5拍照、攝像機功能實戰HTML
- iPhone XS/iPhone XS Max攝像頭拍照解析:蘋果也玩起了AI拍照iPhone蘋果AI
- 微信視訊通話使用虛擬攝像頭
- iOS 儲存攝像頭H264視訊流iOS
- 3、Opencv播放視訊、儲存、暫停視訊,開啟攝像頭OpenCV
- Android CameraX 開啟攝像頭預覽Android
- Android 攝像頭預覽懸浮窗Android
- Android 圓形頭像 相簿和拍照裁剪選取Android
- [OpenGL]未來視覺2-Android攝像頭幀採集視覺Android
- 短視訊程式開發,Android:呼叫系統拍照和相簿Android
- WebRTC網頁開啟攝像頭並錄製視訊Web網頁