Android 用MultiImageSelector實現上傳頭像的拍照跟相簿
最近在公司做一個APP,想要實現拍照或則相簿裁剪圖片的功能
上網查閱了很多資料,然後對其一一做了測試,可是後來發現在小米手機上的裁剪方面沒有起作用,而且還閃退.
後來終於發現了原來是沒有新增: intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
這也是網上很多資料沒有加這句話的原因把,才可能導致有部分文章沒有新增.
後來覺得應該做的比較完善點,想實現微信上類似頭像在相簿中選擇的那種效果,最後功夫不負有心人,然我在github上找到了MultiImageSelector框架可以實現這種微信效果
後來我把三大方法進行了一個封裝成一個工具類,很方便的可以進行使用
原始碼下載
PhotoOrCropUtil.class
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();
}
}
這裡注意的是匯入框架MultiImageSelector,也在上面用到MultiImageSelectorActivity,所以要在AndroidManifest.xml引用它<activity
android:configChanges="orientation|screenSize"
android:name="me.nereo.multi_image_selector.MultiImageSelectorActivity" />
最後附上MainActivity例子import 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);
}
}
activity_main.xml<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>
相關文章
- Android 圓形頭像 相簿和拍照裁剪選取Android
- Android本地圖片上傳(拍照+相簿)Android地圖
- 【Android】【opencv】實現攝像頭拍照和錄影AndroidOpenCV
- Android提供的攝像頭拍照Android
- Android呼叫攝像頭拍照Android
- 手機拍照,調取相簿 裁剪,上傳
- web呼叫攝像頭拍照並上傳到伺服器Web伺服器
- 照片系列之android呼叫攝像頭拍照Android
- Android中呼叫攝像頭拍照儲存,並在相簿中選擇圖片顯示Android
- android實現拍照、相簿選圖、裁剪功能,相容7.0以及小米Android
- Android呼叫攝像頭拍照並顯示照片Android
- 純JavaScript實現的呼叫裝置攝像頭並拍照的功能JavaScript
- html5中呼叫攝像頭拍照並上傳(附繞過https的想法)HTMLHTTP
- Vue+axios+Node+express實現檔案上傳(使用者頭像上傳)VueiOSExpress
- 在Android中呼叫攝像頭拍照並顯示出來Android
- 安卓呼叫攝像頭拍照安卓
- 如何在 Laravel 專案中輕鬆實現上傳頭像功能?Laravel
- Android自定義拍照實現Android
- UVC攝像頭按鍵拍照功能
- android studio呼叫攝像頭拍照及具體步驟演示程式碼Android
- laravel圖片/頭像上傳通用方法Laravel
- Android 呼叫系統相機拍照 . 選取本地相簿Android
- 直播原始碼開發,實現相簿的上傳和縮放裁剪原始碼
- Android Studio 呼叫Camera實現拍照功能Android
- 如何給Dockerhub使用者上傳頭像Docker
- 如何在SAP UI5應用裡新增使用攝像頭拍照的功能UI
- 短視訊程式開發,Android:呼叫系統拍照和相簿Android
- 瀏覽器呼叫攝像頭進行拍照程式瀏覽器
- 如何給Docker hub使用者上傳頭像Docker
- iPhone XS/iPhone XS Max攝像頭拍照解析:蘋果也玩起了AI拍照iPhone蘋果AI
- [譯]Android的多攝像頭支援Android
- [譯] Android 的多攝像頭支援Android
- android 開啟攝像頭Android
- android opencv 前置攝像頭AndroidOpenCV
- Android 拍照及相簿選取圖片功能,已適配Android6.0、7.0、8.0Android
- Maui Blazor 使用攝像頭實現UIBlazor
- 直播平臺軟體開發,Android 10 拍照和相簿選擇Android
- C#上傳頭像剪裁,並生成多種尺寸C#
- UVC 攝像頭在 RK3399 上的應用