系統(tǒng)相機調(diào)用分析_第1頁
系統(tǒng)相機調(diào)用分析_第2頁
系統(tǒng)相機調(diào)用分析_第3頁
系統(tǒng)相機調(diào)用分析_第4頁
系統(tǒng)相機調(diào)用分析_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、android手機有自帶的照相機和圖庫,我們做的項目中有時用到上傳圖片到服務(wù)器,今天做了一個項目用到這個功能,所以把我的代碼記錄下來和大家分享,第一次寫博客希望各位大神多多批評。首先上一段調(diào)用android相冊和相機的代碼:代碼如下 :Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);/調(diào)用 android自帶的照相機startActivityForResult(intent, 1);代碼如下 :Intent i = new Intent(Intent.ACTION_PICK,調(diào)用android的圖庫startActivit

2、yForResult(i, 2);代碼如下 :Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) 完成照相后回調(diào)用此方法super.onActivityResult(requestCode, resultCode, data);case 1:switch (resultCode) case Activity.RESULT_OK:/照相完成點擊確定String sdStatus = Environment.getExternalStorageState();if (!sdSta

3、tus.equals(Environment.MEDIA_MOUNTED) /檢測 sd 是否可用Log.v(TestFile, SD card is not avaiable/writeable right now.);return; Bundle bundle = data.getExtras();Bitmap bitmap = (Bitmap) bundle.get(data);/獲取相機返回的數(shù)據(jù),并轉(zhuǎn)換為Bitmap圖片格式FileOutputStream b = null;File file = new File(/sdcard/pk4fun/);file.mkdirs();/創(chuàng)建

4、文件夾,名稱為pk4fun /照片的命名,目標(biāo)文件夾下,以當(dāng)前時間數(shù)字串為名稱,即可確保每張照片名稱不相同。網(wǎng)上流傳的其他Demo這里的照片名稱都寫死了, 則會發(fā)生無論拍照多少張,后一張總會把前一張照片覆蓋。細(xì)心的同學(xué)還可以設(shè)置這個字符串, 比如加上 “” 字樣等;然后就會發(fā)現(xiàn)sd 卡中 myimage這個文件夾下,會保存剛剛調(diào)用相機拍出來的照片,照片名稱不會重復(fù)。String str = null;Date date = null;SimpleDateFormat format = new SimpleDateFormat(yyyyMMddHHmmss);/獲取當(dāng)前時間,進一步轉(zhuǎn)化為字符串d

5、ate = new Date(resultCode);str = format.format(date);String fileName = /sdcard/myImage/ + str + .jpg;sendBroadcast(fileName);try b = new FileOutputStream(fileName);把數(shù)據(jù)寫入文件 catch (FileNotFoundException e) e.printStackTrace(); finally try b.flush();b.close(); catch (IOException e) e.printStackTrace();

6、 break;case Activity.RESULT_CANCELED:/break;break;case 2:取消switch (resultCode) case Activity.RESULT_OK: Uri uri = data.getData();Cursor cursor = mActivity.getContentResolver().query(uri, null,null, null, null);cursor.moveToFirst();String imgNo = cursor.getString(0); /圖片編號String imgPath = cursor.getS

7、tring(1); /圖片文件路徑String imgSize = cursor.getString(2); /圖片大小String imgName = cursor.getString(3); /圖片文件名cursor.close();Options options = new BitmapFactory.Options();options.inJustDecodeBounds = false;options.inSampleSize = 10;Bitmap bitmap = BitmapFactory.decodeFile(imgPath, options);break;case Acti

8、vity.RESULT_CANCELED:/break;break;取消最后記得加權(quán)限uses-permissionuses-permissionuses-permissionAndroid 調(diào)用系統(tǒng)相機和自定義相機實例本博文主要是介紹了android 上使用相機進行拍照并顯示的兩種方式,并且由于涉及到要把拍到的照片顯示出來,該例子也會涉及到 Android 加載大圖片時候的處理 (避免 OOM),還有簡要提一下有些人 SurfaceView 出現(xiàn)黑屏的原因。Android 應(yīng)用拍照的兩種方式, 下面為兩種形式的Demo展示出來的效果。知識點:一、調(diào)用系統(tǒng)自帶的相機應(yīng)用二、自定義我們自己的拍照

9、界面三、關(guān)于計算機解析圖片原理(如何正確加載圖片到Android 應(yīng)用中)所需權(quán)限:?1 23 45 6 一、調(diào)用系統(tǒng)照相機程序拍照(方式一)1.定義所需要的權(quán)限2.我們需要定義調(diào)用系統(tǒng)相機App 的 Intent, 當(dāng)然是通過設(shè)定 IntentFilter中的 Action來打開我 們想要的 activity了。MediaStore.ACTION_IMAGE_CAPTURE 這-個 Action 將打開拍照的系統(tǒng)相機。返回一個ImageMediaStore.ACTION_VIDEO_CAPTURE -這個 Action 將打開錄像的系統(tǒng)相機。返回一個Video在 MediaStore.ACT

10、ION_IMAGE_CAPTURE中,我們可以看到這段話 :【The callermay pass an extraEXTRA_OUTPUTto controlwhere thisimage will bewritten. If the EXTRA_OUTPUT is not present, then a small sized image is returnedas a Bitmap object in the extra field. This is useful forapplications that onlyneed a small image. If the EXTRA_OUTP

11、UT is present, then the full-sized image willbe written to the Uri value of EXTRA_OUTPUT.】3.API 規(guī)定我們傳入拍照得到圖片的存儲位置的Uri 。否則 Bimmap將以一個壓縮后的形式返回到我們當(dāng)前Aent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); / set theimage file name則會把拍照的圖片存儲到我們傳入的Uri 對應(yīng)的 File里面。4. 我們調(diào)用 startActivityForResult(intent)來啟動這樣一個系統(tǒng)相機 a

