大家好,又见面了,我是你们的朋友全栈君。
这是属于我的第一篇博文,首先说明一下,文章属性为原创,其实不能说是原创,我是在学习的过程中根据自己的理解整理的。文章内容大多为书本上的内容,书本是郭霖的《第一行代码》。
正文:现在很多应用程序会调用摄像头的拍照功能,比如哪个程序要上传一张图片作为用户头像,这是启用摄像头拍照会很方便。当然,还有第二种方法,就是在本地图库选取已经被保存的图片。现在,我就根据自己学习的过程,将这部分只是进行整理,如下:
public class MainActivity extends AppCompatActivity {
private Button button;
private ImageView imageView;
private Uri imageuri;
private Button choose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
button = (Button) findViewById(R.id.button);
imageView = (ImageView) findViewById(R.id.imageView);
choose = (Button) findViewById(R.id.button2);
//此按钮事件是拍照,启动摄像机的功能
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建一个File对象,用于存储接下来照相机拍摄的照片
File file = new File(Environment.getExternalStorageDirectory(), "output_image.jpg");
if (file.exists()) {
file.delete();
}
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
imageuri = Uri.fromFile(file);
//下面这个intent对象就是用于启动照相机的
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri);//指定图片的输出地址
startActivityForResult(intent, 1);//启动照相机,这里传入的参数1,其实只要是固定一个值都行,
//比较好的做法是声明一个全局常量比较好,我在这里没有这么做。
}
});
//此按钮事件是选取本地图片,启动相册
choose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("android.intent.action.GET_CONTENT");//这个intent对象是用于开启本地图库的
intent.setType("image/*");//给intent对象设置必要的参数
startActivityForResult(intent, 3);//开启本地图库
}
});
}
@Override
//因为我们用startActivityForResult方法启动活动,所有它们处理完结果后,会回调上一个活动的onActivityResult方法,这里我们就在MainActivity重写此方法
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1://就是照相机拍好了照片来回调的这个方法的case 1,这个时候我们想要启动照片的裁剪程序
if (resultCode == RESULT_OK) {
Intent intent = new Intent("com.android.camera.action.CROP");//这个intent对象启动裁剪程序
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri);//设置图片的输出地址
intent.setDataAndType(imageuri, "image/*");//设置图片的返回格式
startActivityForResult(intent, 2);
}
break;
case 2://裁剪好了的图片回调此方法的case 2,这个时候我们就要将裁剪好的图片设置到imageview里
if (resultCode == RESULT_OK) {
try {
//BitmapFactory的decodeStream()方法将照片解析成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageuri));
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
case 3://本地图库选取图片后,回调此方法的case 3,在这里我们主要做的就是图片的处理工作
if (resultCode == RESULT_OK) {
//判断系统版本号,如果API>19,即Android 4.4版本以上用这个方法处理图片
if (Build.VERSION.SDK_INT >= 19) {
handleImageOnKitKat(data);
}
else {
//android4.4以下,用这个方法处理图片
handleImageBeforeKitKat(data);
}
}
break;
default:
break;
}
}
@TargetApi(19)
private void handleImageOnKitKat(Intent data) {
//其实这个方法的目标很简单,就是要获取图片的真实路径imagepath,然后我们会再提供一个方法将imagepath作为参数来显示图片
String imagepath = null;
//android4.4以上的版本,我们获取的图片uri不是真实的图片uri,是封装过的,不能直接用来显示图片,我们要进行解析
Uri uri = data.getData();//通过传入intent参数来获取信息,图片的内容uri
//接下来的内容看似复杂,其实很简单,我们进行了很多判断,首先判断这个uri是否为document类型,
//如果是document类型的话,就取出document id处理,如果不是,就普通方式处理
//另外,我们又对uri的权限部分进行判断,如果是media格式,则document id还要再次进行解析
if (DocumentsContract.isDocumentUri(this, uri))//判断如果是document类型,则通过document id处理
{
String docId = DocumentsContract.getDocumentId(uri);//通过uri获取document id。
//判断我们的uri的权限部分,media格式,对document id用":"分割,取出真正的数字id
if ("com.android.provider.media.documents".equals(uri.getAuthority())) {
//split方法返回的结果是一个数组,我们选取第二个,即角标为1,这样我们就解析出数字格式的id
String id = docId.split(":")[1];
String selection = MediaStore.Images.Media._ID + "=" + id;//用id构建新的条件语句,并且在后面query()方法
//进行数据库查询是作为参数,主要是约束我们的查询条件
//getImagepath()方法是我们自己提供的用来获取图片真实路径
imagepath = getImagepath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
} else if ("com.android.provider.downloads.documents".equals(uri.getAuthority())) {
Uri contentUri = ContentUris.withAppendedId(
Uri.parse("conten://downloads/public_downloads"), Long.valueOf(docId));
imagepath = getImagepath(contentUri, null);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
//如果不是document类型的uri,则使用普通方法处理
imagepath = getImagepath(uri, null);
}
displayImage(imagepath);//最后,我们根据路径显示图片
}
private void handleImageBeforeKitKat(Intent data)
{
Uri uri=data.getData();
String imagepath=getImagepath(uri,null);
displayImage(imagepath);
}
//获取图片路径的方法
private String getImagepath(Uri uri, String selection) {
String path = null;
//通过uri和selection获取真实的图片路径
//其实selection就是一个约束条件,让我们指定查询哪一行,就好比name=lee,age=18这样
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToNext()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
//显示图片的方法
private void displayImage(String imagepath)
{
if (imagepath!=null)
{
//BitmapFactory的decodeFile解析路径,使图片为Bitmap对象
Bitmap bitmap=BitmapFactory.decodeFile(imagepath);
imageView.setImageBitmap(bitmap);
}else {
Toast.makeText(this,"图片获取失败",Toast.LENGTH_SHORT).show();
}
}
其实,很多照片即使裁剪了以后体积还是很大,直接加载到内存,很容易使程序崩溃。更好的做法是根据项目需求对照片进行适当的压缩,然后加载到内存。这个时候就要考验我们的阅读文档能力啦,学无止境啊。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/162735.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...