最近在公司做一个APP,想要实现拍照或则相册裁剪图片的功能
上网查阅了很多资料,然后对其一一做了测试,可是后来发现在小米手机上的裁剪方面没有起作用,而且还闪退.
后来终于发现了原来是没有添加: intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
这也是网上很多资料没有加这句话的原因把,才可能导致有部分文章没有添加.
后来觉得应该做的比较完善点,想实现微信上类似头像在相册中选择的那种效果,最后功夫不负有心人,然我在github上找到了MultiImageSelector框架可以实现这种微信效果
后来我把三大方法进行了一个封装成一个工具类,很方便的可以进行使用
源码下载
PhotoOrCropUtil.class这里注意的是导入框架MultiImageSelector,也在上面用到MultiImageSelectorActivity,所以要在AndroidManifest.xml引用它import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.widget.Toast; import java.io.File; import java.io.IOException; import java.util.ArrayList; import me.nereo.multi_image_selector.MultiImageSelectorActivity; /** * Created by shaolin on 6/17/16. */ public class PhotoOrCropUtil { private static final String TAG = "PhotoOrCropUtil"; private static final int PHOTO_REQUEST_GALLERY = 1; private static final int PHOTO_REQUEST_CAREMA = 2; private static final int PHOTO_REQUEST_CUT = 3; private static final String PHOTO_FILE_NAME = "image"; private File tempFile = new File(Environment.getExternalStorageDirectory(), PHOTO_FILE_NAME); private Uri imageUri = null; // 存放图片路径的list private ArrayList<String> mSelectPath; private static PhotoOrCropUtil mInstance; private Context mContext; private PhotoOrCropListener mListener; public static synchronized PhotoOrCropUtil getInstance() { if (mInstance == null) { mInstance = new PhotoOrCropUtil(); } return mInstance; } public void setContext(Context context) { mContext = context; } /* * 从相册获取 */ public void gallery() { Intent intent = new Intent(mContext, MultiImageSelectorActivity.class); // 是否显示拍摄图片 intent.putExtra(MultiImageSelectorActivity.EXTRA_SHOW_CAMERA, true); // 最大可选择图片数量 intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_COUNT, 9); // 选择模式 intent.putExtra(MultiImageSelectorActivity.EXTRA_SELECT_MODE, MultiImageSelectorActivity.MODE_SINGLE); // 默认选择 if (mSelectPath != null && mSelectPath.size() > 0) { intent.putExtra(MultiImageSelectorActivity.EXTRA_DEFAULT_SELECTED_LIST, mSelectPath); } ((Activity) mContext).startActivityForResult(intent, PHOTO_REQUEST_GALLERY); } /* * 从相机获取 */ public void camera() { // 激活相机 Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); // 判断存储卡是否可以用,可用进行存储 if (hasSdcard()) { // 从文件中创建uri Uri uri = Uri.fromFile(tempFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA ((Activity) mContext).startActivityForResult(intent, PHOTO_REQUEST_CAREMA); } /* * 剪切图片 */ private void crop(Uri uri) { Log.e(TAG, "tempFile:" + tempFile.toString()); Log.e(TAG, "uri:" + uri.toString()); Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); //发送裁剪信号 intent.putExtra("crop", "true"); // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // outputX outputY 是裁剪图片宽高 intent.putExtra("outputX", 100); intent.putExtra("outputY", 100); intent.putExtra("scale", true); intent.putExtra("return-data", false); // 将图片裁剪存储在一个路径下,后面在删除掉 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile)); imageUri = Uri.fromFile(tempFile); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); // no face detection // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CUT ((Activity) mContext).startActivityForResult(intent, PHOTO_REQUEST_CUT); } public static boolean hasSdcard() { return Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState()); } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PHOTO_REQUEST_GALLERY) { // 从相册返回的数据 if (data != null) { // 得到图片的全路径 mSelectPath = data.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT); StringBuilder sb = new StringBuilder(); for (String p : mSelectPath) { sb.append(p); } crop(Uri.parse("file://" + sb.toString())); } } else if (requestCode == PHOTO_REQUEST_CAREMA) { // 从相机返回的数据 if (hasSdcard()) { crop(Uri.fromFile(tempFile)); } else { showToast("未找到存储卡,无法存储照片!"); } } else if (requestCode == PHOTO_REQUEST_CUT) { // 从剪切图片返回的数据 if (resultCode == ((Activity) mContext).RESULT_OK) { if (imageUri != null) { try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), imageUri); mListener.uploadAvatar(bitmap); imageUri = null; } catch (IOException e) { e.printStackTrace(); } } } else { imageUri = null; } try { // 将临时文件删除 tempFile.delete(); } catch (Exception e) { e.printStackTrace(); } } } public void setPhotoOrCropListener(PhotoOrCropListener listener) { mListener = listener; } public interface PhotoOrCropListener { void uploadAvatar(Bitmap bitmap); } private void showToast(String message) { Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show(); } }
最后附上MainActivity例子<activity android:configChanges="orientation|screenSize" android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity" />
activity_main.xmlimport android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity implements View.OnClickListener { private Button mBtn1; private Button mBtn2; private ImageView mImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtn1 = (Button) findViewById(R.id.button1); mBtn2 = (Button) findViewById(R.id.button2); mImage = (ImageView) findViewById(R.id.img); mBtn1.setOnClickListener(this); mBtn2.setOnClickListener(this); PhotoOrCropUtil.getInstance().setContext(this); PhotoOrCropUtil.getInstance().setPhotoOrCropListener(new PhotoOrCropUtil.PhotoOrCropListener() { @Override public void uploadAvatar(Bitmap bitmap) { mImage.setImageBitmap(bitmap); } }); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.button1: PhotoOrCropUtil.getInstance().camera(); break; case R.id.button2: PhotoOrCropUtil.getInstance().gallery(); break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { PhotoOrCropUtil.getInstance().onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data); } }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="拍照" /> <Button android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="相册" /> <ImageView android:id="@+id/img" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sourceforge.photo"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:configChanges="orientation|screenSize" android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity" /> </application> </manifest>