12、pp 之后,然后在當(dāng)前應(yīng)用Activity的 onActivityResult()中接受到返回拍照成功或者失敗的消息,做相應(yīng)處理。5. “壓縮處理” (Android應(yīng)用中加載大圖片 ), 并顯示到 ImageView 中。二、自定義照相機1.檢查相機是否存在,并獲取相機 Camera。2.創(chuàng)建一個相機圖像預(yù)覽類: extends SurfaceView并 implementsSurfaceHolder (我定義: MySurfaceView )把這個預(yù)覽類放入一個自定義布局 layout 里面,并且可以在 layout里添加自己的其他按鈕設(shè)置對應(yīng)的拍照按鈕然后聽事件捕獲照片和保存圖片釋放掉我

13、們使用的相機 Camera,不然之后其他應(yīng)用將無法使用它。三、計算機解析圖片的方式和Android 中大圖片 Bitmap 的壓縮顯示處理這個問題有點老生長談了,平時我們經(jīng)常遇到一些圖片資源, 我們把它加載到內(nèi)存發(fā)現(xiàn)拋出內(nèi)存不夠用的異常,即 OOM,當(dāng)然加載圖片時出現(xiàn)的 OOM情況有很多種,比如單張圖片沒有做壓縮, 導(dǎo)致圖片占用內(nèi)存過大而發(fā)生內(nèi)存溢出,也有多張圖片一次性加載進來,導(dǎo)致的內(nèi)存溢出。通常單張大圖,我們加載進來往往會經(jīng)過一個圖片的壓縮處理的過程,而如果多張圖片加載,我們可能就需要一些緩存機制, 再加上一些算法來保證程序不出現(xiàn) OOM。我們這里想要講的知識點跟單張大圖比較有關(guān)系首先,我

14、們知道一個圖片,它是由很多像素點來表示的,而像素點的個數(shù)只跟圖片的分辨率有關(guān),而跟圖片所占的內(nèi)存空間大小無關(guān)。比如我們的桌面壁紙: 1280 * 768 的分辨率, 那么它就有 1280 * 768 = 983040 個像素點,這意味著什么呢?我們知道我們要表示一個像素點的顏色,最經(jīng)常我們需要 RGB三種顏色來表示,而 R:0255,相當(dāng)于兩個 FF 的位置,就是 8 位,這樣的話 RGB合起來,一個像素點的表示就需要 24 位(這就是我們平衡聽到的 24 位圖),而加上透明度的 8 位,就是平時說的 32 位圖。那么一張圖片,它加載到內(nèi)存中的話,它會占用多大的空間呢?計算方法:( 像素點 *

15、一個像素所占用的byte 數(shù)) / 1024 / 1024 (MB)以 1280 * 768 的分辨率, 32 位圖為例:所占內(nèi)存大?。?1280* 768* (32 / 8)) / 1024)/1024=3.75(MB)說了這么多,那么我們再來說下Android 系統(tǒng)的規(guī)定吧, Android 系統(tǒng)嚴(yán)格規(guī)定了每個應(yīng)用所能分配的最大的內(nèi)存為多少,我們知道有一個VM值(在我們創(chuàng)建模擬器的時候),這個VM值里面便是我們所說的堆空間(Heap Size), 當(dāng)你的應(yīng)用占用的空間已經(jīng)超出我們定義的堆空間大小,那么不好意思, OOM這樣的話,我們明白了圖片的大小占據(jù)原理,還有盡量不要超出這個堆空間,那么

