Android實(shí)現(xiàn)攝像頭拍照功能
應(yīng)用場(chǎng)景:
在Android開(kāi)發(fā)過(guò)程中,有時(shí)需要調(diào)用手機(jī)自身設(shè)備的功能,本文側(cè)重?cái)z像頭拍照功能的調(diào)用。
知識(shí)點(diǎn)介紹:
使用權(quán)限:調(diào)用手機(jī)自身設(shè)備功能(攝像頭拍照功能),應(yīng)該確保已經(jīng)在AndroidManifest.xml中正確聲明了對(duì)攝像頭的使用及其它相關(guān)的feature。
<!--攝像頭權(quán)限 --> <uses-permission android:name="android.permission.CAMERA" /> <!--存儲(chǔ)權(quán)限 SD卡讀寫(xiě)權(quán)限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!--Camera Feature 聲明對(duì)camera feature的使用 --> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> <!--視頻、錄音權(quán)限 請(qǐng)求音頻捕獲權(quán)限 --> <uses-permission android:name="android.permission.RECORD_VIDEO"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/>
Class類(lèi):
1、 SurfaceView
視圖(View)的繼承類(lèi),這個(gè)視圖里內(nèi)嵌了一個(gè)專(zhuān)門(mén)用于繪制的Surface。你可以控制這個(gè)Surface的格式和尺寸。Surfaceview控制這個(gè)Surface的繪制位置。
2、 SurfaceHolder
SurfaceHolder是控制surface的一個(gè)抽象接口,你可以通過(guò)SurfaceHolder來(lái)控制surface的尺寸和格式,或者修改surface的像素,監(jiān)視surface的變化等等,SurfaceHolder是SurfaceView的典型接口。
3、 SurfaceHolder.Callback
用戶(hù)可以實(shí)現(xiàn)此接口接收surface變化的消息。當(dāng)用在一個(gè)SurfaceView 中時(shí), 它只在SurfaceHolder.Callback.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之間有效。設(shè)置Callback的方法是SurfaceHolder.addCallback。
使用方式:
第一步:新建一個(gè)Android項(xiàng)目CameraTest,包含兩個(gè)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:background="#FFFFFF" android:layout_height="match_parent" tools:context=".MainActivity" > <LinearLayout android:layout_height="wrap_content" android:layout_width="match_parent"> <ImageView android:id="@+id/main_image" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" android:layout_width="match_parent"/> </LinearLayout> <LinearLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_alignParentBottom="true" android:layout_marginBottom="20dp" android:orientation="horizontal"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:id="@+id/main_camera" android:text="拍照"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="退出" android:id="@+id/main_quit"/> </LinearLayout> </RelativeLayout>
MainActivity.java
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity { private Button cameraButton; //拍照按鈕 private Button quitButton; //退出按鈕 private ImageView imageView; //圖片顯示 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); } private void initViews() { imageView = (ImageView) findViewById(R.id.main_image); // 從本地取圖片(在sdcard中獲取文件) Bitmap bitmap = getLoacalBitmap("/sdcard/mhc.jpg"); Log.e("msgTag", new File("/sdcard/mhc.jpg").exists()+"=========="); imageView .setImageBitmap(bitmap); //設(shè)置Bitmap cameraButton = (Button) findViewById(R.id.main_camera); quitButton = (Button) findViewById(R.id.main_quit); MainOnClickListener mainOnClickListener = new MainOnClickListener(); cameraButton.setOnClickListener(mainOnClickListener); quitButton.setOnClickListener(mainOnClickListener); } private class MainOnClickListener implements OnClickListener{ @Override public void onClick(View v) { switch (v.getId()) { case R.id.main_camera: startActivity(new Intent(MainActivity.this, CameraActivity.class)); break; case R.id.main_quit: MainActivity.this.finish(); break; default: break; } } } /** * 根據(jù)文件路徑獲取所需要文件,并將該文件封裝成Bitmap對(duì)象返回 * @param fileUrl * @return */ public static Bitmap getLoacalBitmap(String fileUrl) { try { FileInputStream fis = new FileInputStream(fileUrl); return BitmapFactory.decodeStream(fis); ///把流轉(zhuǎn)化為Bitmap圖片 } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } }
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:layout_height="match_parent" android:background="#FFFFFF" tools:context=".CameraActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" > <SurfaceView android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical|center_horizontal" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true"> <Button android:id="@+id/camera_save" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="拍照" /> </LinearLayout> </RelativeLayout>
CameraActivity.java
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.graphics.ImageFormat; import android.hardware.Camera; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class CameraActivity extends Activity { private String tag ="CameraActivity"; private SurfaceView surfaceView; //Surface的控制器 private SurfaceHolder surfaceHolder; private Camera camera; private Button saveButton; //拍照的回調(diào)接口 private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { new SavePictureTask().execute(data); camera.startPreview(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); initViews(); } private void initViews() { saveButton = (Button) findViewById(R.id.camera_save); surfaceView = (SurfaceView) findViewById(R.id.camera_preview); surfaceHolder = surfaceView.getHolder(); // 給SurfaceView當(dāng)前的持有者 SurfaceHolder 一個(gè)回調(diào)對(duì)象。 //用戶(hù)可以實(shí)現(xiàn)此接口接收surface變化的消息。當(dāng)用在一個(gè)SurfaceView 中時(shí), //它只在SurfaceHolder.Callback.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之間有效。 //設(shè)置Callback的方法是SurfaceHolder.addCallback. //實(shí)現(xiàn)過(guò)程一般繼承SurfaceView并實(shí)現(xiàn)SurfaceHolder.Callback接口 surfaceHolder.addCallback(surfaceCallback); // 設(shè)置surface不需要自己的維護(hù)緩存區(qū) surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); saveButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { camera.takePicture(null, null, pictureCallback); // Camera.takePicture(shutterCallback,rawCallback,pictureCallback ); // private ShutterCallback shutterCallback = new ShutterCallback(){ // public void onShutter(){ // /* 按快門(mén)瞬間會(huì)執(zhí)行這里的代碼 */ // } // }; // private PictureCallback rawCallback = new PictureCallback(){ // public void onPictureTaken(byte[] _data, Camera _camera){ // /* 如需要處理 raw 則在這里 寫(xiě)代碼 */ // } // }; // //當(dāng)拍照后 存儲(chǔ)JPG文件到 sd卡 // PictureCallback pictureCallback=new PictureCallback(){ // public void onPictureTaken(byte[] data,Camera camera) { // FileOutputStream outSteam=null; // try{ // SimpleDateFormat format=new SimpleDateFormat("yyyyMMddHHmmss"); // String times=format.format((new Date())); // outSteam=new FileOutputStream("/sdcard/"+times+"mhc.jpg"); // outSteam.write(data); // outSteam.close(); // }catch(FileNotFoundException e){ // Log.d("Camera", "row"); // } catch (IOException e) { // e.printStackTrace(); // } // }; // }; } }); } //SurfaceView當(dāng)前的持有者的回調(diào)接口的實(shí)現(xiàn) SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { camera = Camera.open(); Log.e(tag, "攝像頭Open完成"); try { camera.setPreviewDisplay(holder); } catch (IOException e) { camera.release(); camera = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Camera.Parameters parameters = camera.getParameters(); parameters.setPictureFormat(ImageFormat.JPEG); camera.setDisplayOrientation(0); camera.setParameters(parameters); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { camera.stopPreview(); camera.release(); camera = null; } }; class SavePictureTask extends AsyncTask<byte[], String, String> { @Override protected String doInBackground(byte[]... params) { File picture = new File("/sdcard/mhc.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; } } }
下載地址:Android實(shí)現(xiàn)攝像頭拍照功能
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Androidstudio調(diào)用攝像頭拍照并保存照片
- Android調(diào)用手機(jī)攝像頭拍照和錄音功能
- Android實(shí)現(xiàn)調(diào)用攝像頭拍照并存儲(chǔ)照片
- Android調(diào)用系統(tǒng)攝像頭拍照并顯示在ImageView上
- Android實(shí)現(xiàn)調(diào)用攝像頭拍照與視頻功能
- Android調(diào)用攝像頭拍照開(kāi)發(fā)教程
- Android實(shí)現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能
- Android 開(kāi)發(fā)隨手筆記之使用攝像頭拍照
- Android調(diào)用外置攝像頭的方法
- Android實(shí)現(xiàn)控制攝像頭拍照
相關(guān)文章
Android實(shí)現(xiàn)上傳文件到服務(wù)器實(shí)例詳解
本篇文章詳細(xì)介紹了Android實(shí)現(xiàn)上傳文件到服務(wù)器實(shí)例詳解,實(shí)現(xiàn)了文件每隔5秒進(jìn)行上傳,有需要的可以了解一下。2016-11-11Android防止按鈕過(guò)快點(diǎn)擊造成多次事件的解決方法
這篇文章主要介紹了Android防止按鈕過(guò)快點(diǎn)擊造成多次事件的解決方法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07Android實(shí)現(xiàn)用戶(hù)登錄記住密碼功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)用戶(hù)登錄記住密碼功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05Android實(shí)現(xiàn)EditText中添加和刪除bitmap的方法
這篇文章主要介紹了Android實(shí)現(xiàn)EditText中添加和刪除bitmap的方法,實(shí)例分析了Android中EditText控件的bitmap操作技巧,需要的朋友可以參考下2016-01-01漂亮的Android音樂(lè)歌詞控件 仿網(wǎng)易云音樂(lè)滑動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了漂亮的Android音樂(lè)歌詞控件,仿網(wǎng)易云音樂(lè)滑動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Android開(kāi)發(fā)之在程序中時(shí)時(shí)獲取logcat日志信息的方法(附demo源碼下載)
這篇文章主要介紹了Android開(kāi)發(fā)之在程序中時(shí)時(shí)獲取logcat日志信息的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了實(shí)時(shí)獲取logcat日志的原理、步驟與相關(guān)實(shí)現(xiàn)技巧,并附帶相應(yīng)的demo源碼供讀者下載參考,需要的朋友可以參考下2016-02-02Android?Jetpack結(jié)構(gòu)運(yùn)用Compose實(shí)現(xiàn)微博長(zhǎng)按點(diǎn)贊彩虹效果
Compose在動(dòng)畫(huà)方面下足了功夫,提供了豐富的API。但也正由于API種類(lèi)繁多,如果想一氣兒學(xué)下來(lái),最終可能會(huì)消化不良,導(dǎo)致似懂非懂。結(jié)合例子學(xué)習(xí)是一個(gè)不錯(cuò)的方法,本文就帶大家邊學(xué)邊做,通過(guò)實(shí)現(xiàn)一個(gè)微博長(zhǎng)按點(diǎn)贊的動(dòng)畫(huà)效果,學(xué)習(xí)了解Compose動(dòng)畫(huà)的常見(jiàn)思路和開(kāi)發(fā)技巧2022-07-07android 實(shí)現(xiàn)APP中改變頭像圖片的實(shí)例代碼
這篇文章主要介紹了android 實(shí)現(xiàn)APP中改變頭像圖片的實(shí)例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07