




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、android手機(jī)有自帶的照相機(jī)和圖庫,我們做的項(xiàng)目中有時(shí)用到上傳圖片到服務(wù)器,今天做了一個(gè)項(xiàng)目用到這個(gè)功能,所以把我的代碼記錄下來和大家分享,第一次寫博客希望各位大神多多批評(píng)。首先上一段調(diào)用android相冊(cè)和相機(jī)的代碼:代碼如下:Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);/調(diào)用android自帶的照相機(jī)photoUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;startActivityForResult(intent, 1);代碼如下:Intent i = n
2、ew Intent(Intent.ACTION_PICK,vider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);/調(diào)用android的圖庫startActivityForResult(i, 2);代碼如下:Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) /完成照相后回調(diào)用此方法super.onActivityResult(requestCode, resultCode, data);case 1:sw
3、itch (resultCode) case Activity.RESULT_OK:/照相完成點(diǎn)擊確定String sdStatus = Environment.getExternalStorageState();if (!sdStatus.equals(Environment.MEDIA_MOUNTED) / 檢測(cè)sd是否可用Log.v(TestFile, SD card is not avaiable/writeable right now.);return; Bundle bundle = data.getExtras();Bitmap bitmap = (Bitmap) bundle.
4、get(data);/ 獲取相機(jī)返回的數(shù)據(jù),并轉(zhuǎn)換為Bitmap圖片格式FileOutputStream b = null;File file = new File(/sdcard/pk4fun/);file.mkdirs();/ 創(chuàng)建文件夾,名稱為pk4fun / 照片的命名,目標(biāo)文件夾下,以當(dāng)前時(shí)間數(shù)字串為名稱,即可確保每張照片名稱不相同。網(wǎng)上流傳的其他Demo這里的照片名稱都寫死了,則會(huì)發(fā)生無論拍照多少張,后一張總會(huì)把前一張照片覆蓋。細(xì)心的同學(xué)還可以設(shè)置這個(gè)字符串,比如加上“”字樣等;然后就會(huì)發(fā)現(xiàn)sd卡中myimage這個(gè)文件夾下,會(huì)保存剛剛調(diào)用相機(jī)拍出來的照片,照片名稱不會(huì)重復(fù)。Str
5、ing str = null;Date date = null;SimpleDateFormat format = new SimpleDateFormat(yyyyMMddHHmmss);/ 獲取當(dāng)前時(shí)間,進(jìn)一步轉(zhuǎn)化為字符串date = new Date(resultCode);str = format.format(date);String fileName = /sdcard/myImage/ + str + .jpg;sendBroadcast(fileName);try b = new FileOutputStream(fileName);press(Bitmap.CompressF
6、ormat.JPEG, 100, b);/ 把數(shù)據(jù)寫入文件 catch (FileNotFoundException e) e.printStackTrace(); finally try b.flush();b.close(); catch (IOException e) e.printStackTrace(); break;case Activity.RESULT_CANCELED:/ 取消break;break;case 2:switch (resultCode) case Activity.RESULT_OK: Uri uri = data.getData();Cursor curso
7、r = mActivity.getContentResolver().query(uri, null,null, null, null);cursor.moveToFirst();String imgNo = cursor.getString(0); / 圖片編號(hào)String imgPath = cursor.getString(1); / 圖片文件路徑String imgSize = cursor.getString(2); / 圖片大小String imgName = cursor.getString(3); / 圖片文件名cursor.close();/ Options options
8、= new BitmapFactory.Options();/ options.inJustDecodeBounds = false;/ options.inSampleSize = 10;/ Bitmap bitmap = BitmapFactory.decodeFile(imgPath, options);break;case Activity.RESULT_CANCELED:/ 取消break;break;最后記得加權(quán)限Android調(diào)用系統(tǒng)相機(jī)和自定義相機(jī)實(shí)例本博文主要是介紹了android上使用相機(jī)進(jìn)行拍照并顯示的兩種方式,并且由于涉及到要把拍到的照片顯示出來,該例子也會(huì)涉及到And
9、roid加載大圖片時(shí)候的處理(避免OOM),還有簡要提一下有些人SurfaceView出現(xiàn)黑屏的原因。Android應(yīng)用拍照的兩種方式,下面為兩種形式的Demo展示出來的效果。知識(shí)點(diǎn):一、調(diào)用系統(tǒng)自帶的相機(jī)應(yīng)用二、自定義我們自己的拍照界面三、關(guān)于計(jì)算機(jī)解析圖片原理(如何正確加載圖片到Android應(yīng)用中)所需權(quán)限:?123456一、調(diào)用系統(tǒng)照相機(jī)程序拍照(方式一)1.定義所需要的權(quán)限2.我們需要定義調(diào)用系統(tǒng)相機(jī)App的Intent,當(dāng)然是通過設(shè)定IntentFilter中的Action來打開我們想要的activity了。MediaStore.ACTION_IMAGE_CAPTURE - 這個(gè)A
10、ction將打開拍照的系統(tǒng)相機(jī)。返回一個(gè)ImageMediaStore.ACTION_VIDEO_CAPTURE - 這個(gè)Action將打開錄像的系統(tǒng)相機(jī)。返回一個(gè)Video在MediaStore.ACTION_IMAGE_CAPTURE中,我們可以看到這段話:【The caller may pass an extra EXTRA_OUTPUT to control where this image will bewritten. If the EXTRA_OUTPUT is not present, then a small sized image is returnedas a Bitma
11、p object in the extra field. This is useful for applications that onlyneed a small image. If the EXTRA_OUTPUT is present, then the full-sized image willbe written to the Uri value of EXTRA_OUTPUT.】3.API規(guī)定我們傳入拍照得到圖片的存儲(chǔ)位置的Uri。否則Bimmap將以一個(gè)壓縮后的形式返回到我們當(dāng)前Aent.putExtra(MediaStore.EXTRA_OUTPUT, f
12、ileUri); / set the image file name則會(huì)把拍照的圖片存儲(chǔ)到我們傳入的Uri對(duì)應(yīng)的File里面。4.我們調(diào)用startActivityForResult(intent)來啟動(dòng)這樣一個(gè)系統(tǒng)相機(jī)app之后,然后在當(dāng)前應(yīng)用Activity的onActivityResult()中接受到返回拍照成功或者失敗的消息,做相應(yīng)處理。5.“壓縮處理”(Android應(yīng)用中加載大圖片),并顯示到ImageView中。二、自定義照相機(jī)1.檢查相機(jī)是否存在,并獲取相機(jī)Camera。2.創(chuàng)建一個(gè)相機(jī)圖像預(yù)覽類:extends SurfaceView 并 implements Surface
13、Holder (我定義:MySurfaceView)3.把這個(gè)預(yù)覽類放入一個(gè)自定義布局layout里面,并且可以在layout里添加自己的其他按鈕4.設(shè)置對(duì)應(yīng)的拍照按鈕然后聽事件5.捕獲照片和保存圖片6.釋放掉我們使用的相機(jī)Camera,不然之后其他應(yīng)用將無法使用它。三、計(jì)算機(jī)解析圖片的方式和Android中大圖片Bitmap的壓縮顯示處理這個(gè)問題有點(diǎn)老生長談了,平時(shí)我們經(jīng)常遇到一些圖片資源,我們把它加載到內(nèi)存發(fā)現(xiàn)拋出內(nèi)存不夠用的異常,即OOM,當(dāng)然加載圖片時(shí)出現(xiàn)的OOM情況有很多種,比如單張圖片沒有做壓縮,導(dǎo)致圖片占用內(nèi)存過大而發(fā)生內(nèi)存溢出,也有多張圖片一次性加載進(jìn)來,導(dǎo)致的內(nèi)存溢出。通常單
14、張大圖,我們加載進(jìn)來往往會(huì)經(jīng)過一個(gè)圖片的壓縮處理的過程,而如果多張圖片加載,我們可能就需要一些緩存機(jī)制,再加上一些算法來保證程序不出現(xiàn)OOM。我們這里想要講的知識(shí)點(diǎn)跟單張大圖比較有關(guān)系首先,我們知道一個(gè)圖片,它是由很多像素點(diǎn)來表示的,而像素點(diǎn)的個(gè)數(shù)只跟圖片的分辨率有關(guān),而跟圖片所占的內(nèi)存空間大小無關(guān)。比如我們的桌面壁紙:1280 * 768 的分辨率,那么它就有 1280 * 768 = 983040個(gè)像素點(diǎn),這意味著什么呢?我們知道我們要表示一個(gè)像素點(diǎn)的顏色,最經(jīng)常我們需要RGB三種顏色來表示,而R:0255,相當(dāng)于兩個(gè)FF的位置,就是8位,這樣的話RGB合起來,一個(gè)像素點(diǎn)的表示就需要24位
15、(這就是我們平衡聽到的24位圖),而加上透明度的8位,就是平時(shí)說的32位圖。那么一張圖片,它加載到內(nèi)存中的話,它會(huì)占用多大的空間呢?計(jì)算方法:(像素點(diǎn) * 一個(gè)像素所占用的byte數(shù)) / 1024 / 1024 (MB)以1280 * 768 的分辨率,32位圖為例:所占內(nèi)存大?。?(1280 * 768 * (32 / 8)) / 1024)/1024=3.75(MB)說了這么多,那么我們?cè)賮碚f下Android系統(tǒng)的規(guī)定吧,Android系統(tǒng)嚴(yán)格規(guī)定了每個(gè)應(yīng)用所能分配的最大的內(nèi)存為多少,我們知道有一個(gè)VM值(在我們創(chuàng)建模擬器的時(shí)候),這個(gè)VM值里面便是我們所說的堆空間(Heap Size)
16、,當(dāng)你的應(yīng)用占用的空間已經(jīng)超出我們定義的堆空間大小,那么不好意思,OOM這樣的話,我們明白了圖片的大小占據(jù)原理,還有盡量不要超出這個(gè)堆空間,那么OK,現(xiàn)在問題變得簡單了。如果我們有一種方式可以在圖片加載進(jìn)來之前,知道圖片的大小,然后改變它的長、寬,這樣的話,分辨率便變小了,這樣出來的乘積也就變小了。比如:我們的屏幕只有320 * 240, 這時(shí)候你加載大分辨的圖片進(jìn)來最多也只能顯示成這樣,所以我們常采用的是對(duì)圖片進(jìn)行壓縮處理。這里有個(gè)概念叫壓縮比:長:1024 / 320 = 3.2 約等于 3寬:768 / 240 = 3.2那這樣我們?nèi)绻褕D片壓縮成這樣大小的,最后的圖片加載進(jìn)來的大小便是
17、(320* 240* (32 / 8)) / 1024)/1024=0.29(MB)希望我這樣講完,大家都能聽懂了,我這里先把照相機(jī)實(shí)例中出現(xiàn)的關(guān)于如果處理這塊圖片的代碼先粘出來?12345678910111213141516171819202122232425/-Android大圖的處理方式-private void setPicToImageView(ImageView imageView, File imageFile)int imageViewWidth = imageView.getWidth();int imageViewHeight = imageView.getHeight()
18、;BitmapFactory.Options opts =new Options();/設(shè)置這個(gè),只得到Bitmap的屬性信息放入opts,而不把Bitmap加載到內(nèi)存中opts.inJustDecodeBounds =true;BitmapFactory.decodeFile(imageFile.getPath(), opts);int bitmapWidth = opts.outWidth;int bitmapHeight = opts.outHeight;/取最大的比例,保證整個(gè)圖片的長或者寬必定在該屏幕中可以顯示得下int scale = Math.max(imageViewWidth
19、 / bitmapWidth, imageViewHeight / bitmapHeight);/縮放的比例opts.inSampleSize = scale;/內(nèi)存不足時(shí)可被回收opts.inPurgeable =true;/設(shè)置為false,表示不僅Bitmap的屬性,也要加載bitmapopts.inJustDecodeBounds =false;Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getPath(), opts);imageView.setImageBitmap(bitmap);關(guān)于堆空間:堆(HEAP)是VM中占用內(nèi)存
20、最多的部分,通常是動(dòng)態(tài)分配的。堆的大小不是一成不變的,通常有一個(gè)分配機(jī)制來控制它的大小。比如初始的HEAP是4M大,當(dāng)4M的空間被占用超過75%的時(shí)候,重新分配堆為8M大;當(dāng)8M被占用超過75%,分配堆為16M大。倒過來,當(dāng)16M的堆利用不足30%的時(shí)候,縮減它的大小為8M大。重新設(shè)置堆的大小,尤其是壓縮,一般會(huì)涉及到內(nèi)存的拷貝,所以變更堆的大小對(duì)效率有不良影響。廢話少說下面就看代碼咯為了大家看起來方便點(diǎn),代碼的結(jié)構(gòu)可能不是很規(guī)范!源碼下載地址:代碼部分:一、用系統(tǒng)的相機(jī)按鈕點(diǎn)擊之后開啟系統(tǒng)相機(jī)Activity?1234567891011findViewById(R.id.system_cam
21、era_btn).setOnClickListener(new OnClickListener() Overridepublic void onClick(View v) Intent intent =new Intent();intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);imageFileUri = getOutFileUri(TYPE_FILE_IMAGE);/得到一個(gè)File Uriintent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);startActivityForResult
22、(intent, SYSTEM_CAMERA_REQUESTCODE););生成File文件,并得到Uri?123456789101112131415161718192021222324252627282930313233343536373839404142434445/-生成Uri-/得到輸出文件的URIprivate Uri getOutFileUri(int fileType) return Uri.fromFile(getOutFile(fileType);/生成輸出文件private File getOutFile(int fileType) String storageState
23、= Environment.getExternalStorageState();if (Environment.MEDIA_REMOVED.equals(storageState)Toast.makeText(getApplicationContext(),oh,no, SD卡不存在, Toast.LENGTH_SHORT).show();return null;File mediaStorageDir =new File (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),MyPictu
24、res);if (!mediaStorageDir.exists()if (!mediaStorageDir.mkdirs()Log.i(MyPictures,創(chuàng)建圖片存儲(chǔ)路徑目錄失敗);Log.i(MyPictures,mediaStorageDir : + mediaStorageDir.getPath();return null;File file =new File(getFilePath(mediaStorageDir,fileType);return file;/生成輸出文件路徑private String getFilePath(File mediaStorageDir,int
25、fileType)String timeStamp =new SimpleDateFormat(yyyyMMdd_HHmmss).format(new Date();String filePath = mediaStorageDir.getPath() + File.separator;if (fileType = TYPE_FILE_IMAGE)filePath += (IMG_ + timeStamp +.jpg);else if (fileType = TYPE_FILE_VEDIO)filePath += (VIDEO_ + timeStamp +.mp4);elsereturn nu
26、ll;return filePath;二、用自定義的相機(jī)檢測(cè)相機(jī)設(shè)備是否存在:?12345678/*檢測(cè)相機(jī)是否存在*/private boolean checkCameraHardWare(Context context)PackageManager packageManager = context.getPackageManager();if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)return true;return false;按鈕按下之后的判斷:?12345678910111213findViewB
27、yId(R.id.myapp_camera_btn).setOnClickListener(new OnClickListener() Overridepublic void onClick(View v) if (checkCameraHardWare(getApplicationContext()Intent intent =new Intent(getApplicationContext(), MyCameraActivity.class);startActivity(intent);elseToast.makeText(getApplicationContext(),沒有相機(jī)存在, T
28、oast.LENGTH_SHORT).show(););自定義的SurfaceView類:?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172package cn.panghu.camera;import android.content.Context;import android.graphics.Canvas;import android.graphics.Rect;imp
29、ort android.hardware.Camera;import android.util.AttributeSet;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;public class MySurfaceViewextends SurfaceViewimplements SurfaceHolder.Callbackprivate Camera camera =null;private SurfaceHolder surfaceHolder =nu
30、ll;public MySurfaceView(Context context, Camera camera) super(context);this.camera = camera;surfaceHolder = getHolder();surfaceHolder.addCallback(this);surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);public MySurfaceView(Context context) super(context);/ TODO Auto-generated constructo
31、r stubOverridepublic void surfaceCreated(SurfaceHolder holder) trycamera.setPreviewDisplay(surfaceHolder);camera.startPreview();catch(Exception e)e.printStackTrace();Overridepublic void surfaceChanged(SurfaceHolder holder,int format,int width,int height) /根本沒有可處理的SurfaceViewif (surfaceHolder.getSurf
32、ace() =null)return ;/先停止Camera的預(yù)覽trycamera.stopPreview();catch(Exception e)e.printStackTrace();/這里可以做一些我們要做的變換。/重新開啟Camera的預(yù)覽功能trycamera.setPreviewDisplay(surfaceHolder);camera.startPreview();catch(Exception e)e.printStackTrace();Overridepublic void surfaceDestroyed(SurfaceHolder holder) 自定義相機(jī)Activi
33、ty類:(為了避免當(dāng)用戶按下Home鍵,之后再回到我們App中,SurfaceView變黑屏,我們需要將SurfaceView加載到FrameLayout中的代碼寫在onResume中)?12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410
34、5106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200package cn.pan
35、ghu.camera;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import android.app.Activity;import android.hardware.Camera;import android.hardware.Camera.PictureCallback;import .Uri
36、;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.FrameLayout;import android.widget.Toast;import com.example.camerademoapp.R;public class MyCameraActivit
37、yextends Activity private Button btn_camera_capture =null;private Button btn_camera_cancel =null;private Button btn_camera_ok =null;private Camera camera =null;private MySurfaceView mySurfaceView =null;private byte buffer =null;private final int TYPE_FILE_IMAGE =1;private final int TYPE_FILE_VEDIO =
38、2;private PictureCallback pictureCallback =new PictureCallback() Overridepublic void onPictureTaken(byte data, Camera camera) if (data =null)Log.i(MyPicture,picture taken data: null);elseLog.i(MyPicture,picture taken data: + data.length);buffer =new bytedata.length;buffer = data.clone();Overrideprot
39、ected void onCreate(Bundle savedInstanceState) / TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.mycamera_layout);btn_camera_capture = (Button) findViewById(R.id.camera_capture);btn_camera_ok = (Button) findViewById(R.id.camera_ok);btn_camera_cancel = (Butto
40、n) findViewById(R.id.camera_cancel);btn_camera_capture.setOnClickListener(new OnClickListener() Overridepublic void onClick(View v) camera.takePicture(null,null, pictureCallback);btn_camera_capture.setVisibility(View.INVISIBLE);btn_camera_ok.setVisibility(View.VISIBLE);btn_camera_cancel.setVisibilit
41、y(View.VISIBLE););btn_camera_ok.setOnClickListener(new OnClickListener() Overridepublic void onClick(View v) /保存圖片saveImageToFile();camera.startPreview();btn_camera_capture.setVisibility(View.VISIBLE);btn_camera_ok.setVisibility(View.INVISIBLE);btn_camera_cancel.setVisibility(View.INVISIBLE););btn_c
42、amera_cancel.setOnClickListener(new OnClickListener() Overridepublic void onClick(View v) camera.startPreview();btn_camera_capture.setVisibility(View.VISIBLE);btn_camera_ok.setVisibility(View.INVISIBLE);btn_camera_cancel.setVisibility(View.INVISIBLE););Overrideprotected void onPause() / TODO Auto-generated method stubsuper.on
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國古式桌子數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 黑龍江省哈爾濱工大附中2024-2025學(xué)年九年級(jí)下學(xué)期化學(xué)寒假調(diào)研測(cè)試題(含答案)
- 2025年軍隊(duì)文職人員招聘之軍隊(duì)文職政治學(xué)練習(xí)題(一)及答案
- 2019-2025年消防設(shè)施操作員之消防設(shè)備中級(jí)技能通關(guān)提分題庫及完整答案
- 產(chǎn)品采購協(xié)議細(xì)節(jié)
- 房地產(chǎn)公司涉及的設(shè)計(jì)方面協(xié)議年
- 促銷活動(dòng)效果分析統(tǒng)計(jì)表
- 慢病相關(guān)知識(shí)培訓(xùn)課件
- 人力資源招聘與員工離職統(tǒng)計(jì)表
- 河南省駐馬店上蔡縣2024-2025學(xué)年七年級(jí)上學(xué)期期末生物學(xué)試題(含答案)
- 大班語言《母子情深》課件
- 人際關(guān)系與溝通技巧-職場(chǎng)中的上行溝通-下屬與上司溝通
- 超聲引導(dǎo)下椎管內(nèi)麻醉
- (完整版)200210號(hào)文-工程勘察設(shè)計(jì)收費(fèi)標(biāo)準(zhǔn)(2002年修訂本)本月修正2023簡版
- 基于核心素養(yǎng)下小學(xué)英語單元整體作業(yè)設(shè)計(jì)實(shí)踐研究 論文
- XX學(xué)校初高貫通銜接培養(yǎng)實(shí)施方案
- 2022版《義務(wù)教育科學(xué)課程標(biāo)準(zhǔn)》試題及答案
- 組織效能概述和提高組織效能的方法
- 私募股權(quán)投資業(yè)務(wù)激勵(lì)管理辦法
- 廣東省深圳市南山區(qū)2022-2023學(xué)年下學(xué)期學(xué)科素養(yǎng)期末學(xué)業(yè)評(píng)價(jià)三年級(jí)科學(xué)試卷(掃描版無答案)
評(píng)論
0/150
提交評(píng)論