16、 OK,現(xiàn)在問題變得簡單了。 如果我們有一種方式可以在圖片加載進來之前,知道圖片的大小,然后改變它的長、寬,這樣的話,分辨率便變小了,這樣出來的乘積也就變小了。比如:我們的屏幕只有320240, 這時候你加載大分辨的圖片進來最多也只能顯示成這樣,所以我們常采用的是對圖片進行壓縮處理。這里有個概念叫壓縮比:長: 1024 / 320 = 3.2約等于 3寬: 768 / 240 = 3.2那這樣我們?nèi)绻褕D片壓縮成這樣大小的, 最后的圖片加載進來的大小便是(320* 240* (32 / 8) ) / 1024)/1024=0.29(MB)希望我這樣講完, 大家都能聽懂了,我這里先把照相機實例中

17、出現(xiàn)的關(guān)于如果處理這塊圖片的代碼先粘出來?1 /-Android大圖的處理方式2 -3privatevoid setPicToImageView(ImageViewimageView, File imageFile)4intimageViewWidth = imageView.getWidth();5intimageViewHeight = imageView.getHeight();6BitmapFactory.Options opts =new Options();78/設(shè)置這個,只得到 Bitmap的屬性信息放入opts ,而不把 Bitmap加載到內(nèi)存中10opts.inJustDec

18、odeBounds =true ;11BitmapFactory.decodeFile(imageFile.getPath(), opts);1213intbitmapWidth = opts.outWidth;14intbitmapHeight = opts.outHeight;15/ 取最大的比例,保證整個圖片的長或者寬必定在該屏幕中可以顯示得下16intscale = Math.max(imageViewWidth / bitmapWidth,17 imageViewHeight / bitmapHeight);1819/ 縮放的比例20opts.inSampleSize = scale

19、;21/ 內(nèi)存不足時可被回收22opts.inPurgeable =true ;23/ 設(shè)置為 false,表示不僅 Bitmap 的屬性,也要加載 bitmap24opts.inJustDecodeBounds =false ;25Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getPath(),opts);imageView.setImageBitmap(bitmap);關(guān)于堆空間:堆( HEAP)是 VM中占用內(nèi)存最多的部分,通常是動態(tài)分配的。堆的大小不是一成不變的, 通常有一個分配機制來控制它的大小。 比如初始的HEAP是 4M大

20、,當(dāng) 4M的空間被占用超過 75%的時候,重新分配堆為 8M 大;當(dāng) 8M被占用超過 75%,分配堆為 16M大。倒過來,當(dāng) 16M的堆利用不足 30%的時候,縮減它的大小為 8M大。重新設(shè)置堆的大小, 尤其是壓縮,一般會涉及到內(nèi)存的拷貝,所以變更堆的大小對效率有不良影響。廢話少說下面就看代碼咯 為了大家看起來方便點, 代碼的結(jié)構(gòu)可能不是很規(guī)范!源碼下載地址:代碼部分:一、用系統(tǒng)的相機按鈕點擊之后開啟系統(tǒng)相機Activity?new2 OnClickListener() 34Override5public void onClick(View v) 6Intent intent =new Int

21、ent();7intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);8imageFileUri = getOutFileUri(TYPE_FILE_IMAGE);/ 得到一9 個 File Uri10intent.putExtra(MediaStore.EXTRA_OUTPUT,11 imageFileUri);startActivityForResult(intent,SYSTEM_CAMERA_REQUESTCODE););生成 File文件,并得到 Uri?1 -生成/2Uri-/ 得到輸出文件的 URI4privateUri getOutF

