⼀份很易懂的Android⼿机拍照代码
轻松的拍照
hasSystemFeature(PackageManager.FEATURE_CAMERA).
⽤⼀个相机APP来照相
上⾯那段代码,标注的那个位置,开发的时候看不懂,于是去翻了官⽅的⽂档。
给所有有照相功能的APP发去⼀个照相并返回数据的Intent.安卓程序开发用什么软件
调⽤者可以传⼊⼀个EXTRA_OUTPUT的extra,⽤来控制图⽚存储位置。如果这个EXTRA_OUTPUT不存在的话,⼩尺⼨的图⽚将会以Bitmap对象,放到extra⾥返回。这对于那种只需要⼩图⽚的应⽤来说很爽。如果EXTRA_OUTPUT存在的话,全尺⼨图⽚将会存在EXTRA_OUT的URI值所写的位置。(官⽅⽂档后⾯还有两句话是关于版本不同的,我就不翻译了)
这个教程可以教你如何⽤⼀个已经安装的相机APP来拍照
⾸先来请求⼀个相机权限
如果拍照这个功能在你的应⽤⾥是很核⼼的功能,那么你可以在商店⾥要求⽤户的设备必须要有摄像头才能下载安装,你只需要在你的Manifest⽂件⾥加⼊下⾯⼏⾏代码就可以了:
<manifest ... >
<uses-feature android:name="android.hardware.camera"
android:required="true"/>
...
</manifest>
同时你可以⽤代码来检测设备是不是具有摄像头:
;
Android请求使⽤其他APP⼀般是⽤Intent对象,并在这个对象⾥描述你的要求。
下⾯这段程序进⾏了三个⼯作:实例化了⼀个Intent,激活了外部的⼀个Activity,并且写了⼀些代码,⽤于当焦点返回这个Activity时,处理图⽚数据。
这是⼀段拍照的function:
static final int REQUEST_IMAGE_CAPTURE =1;
private void dispatchTakePictureIntent(){
Intent takePictureIntent =new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
solveActivity(getPackageManager())!=null){
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
注意这个startActivityForResult()⽅法,这个⽅法如果你调⽤了⼀个Intent但是没有APP能够响应(⽐如你的⼿机⾥没有可以照相的软件)那么程序就会崩溃,为了安全起见,可以⽤这个resolvActivity()保护它,代码就可以像上⾯那样写,具体的东西就不深⼊挖掘了,毕竟是为了更快的写出照相功能。
得到缩略图
如果这种简单的功能⽆法满⾜你应⽤的需求——你可能需要把拍到的照⽚先处理⼀下。
安卓照相应⽤把图⽚编码以后转成Bitmap对象放到extras⾥,然后提交到onActivityResult(),在Intent的data键下。
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK){
Bundle extras = Extras();
Bitmap imageBitmap =(Bitmap) ("data");
mImageView.setImageBitmap(imageBitmap);
}
}
注意:这个从data返回的缩略图可能适合当⼀个图标,但是它除了当图标也不能当别的了。因为太⼩了。。如果想处理⼤图的话,我们需要⼀些其他的⼯作。搞定⼤图!
如果你指定⼀个⽂件,安卓照相应⽤可以把⼀张全尺⼨的⼤图保存到这个⽂件⾥。如果想这样做的话你必须提供⼀个准确的⽂件名和路径。通常来说,我们拍的照⽚都会存到安卓的公共存储区,这个区在外部储存器⾥,⽐如SD卡,这样可以⽅便很多APP调⽤这个照⽚。
你可以⽤ , ⽅法的属性来获取这个存储区的路径。
因为这个公⽤存储⽂件夹肯定有很多APP都会使⽤,所以我们需要增加相应的和权限。
代码在这⾥:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
...
</manifest>
不过如果你不想存储到公共区,想存储到你的⾃⼰的应⽤专属空间,你可以⽤这个⽅法: .
在安卓4.3以及以下的版本中,往这个⽂件夹中输出⽂件还是需要声明权限的,但是4.4以后的版本就不⽤了,因为这个⽂件夹是不允许其他APP使⽤的,所以你可以在声明你的权限时加上⼀个,  :
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"/>
...
</manifest>
注意:当你使⽤ .的时候,⾥⾯存储的照⽚会随着你卸载应⽤⽽被删除。
好,如果你决定好了你要把照⽚存在什么位置,那么接下来你要给你的⽂件选择⼀个靠谱的⽂件名,不要和其他的⽂件名产⽣冲突。你可能需要把这个⽂件名存到⼀个地⽅⽅便以后使⽤,这⾥给你提供⼀个靠谱的解决⽅法,⽤date-time stamp给你产⽣⼀个独⼀⽆⼆的⽂件名。
String mCurrentPhotoPath;
private File createImageFile()throws IOException{
// Create an image file name
String timeStamp =new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName ="JPEG_"+ timeStamp +"_";
File storageDir =ExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image =ateTempFile(
imageFileName,/* prefix */
".jpg",/* suffix */
storageDir      /* directory */
)
;
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath ="file:"+ AbsolutePath();
return image;
}
⽤这个⽅法可以为你创建⼀个图⽚⽂件,现在你可以创建或者调⽤⼀个Intent了,就像这样:
static final int REQUEST_TAKE_PHOTO =1;
private void dispatchTakePictureIntent(){
Intent takePictureIntent =new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
solveActivity(getPackageManager())!=null){
/
/ Create the File where the photo should go
File photoFile =null;
try{
photoFile = createImageFile();
}catch(IOException ex){
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if(photoFile !=null){
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
这⾥补充⼀句:MediaStore.EXTRA_OUTPUT这个字段在官⽹的说明是:
The name of the Intent-extra used to indicate a content resolver Uri to be used to store the requested image or video.
Constant Value: "output"
把照⽚加⼊相册
你照好照⽚以后,你肯定需要知道你的照⽚在哪,最简单的⽅法就是你可以在相册⾥看到它。
注意:如果你⽤的是 . ⽅法获得路径,那么你的相册是⽆法看到你拍摄的照⽚的。
下⾯的例⼦给你展⽰⼀下系统媒体搜索是怎么把你的照⽚加⼊媒体数据库并且让其他应⽤都可以使⽤它的。
private void galleryAddPic(){
Intent mediaScanIntent =new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f =new File(mCurrentPhotoPath);
Uri contentUri =Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
处理⽂件缩放
如果你内存不够,那么管理很多⼤图的话肯定让你崩溃。如果你发现你的APP展⽰了⼏张图⽚就开始跑不动了,那是因为你⽤掉太多内存了,你可以帅⽓的减少动态堆,把JPEG⽂件放到⼀个内存组⾥,然
后处理⼤⼩,让它们的⼤⼩适合在你想要展⽰的地⽅展⽰。下⾯就是个例⼦:
private void setPic(){
// Get the dimensions of the View
int targetW = Width();
int targetH = Height();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions =new BitmapFactory.Options();
bmOptions.inJustDecodeBounds =true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
/
/ Determine how much to scale down the image
int scaleFactor =Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds =false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable =true;
Bitmap bitmap =BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);    mImageView.setImageBitmap(bitmap);
}