★ 参考代码
package com.zlf.jarzip;
import java.io.ByteArrayOutputStream;
import java.io.File;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
/**
* 获取图片
*
*/
public class SelectPhotoActivity extends Activity {
public static final int REQUEST_CODE_PHOTOGRAPH = 1; // 系统拍照
public static final int REQUEST_CODE_ALBUM = 2; // 本地相册
public static final int REQUEST_CODE_CUT = 3; // 缩放裁剪
public static final String IMAGE_UNSPECIFIED = "image/*";
private ImageView imageView = null;
private Button button0 = null;
private Button button1 = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 选择相册:返回Uri对象
((Button)(findViewById(R.id.graph_btn))).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_UNSPECIFIED);
startActivityForResult(intent, REQUEST_CODE_ALBUM);
}
});
// 选择拍照:获取Uri对象 或者 Bitmap对象
((Button)(findViewById(R.id.album_btn))).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
/*
* 1.如果为Intent添加以下Extra,则拍照完成后,系统自动保存图片文件到指定文件夹下的文件中,intent中包含Uri数据,
* 此时onActivityResult方法中返回的intent data为null:data.getData() == null;
*
* 2.如果不添加,则intent中返回的是Bitmap对象(注意:返回的 Bitmap 对象是缩略图尺寸!)
* Bitmap bmp = data.getParcelableExtra("data");
*
*/
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(
Environment.getExternalStorageDirectory(), "ketwangwai_temp.jpg")));
startActivityForResult(intent, REQUEST_CODE_PHOTOGRAPH);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//必须针对resultCode进行判断,防止在调用系统程序时非正常返回导致的错误
if (resultCode == RESULT_OK){
return;
}
switch (requestCode) {
//系统拍照
case REQUEST_CODE_PHOTOGRAPH:
File picture = new File(Environment.getExternalStorageDirectory()
+ "/ketwangwai_temp.jpg");
startPhotoZoom(Uri.fromFile(picture));
break;
//本地相册
case REQUEST_CODE_ALBUM:
Uri uri = data.getData();
if (uri != null) {
startPhotoZoom(data.getData());
}
break;
//缩放裁剪
case REQUEST_CODE_CUT:
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap photo = extras.getParcelable("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 75, stream);
imageView.setImageBitmap(photo);
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* 调用系统裁剪图片的方法,可以选择参数为Uri对象 或者 Bitmap对象
*
* @param uri
*/
public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, IMAGE_UNSPECIFIED);
// 发送裁剪信号
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪输出图片宽高
intent.putExtra("outputX", 64);
intent.putExtra("outputY", 64);
// intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);//直接输出文件
// intent.putExtra("noFaceDetection", true); //关闭人脸检测
intent.putExtra("return-data", true); // 是否返回数据
startActivityForResult(intent, REQUEST_CODE_CUT);
}
}
★ 注意问题
1.outputX与outputY如果设置参数太大,会出现卡屏问题,可能是参数大,处理图片比较慢造成的,也许应该使用辅助线程吧...
2.使用魅族手机,调用系统裁剪完成后,在onActivityResult中获取不到data数据,其他机器不存在这样的问题,解决办法如下:
mPhoto = extras.getParcelable("data"); if (mPhoto == null) { String filePath = extras.getString("filePath"); if (!StringUtils.isEmpty(filePath)) mPhoto = ImageUtils.decodeSampledBitmapFromFile(filePath, 400, 600); }
出现上述问题,主要存在于部分手机硬件设置,如跳转值拍照界面时,发生横竖屏切换,导致的Activity生命周期的变化(onDestroy --> onCreate),参考如下:
AndroidManifest.xml中的Activity标签中android:configChanges属性:
通过设置这个属性可以使Activity捕捉设备状态变化,以下是可以被识别的内容:
设置方法:将下列字段用“|”符号分隔开,例如:“locale|navigation|orientation
”
Value Description “mcc“ The IMSI mobile country code (MCC) has changed — that is, a SIM hasbeen detected and updated the MCC.移动国家号码,由三位数字组成,每个国家都有自己独立的MCC,可以识别手机用户所属国家。 “mnc“ The IMSI mobile network code (MNC) has changed — that is, a SIM hasbeen detected and updated the MNC.移动网号,在一个国家或者地区中,用于区分手机用户的服务商。 “locale“ The locale has changed — for example, the user has selected a new language that text should be displayed in.用户所在地区发生变化。 “touchscreen“ The touchscreen has changed. (This should never normally happen.) “keyboard“ The keyboard type has changed — for example, the user has plugged in an external keyboard.键盘模式发生变化,例如:用户接入外部键盘输入。 “keyboardHidden“ The keyboard accessibility has changed — for example, the user has slid the keyboard out to expose it.用户打开手机硬件键盘 “navigation“ The navigation type has changed. (This should never normally happen.) “orientation“ The screen orientation has changed — that is, the user has rotated the device.设备旋转,横向显示和竖向显示模式切换。 “fontScale“ The font scaling factor has changed — that is, the user has selected a new global font size.全局字体大小缩放发生改变 在Activity中添加了 android:configChanges属性,目的是当所指定属性(Configuration Changes)发生改变时,通知程序调用 onConfigurationChanged()函数。
横竖屏切换时候activity的生命周期 android:configChanges
01、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
02、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
03、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
3. ImageView setImageURI图片不变化的问题
问题描述:多次拍照或裁剪图片保存本地的时候,如果使用相同的文件名,即URI对应的文件路径相同的情况下,调用setImageURI方法无法更新显示的图片,ImageView始终显示初始的第一张图片。
问题分析:setImageURI方法对uri进行了缓存,导致即使图片内容发生改变,但uri没有变化,所以ImageView显示的还是之前的图片内容,这一点从源码中可以看出:
解决方案:public void setImageURI(Uri uri) { if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) { updateDrawable(null); mResource = 0; mUri = uri; final int oldWidth = mDrawableWidth; final int oldHeight = mDrawableHeight; resolveUri(); if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) { requestLayout(); } invalidate(); } }
01. 使用不同的文件名(即不同的uri),可以利用时间戳等方式实现;
02. 使用setImageBitmap方法替换setImageURI方法显示图片内容。
★ 相关拓展:
/** * 依据Uri获取文件地址 * @param uri * return */ private String getFilePathFromUri(Uri uri) { String[] filePathColumn = { MediaStore.Images.Media.DATA }; Cursor cursor = getContentResolver().query(uri, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); cursor.close(); return picturePath; } /** * 使用Base64对文件编码,并返回字符串 * @param filePath * @return */ public static String fileToBase64String(String filePath) { File photoFile = new File(filePath); try { FileInputStream fis = new FileInputStream(photoFile); ByteArrayOutputStream baos = new ByteArrayOutputStream(10000); byte[] buffer = new byte[1000]; while (fis.read(buffer)!=-1) { baos.write(buffer); } baos.close(); fis.close(); return Base64.encode(baos.toByteArray(), Base64.DEFAULT).toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * zip压缩 * @param filePath * @return 返回zip文件地址 */ public String zipCompass(String filePath){ File zipFile = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".zip"); try{ //指定了两个待压缩的文件,都在assets目录中 String[] filenames = new String[]{ "activity_main.xml", "strings.xml" }; FileOutputStream fos = new FileOutputStream(zipFile); ZipOutputStream zos = new ZipOutputStream(fos); int i = 1; //枚举filenames中的所有待压缩文件 while (i <= filenames.length){ //从filenames数组中取出当前待压缩的文件名,作为压缩后的名称,以保证压缩前后文件名一致 ZipEntry zipEntry = new ZipEntry(filenames[i - 1]); //打开当前的zipEntry对象 zos.putNextEntry(zipEntry); FileInputStream is = new FileInputStream(filePath); byte[] buffer = new byte[8192]; int count = 0; //写入数据 while ((count = is.read(buffer)) >= 0){ zos.write(buffer, 0, count); } zos.flush(); zos.closeEntry(); is.close(); i++; } zos.finish(); zos.close(); return zipFile.getAbsolutePath(); } catch (Exception e){ Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); return null; } }
Android Zip压缩和解压缩参考博文: http://blog.csdn.net/zlfxy/article/details/8625297
参考博客:http://blog.csdn.net/leechee_1986/article/details/25049243
参考官网:https://developer.android.com/training/camera/photobasics.html