22、ileUri(intfileType) 5returnUri.fromFile(getOutFile(fileType);/ 生成輸出文件9privateFile getOutFile(int fileType) 10String storageState = Environment.getExternalStorageState();1if(Environment.MEDIA_REMOVED.equals(storageState)1Toast.makeText(getApplicationContext(),oh,no, SD卡不存在1 , Toast.LENGTH_SHORT).show

23、();2returnnull;131File mediaStorageDir =newFile (Environment4.getExternalStoragePublicDirectory(Environment.DIRECTO1RY_PICTURES)5, MyPictures);1if(!mediaStorageDir.exists()6if(!mediaStorageDir.mkdirs()1Log.i(MyPictures, 創(chuàng)建圖片存儲路徑目錄失敗 );7Log.i(MyPictures,mediaStorageDir : +1mediaStorageDir.getPath();8

24、returnnull;1920File file =new File(getFilePath(mediaStorageDir,fileType);21returnfile;2/ 生成輸出文件路徑2privateString getFilePath(File mediaStorageDir,int fileType)3String timeStamp =new SimpleDateFormat(yyyyMMdd_HHmmss )2.format(new Date();4String filePath = mediaStorageDir.getPath() + File.separator;2if

25、 (fileType = TYPE_FILE_IMAGE)5filePath += (IMG_ + timeStamp +.jpg );2 elseif(fileType = TYPE_FILE_VEDIO)6filePath += (VIDEO_+ timeStamp +.mp4 );2 else7returnnull;28returnfilePath;2930313233343536373839404142434445二、用自定義的相機檢測相機設(shè)備是否存在:?/* 檢測相機是否存在 */2privateboolean checkCameraHardWare(Context context)

26、3PackageManager packageManager = context.getPackageManager();4if5 (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)6returntrue ;78returnfalse;按鈕按下之后的判斷:?1 findViewById(R.id.myapp_camera_btn).setOnClickListener(new2 OnClickListener() 34Override5publicvoidonClick(View v) 6if(checkCameraH

27、ardWare(getApplicationContext()7Intentintent= new Intent(getApplicationContext(),8 MyCameraActivity.class );9startActivity(intent);10 else 11Toast.makeText(getApplicationContext(), 沒有相機12存在 , Toast.LENGTH_SHORT).show();13);自定義的 SurfaceView 類:?1 package23 import4 import5 import6 import7 import8 impor

28、t9 import1 import01 publicclassMySurfaceViewextendsSurfaceViewimplementsSurfaceHolder.Callback1privateCamera camera =null;3privateSurfaceHolder surfaceHolder =null ;14publicMySurfaceView(Context context, Camera camera) 1super (context);5this.camera = camera;1surfaceHolder = getHolder();6surfaceHolde

29、r.addCallback(this);1surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS7 );18publicMySurfaceView(Context context) 1super (context);9/ TODO Auto-generated constructor stub2Override1publicvoidsurfaceCreated(SurfaceHolder holder) 2try2camera.setPreviewDisplay(surfaceHolder);2camera.startPrev

30、iew();3 catch(Exception e)2e.printStackTrace();42Override6publicvoidsurfaceChanged(SurfaceHolder holder,int format,int2 width,7intheight) 2/ 根本沒有可處理的 SurfaceView8if(surfaceHolder.getSurface() =null)2return;930/ 先停止 Camera 的預(yù)覽3try 1camera.stopPreview();3 catch(Exception e)2e.printStackTrace();333/ 這里

31、可以做一些我們要做的變換。43/重新開啟 Camera 的預(yù)覽功能5try3camera.setPreviewDisplay(surfaceHolder);6camera.startPreview();3 catch (Exception e)7e.printStackTrace();3Override4publicvoid surfaceDestroyed(SurfaceHolder holder) 034445464748495051525354555657585960616263646566676869707172自定義相機 Activity 類: ( 為了避免當(dāng)用戶按下 Home鍵,之

32、后再回到我們 App 中, SurfaceView 變黑屏,我們需要將 SurfaceView 加載到 FrameLayout 中的代碼寫在 onResume中)?1 package23 import4 import5 importjava.io.FileOutputStream;6 importjava.io.IOException;7 importjava.text.SimpleDateFormat;8 importjava.util.Date;910 importandroid.app.Activity;11 importandroid.hardware.Camera;12 import

33、android.hardware.Camera.PictureCallback;13 .Uri;14 importandroid.os.Bundle;15 importandroid.os.Environment;16 importandroid.util.Log;17 importandroid.view.View;18 importandroid.view.View.OnClickListener;19 importandroid.widget.Button;20 importandroid.widget.FrameLayout;21 importandroid.widget.Toast;

34、2223 importcom.example.camerademoapp.R;2425 publicclassMyCameraActivityextends Activity 26privateButton btn_camera_capture =null;27privateButton btn_camera_cancel =null;28privateButton btn_camera_ok =null;2930privateCamera camera =null;31privateMySurfaceView mySurfaceView =null ;3233privatebyte buff

35、er =null;3435privatefinalintTYPE_FILE_IMAGE =1;36privatefinalintTYPE_FILE_VEDIO =2;3738privatePictureCallback pictureCallback =new PictureCallback() 3940Override41publicvoid onPictureTaken(byte data, Camera camera) 42if(data =null)43Log.i(MyPicture, picture taken data: null);44 else45Log.i(MyPicture

36、, picture taken data: +46 data.length);474849buffer =new byte data.length;50buffer = data.clone();51;Override54protectedvoidonCreate(Bundle savedInstanceState) 55/ TODO Auto-generated method stub56super.onCreate(savedInstanceState);57setContentView(R.layout.mycamera_layout);5859btn_camera_capture =

37、(Button)60 findViewById(R.id.camera_capture);61btn_camera_ok = (Button) findViewById(R.id.camera_ok);62btn_camera_cancel = (Button) findViewById(R.id.camera_cancel);636465btn_camera_capture.setOnClickListener(new OnClickListener() 66Override67publicvoidonClick(View v) 6869camera.takePicture(null ,nu

38、ll, pictureCallback);7071btn_camera_capture.setVisibility(View.INVISIBLE);72btn_camera_ok.setVisibility(View.VISIBLE);73btn_camera_cancel.setVisibility(View.VISIBLE);7475);76btn_camera_ok.setOnClickListener(newOnClickListener() 7778Override79publicvoidonClick(View v) 80/保存圖片81saveImageToFile();8283c

39、amera.startPreview();84btn_camera_capture.setVisibility(View.VISIBLE);85btn_camera_ok.setVisibility(View.INVISIBLE);86btn_camera_cancel.setVisibility(View.INVISIBLE);8788);89btn_camera_cancel.setOnClickListener(new OnClickListener() 9091Override92publicvoidonClick(View v) 9394camera.startPreview();9

40、5btn_camera_capture.setVisibility(View.VISIBLE);96btn_camera_ok.setVisibility(View.INVISIBLE);97btn_camera_cancel.setVisibility(View.INVISIBLE);989910);010Override1protectedvoidonPause() 10/ TODO Auto-generated method stub2super.onPause();103camera.release();10camera =null;4105Override10protectedvoi

41、donResume() 6/ TODO Auto-generated method stub10super.onResume();7if (camera =null )10camera = getCameraInstance();810/ 必須放在 onResume 中,不然會出現(xiàn)Home 鍵之后,再回到該APP,黑屏9mySurfaceView =new MySurfaceView(getApplicationContext(),11camera);0FrameLayout preview = (FrameLayout)11findViewById(R.id.camera_preview);

42、1preview.addView(mySurfaceView);2/* 得到一相機對象 */3privateCamera getCameraInstance()11Camera camera =null ;4try11camera = camera.open();5 catch(Exception e)11e.printStackTrace();611returncamera;11811/-保存圖片9-12privatevoid saveImageToFile()0File file = getOutFile(TYPE_FILE_IMAGE);12if(file =null )1Toast.m

43、akeText(getApplicationContext(), 文件創(chuàng)建失敗 , 請檢12查 SD 卡讀寫權(quán)限 , Toast.LENGTH_SHORT).show();2return;123Log.i(MyPicture, 自定義相機圖片路徑: + file.getPath();12Toast.makeText(getApplicationContext(), 圖片保存路徑: +4 file.getPath(), Toast.LENGTH_SHORT).show();12if(buffer =null)5Log.i(MyPicture, 自定義相機 Buffer: null);12 els

44、e 6try12FileOutputStream fos =newFileOutputStream(file);7fos.write(buffer);12fos.close();8 catch(IOException e)12e.printStackTrace();9130131/-生成13Uri-/ 得到輸出文件的 URI13privateUri getOutFileUri(intfileType) 3returnUri.fromFile(getOutFile(fileType);4/ 生成輸出文件5privateFile getOutFile(int fileType) 136String

45、 storageState = Environment.getExternalStorageState();13if(Environment.MEDIA_REMOVED.equals(storageState)7Toast.makeText(getApplicationContext(),oh,no, SD 卡不存在13 , Toast.LENGTH_SHORT).show();8returnnull ;13914File mediaStorageDir =new File (Environment0.getExternalStoragePublicDirectory(Environment.DIRECT14ORY_PIC

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論