Android 自定義相機(jī)及分析源碼
Android 自定義相機(jī)及分析源碼
使用Android 系統(tǒng)相機(jī)的方法:
要想讓應(yīng)用有相機(jī)的action,咱們就必須在清單文件中做一些聲明,好讓系統(tǒng)知道,如下
<intent-filter> <action android:name="android.intent.action.IMAGE_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
action的作用就是聲明action的類型,便于Intent的使用,category的作用就是注冊(cè),沒(méi)有它。相關(guān)操作將不起作用。
一種方式是簡(jiǎn)單粗暴的實(shí)現(xiàn),如下
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, REQ_1); //然后在 onActivityResult方法中實(shí)現(xiàn)數(shù)據(jù)的獲取,此處是展示在了一個(gè)ImageView上 if(resultCode==RESULT_OK){ if(requestCode==REQ_1){ Bundle bundle=data.getExtras(); Bitmap bitmap=(Bitmap) bundle.get("data"); imageView.setImageBitmap(bitmap); }
小總結(jié):這樣的好處是簡(jiǎn)單快捷,但是在現(xiàn)在的android智能機(jī)中,好多相片都是很大的,這里獲得的僅僅是一個(gè)縮略圖罷了
另外一種方式是稍微溫婉一點(diǎn)了,而且效果也更好一點(diǎn),好處就在于它是先將照片信息存儲(chǔ)到本地一個(gè)臨時(shí)文件中,然后讓ImageView去相關(guān)路徑下進(jìn)行讀取,這樣就可以獲得清晰度很高的圖片了。如下
/* * 此方法的存在意義就是不在onActivityResult方法的data中獲取我們拍照的縮略圖,而是從我們的文件輸出目錄下直接查看原圖 * 這樣的好處就是可以對(duì)大容量的照片進(jìn)行便捷的準(zhǔn)確的操作 */ public void onStartCarema2(View view){ Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //見(jiàn)你給你路徑傳遞回需要的處理方法中 Uri uri=Uri.fromFile(new File(myFilePath)); //設(shè)置文件的輸出路徑 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, REQ_2); } //然后在onActivityResult方法中進(jìn)行相關(guān)的處理就可以了 else if(requestCode==REQ_2){ FileInputStream fis=null; try { fis=new FileInputStream(myFilePath); Bitmap bitmap=BitmapFactory.decodeStream(fis); imageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //記得最后一定要關(guān)閉相關(guān)的流操作。否則會(huì)引起相關(guān)的異常的。
開(kāi)發(fā)自定義的相機(jī)
由于開(kāi)發(fā)自定義的相機(jī)要進(jìn)行相關(guān)的權(quán)限的生命,所以一定不要忘記在清單文件中做相關(guān)的處理,如下
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA"/>
然后有以下幾個(gè)步驟:
- 創(chuàng)建Camera,并完成初始化Camera,開(kāi)始預(yù)覽,釋放資源三個(gè)方法
- 與Activity的SurfaceView進(jìn)行綁定。
- 在系統(tǒng)的onPause(),onResume()方法中進(jìn)行相關(guān)狀態(tài)設(shè)置
- 對(duì)Camera進(jìn)行參數(shù)設(shè)置,作用就是對(duì)照片類型和狀態(tài)進(jìn)行相關(guān)的設(shè)置
- 將拍得的照片進(jìn)行展示,一般會(huì)新開(kāi)一個(gè)Activity,用ImageView進(jìn)行承載,我們還可以在此Activity上添加TextView,實(shí)現(xiàn)水印效果等其他的美化操作
- 另外,如果想加入自動(dòng)聚焦的功能,就可以在SurfaceView上添加onClickListener(),對(duì)屏幕進(jìn)行偵聽(tīng),調(diào)用myCamera.autoFocus(null);方法即可
以上就是整個(gè)思路
接下來(lái)就是使用系統(tǒng)Camera的代碼展示
(可以直接copy相關(guān)代碼塊,添加到你的應(yīng)用中去,實(shí)現(xiàn)Camera這一功能。)
首先是MainActivity
布局
<LinearLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity" > <Button android:id="@+id/startCarema" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="StartCarema" android:onClick="onStartCarema" /> <Button android:id="@+id/startCarema2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="StartCarema2" android:onClick="onStartCarema2" /> <Button android:id="@+id/customCarema" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="CustomCarema" android:onClick="onCustomCarema" /> <ImageView android:id="@+id/imageview" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
代碼
package com.example.camerademo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity { //為下面的獲取請(qǐng)求所用 private static int REQ_1=1; private static int REQ_2=2; Button btn_startCareme,btn_startCarema2,btn_customCarema; ImageView imageView; //定義照片存儲(chǔ)的路徑 private String myFilePath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_startCareme=(Button) findViewById(R.id.startCarema); btn_startCarema2=(Button) findViewById(R.id.startCarema2); btn_customCarema=(Button) findViewById(R.id.customCarema); imageView=(ImageView) findViewById(R.id.imageview); //初始化不同手機(jī)的SD卡的路徑 myFilePath=Environment.getExternalStorageDirectory().getPath(); myFilePath=myFilePath+"/"+"temperature.png"; } public void onCustomCarema(View view){ Intent intent=new Intent(this,CustomCarema.class); startActivity(intent); } public void onStartCarema(View view){ Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, REQ_1); } /* * 此方法的存在意義就是不在onActivityResult方法的data中獲取我們拍照的縮略圖,而是從我們的文件輸出目錄下直接查看原圖 * 這樣的好處就是可以對(duì)大容量的照片進(jìn)行便捷的準(zhǔn)確的操作 */ public void onStartCarema2(View view){ Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //見(jiàn)你給你路徑傳遞回需要的處理方法中 Uri uri=Uri.fromFile(new File(myFilePath)); //設(shè)置文件的輸出路徑 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, REQ_2); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if(resultCode==RESULT_OK){ if(requestCode==REQ_1){ Bundle bundle=data.getExtras(); Bitmap bitmap=(Bitmap) bundle.get("data"); imageView.setImageBitmap(bitmap); }else if(requestCode==REQ_2){ FileInputStream fis=null; try { fis=new FileInputStream(myFilePath); Bitmap bitmap=BitmapFactory.decodeStream(fis); imageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }
接下來(lái)是自定義相機(jī)的代碼
主界面布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/capture" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="Capture" android:onClick="onCapture" /> <SurfaceView android:id="@+id/preview" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
ResultActivity的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Capture Result" android:textSize="28dp" android:textColor="#BFAACD" android:gravity="center" /> <ImageView android:id="@+id/picture" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="center" /> </LinearLayout>
代碼
首先是CustomCamera類,
package com.example.camerademo; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.content.Intent; import android.graphics.ImageFormat; import android.hardware.Camera; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; @SuppressWarnings("unused") public class CustomCarema extends Activity implements SurfaceHolder.Callback{ private Camera myCamera; private SurfaceView preview; private SurfaceHolder myHolder; //myHolder勇于展現(xiàn)surfaceView的圖像 private Camera.PictureCallback myPictureCallBack=new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera arg1) { //將拍照得到的數(shù)據(jù)信息存儲(chǔ)到本地 File tempFile=new File("/sdcard/temp.png"); try { FileOutputStream fos=new FileOutputStream(tempFile); fos.write(data); fos.close(); //然后將這個(gè)照片的數(shù)據(jù)信息傳送給要進(jìn)行展示的Activity即可 Intent intent=new Intent(CustomCarema.this,ResultActivity.class); intent.putExtra("PicturePath", tempFile.getAbsolutePath()); startActivity(intent); //拍照結(jié)束之后銷毀當(dāng)前的Activity,進(jìn)入到圖片展示界面 CustomCarema.this.finish(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.customcarema); preview=(SurfaceView) findViewById(R.id.preview); myHolder=preview.getHolder(); myHolder.addCallback(this); //實(shí)現(xiàn)點(diǎn)擊屏幕自動(dòng)聚焦的功能,此處并不需要拍照,故只是聚焦 preview.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub myCamera.autoFocus(null); } }); } @Override protected void onResume() { super.onResume(); if(myCamera==null){ myCamera=getCamera(); if(myHolder != null ){ setStartPreview(myCamera, myHolder); } } } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); releaseCamera(); } /** * 釋放相機(jī)的資源 */ private void releaseCamera(){ if(myCamera !=null ){ myCamera.setPreviewCallback(null); myCamera.stopPreview(); myCamera.release(); myCamera=null; } } /** * 拍照的一些參數(shù)設(shè)置,點(diǎn)擊此按鈕之后會(huì)觸發(fā)拍照的會(huì)掉,進(jìn)而實(shí)現(xiàn)拍照的效果 * @param view */ public void onCapture(View view){ Camera.Parameters parameters=myCamera.getParameters(); //設(shè)置照片的類型 parameters.setPictureFormat(ImageFormat.JPEG); parameters.setPictureSize(800, 600); //設(shè)置為自動(dòng)聚焦 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); //設(shè)置為自動(dòng)聚焦是不夠的,因?yàn)槲覀兿鹊玫降氖亲顬榍逦膱D片,所以要在聚焦成功的時(shí)候才進(jìn)行拍照 myCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub if(success){ myCamera.takePicture(null, null, myPictureCallBack); } } }); } /** * 獲取系統(tǒng)的一個(gè)Camera對(duì)象 */ private Camera getCamera(){ Camera camera=null; try{ camera=Camera.open(); }catch(Exception e){ e.printStackTrace(); } return camera; } /** * 開(kāi)始預(yù)覽相機(jī)的內(nèi)容,其實(shí)就是講surfaceHolder與之綁定 */ private void setStartPreview(Camera camera,SurfaceHolder holder){ //直接調(diào)用系統(tǒng)方式綁定預(yù)覽 try { camera.setPreviewDisplay(holder); //由于系統(tǒng)默認(rèn)使用橫屏預(yù)覽,,所以要進(jìn)行設(shè)置 camera.setDisplayOrientation(90); camera.startPreview(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub myCamera.stopPreview(); setStartPreview(myCamera, myHolder); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub setStartPreview(myCamera, myHolder); } @Override public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub releaseCamera(); } }
然后是結(jié)果界面代碼:
package com.example.camerademo; import java.io.FileInputStream; import java.io.FileNotFoundException; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.os.Bundle; import android.widget.ImageView; public class ResultActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.resultactivity); String path=getIntent().getStringExtra("PicturePath"); ImageView imageview=(ImageView) findViewById(R.id.picture); //由于這樣稚嫩獲得橫屏,所以我們要使用流的形式來(lái)轉(zhuǎn)換 // Bitmap bitmap=BitmapFactory.decodeFile(path); // imageview.setImageBitmap(bitmap); FileInputStream fis; try { fis = new FileInputStream(path); Bitmap bitmap=BitmapFactory.decodeStream(fis); Matrix matrix=new Matrix(); matrix.setRotate(90); bitmap=Bitmap.createBitmap(bitmap, 0,0, bitmap.getWidth() ,bitmap.getHeight(),matrix,true); imageview.setImageBitmap(bitmap); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
以上代碼中已經(jīng)做了下關(guān)的代碼注釋
總結(jié):
安卓6.0以上版本記得加動(dòng)態(tài)權(quán)限,不然會(huì)報(bào)空指針哦,還有點(diǎn)擊拍照事件那里 別忘了加進(jìn)去,不然拍照沒(méi)反應(yīng)
以上就是Android 自定義相機(jī)的實(shí)例詳解,如有疑問(wèn)請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
- Android自定義相機(jī)聚焦和顯示框
- Android自定義相機(jī)Camera實(shí)現(xiàn)手動(dòng)對(duì)焦的方法示例
- android 7自定義相機(jī)預(yù)覽及拍照功能
- Android開(kāi)源庫(kù)自定義相機(jī)模塊
- Android 用 camera2 API 自定義相機(jī)
- Android中關(guān)于自定義相機(jī)預(yù)覽界面拉伸問(wèn)題
- Android自定義相機(jī)實(shí)現(xiàn)定時(shí)拍照功能
- Android自定義相機(jī)實(shí)現(xiàn)自動(dòng)對(duì)焦和手動(dòng)對(duì)焦
- Android自定義相機(jī)界面的實(shí)現(xiàn)代碼
- Android自定義相機(jī)、預(yù)覽區(qū)域裁剪
相關(guān)文章
Android apk安裝替換卸載廣播的實(shí)現(xiàn)代碼
以下代碼實(shí)現(xiàn)比較簡(jiǎn)單,根據(jù)接收到的Action來(lái)判斷應(yīng)用程序是安裝 卸載還是被替換成其他版本,需要的朋友可以參考下2013-07-07Android四大組件之Service(服務(wù))實(shí)例詳解
這篇文章主要介紹了Android四大組件之Service(服務(wù))的用法,結(jié)合實(shí)例形式詳細(xì)分析了Service的基本概念,類型,用法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-01-01Android 點(diǎn)擊屏幕空白處收起輸入法軟鍵盤(手動(dòng)打開(kāi))
很多時(shí)候,我們?cè)谑褂脩?yīng)用時(shí),會(huì)出現(xiàn)輸入法軟鍵盤彈出的問(wèn)題,通常情況下,我們默認(rèn)會(huì)使用戶點(diǎn)擊返回鍵或者下一步對(duì)軟鍵盤進(jìn)行隱藏。為了更好的體驗(yàn),我們可以實(shí)現(xiàn)當(dāng)用戶使用完畢軟鍵盤時(shí)。點(diǎn)擊屏幕空白即可實(shí)現(xiàn)收起輸入法軟鍵盤2016-12-12Android?實(shí)現(xiàn)卡片堆疊錢包管理動(dòng)畫效果
這篇文章主要介紹了Android?實(shí)現(xiàn)卡片堆疊錢包管理動(dòng)畫效果,實(shí)現(xiàn)思路是在動(dòng)畫回調(diào)中requestLayout?實(shí)現(xiàn)動(dòng)畫效果,用Bounds?對(duì)象記錄每一個(gè)CardView?對(duì)象的初始位置,當(dāng)前位置,運(yùn)動(dòng)目標(biāo)位置,需要的朋友可以參考下2022-07-07Android實(shí)現(xiàn)繞球心旋轉(zhuǎn)的引導(dǎo)頁(yè)效果
本篇文章主要介紹了Android實(shí)現(xiàn)繞球心旋轉(zhuǎn)的引導(dǎo)頁(yè)效果,想要實(shí)現(xiàn)此效果的同學(xué)可以參考一下本文。2016-11-11