android自定義Camera實現(xiàn)錄像和拍照
本文實例為大家分享了android自定義Camera實現(xiàn)錄像和拍照的具體代碼,供大家參考,具體內(nèi)容如下
源碼:
package com.example.myvideocamera; 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.Calendar; import java.util.Date; import java.util.List; import android.app.Activity; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.Parameters; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.Size; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; /** * 視頻錄制 */ @SuppressWarnings("deprecation") public class MainActivity extends Activity implements OnClickListener, SensorEventListener, Callback { private SurfaceView surfaceView; // 用于繪制緩沖圖像的 private Button luXiang_bt; // 開始錄制的按鈕 private Button tingZhi_bt; // 停止錄制的按鈕 private Button auto_focus; // 進(jìn)行對焦 private Button screenshot; // 截圖 private TextView time_tv; // 顯示時間的文本框 private MediaRecorder mRecorder; private boolean recording; // 記錄是否正在錄像,fasle為未錄像, true 為正在錄像 private File videoFolder; // 存放視頻的文件夾 private File videFile; // 視頻文件 private Handler handler; private int time; // 時間 private Camera myCamera; // 相機(jī)聲明 private SurfaceHolder holder; // 用來訪問surfaceview的接口 private SensorManager sManager; // 傳感器管理者 private Sensor sensor; // 傳感器對象 private int mX, mY, mZ; // x y z 坐標(biāo) private Calendar calendar; // 日歷 private long lasttimestamp = 0; // 上一次用時的標(biāo)志 /** * 錄制過程中,時間變化 */ private Runnable timeRun = new Runnable() { @Override public void run() { time++; time_tv.setText(time + "秒"); handler.postDelayed(timeRun, 1000); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 強(qiáng)制橫屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); initView(); initSensor(); initCreateFile(); } /** * 對傳感器進(jìn)行初始化 */ private void initSensor() { sManager = (SensorManager) getSystemService(SENSOR_SERVICE); sensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (sManager == null) { // throw new IllegalArgumentException("SensorManager is null"); } sManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL); } /** * 文件的創(chuàng)建 */ private void initCreateFile() { // 判斷sd卡是否存在 boolean sdCardExist = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); if (sdCardExist) { // 設(shè)定存放視頻的文件夾的路徑 String path = Environment.getExternalStorageDirectory() .getAbsolutePath() + File.separator + "VideoFolder" + File.separator; // 聲明存放視頻的文件夾的File對象 videoFolder = new File(path); // 如果不存在此文件夾,則創(chuàng)建 if (!videoFolder.exists()) { videoFolder.mkdirs(); } // 設(shè)置surfaceView不管理的緩沖區(qū) surfaceView.getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 設(shè)置surfaceView分辨率 //surfaceView.getHolder().setFixedSize(1000, 500); luXiang_bt.setOnClickListener(this); } else Toast.makeText(this, "未找到sdCard!", Toast.LENGTH_LONG).show(); } /** * 初始化工作 */ private void initView() { // 獲取控件 surfaceView = (SurfaceView) findViewById(R.id.surfaceview); luXiang_bt = (Button) findViewById(R.id.luXiang_bt); tingZhi_bt = (Button) findViewById(R.id.tingZhi_bt); time_tv = (TextView) findViewById(R.id.time); auto_focus = (Button) findViewById(R.id.auto_focus); screenshot = (Button) findViewById(R.id.screenshot); handler = new Handler(); holder = surfaceView.getHolder(); tingZhi_bt.setOnClickListener(this); auto_focus.setOnClickListener(this); screenshot.setOnClickListener(this); // 添加回調(diào) holder.addCallback(this); } /** * 將Camera和mediaRecoder釋放 */ @Override protected void onDestroy() { handler.removeCallbacks(timeRun); if (mRecorder != null) { mRecorder.release(); } if (myCamera != null) { myCamera.stopPreview(); myCamera.release(); } super.onDestroy(); } /** * 控件點擊事件的監(jiān)聽 */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.luXiang_bt: // 錄像點擊事件 if (!recording) { try { // 獲取當(dāng)前時間,作為視頻文件的文件名 String nowTime = java.text.MessageFormat.format( "{0,date,yyyyMMdd_HHmmss}", new Object[] { new java.sql.Date(System .currentTimeMillis()) }); // 聲明視頻文件對象 videFile = new File(videoFolder.getAbsoluteFile() + File.separator + "video" + nowTime + ".mp4"); // 關(guān)閉預(yù)覽并釋放資源 myCamera.unlock(); mRecorder = new MediaRecorder(); mRecorder.setCamera(myCamera); // 創(chuàng)建此視頻文件 videFile.createNewFile(); mRecorder.setPreviewDisplay(surfaceView.getHolder() .getSurface()); // 預(yù)覽 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 視頻源 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 錄音源為麥克風(fēng) mRecorder .setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 輸出格式為mp4 /** *引用android.util.DisplayMetrics 獲取分辨率 */ // DisplayMetrics dm = new DisplayMetrics(); // getWindowManager().getDefaultDisplay().getMetrics(dm); mRecorder.setVideoSize(800, 480); // 視頻尺寸 mRecorder.setVideoEncodingBitRate(2*1280*720); //設(shè)置視頻編碼幀率 mRecorder.setVideoFrameRate(30); // 視頻幀頻率 mRecorder .setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); // 視頻編碼 mRecorder .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 音頻編碼 mRecorder.setMaxDuration(1800000); // 設(shè)置最大錄制時間 mRecorder.setOutputFile(videFile.getAbsolutePath()); // 設(shè)置錄制文件源 mRecorder.prepare(); // 準(zhǔn)備錄像 mRecorder.start(); // 開始錄像 time_tv.setVisibility(View.VISIBLE); // 設(shè)置文本框可見 handler.post(timeRun); // 調(diào)用Runable recording = true; // 改變錄制狀態(tài)為正在錄制 setAutofocus(); } catch (IOException e1) { e1.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } } else Toast.makeText(MainActivity.this, "視頻正在錄制中...", Toast.LENGTH_LONG).show(); break; case R.id.tingZhi_bt: // 停止點擊事件 if (recording) { mRecorder.stop(); mRecorder.release(); handler.removeCallbacks(timeRun); time_tv.setVisibility(View.GONE); int videoTimeLength = time; time = 0; recording = false; Toast.makeText( MainActivity.this, videFile.getAbsolutePath() + " " + videoTimeLength + "秒", Toast.LENGTH_LONG).show(); } // 開啟相機(jī) if (myCamera == null) { myCamera = Camera.open(); try { myCamera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } } myCamera.startPreview(); // 開啟預(yù)覽 break; case R.id.auto_focus: setAutofocus(); break; case R.id.screenshot: myCamera.autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { camera.takePicture(null, null, jpegCallBack); } } }); break; } } /** * 設(shè)置自動對焦 */ private void setAutofocus() { if (myCamera != null) { myCamera.autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { } } }); } } /** * 傳感器改變調(diào)用的方法 */ @Override public void onSensorChanged(SensorEvent event) { if (event.sensor == null) { return; } if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { int x = (int) event.values[0]; int y = (int) event.values[1]; int z = (int) event.values[2]; calendar = Calendar.getInstance(); long stamp = calendar.getTimeInMillis(); int px = Math.abs(mX - x); int py = Math.abs(mY - y); int pz = Math.abs(mZ - z); int maxValue = getMaxValue(px, py, pz); if (maxValue > 2 && (stamp - lasttimestamp) > 30) { lasttimestamp = stamp; setAutofocus(); } mX = x; mY = y; mZ = z; } } /** * 獲取最大改變的值 */ private int getMaxValue(int px, int py, int pz) { int max = 0; if (px > py && px > pz) { max = px; } else if (py > px && py > pz) { max = py; } else if (pz > px && pz > py) { max = pz; } return max; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } /** * suraceView 創(chuàng)建執(zhí)行的操作 */ @Override public void surfaceCreated(SurfaceHolder holder) { // 開啟相機(jī) if (myCamera == null) { myCamera = Camera.open(); try { myCamera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } } } /** * suraceView 狀態(tài)改變執(zhí)行的操作 */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 開始預(yù)覽 myCamera.startPreview(); Parameters parameters = myCamera.getParameters();// 獲取mCamera的參數(shù)對象 Size largestSize = getBestSupportedSize(parameters .getSupportedPreviewSizes()); parameters.setPreviewSize(largestSize.width, largestSize.height);// 設(shè)置預(yù)覽圖片尺寸 largestSize = getBestSupportedSize(parameters .getSupportedPictureSizes());// 設(shè)置捕捉圖片尺寸 parameters.setPictureSize(largestSize.width, largestSize.height); myCamera.setParameters(parameters); } private Size getBestSupportedSize(List<Size> sizes) { // 取能適用的最大的SIZE Size largestSize = sizes.get(0); int largestArea = sizes.get(0).height * sizes.get(0).width; for (Size s : sizes) { int area = s.width * s.height; if (area > largestArea) { largestArea = area; largestSize = s; } } return largestSize; } /** * suraceView 銷毀執(zhí)行的操作 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { // 關(guān)閉預(yù)覽并釋放資源 if (myCamera != null) { myCamera.stopPreview(); myCamera.release(); myCamera = null; } } /** * 創(chuàng)建jpeg圖片回調(diào)數(shù)據(jù)對象 */ private String filepath = ""; private PictureCallback jpegCallBack = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { Bitmap oldBitmap = BitmapFactory.decodeByteArray(data, 0, data.length); Matrix matrix = new Matrix(); matrix.setRotate(90); Bitmap newBitmap = Bitmap.createBitmap(oldBitmap, 0, 0, oldBitmap.getWidth(), oldBitmap.getHeight(), matrix, true); filepath = Environment.getExternalStorageDirectory() + File.separator + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".jpg"; File file = new File(filepath); try { BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(file)); newBitmap.compress(Bitmap.CompressFormat.JPEG, 85, bos); bos.flush(); bos.close(); camera.stopPreview(); camera.startPreview(); newBitmap.recycle(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; }
xml布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff" > <SurfaceView android:id="@+id/surfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <Button android:id="@+id/tingZhi_bt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" android:text="停止"/> <Button android:id="@+id/luXiang_bt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toLeftOf="@id/tingZhi_bt" android:text="錄像"/> <Button android:id="@+id/auto_focus" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toLeftOf="@id/luXiang_bt" android:text="調(diào)焦"/> <Button android:id="@+id/screenshot" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toLeftOf="@id/auto_focus" android:text="拍照"/> <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FF0000" android:text="1秒" android:visibility="gone" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="10dp"/> </RelativeLayout>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義Camera實現(xiàn)拍照功能
- Android實現(xiàn)Camera2預(yù)覽和拍照效果
- android自定義Camera拍照并查看圖片
- Android Camera實現(xiàn)毫秒級拍照實例
- Android中使用Camera類編寫手機(jī)拍照App的實例教程
- android系統(tǒng)在靜音模式下關(guān)閉camera拍照聲音的方法
- Android實現(xiàn)拍照、選擇圖片并裁剪圖片功能
- Android啟動相機(jī)拍照并返回圖片
- Android拍照保存在系統(tǒng)相冊不顯示的問題解決方法
- Android自定義Camera實現(xiàn)拍照小功能
相關(guān)文章
Android?App頁面滑動標(biāo)題欄顏色漸變詳解
這篇文章主要為大家詳細(xì)介紹了Android?App頁面滑動標(biāo)題欄顏色漸變,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02Flutter路由跳轉(zhuǎn)參數(shù)處理技巧詳解
這篇文章主要為大家介紹了Flutter路由跳轉(zhuǎn)參數(shù)處理技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08android項目實現(xiàn)帶進(jìn)度條的系統(tǒng)通知欄消息
本篇文章主要介紹了android項目實現(xiàn)帶進(jìn)度條的系統(tǒng)通知欄消息,就是實現(xiàn)在通知欄看到下載進(jìn)度。具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-10-10創(chuàng)建Android庫的方法及Android .aar文件用法小結(jié)
本文給大家介紹了創(chuàng)建Android庫的方法及Android中 .aar文件生成方法與用法詳解,涉及到創(chuàng)建庫模塊操作步驟及開發(fā)注意事項,需要的朋友參考下吧2017-12-12從源代碼分析Android Universal ImageLoader的緩存處理機(jī)制
這篇文章主要介紹了從源代碼分析Android Universal ImageLoader的緩存處理機(jī)制 的相關(guān)資料,需要的朋友可以參考下2016-01-01解決android studio卡頓,提升studio運行速度的方法
這篇文章主要介紹了解決android studio卡頓,提升studio運行速度的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android實現(xiàn)類似execel的表格 能回顯并能修改表格內(nèi)容的方法
今天小編就為大家分享一篇Android實現(xiàn)類似execel的表格 能回顯并能修改表格內(nèi)容的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08Android中的廣播、服務(wù)、數(shù)據(jù)庫、通知、包等術(shù)語的原理和介紹(圖解)
這篇文章主要介紹了Android中的廣播、服務(wù)、數(shù)據(jù)庫、通知、包等術(shù)語的原理和介紹(圖解),本文用圖文方式總結(jié)了Android中的一些開發(fā)術(shù)語,需要的朋友可以參考下2014-10-10