声明权限
首先应该在“AndroidManifest”文件中声明手机内存读写权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
由于从Android 6.0开始,一些敏感权限需要在对应的Activity再次进行动态申请,因此,需要在我们编写的Activity里再次申请权限:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
Log.d("进入:", "requestPermissions");
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
Log.d("进入:", "requestPermissions");
}
拍照按钮触发事件`
1.拍照按钮的点击事件如下:
mBtnUpload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//点击事件:进行拍照
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile=createImgFile();
photoUri= Uri.fromFile(photoFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent,1);
}
});
2.上述“createImgFile()”函数的功能是自定义图片名,获取照片的file,具体代码如下:
/**
* 自定义图片名,获取照片的file
*/
private File createImgFile(){
//确定文件名
String fileName="img_"+new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())+".jpg";
File dir;
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
dir=Environment.getExternalStorageDirectory();
}else{
dir=getExternalFilesDir(Environment.DIRECTORY_PICTURES);
}
File tempFile=new File(dir,fileName);
try{
if(tempFile.exists()){
tempFile.delete();
}
tempFile.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
//获取文件路径
photoPath = tempFile.getAbsolutePath();
return tempFile;
}
3.由于上述代码采用了“startActivityForResult()”方法,因此在拍照完成后会调用“onActivityResult()”函数。我们重写该函数(以实现照片存储、添加到相册中的功能):
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK){
switch (requestCode){
case 1:
setImageBitmap();
galleryAddPic();
break;
case 2:
//data中自带有返回的uri
photoUri=data.getData();
//获取照片路径
String[] filePathColumn={MediaStore.Audio.Media.DATA};
Cursor cursor=getContentResolver().query(photoUri,filePathColumn,null,null,null);
cursor.moveToFirst();
photoPath=cursor.getString(cursor.getColumnIndex(filePathColumn[0]));
cursor.close();
//有了照片路径,之后就是压缩图片,和之前没有什么区别
setImageBitmap();
break;
}
}
}
注:此处的“case 2”语句块用于从手机本地相册选取照片,由于代码类似,不再进行演示。
4.“setImageBitmap()”函数的功能是压缩我们刚刚拍到的图片,并将该图片展示在我们声明的“ImageView”控件中。具体代码如下:
/**
* 压缩图片
*/
private void setImageBitmap(){
Log.d("Record", "进入压缩图片");
//获取imageview的宽和高
int targetWidth=photoImageView.getWidth();
int targetHeight=photoImageView.getHeight();
//根据图片路径,获取bitmap的宽和高
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeFile(photoPath,options);
int photoWidth=options.outWidth;
int photoHeight=options.outHeight;
Log.d("Record", "获取长和高:"+ photoHeight + "Width:" + photoWidth);
//获取缩放比例
int inSampleSize=1;
if(photoWidth>targetWidth||photoHeight>targetHeight){
int widthRatio=Math.round((float)photoWidth/targetWidth);
int heightRatio=Math.round((float)photoHeight/targetHeight);
inSampleSize=Math.min(widthRatio,heightRatio);
Log.d("Record", "进入缩放比例");
}
//使用现在的options获取Bitmap
options.inSampleSize=inSampleSize;
options.inJustDecodeBounds=false;
Bitmap bitmap=BitmapFactory.decodeFile(photoPath,options);
photoImageView.setImageBitmap(bitmap);
//调用转换函数,将ImageView文件转换为String类型数据,以便传输到云端
String bitmapToString = putImageToShare(getApplicationContext(), photoImageView);
mTvChange.setText(bitmapToString);
//调用上传函数,将String类型数据传送到服务器
UploadImage(getApplicationContext(), bitmapToString);
Log.d("Record", "ToString:" + bitmapToString);
Log.d("Record", "获取Bitmap");
}
其中的“putImageToShare()”、“UploadImage()”方法作用分别是图片转换成String类型的数据、将该数据上传至服务器。如果不需要实现照片上传至服务器的功能,可以删除这两行代码。如果需要实现上传功能,可以看这篇文章:
Android平台实现图片传输到服务器并在服务器文件夹中重现(客户端程序+服务器端程序)
5.“galleryAddPic()”函数的功能是将我们刚刚拍到的照片添加到手机相册中,具体代码如下:
//将图片添加进手机相册
private void galleryAddPic(){
Intent mediaScanIntent=new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(photoUri);
this.sendBroadcast(mediaScanIntent);
}
后记
记录一些编程过程中踩到的坑:
1.在Android 10中,读写手机内存权限还需要进行额外的操作:
在“AndroidManifest”文件中添加语句:
android:requestLegacyExternalStorage="true"
否则ImageView控件无法显示我们的图片。
2.在Android 10中,执行上述代码时,调用相机会闪退。解决方法如下:
在对应Activity中添加语句:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy( builder.build() );
}
参考文章:
https://blog.csdn.net/happy_fsyy/article/details/51986444
——————————————————————————
最后贴一下我的个人公众号:微信搜索“茶迁”或扫描下图。平时会更新一些编程相关的文章,欢迎大家关注~