Android獲取照片、裁剪圖片、壓縮圖片
前言
在做上一個(gè)項(xiàng)目時(shí)深深受到了圖片上傳的苦惱。圖片上傳主要分為兩個(gè)部分,首先要獲取圖片,而獲取圖片可以分為從文件獲取或者拍照獲取。第二個(gè)部分才是上傳圖片,兩個(gè)部分都是走了不少?gòu)澛贰S捎贏ndroid系統(tǒng)的碎片化比較嚴(yán)重,我們可能出現(xiàn)在第一臺(tái)機(jī)子上能獲取圖片,但是換一個(gè)機(jī)子就不能獲取圖片的問(wèn)題,并且在Android6.0,7.0之后也要做一定的適配。由于也是初學(xué)者,很多東西沒(méi)有考慮到,適配起來(lái)也是有點(diǎn)難度的。
這幾天也是從github上找到了一個(gè)庫(kù)(地址在這TakePhoto),經(jīng)過(guò)簡(jiǎn)單的學(xué)習(xí)之后,發(fā)現(xiàn)用起來(lái)還是蠻簡(jiǎn)單的,并且在不同機(jī)型之間都能達(dá)到同樣的效果。更重要的是可以根據(jù)不同配置達(dá)到不同的效果
接下來(lái)看下用法
獲取圖片
1) 獲取TakePhoto對(duì)象
一) 通過(guò)繼承的方式
繼承TakePhotoActivity、TakePhotoFragmentActivity、TakePhotoFragment三者之一。
通過(guò)getTakePhoto()獲取TakePhoto實(shí)例進(jìn)行相關(guān)操作。
重寫(xiě)以下方法獲取結(jié)果
void takeSuccess(TResult result); void takeFail(TResult result,String msg); void takeCancel();
這種方法使用起來(lái)雖然簡(jiǎn)單,但是感覺(jué)定制性不高,必須繼承指定的Activity,而 有時(shí)我們已經(jīng)封裝好了BaseActivity,不想再改了。有時(shí)候通過(guò)繼承無(wú)法滿(mǎn)足實(shí)際項(xiàng)目的需求。
二) 通過(guò)組裝的方式去使用
實(shí)現(xiàn)TakePhoto.TakeResultListener,InvokeListener接口。
在 onCreate,onActivityResult,onSaveInstanceState方法中調(diào)用TakePhoto對(duì)用的方法。
重寫(xiě)onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults),添加如下代碼。
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//以下代碼為處理Android6.0、7.0動(dòng)態(tài)權(quán)限所需
TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
PermissionManager.handlePermissionsResult(this,type,invokeParam,this);
}
重寫(xiě)TPermissionType invoke(InvokeParam invokeParam)方法,添加如下代碼:
@Override
public TPermissionType invoke(InvokeParam invokeParam) {
TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(this),invokeParam.getMethod());
if(TPermissionType.WAIT.equals(type)){
this.invokeParam=invokeParam;
}
return type;
}
添加如下代碼獲取TakePhoto實(shí)例:
/**
* 獲取TakePhoto實(shí)例
* @return
*/
public TakePhoto getTakePhoto(){
if (takePhoto==null){
takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this,this));
}
return takePhoto;
}
2)自定義UI
不僅可以對(duì)于參數(shù)自定義,也可以對(duì)于UI的自定義,比如自定義相冊(cè),自定義Toolbar, 自定義狀態(tài)欄,自定義提示文字,自定義裁切工具(需要使用自帶的TakePhoto裁剪才行)。
3)通過(guò)TakePhoto對(duì)象獲取圖片
支持從相冊(cè)獲取,也支持拍照,相關(guān)Api
* 從相機(jī)獲取圖片并裁剪 * @param outPutUri 圖片裁剪之后保存的路徑 * @param options 裁剪配置 */ void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options); /** * 從相冊(cè)中獲取圖片并裁剪 * @param outPutUri 圖片裁剪之后保存的路徑 * @param options 裁剪配置 */ void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options); /** * 從文件中獲取圖片并裁剪 * @param outPutUri 圖片裁剪之后保存的路徑 * @param options 裁剪配置 */ void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options); /** * 圖片多選,并裁切 * @param limit 最多選擇圖片張數(shù)的限制 * @param options 裁剪配置 * */ void onPickMultipleWithCrop(int limit, CropOptions options);
4)裁剪配置
CropOptions 用于裁剪的配置類(lèi),可以對(duì)圖片的裁剪比例,最大輸出大小,以及是否使用TakePhoto自帶的裁剪工具進(jìn)行裁剪等,進(jìn)行個(gè)性化配置。
壓縮圖片 onEnableCompress(CompressConfig config,boolean showCompressDialog)
指定壓縮工具 takePhoto里面自帶壓縮算法,也可以通過(guò)第三方的Luban進(jìn)行壓縮
對(duì)于TakePhoto的二次封裝
封裝是對(duì)第二種方法的封裝,主要參考了第一種的思想封裝的。
關(guān)于TakePhoto的庫(kù)代碼全部封裝到一個(gè)TakePhotoUtil工具類(lèi)中,看代碼:
public class TakePhotoUtil implements TakePhoto.TakeResultListener, InvokeListener {
private static final String TAG = TakePhotoUtil.class.getName();
private TakePhoto takePhoto;
private InvokeParam invokeParam;
private Activity activity;
private Fragment fragment;
public TakePhotoUtil(Activity activity){
this.activity = activity;
}
public TakePhotoUtil(Fragment fragment){
this.fragment = fragment;
}
/**
* 獲取TakePhoto實(shí)例
* @return
*/
public TakePhoto getTakePhoto(){
if (takePhoto==null){
takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(activity,this));
}
return takePhoto;
}
public void onCreate(Bundle savedInstanceState){
getTakePhoto().onCreate(savedInstanceState);
}
public void onSaveInstanceState(Bundle outState){
getTakePhoto().onSaveInstanceState(outState);
}
public void onActivityResult(int requestCode, int resultCode, Intent data){
getTakePhoto().onActivityResult(requestCode, resultCode, data);
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
PermissionManager.TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
PermissionManager.handlePermissionsResult(activity,type,invokeParam,this);
}
/**
*
* @param result
*/
@Override
public void takeSuccess(TResult result) {
if(listener != null){
listener.takeSuccess(result);
}
// deleteCachePic();
}
@Override
public void takeFail(TResult result, String msg) {
if(listener != null){
listener.takeFail(result, msg);
}
// deleteCachePic();
}
@Override
public void takeCancel() {
if(listener != null){
listener.takeCancel();
}
}
public void deleteCachePic(){
File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/");
if(!file.exists()) return;
File[] files = file.listFiles();
for (File f: files) {
f.delete();
}
}
public interface TakePhotoListener{
void takeSuccess(TResult result);
void takeFail(TResult result, String msg);
void takeCancel();
}
public TakePhotoListener listener;
public void setTakePhotoListener(SimpleTakePhotoListener listener){
this.listener = listener;
}
public static class SimpleTakePhotoListener implements TakePhotoListener{
@Override
public void takeSuccess(TResult result) {
}
@Override
public void takeFail(TResult result, String msg) {
}
@Override
public void takeCancel() {
}
}
@Override
public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) {
PermissionManager.TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(activity),invokeParam.getMethod());
if(PermissionManager.TPermissionType.WAIT.equals(type)){
this.invokeParam=invokeParam;
}
return type;
}
/**
*
* @param select_type
*/
public void takePhoto(Select_type select_type, SimpleTakePhotoListener listener){
takePhoto(select_type, null, listener);
}
public void takePhoto(Select_type select_type, PhotoConfigOptions cropOptions, SimpleTakePhotoListener listener){
if (takePhoto == null){
Toast.makeText(activity, "請(qǐng)先開(kāi)啟照片功能", Toast.LENGTH_SHORT).show();
return;
}
setTakePhotoListener(listener);
if(cropOptions == null){
cropOptions = new PhotoConfigOptions();
}
cropOptions.configCompress(); //壓縮配置
cropOptions.configTakePhoto(); //拍照配置
File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/"+System.currentTimeMillis() + ".jpg");
if (!file.getParentFile().exists())file.getParentFile().mkdirs();
Uri imageUri = Uri.fromFile(file);
switch (select_type){
case PICK_BY_SELECT: //從相冊(cè)獲取
if(cropOptions.limit > 1){
if(cropOptions.crop == true){
takePhoto.onPickMultipleWithCrop(cropOptions.limit, cropOptions.getCropOptions());
}else {
takePhoto.onPickMultiple(cropOptions.limit);
}
}
if(cropOptions.chooseFromFile){
if(cropOptions.crop == true){
takePhoto.onPickFromDocumentsWithCrop(imageUri, cropOptions.getCropOptions());
}else {
takePhoto.onPickFromDocuments();
}
}else {
if(cropOptions.crop == true){
takePhoto.onPickFromGalleryWithCrop(imageUri, cropOptions.getCropOptions());
}else {
takePhoto.onPickFromGallery();
}
}
break;
case PICK_BY_TAKE: //拍照獲取
if(cropOptions.crop == true){
takePhoto.onPickFromCaptureWithCrop(imageUri, cropOptions.getCropOptions());
}else {
takePhoto.onPickFromCapture(imageUri);
}
break;
default:
break;
}
}
/**
* 圖片的裁剪配置選項(xiàng)內(nèi)部類(lèi)
*/
public class PhotoConfigOptions{
//裁剪配置
private boolean crop = true; //是否裁剪
private boolean withWonCrop = true; //是否采用自帶的裁剪工具,默認(rèn)選取第三方的裁剪工具
private boolean cropSize = true; //尺寸還是比例
//壓縮配置
private boolean useOwnCompressTool = true; //使用自帶的壓縮工具
private boolean isCompress = true; //是否壓縮
private boolean showProgressBar = true; //顯示壓縮進(jìn)度條
// private
private int maxSize = 102400;
//選擇圖片配置
private boolean useOwnGallery = true; //選擇使用自帶的相冊(cè)
private boolean chooseFromFile = false; //從文件獲取圖片
private int limit = 1; //選擇最多圖片的配置,選擇多張圖片會(huì)自動(dòng)切換到TakePhoto自帶相冊(cè)
//其它配置
private boolean savePic = true; //選擇完之后是否保存圖片
private boolean correctTool = false; //糾正拍照的照片旋轉(zhuǎn)角度
private int height = 800;
private int width = 800;
/**
* 裁剪相關(guān)配置
* @return
*/
public CropOptions getCropOptions(){
if(crop == false) return null;
CropOptions.Builder builder = new CropOptions.Builder();
if(cropSize){
builder.setOutputX(width).setOutputY(height);
}else {
builder.setAspectX(width).setAspectY(height);
}
builder.setWithOwnCrop(withWonCrop); //默認(rèn)采用第三方配置
return builder.create();
}
/**
* 圖片壓縮相關(guān)配置
*/
public void configCompress(){
if(isCompress == false) {
takePhoto.onEnableCompress(null, false);
return;
}
CompressConfig config;
if(useOwnCompressTool){
config = new CompressConfig.Builder()
.setMaxSize(maxSize)
.setMaxPixel(width>height?width:height)
.enableReserveRaw(savePic)
.create();
}else {
LubanOptions options = new LubanOptions.Builder()
.setMaxHeight(height)
.setMaxWidth(maxSize)
.create();
config = CompressConfig.ofLuban(options);
config.enableReserveRaw(savePic);
}
takePhoto.onEnableCompress(config, showProgressBar);
}
public void configTakePhoto(){
TakePhotoOptions.Builder builder = new TakePhotoOptions.Builder();
if(useOwnGallery){
builder.setWithOwnGallery(true);
}
if(correctTool){
builder.setCorrectImage(true);
}
takePhoto.setTakePhotoOptions(builder.create());
}
public void setCrop(boolean crop) {
this.crop = crop;
}
public void setWithWonCrop(boolean withWonCrop) {
this.withWonCrop = withWonCrop;
}
public void setCropSize(boolean cropSize) {
this.cropSize = cropSize;
}
public void setUseOwnCompressTool(boolean useOwnCompressTool) {
this.useOwnCompressTool = useOwnCompressTool;
}
public void setCompress(boolean compress) {
isCompress = compress;
}
public void setShowProgressBar(boolean showProgressBar) {
this.showProgressBar = showProgressBar;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
public void setUseOwnGallery(boolean useOwnGallery) {
this.useOwnGallery = useOwnGallery;
}
public void setChooseFromFile(boolean chooseFromFile) {
this.chooseFromFile = chooseFromFile;
}
public void setLimit(int limit) {
this.limit = limit;
}
public void setSavePic(boolean savePic) {
this.savePic = savePic;
}
public void setCorrectTool(boolean correctTool) {
this.correctTool = correctTool;
}
public void setHeight(int height) {
this.height = height;
}
public void setWidth(int width) {
this.width = width;
}
}
/**
* 照片獲取方式, 從相冊(cè)獲取或拍照處理
*/
public enum Select_type{
PICK_BY_SELECT, PICK_BY_TAKE
}
}
封裝了一個(gè)BaseTakePhotoActivity,里面的代碼如下:
protected TakePhotoUtil takePhotoUtil;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
takePhotoUtil = new TakePhotoUtil(this);
if(useTakePhoto()){
takePhotoUtil.onCreate(savedInstanceState);
}
super.onCreate(savedInstanceState);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
if(useTakePhoto()){
takePhotoUtil.onSaveInstanceState(outState);
}
super.onSaveInstanceState(outState);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(useTakePhoto()){
takePhotoUtil.onActivityResult(requestCode, resultCode, data);
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(useTakePhoto()){
takePhotoUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected boolean useTakePhoto(){
return false;
}
其他對(duì)于業(yè)務(wù)的封裝,可以再封裝一個(gè)BaseActivity,繼承自BaseTakePhotoActivity,這樣就可以不影響B(tài)aseActivity的使用,如果我們?cè)谥鰽ctivity中使用獲取圖片的功能需要兩步
1)開(kāi)啟TakePhoto功能
@Override
protected boolean useTakePhoto() {
return true;
}
2 ) 獲取圖片
takePhotoUtil.takePhoto(TakePhotoUtil.Select_type.PICK_BY_TAKE, new TakePhotoUtil.SimpleTakePhotoListener(){
@Override
public void takeSuccess(TResult result) {
String s = result.getImage().getCompressPath();
Bitmap bitmap = BitmapFactory.decodeFile(s);
iv.setImageBitmap(bitmap);
}
});
takePhoto()的第一個(gè)參數(shù)是一個(gè)枚舉類(lèi)型的參數(shù),分別為從相冊(cè)獲取和拍照獲取,第二個(gè)參數(shù)為獲取成功失敗,有三個(gè)回調(diào),由于有些回調(diào)不是必須的,所以對(duì)Listener做了一個(gè)適配,只需要回調(diào)想要的方法即可,獲取成功之后就可以通過(guò)TResult封裝的參數(shù)獲取想要的圖片以及圖片地址。對(duì)于獲取到的圖片地址就可以做一些上傳處理。
圖片上傳
可以借助okhttp3實(shí)現(xiàn)上傳功能
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
RequestBody requestBody = RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("dir", file.getName(), requestBody);
builder.addPart(part);
Request.Builder builder1 = new Request.Builder().url(url).post(builder.build());
Request request = builder1.build();
HttpUtils.client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String s = response.body().string();
((Activity)context).runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
}
});
大致代碼如上
最后
由于當(dāng)時(shí)沒(méi)有找到這個(gè)庫(kù),于是跑去問(wèn)公司另一個(gè)做Android的,看了下他封裝的代碼,確實(shí)也是值得學(xué)習(xí)的,他的代碼也是適配到了Android7.0,貼下它的代碼,方便以后學(xué)習(xí):
public class CameraUtil {
private static final int REQUEST_CAPTURE_CAMERA = 1221;
private static final int REQUEST_CROP = 1222;
private static final int REQUEST_OPEN_ALBUM = 1223;
private static final String TAG = "Camera";
private static Uri mCacheUri;
private CameraUtil() {
}
@RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
public static void getImageFromCamera(Activity activity) {
if (checkExternalStorageState(activity)) {
activity.startActivityForResult(getImageFromCamera(activity.getApplicationContext()), REQUEST_CAPTURE_CAMERA);
}
}
@RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
@Deprecated
public static void getImageFromCamera(Fragment fragment) {
if (checkExternalStorageState(fragment.getContext())) {
fragment.startActivityForResult(getImageFromCamera(fragment.getContext()), REQUEST_CAPTURE_CAMERA);
}
}
private static Intent getImageFromCamera(Context context) {
Intent getImageByCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mCacheUri = getCachePhotoUri(context.getApplicationContext());
getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, mCacheUri);
getImageByCamera.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
grantUriPermission(context, getImageByCamera, mCacheUri);
return getImageByCamera;
}
private static boolean checkExternalStorageState(Context context) {
if (TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)) {
return true;
}
Toast.makeText(context.getApplicationContext(), "請(qǐng)確認(rèn)SD卡", Toast.LENGTH_LONG).show();
return false;
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public static File getCachePhotoFile() {
File file = new File(Environment.getExternalStorageDirectory(), "/lenso/cache/CameraTakePhoto" + System.currentTimeMillis() + ".jpg");
if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
return file;
}
private static Uri getCachePhotoUri(Context context) {
return FileProvider.getUriForFile(context, getAuthority(context), getCachePhotoFile());
}
private static Uri getCachePhotoUri(Context context, File file) {
return FileProvider.getUriForFile(context, getAuthority(context), file);
}
public static void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data, OnActivityResultListener listener) {
onActivityResult(activity, null, requestCode, resultCode, data, listener);
}
/**
* getCachePhotoFile().getParentFile().getAbsolutePath()
* @param dir
* @return
*/
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return dir.delete();
}
public static File saveBitmap(Bitmap bitmap) {
File file = getCachePhotoFile();
if (bitmap == null || bitmap.isRecycled()) return file;
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (outputStream != null)
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
bitmap.recycle();
}
return file;
}
public static void copy(File file, File point) {
if (!file.exists()) return;
if (!point.getParentFile().exists()) point.getParentFile().mkdirs();
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
outputStream = new BufferedOutputStream(new FileOutputStream(point));
byte[] buff = new byte[1024 * 1024 * 2];
int len;
while ((len = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, len);
outputStream.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeStream(inputStream);
closeStream(outputStream);
}
}
private static void closeStream(Closeable closeable) {
if (closeable != null) try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void onActivityResult(Activity activity, CropOption crop, int requestCode, int resultCode, Intent data, OnActivityResultListener listener) {
if (resultCode == Activity.RESULT_CANCELED) return;
Uri uri;
switch (requestCode) {
case REQUEST_OPEN_ALBUM:
uri = data.getData();
if (uri != null) {
mCacheUri = getCachePhotoUri(activity);
copy(new File(getRealFilePath(activity, uri)), new File(getRealFilePath(activity, mCacheUri)));
} else {
Bitmap bitmap = data.getParcelableExtra("data");
File file = saveBitmap(bitmap);
mCacheUri = getCachePhotoUri(activity, file);
}
case REQUEST_CAPTURE_CAMERA:
uri = mCacheUri;
if (listener != null) {
listener.requestCaptureCamera(getRealFilePath(activity, uri), null);
}
if (crop == null) return;
crop.setSource(uri);
Intent intent = crop.create();
grantUriPermission(activity, intent, crop.getOutput());
activity.startActivityForResult(intent, REQUEST_CROP);
break;
case REQUEST_CROP:
if (listener != null && data != null)
{
listener.requestCrop(getRealFilePath(activity, mCacheUri), (Bitmap) data.getParcelableExtra("data"));
}
break;
}
}
@RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static void getImageFromAlbum(Activity activity) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");//相片類(lèi)型
activity.startActivityForResult(intent, REQUEST_OPEN_ALBUM);
}
@RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
@Deprecated
public static void getImageFromAlbum(Fragment fragment) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");//相片類(lèi)型
fragment.startActivityForResult(intent, REQUEST_OPEN_ALBUM);
}
public interface OnActivityResultListener {
void requestCaptureCamera(String path, Bitmap bitmap);
void requestCrop(String path, Bitmap bitmap);
}
/**
* Try to return the absolute file path from the given Uri
*
* @param context context
* @param uri uri
* @return the file path or null
*/
public static String getRealFilePath(final Context context, final Uri uri) {
if (null == uri) return null;
String path = uri.toString();
if (path.startsWith("content://" + getAuthority(context) + "/rc_external_path")) {
return path.replace("content://" + getAuthority(context) + "/rc_external_path", Environment.getExternalStorageDirectory().getAbsolutePath());
}
final String scheme = uri.getScheme();
String data = null;
if (scheme == null)
data = uri.getPath();
else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
data = uri.getPath();
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (index > -1) {
data = cursor.getString(index);
}
}
cursor.close();
}
}
return data;
}
private static String getAuthority(Context context) {
return context.getPackageName() + ".FileProvider";
}
public static class CropOption {
private int aspectX=1;//x比例
private int aspectY=1;//y比例
private boolean returnData = false;//是返回bitmap,否返回uri
private String outputFormat;//輸出流保存格式JPG PNG ...
private int outputX=200;//返回的bitmap寬
private int outputY=200;//返回的bitmap高
private Uri output;//輸出流保存路徑
private Uri source;//需要截圖的圖片uri
private boolean noFaceDetection = true;//是否關(guān)閉人臉識(shí)別功能
// get和set方法省略
private Intent create() {
if (source == null)
throw new NullPointerException("沒(méi)有設(shè)置圖片uri");
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(source, "image/*");
intent.putExtra("crop", "true");
if (aspectX > 0)
intent.putExtra("aspectX", aspectX);
if (aspectY > 0)
intent.putExtra("aspectY", aspectY);
if (outputX > 0)
intent.putExtra("outputX", outputX);
if (outputY > 0)
intent.putExtra("outputY", outputY);
intent.putExtra("return-data", returnData);
if (!returnData) {
output = output == null ? source : output;
outputFormat = outputFormat == null ? Bitmap.CompressFormat.JPEG.toString() : outputFormat;
intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
intent.putExtra("outputFormat", outputFormat);
intent.setType("image/*");
intent.putExtra("noFaceDetection", noFaceDetection);
}
return intent;
}
}
private static void grantUriPermission(Context context, Intent intent, Uri uri) {
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
}
//xml文件部分
<?xml version="1.0" encoding="utf-8"?>
<resources >
<paths>
<external-path path="" name="rc_external_path" />
</paths>
</resources>
//清單文件注冊(cè)部分
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.lenso.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
也封裝了從本地獲取,以及拍照獲取的相關(guān)功能,可以值得學(xué)習(xí),畢竟不少坑。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android應(yīng)用中使用ViewPager和ViewPager指示器來(lái)制作Tab標(biāo)簽
這篇文章主要介紹了Android中使用ViewPager和ViewPager指示器來(lái)制作Tab標(biāo)簽的方法,ViewPager指示器ViewPageIndicator是一個(gè)開(kāi)源庫(kù),文中舉了一個(gè)仿網(wǎng)易新聞客戶(hù)端Tab標(biāo)簽的例子,需要的朋友可以參考下2016-03-03
Android動(dòng)畫(huà)系列之屬性動(dòng)畫(huà)的基本使用教程
這篇文章主要給大家介紹了關(guān)于Android動(dòng)畫(huà)系列教程之屬性動(dòng)畫(huà)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
OKhttp攔截器實(shí)現(xiàn)實(shí)踐環(huán)節(jié)源碼解析
這篇文章主要為大家介紹了OKhttp攔截器實(shí)現(xiàn)實(shí)踐環(huán)節(jié)源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android編程實(shí)現(xiàn)的短信編輯器功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)的短信編輯器功能,涉及Android權(quán)限控制、界面布局及短信功能相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Android動(dòng)態(tài)給ViewPager添加Indicator導(dǎo)航
這篇文章主要為大家詳細(xì)介紹了Android動(dòng)態(tài)給ViewPager添加Indicator導(dǎo)航的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Android實(shí)現(xiàn)一個(gè)絲滑的自動(dòng)輪播控件實(shí)例代碼
輪播圖對(duì)大家來(lái)說(shuō)應(yīng)該再熟悉不過(guò)了,下面這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)一個(gè)絲滑的自動(dòng)輪播控件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
Android實(shí)現(xiàn)滑動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)滑動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09
Android?Activity共享元素動(dòng)畫(huà)示例解析
這篇文章主要為大家介紹了Android?Activity共享元素動(dòng)畫(huà)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09

